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