| 1 | /** \file grad.c
 | 
|---|
| 2 |  * Gradient Calculation.
 | 
|---|
| 3 |  * 
 | 
|---|
| 4 |  * The most important structure is Gradient with its Gradient::GradientArray.
 | 
|---|
| 5 |  * It contains the various stages of the calculated conjugate direction, beginning
 | 
|---|
| 6 |  * from the Psis::LocalPsiStatus. Subsequently, CalculateCGGradient(), CalculatePreConGrad(),
 | 
|---|
| 7 |  * CalculateConDir() and CalculateLineSearch() are called which use earlier stages to
 | 
|---|
| 8 |  * calculate the latter ones: ActualGradient, PreConDirGradient, ConDirGradient and OldConDirGradient,
 | 
|---|
| 9 |  * do the one-dimensional minimisation and finally update the coefficients of the wave function,
 | 
|---|
| 10 |  * whilst these ought to remain orthogonal.
 | 
|---|
| 11 |  * 
 | 
|---|
| 12 |  * Initialization of the Gradient structure and arrays is done in InitGradients(), deallocation
 | 
|---|
| 13 |  * in RemoveGradients().
 | 
|---|
| 14 |  * 
 | 
|---|
| 15 |  * Small functions calculate the scalar product between two gradient directions GradSP(), find
 | 
|---|
| 16 |  * the minimal angle in the line search CalculateDeltaI() or evaluate complex expressions
 | 
|---|
| 17 |  * CalculateConDirHConDir(), down to basic calculation of the gradient of the wave function
 | 
|---|
| 18 |  * CalculateGradientNoRT(). CalculateHamiltonian() sets up the Hamiltonian for the Kohn-Sham
 | 
|---|
| 19 |  * orbitals and calculates the eigenvalues.
 | 
|---|
| 20 |  * 
 | 
|---|
| 21 |  * Other functions update the coefficients after the position of the ion has changed - 
 | 
|---|
| 22 |  * CalcAlphaForUpdateWaveAfterIonMove() and UpdateWaveAfterIonMove().
 | 
|---|
| 23 |  * 
 | 
|---|
| 24 |  * 
 | 
|---|
| 25 |   Project: ParallelCarParrinello
 | 
|---|
| 26 |  \author Jan Hamaekers
 | 
|---|
| 27 |  \date 2000
 | 
|---|
| 28 | 
 | 
|---|
| 29 |   File: grad.c
 | 
|---|
| 30 |   $Id: grad.c,v 1.90 2007-03-29 13:38:04 foo Exp $
 | 
|---|
| 31 | */
 | 
|---|
| 32 | 
 | 
|---|
| 33 | #include <stdlib.h>
 | 
|---|
| 34 | #include <stdio.h>
 | 
|---|
| 35 | #include <stddef.h>
 | 
|---|
| 36 | #include <math.h>
 | 
|---|
| 37 | #include <string.h>
 | 
|---|
| 38 | #include <gsl/gsl_matrix.h>
 | 
|---|
| 39 | #include <gsl/gsl_eigen.h>
 | 
|---|
| 40 | #include <gsl/gsl_heapsort.h>
 | 
|---|
| 41 | #include <gsl/gsl_complex.h>
 | 
|---|
| 42 | #include <gsl/gsl_complex_math.h>
 | 
|---|
| 43 | #include <gsl/gsl_sort_vector.h>
 | 
|---|
| 44 | #include <gsl/gsl_blas.h>
 | 
|---|
| 45 | 
 | 
|---|
| 46 | #include "mymath.h"
 | 
|---|
| 47 | #include "data.h"
 | 
|---|
| 48 | #include "errors.h"
 | 
|---|
| 49 | #include "energy.h"
 | 
|---|
| 50 | #include "helpers.h"
 | 
|---|
| 51 | #include "myfft.h"
 | 
|---|
| 52 | #include "density.h"
 | 
|---|
| 53 | #include "gramsch.h"
 | 
|---|
| 54 | #include "perturbed.h"
 | 
|---|
| 55 | #include "pseudo.h"
 | 
|---|
| 56 | #include "grad.h"
 | 
|---|
| 57 | #include "run.h"
 | 
|---|
| 58 | #include "wannier.h"
 | 
|---|
| 59 | 
 | 
|---|
| 60 | /** Initialization of Gradient Calculation.
 | 
|---|
| 61 |  * Gradient::GradientArray[GraSchGradient] is set onto "extra" Psis::LocalPsi (needed
 | 
|---|
| 62 |  * for orthogonal conjugate gradient directions!),
 | 
|---|
| 63 |  * for the remaining GradientTypes memory is allocated and zerod.
 | 
|---|
| 64 |  * \param *P Problem at hand
 | 
|---|
| 65 |  * \param *Grad Gradient structure
 | 
|---|
| 66 |  */
 | 
|---|
| 67 | void InitGradients(struct Problem *P, struct Gradient *Grad)
 | 
|---|
| 68 | {
 | 
|---|
| 69 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
| 70 |   struct RunStruct *R = &P->R;
 | 
|---|
| 71 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
| 72 |   struct LatticeLevel *ILevS = R->InitLevS;
 | 
|---|
| 73 |   struct Psis *Psi = &Lat->Psi;
 | 
|---|
| 74 |   int i;
 | 
|---|
| 75 |   Grad->GradientArray[GraSchGradient] = LevS->LPsi->LocalPsi[Psi->LocalNo];
 | 
|---|
| 76 |   for (i=1; i<MaxGradientArrayTypes; i++) {
 | 
|---|
| 77 |     Grad->GradientArray[i] = (fftw_complex *) Malloc(sizeof(fftw_complex)*ILevS->MaxG, "InitGradients");
 | 
|---|
| 78 |     SetArrayToDouble0((double*)Grad->GradientArray[i], 2*ILevS->MaxG);
 | 
|---|
| 79 |   }
 | 
|---|
| 80 | }
 | 
|---|
| 81 | 
 | 
|---|
| 82 | /** Deallocates memory used in Gradient::GradientArray.
 | 
|---|
| 83 |  * Gradient::GradientArray[GraSchGradient] is set to null.
 | 
|---|
| 84 |  * \param *P Problem at hand
 | 
|---|
| 85 |  * \param *Grad Gradient structure
 | 
|---|
| 86 |  */
 | 
|---|
| 87 | void RemoveGradients(struct Problem *P, struct Gradient *Grad)
 | 
|---|
| 88 | {
 | 
|---|
| 89 |   int i;
 | 
|---|
| 90 |   P=P;
 | 
|---|
| 91 |   Grad->GradientArray[GraSchGradient] = NULL;
 | 
|---|
| 92 |   for (i=1; i<MaxGradientArrayTypes; i++)
 | 
|---|
| 93 |     Free(Grad->GradientArray[i], "RemoveGradients: Grad->GradientArray[i]");
 | 
|---|
| 94 | }
 | 
|---|
| 95 | 
 | 
|---|
| 96 | /** Calculates the scalar product of two wave functions with equal symmetry.
 | 
|---|
| 97 |  * \param *P Problem at hand
 | 
|---|
| 98 |  * \param *Lev LatticeLevel structure
 | 
|---|
| 99 |  * \param *LPsiDatA first array of complex wave functions coefficients
 | 
|---|
| 100 |  * \param *LPsiDatB second array of complex wave functions coefficients
 | 
|---|
| 101 |  * \return complex scalar product of the two wave functions.
 | 
|---|
| 102 |  * \warning MPI_Allreduce has to be done still, remember coefficients are shared among processes!
 | 
|---|
| 103 |  */
 | 
|---|
| 104 | double GradSP(struct Problem *P, struct LatticeLevel *Lev, const fftw_complex *LPsiDatA, const fftw_complex *LPsiDatB) {
 | 
|---|
| 105 |   double LocalSP=0.0;
 | 
|---|
| 106 |   int i = 0;
 | 
|---|
| 107 |   if (Lev->GArray[0].GSq == 0.0) {
 | 
|---|
| 108 |     LocalSP += LPsiDatA[0].re * LPsiDatB[0].re;
 | 
|---|
| 109 |     i++;
 | 
|---|
| 110 |   }
 | 
|---|
| 111 |   for (; i < Lev->MaxG; i++) {
 | 
|---|
| 112 |     LocalSP += 2.*(LPsiDatA[i].re * LPsiDatB[i].re + LPsiDatA[i].im * LPsiDatB[i].im); // factor 2 because of the symmetry arising from gamma point!
 | 
|---|
| 113 |   }
 | 
|---|
| 114 |   return(LocalSP);
 | 
|---|
| 115 | }
 | 
|---|
| 116 | 
 | 
|---|
| 117 | /** Calculates the scalar product of two wave functions with unequal symmetry.
 | 
|---|
| 118 |  * \param *P Problem at hand
 | 
|---|
| 119 |  * \param *Lev LatticeLevel structure
 | 
|---|
| 120 |  * \param *LPsiDatA first array of complex wave functions coefficients
 | 
|---|
| 121 |  * \param *LPsiDatB second array of complex wave functions coefficients
 | 
|---|
| 122 |  * \return complex scalar product of the two wave functions.
 | 
|---|
| 123 |  * \warning MPI_Allreduce has to be done still, remember coefficients are shared among processes!
 | 
|---|
| 124 |  */
 | 
|---|
| 125 | double GradImSP(struct Problem *P, struct LatticeLevel *Lev, fftw_complex *LPsiDatA, fftw_complex *LPsiDatB) {
 | 
|---|
| 126 |   double LocalSP=0.0;
 | 
|---|
| 127 |   int i = 0;
 | 
|---|
| 128 |   if (Lev->GArray[0].GSq == 0.0) {
 | 
|---|
| 129 |     i++;
 | 
|---|
| 130 |   }
 | 
|---|
| 131 |   for (; i < Lev->MaxG; i++) {
 | 
|---|
| 132 |     LocalSP += 2.*(LPsiDatA[i].re * LPsiDatB[i].im - LPsiDatA[i].im * LPsiDatB[i].re); // factor 2 because of the symmetry arising from gamma point!
 | 
|---|
| 133 |   }
 | 
|---|
| 134 |   return(LocalSP);
 | 
|---|
| 135 | }
 | 
|---|
| 136 | 
 | 
|---|
| 137 | /** Calculation of gradient of wave function(without RiemannTensor).
 | 
|---|
| 138 |  * We want to calculate the variational derivative \f$\frac{\delta}{\delta \psi^*_j} E[{\psi^*_j}]\f$,
 | 
|---|
| 139 |  * which we need for the minimisation of the energy functional. In the plane wave basis this evaluates to
 | 
|---|
| 140 |  * \f[
 | 
|---|
| 141 |  *    \langle \chi_G| -\frac{1}{2}\nabla^2 + \underbrace{V^H + V^{ps,loc} + V^{XC}}_{V^{loc}} + V^{ps,nl} | \psi_i \rangle
 | 
|---|
| 142 |  *    \qquad (section 4.3)
 | 
|---|
| 143 |  * \f]
 | 
|---|
| 144 |  * Therefore, DensityType#HGDensity is back-transformed, exchange correlation potential added up (CalculateXCPotentialNoRT()),
 | 
|---|
| 145 |  * and vector multiplied with the wave function Psi (per node R), transformation into reciprocal grid space and we are back
 | 
|---|
| 146 |  * in the plane wave basis set as desired. CalculateAddNLPot() adds the non-local potential. Finally, the kinetic term
 | 
|---|
| 147 |  * is added up (simple in reciprocal space). The energy eigenvalue \a *Lambda is computed by summation over all reciprocal grid
 | 
|---|
| 148 |  * vectors and in the meantime also the gradient direction (negative derivative) stored in \a *grad while the old values
 | 
|---|
| 149 |  * are moved to \a *oldgrad. At last, \a *Lambda is summed up among all processes.
 | 
|---|
| 150 |  * \f[
 | 
|---|
| 151 |  *    \varphi_i^{(m)} (G) = \frac{1}{2} |G|^2 c_{i,G} + \underbrace{V^H (G) + V^{ps,loc} (G)}_{+V^{HG} (G)} + V^{ps,nl} (G) | \psi_i (G) \rangle
 | 
|---|
| 152 |  *    \qquad (\textnormal{end of section 4.5.2})
 | 
|---|
| 153 |  * \f]
 | 
|---|
| 154 |  * \param *P Problem at hand, contains Lattice and RunStruct
 | 
|---|
| 155 |  * \param *source source wave function coefficients
 | 
|---|
| 156 |  * \param PsiFactor occupation number, see Psis::PsiFactor
 | 
|---|
| 157 |  * \param *Lambda eigenvalue \f$\lambda_i = \langle \psi_i |h|\psi_i \rangle\f$, see OnePsiElementAddData::Lambda
 | 
|---|
| 158 |  * \param ***fnl non-local form factors over ion type, ion of type and reciprocal grid vector, see PseudoPot::fnl
 | 
|---|
| 159 |  * \param *grad return array for (negative) gradient coefficients \f$\varphi_i^{(m)} (G)\f$
 | 
|---|
| 160 |  * \param *oldgrad return array for (negative) gradient coefficients \f$\varphi_i^{(m-1)} (G)\f$
 | 
|---|
| 161 |  * \param *Hc_grad return array for complex coefficients of \f$H | \psi_i (G) \rangle\f$, see GradientArray#HcGradient
 | 
|---|
| 162 |  * \sa CalculateConDirHConDir() - similar calculation for another explanation.
 | 
|---|
| 163 |  */
 | 
|---|
| 164 | void CalculateGradientNoRT(struct Problem *P, fftw_complex *source, const double PsiFactor, double *Lambda, fftw_complex ***fnl, fftw_complex *grad, fftw_complex *oldgrad, fftw_complex *Hc_grad)
 | 
|---|
| 165 | {
 | 
|---|
| 166 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
| 167 |   struct RunStruct *R = &P->R;
 | 
|---|
| 168 |   struct LatticeLevel *Lev0 = R->Lev0;
 | 
|---|
| 169 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
| 170 |   struct Density *Dens0 = Lev0->Dens;
 | 
|---|
| 171 |   struct  fft_plan_3d *plan = Lat->plan; 
 | 
|---|
| 172 |   int Index, g;
 | 
|---|
| 173 |   fftw_complex *work = Dens0->DensityCArray[TempDensity];
 | 
|---|
| 174 |   fftw_real *HGcR = Dens0->DensityArray[HGcDensity];
 | 
|---|
| 175 |   fftw_complex *HGcRC = (fftw_complex*)HGcR;
 | 
|---|
| 176 |   fftw_complex *HGC = Dens0->DensityCArray[HGDensity];
 | 
|---|
| 177 |   fftw_real *HGCR = (fftw_real *)HGC;
 | 
|---|
| 178 |   fftw_complex *PsiC = Dens0->DensityCArray[ActualPsiDensity];
 | 
|---|
| 179 |   fftw_real *PsiCR = (fftw_real *)PsiC;
 | 
|---|
| 180 |   int nx,ny,nz,iS,i0,s;
 | 
|---|
| 181 |   const int Nx = LevS->Plan0.plan->local_nx;
 | 
|---|
| 182 |   const int Ny = LevS->Plan0.plan->N[1];
 | 
|---|
| 183 |   const int Nz = LevS->Plan0.plan->N[2];
 | 
|---|
| 184 |   const int NUpx = LevS->NUp[0];
 | 
|---|
| 185 |   const int NUpy = LevS->NUp[1];
 | 
|---|
| 186 |   const int NUpz = LevS->NUp[2];
 | 
|---|
| 187 |   double lambda;
 | 
|---|
| 188 |   const double HGcRCFactor = 1./LevS->MaxN;
 | 
|---|
| 189 |   SpeedMeasure(P, LocTime, StartTimeDo);
 | 
|---|
| 190 |   // back-transform HGDensity
 | 
|---|
| 191 |   //if (isnan(HGC[0].re)) { fprintf(stderr,"WARNGING: CalculateGradientNoRT(): HGC[%i]_%i.re = NaN!\n", 0, R->ActualLocalPsiNo); Error(SomeError, "NaN-Fehler!"); }
 | 
|---|
| 192 |   fft_3d_complex_to_real(plan, Lev0->LevelNo, FFTNF1, HGC, work);
 | 
|---|
| 193 |   // evaluate exchange potential with this density, add up onto HGCR
 | 
|---|
| 194 |   //if (isnan(HGCR[0])) { fprintf(stderr,"WARNGING: CalculateGradientNoRT(): HGcR[:%i:]_%i = NaN!\n", 0, R->ActualLocalPsiNo); Error(SomeError, "NaN-Fehler!"); }
 | 
|---|
| 195 |   CalculateXCPotentialNoRT(P, HGCR); // add V^{xc} or \epsilon^{xc} upon V^H + V^{ps}
 | 
|---|
| 196 |   for (nx=0;nx<Nx;nx++)  
 | 
|---|
| 197 |     for (ny=0;ny<Ny;ny++) 
 | 
|---|
| 198 |       for (nz=0;nz<Nz;nz++) {
 | 
|---|
| 199 |         i0 = nz*NUpz+Nz*NUpz*(ny*NUpy+Ny*NUpy*nx*NUpx);
 | 
|---|
| 200 |         iS = nz+Nz*(ny+Ny*nx);
 | 
|---|
| 201 |         HGcR[iS] = HGCR[i0]*PsiCR[i0]; /* Matrix Vector Mult */
 | 
|---|
| 202 |         //if (isnan(PsiCR[i0])) { fprintf(stderr,"WARNGING: CalculateGradientNoRT(): PsiCR[%i]_%i = NaN!\n", i0, R->ActualLocalPsiNo); Error(SomeError, "NaN-Fehler!"); }
 | 
|---|
| 203 |         //if (isnan(HGCR[i0])) { fprintf(stderr,"WARNGING: CalculateGradientNoRT(): HGCR[%i]_%i = NaN!\n", i0, R->ActualLocalPsiNo); Error(SomeError, "NaN-Fehler!"); }
 | 
|---|
| 204 |       }
 | 
|---|
| 205 |   fft_3d_real_to_complex(plan, LevS->LevelNo, FFTNF1, HGcRC, work);
 | 
|---|
| 206 |   SpeedMeasure(P, LocTime, StopTimeDo);
 | 
|---|
| 207 |   /* NonLocalPP */
 | 
|---|
| 208 |   //SpeedMeasure(P, NonLocTime, StartTimeDo);
 | 
|---|
| 209 |   CalculateAddNLPot(P, Hc_grad, fnl, PsiFactor);  // also resets Hc_grad beforehand
 | 
|---|
| 210 |   //SetArrayToDouble0((double *)Hc_grad,2*LevS->MaxG);
 | 
|---|
| 211 |   SpeedMeasure(P, NonLocTime, StopTimeDo);
 | 
|---|
| 212 |   /* Lambda und Grad */
 | 
|---|
| 213 |   for (g=0;g<LevS->MaxG;g++) {
 | 
|---|
| 214 |     Index = LevS->GArray[g].Index; /* FIXME - factoren */
 | 
|---|
| 215 |     Hc_grad[g].re += PsiFactor*(HGcRC[Index].re*HGcRCFactor + 0.5*LevS->GArray[g].GSq*source[g].re);
 | 
|---|
| 216 |     Hc_grad[g].im += PsiFactor*(HGcRC[Index].im*HGcRCFactor + 0.5*LevS->GArray[g].GSq*source[g].im);
 | 
|---|
| 217 |     //if (isnan(source[g].re)) { fprintf(stderr,"WARNGING: CalculateGradientNoRT(): source_%i(%i) = NaN!\n", R->ActualLocalPsiNo, g); Error(SomeError, "NaN-Fehler!"); }  
 | 
|---|
| 218 |   }
 | 
|---|
| 219 |   if (grad != NULL) {
 | 
|---|
| 220 |     lambda = 0.0;
 | 
|---|
| 221 |     s = 0;
 | 
|---|
| 222 |     if (LevS->GArray[0].GSq == 0.0) {
 | 
|---|
| 223 |       lambda += Hc_grad[0].re*source[0].re + Hc_grad[0].im*source[0].im;
 | 
|---|
| 224 |       oldgrad[0].re = grad[0].re; // store away old preconditioned steepest decent gradient
 | 
|---|
| 225 |       oldgrad[0].im = grad[0].im;
 | 
|---|
| 226 |       grad[0].re = -Hc_grad[0].re;
 | 
|---|
| 227 |       grad[0].im = -Hc_grad[0].im;
 | 
|---|
| 228 |       s++;
 | 
|---|
| 229 |     }
 | 
|---|
| 230 |     for (g=s;g<LevS->MaxG;g++) {
 | 
|---|
| 231 |       lambda += 2.*(Hc_grad[g].re*source[g].re + Hc_grad[g].im*source[g].im);
 | 
|---|
| 232 |       oldgrad[g].re = grad[g].re; // store away old preconditioned steepest decent gradient
 | 
|---|
| 233 |       oldgrad[g].im = grad[g].im;
 | 
|---|
| 234 |       grad[g].re = -Hc_grad[g].re;
 | 
|---|
| 235 |       grad[g].im = -Hc_grad[g].im;
 | 
|---|
| 236 |       //if (isnan(Hc_grad[g].re)) { fprintf(stderr,"WARNGING: CalculateGradientNoRT(): Hc_grad_%i(%i) = NaN!\n", R->ActualLocalPsiNo, g); Error(SomeError, "NaN-Fehler!"); }
 | 
|---|
| 237 |     }
 | 
|---|
| 238 |     MPI_Allreduce ( &lambda, Lambda, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
 | 
|---|
| 239 |     //fprintf(stderr,"(%i) Lambda = %e\n",P->Par.me, *Lambda);
 | 
|---|
| 240 |   }
 | 
|---|
| 241 | }
 | 
|---|
| 242 | 
 | 
|---|
| 243 | 
 | 
|---|
| 244 | /** Calculates the Hamiltonian matrix in Kohn-Sham basis set and outputs to file.
 | 
|---|
| 245 |  * In a similiar manner to TestGramSch() all necessary coefficients are retrieved from the
 | 
|---|
| 246 |  * other processes and \f$\langle Psi_i |  H | Psi_j \rangle\f$ = \f$\lambda_{i,j}\f$ calculated.
 | 
|---|
| 247 |  * \param *P Problem at hand
 | 
|---|
| 248 |  * \sa CalculateGradientNoRT() - same calculation (of \f$\lambda_i\f$), yet only for diagonal elements
 | 
|---|
| 249 |  */
 | 
|---|
| 250 | void CalculateHamiltonian(struct Problem *P) {
 | 
|---|
| 251 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
| 252 |   struct FileData *F = &P->Files;
 | 
|---|
| 253 |   struct RunStruct *R = &P->R;
 | 
|---|
| 254 |   struct Psis *Psi = &Lat->Psi;
 | 
|---|
| 255 |   struct LatticeLevel *Lev0 = R->Lev0;
 | 
|---|
| 256 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
| 257 |   //struct LevelPsi *LPsi = LevS->LPsi;
 | 
|---|
| 258 |   struct Density *Dens0 = Lev0->Dens;
 | 
|---|
| 259 |   int Index;
 | 
|---|
| 260 |   struct  fft_plan_3d *plan = Lat->plan; 
 | 
|---|
| 261 |   fftw_complex *work = Dens0->DensityCArray[TempDensity];
 | 
|---|
| 262 |   fftw_real *HGcR = Dens0->DensityArray[HGcDensity];
 | 
|---|
| 263 |   fftw_complex *HGcRC = (fftw_complex*)HGcR;
 | 
|---|
| 264 |   fftw_complex *HGC = Dens0->DensityCArray[HGDensity];
 | 
|---|
| 265 |   fftw_real *HGCR = (fftw_real *)HGC;
 | 
|---|
| 266 |   fftw_complex *PsiC = Dens0->DensityCArray[ActualPsiDensity];
 | 
|---|
| 267 |   fftw_real *PsiCR = (fftw_real *)PsiC;
 | 
|---|
| 268 |   fftw_complex ***fnl;
 | 
|---|
| 269 |   fftw_complex *Hc_grad = P->Grad.GradientArray[HcGradient];
 | 
|---|
| 270 |   int nx,ny,nz,iS,i0,s;
 | 
|---|
| 271 |   const int Nx = LevS->Plan0.plan->local_nx;
 | 
|---|
| 272 |   const int Ny = LevS->Plan0.plan->N[1];
 | 
|---|
| 273 |   const int Nz = LevS->Plan0.plan->N[2];
 | 
|---|
| 274 |   const int NUpx = LevS->NUp[0];
 | 
|---|
| 275 |   const int NUpy = LevS->NUp[1];
 | 
|---|
| 276 |   const int NUpz = LevS->NUp[2];
 | 
|---|
| 277 |   double lambda, Lambda;
 | 
|---|
| 278 |   const double HGcRCFactor = 1./LevS->MaxN;
 | 
|---|
| 279 |   double pot_xc, Pot_xc;
 | 
|---|
| 280 |   int PsiFactorA = 1;
 | 
|---|
| 281 |   int PsiFactorB = 1;
 | 
|---|
| 282 |   int NoPsis = 0;
 | 
|---|
| 283 |   int NoOfPsis = 0;
 | 
|---|
| 284 | 
 | 
|---|
| 285 |   if (P->Call.out[LeaderOut])
 | 
|---|
| 286 |     fprintf(stderr, "(%i)Setting up Hamiltonian for Level %d...",P->Par.me, LevS->LevelNo);
 | 
|---|
| 287 |   if (P->Call.out[StepLeaderOut])
 | 
|---|
| 288 |     fprintf(stderr, "\n(%i) H = \n",P->Par.me);
 | 
|---|
| 289 | 
 | 
|---|
| 290 |   ApplyTotalHamiltonian(P,LevS->LPsi->LocalPsi[0],Hc_grad, P->PP.fnl[0], 1., 1); // update HGDensity->
 | 
|---|
| 291 |   
 | 
|---|
| 292 |   // go through all pairs of orbitals
 | 
|---|
| 293 |   int i,k,l,m,j=0,RecvSource;
 | 
|---|
| 294 |   MPI_Status status;
 | 
|---|
| 295 |   struct OnePsiElement *OnePsiB, *OnePsiA, *LOnePsiA, *LOnePsiB;
 | 
|---|
| 296 |   int ElementSize = (sizeof(fftw_complex) / sizeof(double));
 | 
|---|
| 297 |   fftw_complex *LPsiDatA=NULL, *LPsiDatB;
 | 
|---|
| 298 |   
 | 
|---|
| 299 |   l = -1;
 | 
|---|
| 300 |   switch (Psi->PsiST) {
 | 
|---|
| 301 |     case SpinDouble:
 | 
|---|
| 302 |       NoOfPsis = NoPsis = Psi->GlobalNo[PsiMaxNoDouble];
 | 
|---|
| 303 |       NoOfPsis += Psi->GlobalNo[PsiMaxAdd];      
 | 
|---|
| 304 |       break;
 | 
|---|
| 305 |     case SpinUp:
 | 
|---|
| 306 |       NoOfPsis = NoPsis = Psi->GlobalNo[PsiMaxNoUp];
 | 
|---|
| 307 |       NoOfPsis += Psi->GlobalNo[PsiMaxAdd];      
 | 
|---|
| 308 |       break;
 | 
|---|
| 309 |     case SpinDown:
 | 
|---|
| 310 |       NoOfPsis = NoPsis = Psi->GlobalNo[PsiMaxNoDown];
 | 
|---|
| 311 |       NoOfPsis += Psi->GlobalNo[PsiMaxAdd];      
 | 
|---|
| 312 |       break;
 | 
|---|
| 313 |   };
 | 
|---|
| 314 |   gsl_matrix *H = gsl_matrix_calloc(NoOfPsis,NoOfPsis);
 | 
|---|
| 315 |   for (i=0; i < Psi->MaxPsiOfType+P->Par.Max_me_comm_ST_PsiT; i++) {  // go through all wave functions
 | 
|---|
| 316 |     //fprintf(stderr,"(%i) GlobalNo: %d\tLocalNo: %d\n", P->Par.me,Psi->AllPsiStatus[i].MyGlobalNo,Psi->AllPsiStatus[i].MyLocalNo);
 | 
|---|
| 317 |     OnePsiA = &Psi->AllPsiStatus[i];    // grab OnePsiA
 | 
|---|
| 318 |     if (OnePsiA->PsiType <= UnOccupied) {   // drop the extra and perturbed ones
 | 
|---|
| 319 |       l++;
 | 
|---|
| 320 |       if (OnePsiA->my_color_comm_ST_Psi == P->Par.my_color_comm_ST_Psi) // local?
 | 
|---|
| 321 |          LOnePsiA = &Psi->LocalPsiStatus[OnePsiA->MyLocalNo];
 | 
|---|
| 322 |       else 
 | 
|---|
| 323 |          LOnePsiA = NULL;
 | 
|---|
| 324 |       if (LOnePsiA == NULL) {   // if it's not local ... receive it from respective process into TempPsi
 | 
|---|
| 325 |         RecvSource = OnePsiA->my_color_comm_ST_Psi;
 | 
|---|
| 326 |         MPI_Recv( LevS->LPsi->TempPsi, LevS->MaxG*ElementSize, MPI_DOUBLE, RecvSource, HamiltonianTag, P->Par.comm_ST_PsiT, &status );
 | 
|---|
| 327 |         LPsiDatA=LevS->LPsi->TempPsi;
 | 
|---|
| 328 |       } else {                  // .. otherwise send it to all other processes (Max_me... - 1)
 | 
|---|
| 329 |         for (k=0;k<P->Par.Max_me_comm_ST_PsiT;k++)
 | 
|---|
| 330 |           if (k != OnePsiA->my_color_comm_ST_Psi) 
 | 
|---|
| 331 |             MPI_Send( LevS->LPsi->LocalPsi[OnePsiA->MyLocalNo], LevS->MaxG*ElementSize, MPI_DOUBLE, k, HamiltonianTag, P->Par.comm_ST_PsiT);
 | 
|---|
| 332 |         LPsiDatA=LevS->LPsi->LocalPsi[OnePsiA->MyLocalNo];
 | 
|---|
| 333 |       } // LPsiDatA is now set to the coefficients of OnePsi either stored or MPI_Received
 | 
|---|
| 334 | 
 | 
|---|
| 335 |       if (LOnePsiA != NULL) { // if fnl (!) are locally available!
 | 
|---|
| 336 |         // Trick is: fft wave function by moving it to higher level and there take only each ...th element into account
 | 
|---|
| 337 |         PsiFactorA = 1; //Psi->LocalPsiStatus[OnePsiA->MyLocalNo].PsiFactor;
 | 
|---|
| 338 |         CalculateOneDensityR(Lat, LevS, Dens0, LPsiDatA, Dens0->DensityArray[ActualDensity], R->FactorDensityR*PsiFactorA, 1);
 | 
|---|
| 339 |         // note: factor is not used when storing result in DensityCArray[ActualPsiDensity] in CalculateOneDensityR()!
 | 
|---|
| 340 |         for (nx=0;nx<Nx;nx++)  
 | 
|---|
| 341 |           for (ny=0;ny<Ny;ny++) 
 | 
|---|
| 342 |             for (nz=0;nz<Nz;nz++) {
 | 
|---|
| 343 |               i0 = nz*NUpz+Nz*NUpz*(ny*NUpy+Ny*NUpy*nx*NUpx);
 | 
|---|
| 344 |               iS = nz+Nz*(ny+Ny*nx);
 | 
|---|
| 345 |               HGcR[iS] = HGCR[i0]*PsiCR[i0]; /* Matrix Vector Mult */
 | 
|---|
| 346 |             }
 | 
|---|
| 347 |         // V^{HG} (R) + V^{XC} (R) | \Psi_b (R) \rangle
 | 
|---|
| 348 |         fft_3d_real_to_complex(plan, LevS->LevelNo, FFTNF1, HGcRC, work);
 | 
|---|
| 349 |         // V^{HG} (G) + V^{XC} (G) | \Psi_b (G) \rangle          
 | 
|---|
| 350 |         /* NonLocalPP */
 | 
|---|
| 351 |         fnl = P->PP.fnl[OnePsiA->MyLocalNo];    // fnl only locally available!
 | 
|---|
| 352 |         CalculateAddNLPot(P, Hc_grad, fnl, PsiFactorA); // sets Hc_grad to zero beforehand
 | 
|---|
| 353 |         // V^{ps,nl} (G)| \Psi_b (G) + [V^{HG} (G) + V^{XC} (G)] | \Psi_b (G) \rangle          
 | 
|---|
| 354 |         /* Lambda und Grad */
 | 
|---|
| 355 |         s = 0;
 | 
|---|
| 356 |         if (LevS->GArray[0].GSq == 0.0) {
 | 
|---|
| 357 |           Index = LevS->GArray[0].Index; /* FIXME - factoren */
 | 
|---|
| 358 |           Hc_grad[0].re += PsiFactorA*(HGcRC[Index].re*HGcRCFactor + 0.5*LevS->GArray[0].GSq*LPsiDatA[0].re);
 | 
|---|
| 359 |           Hc_grad[0].im += PsiFactorA*(HGcRC[Index].im*HGcRCFactor + 0.5*LevS->GArray[0].GSq*LPsiDatA[0].im);
 | 
|---|
| 360 |           s++;
 | 
|---|
| 361 |         }
 | 
|---|
| 362 |         for (;s<LevS->MaxG;s++) {
 | 
|---|
| 363 |           Index = LevS->GArray[s].Index; /* FIXME - factoren */
 | 
|---|
| 364 |           Hc_grad[s].re += PsiFactorA*(HGcRC[Index].re*HGcRCFactor + 0.5*LevS->GArray[s].GSq*LPsiDatA[s].re);
 | 
|---|
| 365 |           Hc_grad[s].im += PsiFactorA*(HGcRC[Index].im*HGcRCFactor + 0.5*LevS->GArray[s].GSq*LPsiDatA[s].im);
 | 
|---|
| 366 |         }
 | 
|---|
| 367 |         // 1/2 |G|^2 + V^{ps,nl} (G) + V^{HG} (G) + V^{XC} (G) | \Psi_b (G) \rangle          
 | 
|---|
| 368 |       } else {
 | 
|---|
| 369 |         SetArrayToDouble0((double *)Hc_grad,2*LevS->MaxG);     
 | 
|---|
| 370 |       }
 | 
|---|
| 371 | 
 | 
|---|
| 372 |       m = -1;
 | 
|---|
| 373 |       // former border of following loop: Psi->GlobalNo[Psi->PsiST+1]+Psi->GlobalNo[Psi->PsiST+4]+P->Par.Max_me_comm_ST_PsiT
 | 
|---|
| 374 |       for (j=0; j < Psi->MaxPsiOfType+P->Par.Max_me_comm_ST_PsiT; j++) {  // go through all wave functions
 | 
|---|
| 375 |         OnePsiB = &Psi->AllPsiStatus[j];    // grab OnePsiA
 | 
|---|
| 376 |         if (OnePsiB->PsiType <= UnOccupied) {   // drop the extra ones
 | 
|---|
| 377 |           m++;
 | 
|---|
| 378 |           if (OnePsiB->my_color_comm_ST_Psi == P->Par.my_color_comm_ST_Psi) // local?
 | 
|---|
| 379 |              LOnePsiB = &Psi->LocalPsiStatus[OnePsiB->MyLocalNo];
 | 
|---|
| 380 |           else 
 | 
|---|
| 381 |              LOnePsiB = NULL;
 | 
|---|
| 382 |           if (LOnePsiB == NULL) {   // if it's not local ... receive it from respective process into TempPsi
 | 
|---|
| 383 |             RecvSource = OnePsiB->my_color_comm_ST_Psi;
 | 
|---|
| 384 |             MPI_Recv( LevS->LPsi->TempPsi, LevS->MaxG*ElementSize, MPI_DOUBLE, RecvSource, HamiltonianTag, P->Par.comm_ST_PsiT, &status );
 | 
|---|
| 385 |             LPsiDatB=LevS->LPsi->TempPsi;
 | 
|---|
| 386 |           } else {                  // .. otherwise send it to all other processes (Max_me... - 1)
 | 
|---|
| 387 |             for (k=0;k<P->Par.Max_me_comm_ST_PsiT;k++)
 | 
|---|
| 388 |               if (k != OnePsiB->my_color_comm_ST_Psi) 
 | 
|---|
| 389 |                 MPI_Send( LevS->LPsi->LocalPsi[OnePsiB->MyLocalNo], LevS->MaxG*ElementSize, MPI_DOUBLE, k, HamiltonianTag, P->Par.comm_ST_PsiT);
 | 
|---|
| 390 |             LPsiDatB=LevS->LPsi->LocalPsi[OnePsiB->MyLocalNo];
 | 
|---|
| 391 |           } // LPsiDatB is now set to the coefficients of OnePsi either stored or MPI_Received
 | 
|---|
| 392 | 
 | 
|---|
| 393 |           PsiFactorB = 1; //Psi->LocalPsiStatus[OnePsiB->MyLocalNo].PsiFactor;
 | 
|---|
| 394 |           lambda = 0; //PsiFactorB * GradSP(P, LevS, LPsiDatB, Hc_grad); 
 | 
|---|
| 395 |           Lambda = 0; 
 | 
|---|
| 396 |           s=0;
 | 
|---|
| 397 |           if (LevS->GArray[0].GSq == 0.0) {
 | 
|---|
| 398 |             lambda += GSL_REAL(gsl_complex_mul(gsl_complex_conjugate(convertComplex(LPsiDatB[s])), convertComplex(Hc_grad[s])));
 | 
|---|
| 399 |             s++;
 | 
|---|
| 400 |           }
 | 
|---|
| 401 |           for (; s < LevS->MaxG; s++) {
 | 
|---|
| 402 |             lambda += GSL_REAL(gsl_complex_mul(gsl_complex_conjugate(convertComplex(LPsiDatB[s])), convertComplex(Hc_grad[s]))); 
 | 
|---|
| 403 |             lambda += GSL_REAL(gsl_complex_mul(convertComplex(LPsiDatB[s]), gsl_complex_conjugate(convertComplex(Hc_grad[s]))));  // c(-G) = c^\ast (G) due to gamma point symmetry !
 | 
|---|
| 404 |           } // due to the symmetry the resulting lambda is both real and symmetric in l,m (i,j) !
 | 
|---|
| 405 |           lambda *= PsiFactorB;
 | 
|---|
| 406 |           // \langle \Psi_a | 1/2 |G|^2 + V^{ps,nl} (G) + V^{HG} (G) + V^{XC} (G) | \Psi_b (G) \rangle
 | 
|---|
| 407 |           MPI_Allreduce ( &lambda, &Lambda, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST);  // gather from all(!) (coeffs- and Psis-sharing) groups
 | 
|---|
| 408 | 
 | 
|---|
| 409 |           //if (P->Par.me == 0) {
 | 
|---|
| 410 |           // and Output
 | 
|---|
| 411 |             if (P->Call.out[StepLeaderOut])
 | 
|---|
| 412 |               fprintf(stderr,"%2.5lg\t",Lambda);
 | 
|---|
| 413 |             if (P->Par.me == 0) fprintf(F->HamiltonianFile, "%lg\t", Lambda);
 | 
|---|
| 414 |           //}
 | 
|---|
| 415 |           if (m < NoOfPsis && l < NoOfPsis) {
 | 
|---|
| 416 |             //fprintf(stderr,"Index (%i/%i,%i/%i): %e \n",l,NoOfPsis,m,NoOfPsis, Lambda);
 | 
|---|
| 417 |             gsl_matrix_set(H,l,m,Lambda);
 | 
|---|
| 418 |           } else
 | 
|---|
| 419 |             fprintf(stderr,"Index (%i,%i) out of range %i\n",l,m,NoOfPsis);
 | 
|---|
| 420 |         }
 | 
|---|
| 421 |         if ((P->Par.me == 0) && (j == NoOfPsis-1))
 | 
|---|
| 422 |           fprintf(F->HamiltonianFile, "\n");        
 | 
|---|
| 423 |         if ((P->Call.out[StepLeaderOut]) && (j == NoOfPsis-1))
 | 
|---|
| 424 |             fprintf(stderr,"\n");       
 | 
|---|
| 425 |       }
 | 
|---|
| 426 |     }
 | 
|---|
| 427 |   }
 | 
|---|
| 428 |   if (P->Par.me == 0) {
 | 
|---|
| 429 |     fprintf(F->HamiltonianFile, "\n");
 | 
|---|
| 430 |     fflush(F->HamiltonianFile);
 | 
|---|
| 431 |   }
 | 
|---|
| 432 |   if ((P->Call.out[LeaderOut]) && (!P->Call.out[StepLeaderOut])) {
 | 
|---|
| 433 |     fprintf(stderr,"finished.\n");
 | 
|---|
| 434 |   }
 | 
|---|
| 435 |   
 | 
|---|
| 436 |   // storing H matrix for latter use in perturbed calculation
 | 
|---|
| 437 |   for (i=0;i<Psi->NoOfPsis;i++)
 | 
|---|
| 438 |     for (j=0;j<Psi->NoOfPsis;j++)
 | 
|---|
| 439 |       Psi->lambda[i][j] = gsl_matrix_get(H,i,j);
 | 
|---|
| 440 | 
 | 
|---|
| 441 |   // retrieve EW from H
 | 
|---|
| 442 |   gsl_vector *eval = gsl_vector_alloc(NoOfPsis);
 | 
|---|
| 443 |   gsl_eigen_symm_workspace *w = gsl_eigen_symm_alloc(NoOfPsis);
 | 
|---|
| 444 |   gsl_eigen_symm(H, eval, w);
 | 
|---|
| 445 |   gsl_eigen_symm_free(w);
 | 
|---|
| 446 |   gsl_matrix_free(H);
 | 
|---|
| 447 |   
 | 
|---|
| 448 |   // print eigenvalues
 | 
|---|
| 449 |   if(P->Call.out[LeaderOut]) {
 | 
|---|
| 450 |     fprintf(stderr,"(%i) Unsorted Eigenvalues:", P->Par.me);
 | 
|---|
| 451 |     for (i=0;i<NoOfPsis;i++)
 | 
|---|
| 452 |       fprintf(stderr,"\t%lg",gsl_vector_get(eval,i));
 | 
|---|
| 453 |     fprintf(stderr,"\n");
 | 
|---|
| 454 |   }
 | 
|---|
| 455 |   gsl_sort_vector(eval);  // sort eigenvalues
 | 
|---|
| 456 |   // print eigenvalues
 | 
|---|
| 457 |   if(P->Call.out[LeaderOut]) {
 | 
|---|
| 458 |     fprintf(stderr,"(%i) All Eigenvalues:", P->Par.me);
 | 
|---|
| 459 |     for (i=0;i<NoOfPsis;i++)
 | 
|---|
| 460 |       fprintf(stderr,"\t%lg",gsl_vector_get(eval,i));
 | 
|---|
| 461 |     fprintf(stderr,"\n");
 | 
|---|
| 462 |     fprintf(stderr,"(%i) KS Eigenvalues:", P->Par.me);
 | 
|---|
| 463 |     for (i=0;i<NoOfPsis;i++)
 | 
|---|
| 464 |       fprintf(stderr,"\t%lg",Psi->AddData[i].Lambda);
 | 
|---|
| 465 |     fprintf(stderr,"\n");
 | 
|---|
| 466 |   }
 | 
|---|
| 467 |   
 | 
|---|
| 468 |   // print difference between highest occupied and lowest unoccupied
 | 
|---|
| 469 |   if (P->Lat.Psi.GlobalNo[PsiMaxAdd] != 0) {
 | 
|---|
| 470 |     Lat->Energy[UnOccupied].bandgap = gsl_vector_get(eval, Psi->NoOfPsis) - gsl_vector_get(eval, Psi->NoOfPsis-1);
 | 
|---|
| 471 |     //Lat->Energy[UnOccupied].homolumo = gsl_vector_get(eval, Psi->NoOfPsis/2 + 1) - gsl_vector_get(eval, (Psi->NoOfPsis-1)/2);
 | 
|---|
| 472 |     if (P->Call.out[NormalOut])
 | 
|---|
| 473 |       fprintf(stderr,"(%i) Band gap: \\epsilon_{%d+%d}(%d+1) - \\epsilon_{%d+%d}(%d) = %lg Ht\n", P->Par.me, NoPsis,P->Lat.Psi.GlobalNo[PsiMaxAdd],NoPsis, NoPsis, P->Lat.Psi.GlobalNo[PsiMaxAdd], NoPsis, Lat->Energy[UnOccupied].bandgap);
 | 
|---|
| 474 |       //fprintf(stderr,"(%i) HOMO-LUMO gap (HOMO is: %i, LUMO is %i): %lg Ht\n", P->Par.me, Psi->NoOfPsis/2 + 1, (Psi->NoOfPsis-1)/2, Lat->Energy[UnOccupied].homolumo);
 | 
|---|
| 475 |   }
 | 
|---|
| 476 |   // now, calculate \int v_xc (r) n(r) d^3r
 | 
|---|
| 477 |   SetArrayToDouble0((double *)HGCR,2*Dens0->TotalSize);
 | 
|---|
| 478 |   CalculateXCPotentialNoRT(P, HGCR); /* FIXME - kann man halbieren */
 | 
|---|
| 479 |   pot_xc = 0;
 | 
|---|
| 480 |   Pot_xc = 0;
 | 
|---|
| 481 |   for (i=0;i<Dens0->LocalSizeR;i++)
 | 
|---|
| 482 |     pot_xc += HGCR[i]*Dens0->DensityArray[TotalDensity][i];
 | 
|---|
| 483 |   MPI_Allreduce ( &pot_xc, &Pot_xc, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
 | 
|---|
| 484 |   if (P->Call.out[StepLeaderOut]) {
 | 
|---|
| 485 |     fprintf(stderr,"(%i) Exchange-Correlation potential energy: \\int v_xc[n] (r) n(r) d^3r = %lg\n", P->Par.me, HGcRCFactor*Pot_xc*Lat->Volume);
 | 
|---|
| 486 |   }
 | 
|---|
| 487 |   gsl_vector_free(eval);
 | 
|---|
| 488 | }
 | 
|---|
| 489 | 
 | 
|---|
| 490 | 
 | 
|---|
| 491 | /** Calculation of direction of steepest descent.
 | 
|---|
| 492 |  * The Gradient has been evaluated in CalculateGradient(). Now the SD-direction
 | 
|---|
| 493 |  * \f$\zeta_i = - (H-\lambda_i)\psi_i\f$ is stored in 
 | 
|---|
| 494 |  * Gradient::GradientArray[GradientTypes#GraSchGradient].
 | 
|---|
| 495 |  * Afterwards, the "extra" local Psi (which is the above gradient) is orthogonalized
 | 
|---|
| 496 |  * under exclusion of the to be minimialized Psi to ascertain Orthonormality of this
 | 
|---|
| 497 |  * gradient with respect to all other states/orbits. 
 | 
|---|
| 498 |  * \param *P Problem at hand, contains Lattice and RunStruct
 | 
|---|
| 499 |  * \param *source source wave function coefficients, \f$\psi_i\f$
 | 
|---|
| 500 |  * \param *grad gradient coefficients, see CalculateGradient(), on return contains conjugate gradient coefficients, \f$\varphi_i^{(m)}\f$
 | 
|---|
| 501 |  * \param *Lambda eigenvalue \f$\lambda_i\f$ = \f$\langle \psi_i^{(m)}|H|\psi_i^{(m)} \rangle\f$
 | 
|---|
| 502 |  * \warning coefficients in \a *grad are overwritten
 | 
|---|
| 503 |  */
 | 
|---|
| 504 | static void CalculateCGGradient(struct Problem *P, fftw_complex *source, fftw_complex *grad, double Lambda)
 | 
|---|
| 505 | {
 | 
|---|
| 506 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
| 507 |   struct RunStruct *R = &P->R;
 | 
|---|
| 508 |   struct Psis *Psi = &Lat->Psi; 
 | 
|---|
| 509 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
| 510 |   fftw_complex *GradOrtho = P->Grad.GradientArray[GraSchGradient];
 | 
|---|
| 511 |   int g;
 | 
|---|
| 512 |   int ElementSize = (sizeof(fftw_complex) / sizeof(double));
 | 
|---|
| 513 |   for (g=0;g<LevS->MaxG;g++) {
 | 
|---|
| 514 |     GradOrtho[g].re = grad[g].re+Lambda*source[g].re;
 | 
|---|
| 515 |     GradOrtho[g].im = grad[g].im+Lambda*source[g].im;
 | 
|---|
| 516 |   }
 | 
|---|
| 517 |   // include the ExtraPsi (which is the GraSchGradient!)
 | 
|---|
| 518 |   SetGramSchExtraPsi(P, Psi, NotOrthogonal);
 | 
|---|
| 519 |   // exclude the minimised Psi
 | 
|---|
| 520 |   SetGramSchActualPsi(P, Psi, NotUsedToOrtho);
 | 
|---|
| 521 |   SpeedMeasure(P, GramSchTime, StartTimeDo);
 | 
|---|
| 522 |   // makes conjugate gradient orthogonal to all other orbits
 | 
|---|
| 523 |   //fprintf(stderr,"CalculateCGGradient: GramSch() for extra orbital\n");
 | 
|---|
| 524 |   GramSch(P, LevS, Psi, Orthogonalize);
 | 
|---|
| 525 |   SpeedMeasure(P, GramSchTime, StopTimeDo);
 | 
|---|
| 526 |   SetGramSchActualPsi(P, Psi, IsOrthonormal);
 | 
|---|
| 527 |   memcpy(grad, GradOrtho, ElementSize*LevS->MaxG*sizeof(double));
 | 
|---|
| 528 | }
 | 
|---|
| 529 | 
 | 
|---|
| 530 | /** Preconditioning for the gradient calculation.
 | 
|---|
| 531 |  * A suitable matrix for preconditioning is [TPA89]
 | 
|---|
| 532 |  * \f[
 | 
|---|
| 533 |  *    M_{G,G'} = \delta_{G,G'} \frac{27+18x+12x^2+8x^3}{27+18x+12x^2+8x^3+16x^4} \qquad (5.3)
 | 
|---|
| 534 |  * \f]
 | 
|---|
| 535 |  *  where \f$x= \frac{\langle \xi_G|-\frac{1}{2}\nabla^2|\xi_G \rangle}
 | 
|---|
| 536 |  *    {\langle \psi_i^{(m)}|-\frac{1}{2}\nabla^2|\psi_i^{(m)} \rangle}\f$.
 | 
|---|
| 537 |  * (This simple form is due to the diagonal dominance of the kinetic term in Hamiltonian, and
 | 
|---|
| 538 |  * x is much simpler to evaluate in reciprocal space!)
 | 
|---|
| 539 |  * With this one the higher plane wave states are being transformed such that they
 | 
|---|
| 540 |  * nearly equal the error vector and converge at an equal rate.
 | 
|---|
| 541 |  * So that the new steepest descent direction is \f$M \tilde{\zeta}_i\f$.
 | 
|---|
| 542 |  * Afterwards, the new direction is orthonormalized via GramSch() and the "extra"
 | 
|---|
| 543 |  * local Psi in a likewise manner to CalculateCGGradient().
 | 
|---|
| 544 |  * 
 | 
|---|
| 545 |  * \param *P Problem at hand, contains LatticeLevel and RunStruct
 | 
|---|
| 546 |  * \param *grad array of steepest descent coefficients, \f$\varphi_i^{(m)}\f$
 | 
|---|
| 547 |  * \param *PCgrad return array for preconditioned steepest descent coefficients, \f$\tilde{\varphi}_i^{(m)}\f$
 | 
|---|
| 548 |  * \param T kinetic eigenvalue \f$\langle \psi_i | - \frac{1}{2} \nabla^2 | \psi_i \rangle\f$
 | 
|---|
| 549 |  */
 | 
|---|
| 550 | static void CalculatePreConGrad(struct Problem *P, fftw_complex *grad, fftw_complex *PCgrad, double T)
 | 
|---|
| 551 | {
 | 
|---|
| 552 |   struct RunStruct *R = &P->R;
 | 
|---|
| 553 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
| 554 |   int g;
 | 
|---|
| 555 |   double x, K, dK;
 | 
|---|
| 556 |   struct Psis *Psi = &P->Lat.Psi; 
 | 
|---|
| 557 |   fftw_complex *PCOrtho = P->Grad.GradientArray[GraSchGradient];
 | 
|---|
| 558 |   int ElementSize = (sizeof(fftw_complex) / sizeof(double));
 | 
|---|
| 559 |   if (fabs(T) < MYEPSILON) T = 1;
 | 
|---|
| 560 |   for (g=0;g<LevS->MaxG;g++) {
 | 
|---|
| 561 |     x = LevS->GArray[g].GSq;
 | 
|---|
| 562 |     x /= T;
 | 
|---|
| 563 |     K = (((8*x+12)*x +18)*x+27);
 | 
|---|
| 564 |     dK = ((((16*x+8)*x +12)*x+18)*x+27);
 | 
|---|
| 565 |     K /= dK;
 | 
|---|
| 566 |     c_re(PCOrtho[g]) = K*c_re(grad[g]);
 | 
|---|
| 567 |     c_im(PCOrtho[g]) = K*c_im(grad[g]);  
 | 
|---|
| 568 |   }
 | 
|---|
| 569 |   SetGramSchExtraPsi(P, Psi, NotOrthogonal);
 | 
|---|
| 570 |   SpeedMeasure(P, GramSchTime, StartTimeDo);
 | 
|---|
| 571 |   // preconditioned direction is orthogonalized
 | 
|---|
| 572 |   //fprintf(stderr,"CalculatePreConGrad: GramSch() for extra orbital\n");
 | 
|---|
| 573 |   GramSch(P, LevS, Psi, Orthogonalize);
 | 
|---|
| 574 |   SpeedMeasure(P, GramSchTime, StopTimeDo);
 | 
|---|
| 575 |   memcpy(PCgrad, PCOrtho, ElementSize*LevS->MaxG*sizeof(double));
 | 
|---|
| 576 | }
 | 
|---|
| 577 | 
 | 
|---|
| 578 | /** Calculation of conjugate direction.
 | 
|---|
| 579 |  * The new conjugate direction is according to the algorithm of Fletcher-Reeves:
 | 
|---|
| 580 |  * \f[
 | 
|---|
| 581 |  *  \varphi^{(m)}_i = 
 | 
|---|
| 582 |  *    \tilde{\eta}^{(m)}_i + \frac{\langle \tilde{\eta}^{(m)}_i | \tilde{\varphi}_i^{(m)} \rangle}{\langle \tilde{\eta}^{(m-1)}_i | \tilde{\varphi}_i^{(m-1)} \rangle} \varphi_i^{(m-1)}  
 | 
|---|
| 583 |  * \f]
 | 
|---|
| 584 |  * Instead we use the algorithm of Polak-Ribiere:
 | 
|---|
| 585 |  * \f[
 | 
|---|
| 586 |  *  \varphi^{(m)}_i = 
 | 
|---|
| 587 |  *    \tilde{\eta}^{(m)}_i + \frac{\langle \tilde{\eta}^{(m)}_i | \bigl (\tilde{\varphi}_i^{(m)} \rangle - \tilde{\varphi}_i^{(m-1)} \rangle \bigr)}{\langle \tilde{\eta}^{(m-1)}_i | \tilde{\varphi}_i^{(m-1)} \rangle} \varphi_i^{(m-1)}  
 | 
|---|
| 588 |  * \f]
 | 
|---|
| 589 |  * with an additional automatic restart:
 | 
|---|
| 590 |  * \f[
 | 
|---|
| 591 |  *  \varphi^{(m)}_i = \tilde{\eta}^{(m)}_i \quad \textnormal{if}\ \frac{\langle \tilde{\eta}^{(m)}_i | \bigl (\tilde{\varphi}_i^{(m)} \rangle - \tilde{\varphi}_i^{(m-1)} \rangle \bigr)}{\langle \tilde{\eta}^{(m-1)}_i | \tilde{\varphi}_i^{(m-1)} \rangle} <= 0
 | 
|---|
| 592 |  * \f]
 | 
|---|
| 593 |  * That's why ConDirGradient and OldConDirGradient are stored, the scalar product - summed up among all processes - 
 | 
|---|
| 594 |  * is saved in OnePsiAddData::Gamma. The conjugate direction is again orthonormalized by GramSch() and stored
 | 
|---|
| 595 |  * in \a *ConDir.
 | 
|---|
| 596 |  * \param *P Problem at hand, containing LatticeLevel and RunStruct
 | 
|---|
| 597 |  * \param step minimisation step m
 | 
|---|
| 598 |  * \param *GammaDiv scalar product \f$\langle \tilde{\eta}^{(m-1)}_i | \tilde{\varphi}_i^{(m-1)} \rangle\f$, on calling expects (m-1), on return contains (m)
 | 
|---|
| 599 |  * \param *grad array for coefficients of steepest descent direction \f$\tilde{\zeta}_i^{(m)}\f$
 | 
|---|
| 600 |  * \param *oldgrad array for coefficients of steepest descent direction of \a step-1 \f$\tilde{\zeta}_i^{(m-1)}\f$
 | 
|---|
| 601 |  * \param *PCgrad array for coefficients of preconditioned steepest descent direction \f$\tilde{\eta}_i^{(m)}\f$
 | 
|---|
| 602 |  * \param *ConDir return array for coefficients of conjugate array of \a step, \f$\tilde{\varphi}_i^{(m)}\f$ = \f$\frac{\tilde{\varphi}_i^{(m)}} {||\tilde{\varphi}_i^{(m)}||}\f$
 | 
|---|
| 603 |  * \param *ConDir_old array for coefficients of conjugate array of \a step-1, \f$\tilde{\varphi}_i^{(m-1)}\f$
 | 
|---|
| 604 |  */
 | 
|---|
| 605 | static void CalculateConDir(struct Problem *P, int step, double *GammaDiv,
 | 
|---|
| 606 |                             fftw_complex *grad,  
 | 
|---|
| 607 |           fftw_complex *oldgrad,  
 | 
|---|
| 608 |                             fftw_complex *PCgrad,
 | 
|---|
| 609 |                             fftw_complex *ConDir, fftw_complex *ConDir_old) {
 | 
|---|
| 610 |   struct RunStruct *R = &P->R;
 | 
|---|
| 611 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
| 612 |   struct Psis *Psi = &P->Lat.Psi; 
 | 
|---|
| 613 |   fftw_complex *Ortho = P->Grad.GradientArray[GraSchGradient];
 | 
|---|
| 614 |   int ElementSize = (sizeof(fftw_complex) / sizeof(double));
 | 
|---|
| 615 |   int g;
 | 
|---|
| 616 |   double S[3], Gamma, GammaDivOld = *GammaDiv;
 | 
|---|
| 617 |   double LocalSP[2], PsiSP[2];
 | 
|---|
| 618 |   LocalSP[0] = GradSP(P, LevS, PCgrad, grad);
 | 
|---|
| 619 |   LocalSP[1] = GradSP(P, LevS, PCgrad, oldgrad);
 | 
|---|
| 620 | 
 | 
|---|
| 621 |   MPI_Allreduce ( LocalSP, PsiSP, 2, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
 | 
|---|
| 622 |   *GammaDiv = S[0] = PsiSP[0];
 | 
|---|
| 623 |   S[1] = GammaDivOld;
 | 
|---|
| 624 |   S[2] = PsiSP[1]; 
 | 
|---|
| 625 |   if (step) { // only in later steps is the scalar product used, but always condir stored in oldcondir and Ortho (working gradient)
 | 
|---|
| 626 |     if (fabs(S[1]) < MYEPSILON) {
 | 
|---|
| 627 |       if (fabs((S[0]-S[2])) < MYEPSILON)  
 | 
|---|
| 628 |         Gamma = 1.0;
 | 
|---|
| 629 |       else
 | 
|---|
| 630 |         Gamma = 0.0;
 | 
|---|
| 631 |     } else
 | 
|---|
| 632 |       Gamma = (S[0]-S[2])/S[1];  // the final CG beta coefficient (Polak-Ribiere)  
 | 
|---|
| 633 |     if (Gamma < 0) { // Polak-Ribiere with automatic restart: gamma = max {0, gamma}
 | 
|---|
| 634 |       Gamma = 0.;
 | 
|---|
| 635 |       if (P->Call.out[StepLeaderOut]) fprintf(stderr,"(%i) Polak-Ribiere: Restarting iteration by setting gamma = 0.\n", P->Par.me);
 | 
|---|
| 636 |     }
 | 
|---|
| 637 |     for (g=0; g < LevS->MaxG; g++) {
 | 
|---|
| 638 |       c_re(ConDir[g]) = c_re(PCgrad[g]) + Gamma*c_re(ConDir_old[g]);
 | 
|---|
| 639 |       c_im(ConDir[g]) = c_im(PCgrad[g]) + Gamma*c_im(ConDir_old[g]);
 | 
|---|
| 640 |       c_re(ConDir_old[g]) = c_re(ConDir[g]);
 | 
|---|
| 641 |       c_im(ConDir_old[g]) = c_im(ConDir[g]);
 | 
|---|
| 642 |       c_re(Ortho[g]) = c_re(ConDir[g]);
 | 
|---|
| 643 |       c_im(Ortho[g]) = c_im(ConDir[g]);
 | 
|---|
| 644 |     }
 | 
|---|
| 645 |   } else {
 | 
|---|
| 646 |     Gamma = 0.0;
 | 
|---|
| 647 |     for (g=0; g < LevS->MaxG; g++) {
 | 
|---|
| 648 |       c_re(ConDir[g]) = c_re(PCgrad[g]);
 | 
|---|
| 649 |       c_im(ConDir[g]) = c_im(PCgrad[g]);
 | 
|---|
| 650 |       c_re(ConDir_old[g]) = c_re(ConDir[g]);
 | 
|---|
| 651 |       c_im(ConDir_old[g]) = c_im(ConDir[g]);
 | 
|---|
| 652 |       c_re(Ortho[g]) = c_re(ConDir[g]);
 | 
|---|
| 653 |       c_im(Ortho[g]) = c_im(ConDir[g]);
 | 
|---|
| 654 |     }
 | 
|---|
| 655 |   }
 | 
|---|
| 656 |   // orthonormalize
 | 
|---|
| 657 |   SetGramSchExtraPsi(P, Psi, NotOrthogonal);
 | 
|---|
| 658 |   SpeedMeasure(P, GramSchTime, StartTimeDo);
 | 
|---|
| 659 |   //fprintf(stderr,"CalculateConDir: GramSch() for extra orbital\n");
 | 
|---|
| 660 |   GramSch(P, LevS, Psi, Orthonormalize);
 | 
|---|
| 661 |   SpeedMeasure(P, GramSchTime, StopTimeDo);
 | 
|---|
| 662 |   memcpy(ConDir, Ortho, ElementSize*LevS->MaxG*sizeof(double));
 | 
|---|
| 663 | }
 | 
|---|
| 664 | 
 | 
|---|
| 665 | /** Calculation of \f$\langle \widetilde{\widetilde{\varphi}}_i^{(m)}|H|\widetilde{\widetilde{\varphi}}_i^{(m)} \rangle\f$.
 | 
|---|
| 666 |  * Evaluates most of the parts of the second derivative of the energy functional \f$\frac{\delta^2 E}{\delta \Theta^2}|_{\Theta=0}\f$,
 | 
|---|
| 667 |  * most importantly the energy expection value of the conjugate direction.
 | 
|---|
| 668 |  * \f[
 | 
|---|
| 669 |  *    \langle \widetilde{\widetilde{\varphi}}_i^{(m)} (G) | -\frac{1}{2} \nabla^2 + \underbrace{V^H (G) + V^{ps,loc} (G)}_{=V^{HG}(G)} + V^{ps,nl} | \widetilde{\widetilde{\varphi}} (G) \rangle
 | 
|---|
| 670 |  * \f]
 | 
|---|
| 671 |  * The conjugate direction coefficients \f$\varphi_i^{(m)} (G)\f$ are fftransformed to \f$\varphi_i^{(m)} (R)\f$,
 | 
|---|
| 672 |  * times the DoubleDensityTypes#HGDensity \f$V^{HG} (R) \f$we have the first part,
 | 
|---|
| 673 |  * then \f$\rho (R) = 2\frac{f_i}{V} \Re (\varphi_i^{(m)} (R) \cdot \psi_i (R))\f$is evaluated,
 | 
|---|
| 674 |  * HGDensity is fftransformed to \f$V^{HG} | \varphi_i^{(m)} (G) \rangle\f$,
 | 
|---|
| 675 |  * CalculateAddNLPot() adds non-local potential \f$V^{ps,nl} (G)\f$ to it,
 | 
|---|
| 676 |  * kinetic term is added in the reciprocal base as well \f$-\frac{1}{2} |G|^2\f$,
 | 
|---|
| 677 |  * and at last scalar product between it and the conjugate direction, and done.
 | 
|---|
| 678 |  *
 | 
|---|
| 679 |  * Meanwhile the fftransformed ConDir density \f$\rho (R)\f$ is used for the ddEddt0s \f$A_H\f$, \f$A_{XC}\f$.
 | 
|---|
| 680 |  * In case of RunStruct::DoCalcCGGauss in the following expression additionally \f$\hat{n}^{Gauss}\f$
 | 
|---|
| 681 |  * is evaluted, otherwise left out:
 | 
|---|
| 682 |  * \f[
 | 
|---|
| 683 |  *    A^H = \frac{4\pi}{V} \sum_G \frac{|\frac{\rho(G)}{V^2 N} + \hat{n}^{Gauss}|}{|G|^2} 
 | 
|---|
| 684 |  *    \qquad (\textnormal{section 5.1, line search})
 | 
|---|
| 685 |  * \f]
 | 
|---|
| 686 |  * \param *P Problem at hand
 | 
|---|
| 687 |  * \param *ConDir conjugate direction \f$\tilde{\tilde{\varphi}}_i^{(m)}\f$
 | 
|---|
| 688 |  * \param PsiFactor occupation number, see Psis::PsiFactor
 | 
|---|
| 689 |  * \param *ConDirHConDir first return value: energy expectation value for conjugate direction
 | 
|---|
| 690 |  * \param *HartreeddEddt0 second return value: second derivative of Hartree energy \f$A_H\f$
 | 
|---|
| 691 |  * \param *XCddEddt0 third return value: second derivative of exchange correlation energy \f$A_{XC}\f$
 | 
|---|
| 692 |  * \warning The MPI_Allreduce for the scalar product in the end has not been done!
 | 
|---|
| 693 |  * \sa CalculateLineSearch() - used there
 | 
|---|
| 694 |  */
 | 
|---|
| 695 | void CalculateConDirHConDir(struct Problem *P, fftw_complex *ConDir, const double PsiFactor,
 | 
|---|
| 696 |                                    double *ConDirHConDir, double *HartreeddEddt0, double *XCddEddt0)
 | 
|---|
| 697 | {
 | 
|---|
| 698 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
| 699 |   struct PseudoPot *PP = &P->PP;
 | 
|---|
| 700 |   struct RunStruct *R = &P->R;
 | 
|---|
| 701 |   struct LatticeLevel *Lev0 = R->Lev0;
 | 
|---|
| 702 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
| 703 |   struct Density *Dens0 = Lev0->Dens;
 | 
|---|
| 704 |   int Index, g, i, pos, s=0;
 | 
|---|
| 705 |   struct  fft_plan_3d *plan = Lat->plan; 
 | 
|---|
| 706 |   fftw_complex *work = Dens0->DensityCArray[TempDensity];
 | 
|---|
| 707 |   fftw_real *PsiCD = (fftw_real *)work;
 | 
|---|
| 708 |   fftw_complex *PsiCDC = work;
 | 
|---|
| 709 |   fftw_real *PsiR = (fftw_real *)Dens0->DensityCArray[ActualPsiDensity];
 | 
|---|
| 710 |   fftw_complex *tempdestRC = (fftw_complex *)Dens0->DensityArray[TempDensity];
 | 
|---|
| 711 |   fftw_real *HGCDR = Dens0->DensityArray[HGcDensity];
 | 
|---|
| 712 |   fftw_complex *HGCDRC = (fftw_complex*)HGCDR;
 | 
|---|
| 713 |   fftw_complex *HGC = Dens0->DensityCArray[HGDensity];
 | 
|---|
| 714 |   fftw_real *HGCR = (fftw_real *)HGC;
 | 
|---|
| 715 |   fftw_complex *posfac, *destpos, *destRCS, *destRCD;
 | 
|---|
| 716 |   const double HartreeFactorR = 2.*R->FactorDensityR*PsiFactor;
 | 
|---|
| 717 |   double HartreeFactorC = 4.*PI*Lat->Volume;
 | 
|---|
| 718 |   double HartreeFactorCGauss = 1./Lev0->MaxN; //R->FactorDensityC*R->HGcFactor/Lev0->MaxN; // same expression as first and second factor cancel each other
 | 
|---|
| 719 |   int nx,ny,nz,iS,i0;
 | 
|---|
| 720 |   const int Nx = LevS->Plan0.plan->local_nx;
 | 
|---|
| 721 |   const int Ny = LevS->Plan0.plan->N[1];
 | 
|---|
| 722 |   const int Nz = LevS->Plan0.plan->N[2];
 | 
|---|
| 723 |   const int NUpx = LevS->NUp[0];
 | 
|---|
| 724 |   const int NUpy = LevS->NUp[1];
 | 
|---|
| 725 |   const int NUpz = LevS->NUp[2];
 | 
|---|
| 726 |   const double HGcRCFactor = 1./LevS->MaxN;
 | 
|---|
| 727 |   fftw_complex *HConDir = P->Grad.GradientArray[TempGradient];
 | 
|---|
| 728 |   int DoCalcCGGauss = R->DoCalcCGGauss;
 | 
|---|
| 729 |   fftw_complex rp, rhog;
 | 
|---|
| 730 |   int it;
 | 
|---|
| 731 |   struct Ions *I = &P->Ion;
 | 
|---|
| 732 | 
 | 
|---|
| 733 |   /* ConDir H ConDir */
 | 
|---|
| 734 |   // (G)->(R): retrieve density from wave functions into PsiCD in the usual manner (yet within the same level!) (see CalculateOneDensityR())
 | 
|---|
| 735 |   SetArrayToDouble0((double *)tempdestRC, Dens0->TotalSize*2);
 | 
|---|
| 736 |   for (i=0;i<LevS->MaxG;i++) {
 | 
|---|
| 737 |     Index = LevS->GArray[i].Index;
 | 
|---|
| 738 |     posfac = &LevS->PosFactorUp[LevS->MaxNUp*i];
 | 
|---|
| 739 |     destpos = &tempdestRC[LevS->MaxNUp*Index];
 | 
|---|
| 740 |     for (pos=0; pos < LevS->MaxNUp; pos++) {
 | 
|---|
| 741 |       destpos[pos].re = ConDir[i].re*posfac[pos].re-ConDir[i].im*posfac[pos].im;
 | 
|---|
| 742 |       destpos[pos].im = ConDir[i].re*posfac[pos].im+ConDir[i].im*posfac[pos].re;
 | 
|---|
| 743 |     }
 | 
|---|
| 744 |   }
 | 
|---|
| 745 |   for (i=0; i<LevS->MaxDoubleG; i++) {
 | 
|---|
| 746 |     destRCS = &tempdestRC[LevS->DoubleG[2*i]*LevS->MaxNUp];
 | 
|---|
| 747 |     destRCD = &tempdestRC[LevS->DoubleG[2*i+1]*LevS->MaxNUp];
 | 
|---|
| 748 |     for (pos=0; pos < LevS->MaxNUp; pos++) {
 | 
|---|
| 749 |       destRCD[pos].re =  destRCS[pos].re;
 | 
|---|
| 750 |       destRCD[pos].im = -destRCS[pos].im;
 | 
|---|
| 751 |     }
 | 
|---|
| 752 |   }
 | 
|---|
| 753 |   fft_3d_complex_to_real(plan, LevS->LevelNo, FFTNFUp, tempdestRC, work);
 | 
|---|
| 754 |   DensityRTransformPos(LevS,(fftw_real*)tempdestRC, PsiCD);
 | 
|---|
| 755 |   // HGCR contains real(!) HGDensity from CalculateGradientNoRT() !
 | 
|---|
| 756 |   for (nx=0;nx<Nx;nx++)  
 | 
|---|
| 757 |     for (ny=0;ny<Ny;ny++) 
 | 
|---|
| 758 |       for (nz=0;nz<Nz;nz++) {
 | 
|---|
| 759 |         i0 = nz*NUpz+Nz*NUpz*(ny*NUpy+Ny*NUpy*nx*NUpx);
 | 
|---|
| 760 |         iS = nz+Nz*(ny+Ny*nx);
 | 
|---|
| 761 |         HGCDR[iS] = HGCR[i0]*PsiCD[i0]; /* Matrix Vector Mult */
 | 
|---|
| 762 |       }
 | 
|---|
| 763 |    // now we have V^HG + V^XC | \varphi \rangle
 | 
|---|
| 764 |   /*
 | 
|---|
| 765 |     Hartree & Exchange Correlaton ddt0
 | 
|---|
| 766 |    */
 | 
|---|
| 767 |   for (i=0; i<Dens0->LocalSizeR; i++) 
 | 
|---|
| 768 |     PsiCD[i] *= HartreeFactorR*PsiR[i];   // is rho(r) = PsiFactor times \psi_i is in PsiR times 1/V times \varphi_i^{(m)}
 | 
|---|
| 769 |   *XCddEddt0 = CalculateXCddEddt0NoRT(P, PsiCD);    // calcs A^{XC}
 | 
|---|
| 770 |   fft_3d_real_to_complex(plan, Lev0->LevelNo, FFTNF1, PsiCDC, tempdestRC);
 | 
|---|
| 771 |   s = 0;
 | 
|---|
| 772 |   *HartreeddEddt0 = 0.0;
 | 
|---|
| 773 |   if (Lev0->GArray[0].GSq == 0.0)
 | 
|---|
| 774 |     s++;
 | 
|---|
| 775 |   if (DoCalcCGGauss) {  // this part is wrong, n^Gauss is not part of HartreeddEddt0 (only appears in 2*(<phi_i| H |phi_i> - ...)) 
 | 
|---|
| 776 |     for (g=s; g < Lev0->MaxG; g++) {
 | 
|---|
| 777 |       Index = Lev0->GArray[g].Index;
 | 
|---|
| 778 |       rp.re = 0.0; rp.im = 0.0;
 | 
|---|
| 779 |       for (it = 0; it < I->Max_Types; it++) {
 | 
|---|
| 780 |         c_re(rp) += (c_re(I->I[it].SFactor[g])*PP->FacGauss[it][g]); 
 | 
|---|
| 781 |         c_im(rp) += (c_im(I->I[it].SFactor[g])*PP->FacGauss[it][g]);
 | 
|---|
| 782 |       }
 | 
|---|
| 783 |       c_re(rhog) = c_re(PsiCDC[Index])*HartreeFactorCGauss+c_re(rp);
 | 
|---|
| 784 |       c_im(rhog) = c_im(PsiCDC[Index])*HartreeFactorCGauss+c_im(rp);
 | 
|---|
| 785 |       if (Lev0->GArray[g].GSq < MYEPSILON) fprintf(stderr,"CalculateConDirHConDir: Lev0->GArray[g].GSq = %lg",Lev0->GArray[g].GSq);
 | 
|---|
| 786 |       *HartreeddEddt0 += (c_re(rhog)*c_re(rhog)+c_im(rhog)*c_im(rhog))/(Lev0->GArray[g].GSq);
 | 
|---|
| 787 |     }
 | 
|---|
| 788 |   } else {
 | 
|---|
| 789 |     HartreeFactorC *= HartreeFactorCGauss*HartreeFactorCGauss;
 | 
|---|
| 790 |     for (g=s; g < Lev0->MaxG; g++) {
 | 
|---|
| 791 |       Index = Lev0->GArray[g].Index;
 | 
|---|
| 792 |       if (Lev0->GArray[g].GSq < MYEPSILON) fprintf(stderr,"CalculateConDirHConDir: Lev0->GArray[g].GSq = %lg",Lev0->GArray[g].GSq);
 | 
|---|
| 793 |       *HartreeddEddt0 += (c_re(PsiCDC[Index])*c_re(PsiCDC[Index])+c_im(PsiCDC[Index])*c_im(PsiCDC[Index]))/(Lev0->GArray[g].GSq);
 | 
|---|
| 794 |     }
 | 
|---|
| 795 |   }
 | 
|---|
| 796 |   *HartreeddEddt0 *= HartreeFactorC;
 | 
|---|
| 797 |   /* fertig mit ddEddt0 */
 | 
|---|
| 798 |   
 | 
|---|
| 799 |   fft_3d_real_to_complex(plan, LevS->LevelNo, FFTNF1, HGCDRC, work);
 | 
|---|
| 800 |   CalculateCDfnl(P, ConDir, PP->CDfnl); // calculate needed non-local form factors
 | 
|---|
| 801 |   CalculateAddNLPot(P, HConDir, PP->CDfnl, PsiFactor); // add non-local potential, sets to zero beforehand
 | 
|---|
| 802 |   //SetArrayToDouble0((double *)HConDir,2*LevS->MaxG);
 | 
|---|
| 803 |   // now we have V^{HG} + V^{XC} + V^{ps,nl} | \varphi \rangle
 | 
|---|
| 804 |   for (g=0;g<LevS->MaxG;g++) {  // factor by one over volume and add kinetic part
 | 
|---|
| 805 |     Index = LevS->GArray[g].Index; /* FIXME - factoren */
 | 
|---|
| 806 |     HConDir[g].re += PsiFactor*(HGCDRC[Index].re*HGcRCFactor + 0.5*LevS->GArray[g].GSq*ConDir[g].re);
 | 
|---|
| 807 |     HConDir[g].im += PsiFactor*(HGCDRC[Index].im*HGcRCFactor + 0.5*LevS->GArray[g].GSq*ConDir[g].im);
 | 
|---|
| 808 |   }
 | 
|---|
| 809 |    // now, T^{kin} + V^{HG} + V^{XC} + V^{ps,nl} | \varphi \rangle
 | 
|---|
| 810 |   *ConDirHConDir = GradSP(P, LevS, ConDir, HConDir);
 | 
|---|
| 811 |    // finally, \langle \varphi | V^{HG} + V^{XC} + V^{ps,nl} | \varphi \rangle which is returned
 | 
|---|
| 812 | }
 | 
|---|
| 813 | 
 | 
|---|
| 814 | /** Find the minimal \f$\Theta_{min}\f$ for the line search.
 | 
|---|
| 815 |  * We find it as
 | 
|---|
| 816 |  * \f[ 
 | 
|---|
| 817 |  *  \widetilde{\Theta}_{min} = \frac{1}{2} \tan^{-1} \Bigl ( -\frac{ \frac{\delta E}{\delta \Theta}_{|\Theta =0} }
 | 
|---|
| 818 |  *    { \frac{1}{2} \frac{\delta^2 E}{\delta^2 \Theta}_{|\Theta =0} } \Bigr )
 | 
|---|
| 819 |  * \f]
 | 
|---|
| 820 |  * Thus, with given \f$E(0)\f$, \f$\frac{\delta E}{\delta \Theta}_{|\Theta =0}\f$ and \f$\frac{\delta^2 E}{\delta^2 \Theta}_{|\Theta =0}\f$
 | 
|---|
| 821 |  * \f$\Theta_{min}\f$is calculated and the unknowns A, B and C (see CalculateLineSearch()) obtained. So that our
 | 
|---|
| 822 |  * approximating formula \f$\widetilde{E}(\Theta) = A + B cos(2\Theta) + CSin(2\Theta)\f$ is fully known and we
 | 
|---|
| 823 |  * can evaluate the energy functional and its derivative at \f$\Theta_{min} \f$.
 | 
|---|
| 824 |  * \param E0 energy eigenvalue at \f$\Theta = 0\f$: \f$A= E(0) - B\f$
 | 
|---|
| 825 |  * \param dEdt0 first derivative of energy eigenvalue at \f$\Theta = 0\f$: \f$C = \frac{1}{2} \frac{\delta E}{\delta \Theta}|_{\Theta=0}\f$
 | 
|---|
| 826 |  * \param ddEddt0 first derivative of energy eigenvalue at \f$\Theta = 0\f$: \f$B = -\frac{1}{4} \frac{\delta^2 E}{\delta \Theta^2}|_{\Theta=0}\f$
 | 
|---|
| 827 |  * \param *E returned energy functional at \f$\Theta_{min}\f$
 | 
|---|
| 828 |  * \param *dE returned first derivative energy functional at \f$\Theta_{min}\f$
 | 
|---|
| 829 |  * \param *ddE returned second derivative energy functional at \f$\Theta_{min}\f$
 | 
|---|
| 830 |  * \param *dcos cosine of the found minimal angle
 | 
|---|
| 831 |  * \param *dsin sine of the found minimal angle
 | 
|---|
| 832 |  * \return \f$\Theta_{min}\f$
 | 
|---|
| 833 |  * \sa CalculateLineSearch() - used there
 | 
|---|
| 834 |  */
 | 
|---|
| 835 | double CalculateDeltaI(double E0, double dEdt0, double ddEddt0, double *E, double *dE, double *ddE, double *dcos, double *dsin) 
 | 
|---|
| 836 | {
 | 
|---|
| 837 |   double delta, dcos2, dsin2, A, B, Eavg;
 | 
|---|
| 838 |   if (fabs(ddEddt0) < MYEPSILON) fprintf(stderr,"CalculateDeltaI: ddEddt0 = %lg",ddEddt0);
 | 
|---|
| 839 |   delta = atan(-2.*dEdt0/ddEddt0)/2.0; //.5*
 | 
|---|
| 840 |   *dcos = cos(delta);
 | 
|---|
| 841 |   *dsin = sin(delta);
 | 
|---|
| 842 |   dcos2 = cos(delta*2.0); //2.*
 | 
|---|
| 843 |   dsin2 = sin(delta*2.0); //2.*
 | 
|---|
| 844 |   A = -ddEddt0/4.;
 | 
|---|
| 845 |   B = dEdt0/2.;
 | 
|---|
| 846 |   //fprintf(stderr,"CalculateDeltaI: A = %lg, B = %lg\n", A, B);
 | 
|---|
| 847 |   Eavg = E0-A;
 | 
|---|
| 848 |   *E = Eavg + A*dcos2 + B*dsin2;
 | 
|---|
| 849 |   *dE = -2.*A*dsin2+2.*B*dcos2;
 | 
|---|
| 850 |   *ddE = -4.*A*dcos2-4.*B*dsin2;
 | 
|---|
| 851 |   if (*ddE < 0) { // if it's a maximum (indicated by positive second derivative at found theta)
 | 
|---|
| 852 |     if (delta < 0) {  // go the minimum - the two are always separated by PI/2 by the ansatz
 | 
|---|
| 853 |       delta += PI/2.0; ///2.
 | 
|---|
| 854 |     } else {
 | 
|---|
| 855 |       delta -= PI/2.0; ///2.
 | 
|---|
| 856 |     }
 | 
|---|
| 857 |     *dcos = cos(delta);
 | 
|---|
| 858 |     *dsin = sin(delta);
 | 
|---|
| 859 |     dcos2 = cos(delta*2.0); //2.*
 | 
|---|
| 860 |     dsin2 = sin(delta*2.0); //2.*
 | 
|---|
| 861 |     *E = Eavg + A*dcos2 + B*dsin2;
 | 
|---|
| 862 |     *dE = -2.*A*dsin2+2.*B*dcos2;
 | 
|---|
| 863 |     *ddE = -4.*A*dcos2-4.*B*dsin2;
 | 
|---|
| 864 |   }
 | 
|---|
| 865 |   return(delta);
 | 
|---|
| 866 | }
 | 
|---|
| 867 | 
 | 
|---|
| 868 | 
 | 
|---|
| 869 | /** Line search: One-dimensional minimisation along conjugate direction.
 | 
|---|
| 870 |  * We want to minimize the energy functional along the calculated conjugate direction.
 | 
|---|
| 871 |  * States \f$\psi_i^{(m)}(\Theta) = \widetilde{\psi}_i^{(m)} \cos(\Theta) + \widetilde{\widetilde{\varphi}}_i^{(m)}
 | 
|---|
| 872 |  * \sin(\Theta)\f$ are normalized and orthogonal for every \f$\Theta \in {\cal R}\f$. Thus we
 | 
|---|
| 873 |  * want to find the minimal \f$\Theta_{min}\f$. Intenting to evaluate the energy functional as
 | 
|---|
| 874 |  * seldom as possible, we approximate it by:
 | 
|---|
| 875 |  * \f$\widetilde{E}(\Theta) = A + B cos(2\Theta) + CSin(2\Theta)\f$
 | 
|---|
| 876 |  * where the functions shall match the energy functional and its first and second derivative at
 | 
|---|
| 877 |  * \f$\Theta = 0\f$, fixing the unknowns A, B and C.\n
 | 
|---|
| 878 |  * \f$\frac{\delta E}{\delta \Theta}_{|\Theta =0} = 
 | 
|---|
| 879 |  *   2 \Re \bigl ( \langle \widetilde{\widetilde{\varphi}}_i^{(m)}|H|\psi_i^{(m)} \rangle \bigr )\f$
 | 
|---|
| 880 |  * and 
 | 
|---|
| 881 |  * \f$\frac{\delta^2 E}{\delta^2 \Theta}_{|\Theta =0} = 
 | 
|---|
| 882 |  *  2\bigl( \langle \widetilde{\widetilde{\varphi}}_i^{(m)}|H|\widetilde{\widetilde{\varphi}}_i^{(m)} \rangle 
 | 
|---|
| 883 |  *  - \langle \psi_i^{(m)}|H|\psi_i^{(m)} \rangle
 | 
|---|
| 884 |  *  + \underbrace{\int_\Omega \nu_H[\rho](r)\rho(r)dr}_{A_H} 
 | 
|---|
| 885 |  *  + \underbrace{\int_\Omega \rho(r)^2 \frac{\delta V^{xc}}{\delta n}(r) dr}_{A_{xc}}\f$. \n
 | 
|---|
| 886 |  * \f$A_H\f$ and \f$A_{xc}\f$ can be calculated from the Hartree respectively the exchange
 | 
|---|
| 887 |  * correlation energy.\n
 | 
|---|
| 888 |  * Basically, this boils down to using CalculateConDirHConDir() (we already have OnePsiAddData::Lambda),
 | 
|---|
| 889 |  * in evaluation of the energy functional and its derivatives as shown in the above formulas 
 | 
|---|
| 890 |  * and calling with these CalculateDeltaI() which finds the above \f$\Theta_{min} \f$. \n
 | 
|---|
| 891 |  * The coefficients of the current wave function are recalculated, thus we have the new wave function,
 | 
|---|
| 892 |  * the total energy and its derivatives printed to stderr.\n
 | 
|---|
| 893 |  * 
 | 
|---|
| 894 |  * \param *P Problem at hand
 | 
|---|
| 895 |  * \param *source current minimised wave function
 | 
|---|
| 896 |  * \param *ConDir conjugate direction,  \f$\tilde{\tilde{\varphi}}_i^{(m)}\f$
 | 
|---|
| 897 |  * \param *Hc_grad complex coefficients of \f$H | \psi_i (G) \rangle\f$, see GradientArray#HcGradient
 | 
|---|
| 898 |  * \param x if NULL do approximative line search by second order taylor expansion, otherwise use given
 | 
|---|
| 899 |  *        parameter between -M_PI...M_PI. Is simply put through to CalculateLineSearch()
 | 
|---|
| 900 |  * \param PsiFactor occupation number
 | 
|---|
| 901 |  */
 | 
|---|
| 902 | static void CalculateLineSearch(struct Problem *P, 
 | 
|---|
| 903 |                                 fftw_complex *source,
 | 
|---|
| 904 |                                 fftw_complex *ConDir,
 | 
|---|
| 905 |                                 fftw_complex *Hc_grad, const double PsiFactor, const double *x)
 | 
|---|
| 906 | {
 | 
|---|
| 907 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
| 908 |   struct RunStruct *R = &P->R;
 | 
|---|
| 909 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
| 910 |   struct FileData *F = &P->Files;
 | 
|---|
| 911 |   //struct LatticeLevel *Lev0 = R->Lev0;
 | 
|---|
| 912 |   //struct Density *Dens = Lev0->Dens;
 | 
|---|
| 913 |   //struct Psis *Psi = &P->Lat.Psi;
 | 
|---|
| 914 |   struct Energy *En = Lat->E; 
 | 
|---|
| 915 |   //int ElementSize = (sizeof(fftw_complex) / sizeof(double));
 | 
|---|
| 916 |   double dEdt0, ddEddt0, ConDirHConDir, Eavg, A, B;//, sourceHsource;
 | 
|---|
| 917 |   double E0, E, dE, ddE, delta, dcos, dsin, dcos2, dsin2;
 | 
|---|
| 918 |   double EI, dEI, ddEI, deltaI, dcosI, dsinI;
 | 
|---|
| 919 |   double HartreeddEddt0, XCddEddt0;
 | 
|---|
| 920 |   double d[4],D[4], Diff;
 | 
|---|
| 921 |   //double factorDR = R->FactorDensityR;
 | 
|---|
| 922 |   int g, i;
 | 
|---|
| 923 |   //int ActNum;
 | 
|---|
| 924 | 
 | 
|---|
| 925 |   // ========= dE / dt | 0 ============
 | 
|---|
| 926 |   //fprintf(stderr,"(%i) |ConDir| = %lg, |Hc_grad| = %lg\n", P->Par.me, sqrt(GradSP(P, LevS, ConDir, ConDir)), sqrt(GradSP(P, LevS, Hc_grad, Hc_grad)));
 | 
|---|
| 927 |   d[0] = 2.*GradSP(P, LevS, ConDir, Hc_grad);
 | 
|---|
| 928 | 
 | 
|---|
| 929 |   // ========== ddE / ddt | 0 =========
 | 
|---|
| 930 |   CalculateConDirHConDir(P, ConDir, PsiFactor, &d[1], &d[2], &d[3]);
 | 
|---|
| 931 |   
 | 
|---|
| 932 |   MPI_Allreduce ( &d, &D, 4, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi);
 | 
|---|
| 933 |   dEdt0 = D[0];
 | 
|---|
| 934 |   for (i=MAXOLD-1; i > 0; i--)
 | 
|---|
| 935 |     En->dEdt0[i] = En->dEdt0[i-1];
 | 
|---|
| 936 |   En->dEdt0[0] = dEdt0;
 | 
|---|
| 937 |   ConDirHConDir = D[1];
 | 
|---|
| 938 |   HartreeddEddt0 = D[2];
 | 
|---|
| 939 |   XCddEddt0 = D[3];
 | 
|---|
| 940 |   ddEddt0 = 0.0;
 | 
|---|
| 941 |   switch (R->CurrentMin) {
 | 
|---|
| 942 |     case Occupied:
 | 
|---|
| 943 |       ddEddt0 = HartreeddEddt0+XCddEddt0;    // these terms drop out in unoccupied variation due to lacking dependence of n^{tot}
 | 
|---|
| 944 |     case UnOccupied:
 | 
|---|
| 945 |       ddEddt0 += 2.*(ConDirHConDir - Lat->Psi.AddData[R->ActualLocalPsiNo].Lambda);
 | 
|---|
| 946 |       break;
 | 
|---|
| 947 |     default:
 | 
|---|
| 948 |     ddEddt0 = 0.0;
 | 
|---|
| 949 |       break;
 | 
|---|
| 950 |   }
 | 
|---|
| 951 |   //if (R->CurrentMin <= UnOccupied)
 | 
|---|
| 952 |     //fprintf(stderr,"ConDirHConDir = %lg\tLambda = %lg\t Hartree = %lg\t XC = %lg\n",ConDirHConDir,Lat->Psi.AddData[R->ActualLocalPsiNo].Lambda,HartreeddEddt0,XCddEddt0);
 | 
|---|
| 953 | 
 | 
|---|
| 954 |   for (i=MAXOLD-1; i > 0; i--)
 | 
|---|
| 955 |     En->ddEddt0[i] = En->ddEddt0[i-1];
 | 
|---|
| 956 |   En->ddEddt0[0] = ddEddt0;
 | 
|---|
| 957 |   E0 = En->TotalEnergy[0];
 | 
|---|
| 958 | 
 | 
|---|
| 959 |   if (x == NULL) {
 | 
|---|
| 960 |     // delta
 | 
|---|
| 961 |     //if (isnan(E0)) { fprintf(stderr,"(%i) WARNING in CalculateLineSearch(): E0_%i[%i] = NaN!\n", P->Par.me, i, 0); Error(SomeError, "NaN-Fehler!"); }
 | 
|---|
| 962 |     //if (isnan(dEdt0)) { fprintf(stderr,"(%i) WARNING in CalculateLineSearch(): dEdt0_%i[%i] = NaN!\n", P->Par.me, i, 0); Error(SomeError, "NaN-Fehler!"); }
 | 
|---|
| 963 |     //if (isnan(ddEddt0)) { fprintf(stderr,"(%i) WARNING in CalculateLineSearch(): ddEddt0_%i[%i] = NaN!\n", P->Par.me, i, 0); Error(SomeError, "NaN-Fehler!"); }
 | 
|---|
| 964 |     deltaI = CalculateDeltaI(E0, dEdt0, ddEddt0, 
 | 
|---|
| 965 |                            &EI, &dEI, &ddEI, &dcosI, &dsinI);
 | 
|---|
| 966 |   } else {
 | 
|---|
| 967 |     deltaI = *x;
 | 
|---|
| 968 |     dcosI = cos(deltaI);
 | 
|---|
| 969 |     dsinI = sin(deltaI);
 | 
|---|
| 970 |     dcos2 = cos(deltaI*2.0); //2.*
 | 
|---|
| 971 |     dsin2 = sin(deltaI*2.0); //2.*
 | 
|---|
| 972 |     A = -ddEddt0/4.;
 | 
|---|
| 973 |     B = dEdt0/2.;
 | 
|---|
| 974 |     //fprintf(stderr,"CalculateDeltaI: A = %lg, B = %lg\n", A, B);
 | 
|---|
| 975 |     Eavg = E0-A;
 | 
|---|
| 976 |     EI = Eavg + A*dcos2 + B*dsin2;
 | 
|---|
| 977 |     dEI = -2.*A*dsin2+2.*B*dcos2;
 | 
|---|
| 978 |     ddEI = -4.*A*dcos2-4.*B*dsin2;
 | 
|---|
| 979 |   }
 | 
|---|
| 980 |   delta = deltaI; E = EI; dE = dEI; ddE = ddEI; dcos = dcosI; dsin = dsinI; 
 | 
|---|
| 981 |   if (R->ScanPotential >= R->ScanAtStep) {
 | 
|---|
| 982 |     delta = (R->ScanPotential-(R->ScanAtStep-1))*R->ScanDelta;
 | 
|---|
| 983 |     dcos = cos(delta);
 | 
|---|
| 984 |     dsin = sin(delta);
 | 
|---|
| 985 |     //fprintf(stderr,"(%i) Scaning Potential form with delta %lg\n", P->Par.me, delta);
 | 
|---|
| 986 |   }
 | 
|---|
| 987 |   // shift energy delta values
 | 
|---|
| 988 |   for (i=MAXOLD-1; i > 0; i--) {
 | 
|---|
| 989 |     En->delta[i] = En->delta[i-1];
 | 
|---|
| 990 |     En->ATE[i] = En->ATE[i-1]; 
 | 
|---|
| 991 |   }
 | 
|---|
| 992 |   // store new one
 | 
|---|
| 993 |   En->delta[0] = delta;
 | 
|---|
| 994 |   En->ATE[0] = E;
 | 
|---|
| 995 | 
 | 
|---|
| 996 |   if (R->MinStep != 0)
 | 
|---|
| 997 |     Diff = fabs(En->TotalEnergy[1] - E0)/(En->TotalEnergy[1] - E0)*fabs((E0 - En->ATE[1])/E0);
 | 
|---|
| 998 |   else
 | 
|---|
| 999 |     Diff = 0.;
 | 
|---|
| 1000 |   
 | 
|---|
| 1001 |   // rotate local Psi and ConDir according to angle Theta
 | 
|---|
| 1002 |   for (g = 0; g < LevS->MaxG; g++) {  // Here all coefficients are updated for the new found wave function
 | 
|---|
| 1003 |     //if (isnan(ConDir[g].re)) { fprintf(stderr,"WARNGING: CalculateLineSearch(): ConDir_%i(%i) = NaN!\n", R->ActualLocalPsiNo, g); Error(SomeError, "NaN-Fehler!"); }
 | 
|---|
| 1004 |     c_re(source[g]) = c_re(source[g])*dcos + c_re(ConDir[g])*dsin;
 | 
|---|
| 1005 |     c_im(source[g]) = c_im(source[g])*dcos + c_im(ConDir[g])*dsin;
 | 
|---|
| 1006 |   }
 | 
|---|
| 1007 |   // print to stderr
 | 
|---|
| 1008 |   if (P->Call.out[StepLeaderOut] && x == NULL) {
 | 
|---|
| 1009 |     if (1)
 | 
|---|
| 1010 |     switch (R->CurrentMin) {
 | 
|---|
| 1011 |       case UnOccupied:
 | 
|---|
| 1012 |         fprintf(stderr, "(%i,%i,%i)S(%i,%i,%i):\tTGE: %e\tATGE: %e\t Diff: %e\t --- d: %e\tdEdt0: %e\tddEddt0: %e\n",P->Par.my_color_comm_ST,P->Par.me_comm_ST, P->Par.me_comm_ST_PsiT, R->MinStep, R->ActualLocalPsiNo, R->PsiStep, Lat->Energy[UnOccupied].TotalEnergy[0], E, Diff, delta, dEdt0, ddEddt0);
 | 
|---|
| 1013 |         break;
 | 
|---|
| 1014 |       default:
 | 
|---|
| 1015 |         fprintf(stderr, "(%i,%i,%i)S(%i,%i,%i):\tTE: %e\tATE: %e\t Diff: %e\t --- d: %e\tdEdt0: %e\tddEddt0: %e\n",P->Par.my_color_comm_ST,P->Par.me_comm_ST, P->Par.me_comm_ST_PsiT, R->MinStep, R->ActualLocalPsiNo, R->PsiStep, Lat->Energy[Occupied].TotalEnergy[0], E, Diff, delta, dEdt0, ddEddt0);
 | 
|---|
| 1016 |         break;
 | 
|---|
| 1017 |     }
 | 
|---|
| 1018 |   } 
 | 
|---|
| 1019 |   if ((P->Par.me == 0) && (R->ScanFlag || (R->ScanPotential < R->ScanAtStep))) {
 | 
|---|
| 1020 |     fprintf(F->MinimisationFile, "%i\t%i\t%i\t%e\t%e\t%e\t%e\t%e\n",R->MinStep, R->ActualLocalPsiNo, R->PsiStep, E0, E, delta, dEdt0, ddEddt0);
 | 
|---|
| 1021 |     fflush(F->MinimisationFile);
 | 
|---|
| 1022 |   }
 | 
|---|
| 1023 | }
 | 
|---|
| 1024 | 
 | 
|---|
| 1025 | /** Find the new minimised wave function.
 | 
|---|
| 1026 |  * Note, the gradient wave the function is expected in GradientTypes#ActualGradient. Then,
 | 
|---|
| 1027 |  * subsequently calls (performing thereby a conjugate gradient minimisation algorithm
 | 
|---|
| 1028 |  * of Fletchers&Reeves):
 | 
|---|
| 1029 |  * - CalculateCGGradient()\n
 | 
|---|
| 1030 |  *    find direction of steepest descent: GradientTypes#ActualGradient
 | 
|---|
| 1031 |  * - CalculatePreConGrad()\n
 | 
|---|
| 1032 |  *    precondition steepest descent direction: GradientTypes#PreConGradient
 | 
|---|
| 1033 |  * - CalculateConDir()\n
 | 
|---|
| 1034 |  *    calculate conjugate direction: GradientTypes#ConDirGradient and GradientTypes#OldConDirGradient
 | 
|---|
| 1035 |  * - CalculateLineSearch()\n
 | 
|---|
| 1036 |  *    perform the minimisation in this one-dimensional subspace: LevelPsi::LocalPsi[RunStruct::ActualLocalPsiNo]
 | 
|---|
| 1037 |  * \note CalculateGradient() is not re-done.
 | 
|---|
| 1038 |  * \param *P Problem at hand
 | 
|---|
| 1039 |  * \param x if NULL do approximative line search by second order taylor expansion, otherwise use given paramter between -M_PI...M_PI
 | 
|---|
| 1040 |  */
 | 
|---|
| 1041 | void CalculateNewWave(struct Problem *P, double *x) 
 | 
|---|
| 1042 | {
 | 
|---|
| 1043 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
| 1044 |   struct RunStruct *R = &P->R;
 | 
|---|
| 1045 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
| 1046 |   const int i = R->ActualLocalPsiNo;
 | 
|---|
| 1047 |   const int ConDirStep = R->PsiStep;
 | 
|---|
| 1048 |   if (((!R->ScanPotential) || (R->ScanPotential < R->ScanAtStep)) && (Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent != 1)) { // only evaluate CG once
 | 
|---|
| 1049 |     //if (isnan(P->Grad.GradientArray[ActualGradient][0].re)) { fprintf(stderr,"(%i) WARNING in CalculateNewWave(): ActualGradient_%i[%i] = NaN!\n", P->Par.me, i, 0); Error(SomeError, "NaN-Fehler!"); }
 | 
|---|
| 1050 |     //fprintf(stderr,"(%i) Evaluating ConDirGradient from SD direction...\n", P->Par.me);
 | 
|---|
| 1051 |     CalculateCGGradient(P, LevS->LPsi->LocalPsi[i], 
 | 
|---|
| 1052 |                       P->Grad.GradientArray[ActualGradient], 
 | 
|---|
| 1053 |                       Lat->Psi.AddData[i].Lambda);
 | 
|---|
| 1054 |     //fprintf(stderr,"CalculateCGGradient: %lg\n", GradSP(P, LevS, P->Grad.GradientArray[ActualGradient], P->Grad.GradientArray[ActualGradient]));
 | 
|---|
| 1055 |     CalculatePreConGrad(P, P->Grad.GradientArray[ActualGradient], 
 | 
|---|
| 1056 |                       P->Grad.GradientArray[PreConGradient], 
 | 
|---|
| 1057 |                       Lat->Psi.AddData[i].T);
 | 
|---|
| 1058 |     //if (isnan(P->Grad.GradientArray[PreConGradient][0].re)) { fprintf(stderr,"(%i) WARNING in CalculateNewWave(): PreConGradient_%i[%i] = NaN!\n", P->Par.me, i, 0); Error(SomeError, "NaN-Fehler!"); }
 | 
|---|
| 1059 |     //fprintf(stderr,"CalculatePreConGrad: %lg\n", GradSP(P, LevS, P->Grad.GradientArray[PreConGradient], P->Grad.GradientArray[PreConGradient]));
 | 
|---|
| 1060 |     CalculateConDir(P, ConDirStep, &Lat->Psi.AddData[i].Gamma,
 | 
|---|
| 1061 |                   P->Grad.GradientArray[ActualGradient],
 | 
|---|
| 1062 |         P->Grad.GradientArray[OldActualGradient],
 | 
|---|
| 1063 |                   P->Grad.GradientArray[PreConGradient],
 | 
|---|
| 1064 |                   P->Grad.GradientArray[ConDirGradient],
 | 
|---|
| 1065 |         P->Grad.GradientArray[OldConDirGradient]);
 | 
|---|
| 1066 |     //if (isnan(P->Grad.GradientArray[ConDirGradient][0].re)) { fprintf(stderr,"(%i) WARNING in CalculateNewWave(): ConDirGradient_%i[%i] = NaN!\n", P->Par.me, i, 0); Error(SomeError, "NaN-Fehler!"); }
 | 
|---|
| 1067 |     //fprintf(stderr,"CalculateConDir: %lg\n", GradSP(P, LevS, P->Grad.GradientArray[ConDirGradient], P->Grad.GradientArray[ConDirGradient]));
 | 
|---|
| 1068 |   } //else 
 | 
|---|
| 1069 |     //TestForOrth(P,R->LevS,P->Grad.GradientArray[GraSchGradient]);
 | 
|---|
| 1070 |   //fprintf(stderr,"(%i) DoBrent[%i] = %i\n", P->Par.me, R->ActualLocalPsiNo, Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent);
 | 
|---|
| 1071 |   if (R->ScanPotential) R->ScanPotential++;  // increment by one
 | 
|---|
| 1072 |   CalculateLineSearch(P, 
 | 
|---|
| 1073 |                       LevS->LPsi->LocalPsi[i],
 | 
|---|
| 1074 |                       P->Grad.GradientArray[ConDirGradient],
 | 
|---|
| 1075 |                       P->Grad.GradientArray[HcGradient],
 | 
|---|
| 1076 |                       Lat->Psi.LocalPsiStatus[i].PsiFactor, x);
 | 
|---|
| 1077 |   //if (isnan(LevS->LPsi->LocalPsi[i][0].re)) { fprintf(stderr,"(%i) WARNING in CalculateNewWave(): {\\wildetilde \\varphi}_%i[%i] = NaN!\n", P->Par.me, i, 0); Error(SomeError, "NaN-Fehler!"); }
 | 
|---|
| 1078 |   SetGramSchExtraPsi(P, &Lat->Psi, NotUsedToOrtho);
 | 
|---|
| 1079 |   //TestForOrth(P,R->LevS,P->Grad.GradientArray[GraSchGradient]);
 | 
|---|
| 1080 | }
 | 
|---|
| 1081 | 
 | 
|---|
| 1082 | 
 | 
|---|
| 1083 | /** Calculates the parameter alpha for UpdateWaveAfterIonMove()
 | 
|---|
| 1084 |  * Takes ratios of differences of old and older positions with old and current,
 | 
|---|
| 1085 |  * respectively with old and older. Alpha is then the ratio between the two:
 | 
|---|
| 1086 |  * \f[
 | 
|---|
| 1087 |  *    \alpha = \frac{v_x[old] \cdot v_x[now] + v_y[old] \cdot v_y[now] + v_z[old] \cdot v_z[now]}{v_x[old]^2 + v_y[old]^2 + v_z[old]^2}
 | 
|---|
| 1088 |  * \f]
 | 
|---|
| 1089 |  * Something like a rate of change in the ion velocity.
 | 
|---|
| 1090 |  * \param *P Problem at hand
 | 
|---|
| 1091 |  * \return alpha
 | 
|---|
| 1092 |  */
 | 
|---|
| 1093 | static double CalcAlphaForUpdateWaveAfterIonMove(struct Problem *P) 
 | 
|---|
| 1094 | {
 | 
|---|
| 1095 |   struct Ions *I = &P->Ion;
 | 
|---|
| 1096 |   struct RunStruct *Run = &P->R;
 | 
|---|
| 1097 |   double alpha=0;
 | 
|---|
| 1098 |   double Sum1=0;
 | 
|---|
| 1099 |   double Sum2=0;
 | 
|---|
| 1100 |   int is,ia;
 | 
|---|
| 1101 |   double *R,*R_old,*R_old_old;
 | 
|---|
| 1102 |   Run->AlphaStep++;
 | 
|---|
| 1103 |   if (Run->AlphaStep <= 1) return(0.0);
 | 
|---|
| 1104 |   for (is=0; is < I->Max_Types; is++) {
 | 
|---|
| 1105 |     for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
 | 
|---|
| 1106 |       //if (I->I[is].IMT[ia] == MoveIon) {  // Even FixedIon moves, only not by other's forces
 | 
|---|
| 1107 |                                 R = &I->I[is].R[NDIM*ia];
 | 
|---|
| 1108 |                                 R_old = &I->I[is].R_old[NDIM*ia];
 | 
|---|
| 1109 |                                 R_old_old = &I->I[is].R_old_old[NDIM*ia];  
 | 
|---|
| 1110 |                                 Sum1 += (R_old[0]-R_old_old[0])*(R[0]-R_old[0]);
 | 
|---|
| 1111 |                                 Sum1 += (R_old[1]-R_old_old[1])*(R[1]-R_old[1]);
 | 
|---|
| 1112 |                                 Sum1 += (R_old[2]-R_old_old[2])*(R[2]-R_old[2]);
 | 
|---|
| 1113 |                                 Sum2 += (R_old[0]-R_old_old[0])*(R_old[0]-R_old_old[0]);
 | 
|---|
| 1114 |                                 Sum2 += (R_old[1]-R_old_old[1])*(R_old[1]-R_old_old[1]);
 | 
|---|
| 1115 |                                 Sum2 += (R_old[2]-R_old_old[2])*(R_old[2]-R_old_old[2]);
 | 
|---|
| 1116 |       //}
 | 
|---|
| 1117 |     }
 | 
|---|
| 1118 |   }
 | 
|---|
| 1119 |   if (fabs(Sum2) > MYEPSILON) {
 | 
|---|
| 1120 |     alpha = Sum1/Sum2;
 | 
|---|
| 1121 |   } else {
 | 
|---|
| 1122 |     fprintf(stderr,"(%i) Sum2 <= MYEPSILON\n", P->Par.me);
 | 
|---|
| 1123 |     alpha = 0.0;
 | 
|---|
| 1124 |   }
 | 
|---|
| 1125 |   //if (isnan(alpha)) { fprintf(stderr,"(%i) CalcAlphaForUpdateWaveAfterIonMove: alpha is NaN!\n", P->Par.me); Error(SomeError, "NaN-Fehler!");}
 | 
|---|
| 1126 |   return (alpha);
 | 
|---|
| 1127 | }
 | 
|---|
| 1128 | 
 | 
|---|
| 1129 | /** Updates Wave functions after UpdateIonsR.
 | 
|---|
| 1130 |  * LocalPsi coefficients are shifted by the difference between LevelPsi::LocalPsi and LevelPsi::OldLocalPsi
 | 
|---|
| 1131 |  * multiplied by alpha, new value stored in old one.
 | 
|---|
| 1132 |  * Afterwards all local wave functions are set to NotOrthogonal and then orthonormalized via
 | 
|---|
| 1133 |  * GramSch().
 | 
|---|
| 1134 |  * 
 | 
|---|
| 1135 |  * \param *P Problem at hand
 | 
|---|
| 1136 |  * \sa CalcAlphaForUpdateWaveAfterIonMove() - alpha is calculated here
 | 
|---|
| 1137 |  */
 | 
|---|
| 1138 | double UpdateWaveAfterIonMove(struct Problem *P) 
 | 
|---|
| 1139 | #if 0
 | 
|---|
| 1140 | static double CalculateDeltaII(double E0, double dEdt0, double E1, double deltastep, double *E, double *dE, double *ddE, double *dcos, double *dsin) 
 | 
|---|
| 1141 | {
 | 
|---|
| 1142 |   double delta, dcos2, dsin2, A, B, Eavg;
 | 
|---|
| 1143 |   if (fabs(1-cos(2*deltastep) < MYEPSILON) fprintf(stderr,"CalculateDeltaII: (1-cos(2*deltastep) = %lg",(1-cos(2*deltastep));
 | 
|---|
| 1144 |   A = (E0-E1+0.5*dEdt0*sin(2*deltastep))/(1-cos(2*deltastep));
 | 
|---|
| 1145 |   B = 0.5*dEdt0;
 | 
|---|
| 1146 |   Eavg = E0-A;
 | 
|---|
| 1147 |   if (fabs(A) < MYEPSILON) fprintf(stderr,"CalculateDeltaII: A = %lg",A);
 | 
|---|
| 1148 |   delta = 0.5*atan(B/A);
 | 
|---|
| 1149 |   *dcos = cos(delta);
 | 
|---|
| 1150 |   *dsin = sin(delta);
 | 
|---|
| 1151 |   dcos2 = cos(2.*delta);
 | 
|---|
| 1152 |   dsin2 = sin(2.*delta);
 | 
|---|
| 1153 |   *E = Eavg + A*dcos2 + B*dsin2;
 | 
|---|
| 1154 |   *dE = -2.*A*dsin2+2.*B*dcos2;
 | 
|---|
| 1155 |   *ddE = -4.*A*dcos2-4.*B*dsin2;
 | 
|---|
| 1156 |   if (*ddE < 0) {
 | 
|---|
| 1157 |     if (delta < 0) {
 | 
|---|
| 1158 |       delta += PI/2.;
 | 
|---|
| 1159 |     } else {
 | 
|---|
| 1160 |       delta -= PI/2.;
 | 
|---|
| 1161 |     }
 | 
|---|
| 1162 |     *dcos = cos(delta);
 | 
|---|
| 1163 |     *dsin = sin(delta);
 | 
|---|
| 1164 |     dcos2 = cos(2.*delta);
 | 
|---|
| 1165 |     dsin2 = sin(2.*delta);
 | 
|---|
| 1166 |     *E = Eavg + A*dcos2 + B*dsin2;
 | 
|---|
| 1167 |     *dE = -2.*A*dsin2+2.*B*dcos2;
 | 
|---|
| 1168 |     *ddE = -4.*A*dcos2-4.*B*dsin2;
 | 
|---|
| 1169 |   }
 | 
|---|
| 1170 |   return(delta);
 | 
|---|
| 1171 | }
 | 
|---|
| 1172 | #endif
 | 
|---|
| 1173 | {
 | 
|---|
| 1174 |   struct RunStruct *R = &P->R;
 | 
|---|
| 1175 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
| 1176 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
| 1177 |   struct Psis *Psi = &Lat->Psi;
 | 
|---|
| 1178 |   double alpha=CalcAlphaForUpdateWaveAfterIonMove(P);
 | 
|---|
| 1179 |   int i,g,p,ResetNo=0;
 | 
|---|
| 1180 |   fftw_complex *source, *source_old;
 | 
|---|
| 1181 |   struct OnePsiElement *OnePsi = NULL;
 | 
|---|
| 1182 |   //fprintf(stderr, "%lg\n", alpha);
 | 
|---|
| 1183 |   if (P->R.AlphaStep > 1 && alpha != 0.0) {
 | 
|---|
| 1184 |     for (i=Psi->TypeStartIndex[Occupied]; i < Psi->TypeStartIndex[Perturbed_P0]; i++) {
 | 
|---|
| 1185 |       source = LevS->LPsi->LocalPsi[i];
 | 
|---|
| 1186 |       source_old = LevS->LPsi->OldLocalPsi[i];
 | 
|---|
| 1187 |       for (g=0; g < LevS->MaxG; g++) {
 | 
|---|
| 1188 |                                 c_re(source[g]) = c_re(source[g])+alpha*(c_re(source[g])-c_re(source_old[g]));
 | 
|---|
| 1189 |                                 c_im(source[g]) = c_im(source[g])+alpha*(c_im(source[g])-c_im(source_old[g]));
 | 
|---|
| 1190 |                                 c_re(source_old[g])=c_re(source[g]);
 | 
|---|
| 1191 |                                 c_im(source_old[g])=c_im(source[g]);
 | 
|---|
| 1192 |       }
 | 
|---|
| 1193 |     }
 | 
|---|
| 1194 |   } else {
 | 
|---|
| 1195 |     for (i=Psi->TypeStartIndex[Occupied]; i < Psi->TypeStartIndex[Perturbed_P0]; i++) {
 | 
|---|
| 1196 |       source = LevS->LPsi->LocalPsi[i];
 | 
|---|
| 1197 |       source_old = LevS->LPsi->OldLocalPsi[i];
 | 
|---|
| 1198 |       for (g=0; g < LevS->MaxG; g++) {
 | 
|---|
| 1199 |                                 c_re(source_old[g])=c_re(source[g]);
 | 
|---|
| 1200 |                                 c_im(source_old[g])=c_im(source[g]);
 | 
|---|
| 1201 |       }
 | 
|---|
| 1202 |     }
 | 
|---|
| 1203 |   }
 | 
|---|
| 1204 |   //fprintf(stderr, "(%i) alpha = %lg\n", P->Par.me, alpha);
 | 
|---|
| 1205 |   if (alpha != 0.0) {
 | 
|---|
| 1206 |     for (p=0; p< Psi->LocalNo; p++) {
 | 
|---|
| 1207 |       Psi->LocalPsiStatus[p].PsiGramSchStatus = (Psi->LocalPsiStatus[p].PsiType == Occupied) ? (int)NotOrthogonal : (int)NotUsedToOrtho;
 | 
|---|
| 1208 |       //if (R->CurrentMin > UnOccupied) 
 | 
|---|
| 1209 |       //fprintf(stderr,"(%i) Setting L-Status of %i to %i\n",P->Par.me,p, Psi->LocalPsiStatus[p].PsiGramSchStatus);
 | 
|---|
| 1210 |     }
 | 
|---|
| 1211 |     ResetNo=0;
 | 
|---|
| 1212 |     for (i=0; i < P->Par.Max_me_comm_ST_PsiT; i++) {
 | 
|---|
| 1213 |       for (p=ResetNo; p < ResetNo+Psi->AllLocalNo[i]-1; p++) {
 | 
|---|
| 1214 |                                 Psi->AllPsiStatus[p].PsiGramSchStatus = (Psi->AllPsiStatus[p].PsiType == Occupied) ? (int)NotOrthogonal : (int)NotUsedToOrtho;
 | 
|---|
| 1215 |         //if (R->CurrentMin > UnOccupied) 
 | 
|---|
| 1216 |         //fprintf(stderr,"(%i) Setting A-Status of %i to %i\n",P->Par.me,p, Psi->AllPsiStatus[p].PsiGramSchStatus);
 | 
|---|
| 1217 |       }
 | 
|---|
| 1218 |       ResetNo += Psi->AllLocalNo[i];
 | 
|---|
| 1219 |       OnePsi = &Psi->AllPsiStatus[ResetNo-1]; // extra wave function is set to NotUsed
 | 
|---|
| 1220 |       //if (R->CurrentMin > UnOccupied) fprintf(stderr,"Setting A-Status of %i to %i\n",ResetNo-1, NotUsedToOrtho);
 | 
|---|
| 1221 |       OnePsi->PsiGramSchStatus =  (int)NotUsedToOrtho;
 | 
|---|
| 1222 |     }
 | 
|---|
| 1223 |     SpeedMeasure(P, InitGramSchTime, StartTimeDo);
 | 
|---|
| 1224 |     //fprintf(stderr,"(%i) UpdateWaveAfterIonMove: ResetGramSch() for %i orbitals\n",P->Par.me, p);
 | 
|---|
| 1225 |     GramSch(P, LevS, Psi, Orthonormalize);
 | 
|---|
| 1226 |     SpeedMeasure(P, InitGramSchTime, StartTimeDo);
 | 
|---|
| 1227 |   }
 | 
|---|
| 1228 |   return(alpha);
 | 
|---|
| 1229 | }
 | 
|---|
| 1230 | 
 | 
|---|