| [a0bcf1] | 1 | /** \file energy.c | 
|---|
|  | 2 | * Energy calculation, especially kinetic and electronic. | 
|---|
|  | 3 | * | 
|---|
|  | 4 | * Contains routines for output of calculated values EnergyOutput(), | 
|---|
|  | 5 | * initialization of the Energy structure InitEnergyArray() or inital calculations | 
|---|
|  | 6 | * InitPsiEnergyCalculation(), | 
|---|
|  | 7 | * updating UpdateEnergyArray() and UpdatePsiEnergyCalculation() and of course | 
|---|
|  | 8 | * calculation of the various parts: Density CalculateDensityEnergy(), ionic | 
|---|
|  | 9 | * CalculateIonsEnergy(), electronic CalculatePsiEnergy(), kinetic with RiemannTensor | 
|---|
|  | 10 | * CalculateKineticEnergyUseRT() (calling EnergyGNSP()) and without | 
|---|
|  | 11 | * CalculateKineticEnergyNoRT() (using EnergyLapNSP()). CalculateGapEnergy() evaluates | 
|---|
|  | 12 | * would-be addition from unoccupied states to total energy. | 
|---|
|  | 13 | * Smaller functions such as EnergyAllReduce() gather intermediate results from all | 
|---|
|  | 14 | * processes and sum up to total value. | 
|---|
|  | 15 | * \note Some others are stored in excor.c (exchange energies) and pseudo.c (density | 
|---|
|  | 16 | *       energies) | 
|---|
|  | 17 | * | 
|---|
|  | 18 | * | 
|---|
|  | 19 | Project: ParallelCarParrinello | 
|---|
|  | 20 | \author Jan Hamaekers | 
|---|
|  | 21 | \date 2000 | 
|---|
|  | 22 |  | 
|---|
|  | 23 | File: energy.c | 
|---|
|  | 24 | $Id: energy.c,v 1.68 2007/02/09 09:13:48 foo Exp $ | 
|---|
|  | 25 | */ | 
|---|
|  | 26 |  | 
|---|
|  | 27 | #include <stdlib.h> | 
|---|
|  | 28 | #include <stdio.h> | 
|---|
|  | 29 | #include <stddef.h> | 
|---|
|  | 30 | #include <math.h> | 
|---|
|  | 31 | #include <string.h> | 
|---|
|  | 32 |  | 
|---|
|  | 33 | #include "data.h" | 
|---|
|  | 34 | #include "errors.h" | 
|---|
|  | 35 | #include "helpers.h" | 
|---|
|  | 36 | #include "energy.h" | 
|---|
|  | 37 | #include "riemann.h" | 
|---|
|  | 38 | #include "excor.h" | 
|---|
|  | 39 | #include "myfft.h" | 
|---|
|  | 40 | #include "mymath.h" | 
|---|
|  | 41 | //#include "output.h" | 
|---|
|  | 42 | #include "run.h" | 
|---|
|  | 43 |  | 
|---|
|  | 44 | /** Calculates kinetic energy for a given wave function in reciprocal base. | 
|---|
|  | 45 | * \param *P Problem at hand | 
|---|
|  | 46 | * \param *Lev LatticeLevel structure | 
|---|
|  | 47 | * \param *LPsiDatA complex wave function coefficients \f$c_{i,G}\f$ (reciprocal base) | 
|---|
|  | 48 | * \param *T kinetic eigenvalue, herein result is additionally stored | 
|---|
|  | 49 | * \param Factor  Additional factor for return value (such as occupation number \f$f_i\f$ ) | 
|---|
|  | 50 | * \return \f$E_{kin} = \frac{1}{2} f_i \sum_G |G|^2 |c_{i,G}|^2\f$ | 
|---|
|  | 51 | * \sa used in CalculateKineticEnergyNoRT() | 
|---|
|  | 52 | */ | 
|---|
|  | 53 | static double EnergyGNSP(const struct Problem *P, const struct LatticeLevel *Lev, fftw_complex *LPsiDatA, double *T, const double Factor) { | 
|---|
|  | 54 | double LocalSP=0.0,PsiSP; | 
|---|
|  | 55 | int i,s = 0; | 
|---|
|  | 56 | struct OneGData *G = Lev->GArray; | 
|---|
|  | 57 | if (Lev->GArray[0].GSq == 0.0) {  // only for continuity (see other functions) | 
|---|
|  | 58 | LocalSP += G[0].GSq*LPsiDatA[0].re*LPsiDatA[0].re; | 
|---|
|  | 59 | s++; | 
|---|
|  | 60 | } | 
|---|
|  | 61 | /// Performs complex product for each reciprocal grid vector times twice this vector's norm. | 
|---|
|  | 62 | for (i=s; i < Lev->MaxG; i++) { | 
|---|
|  | 63 | LocalSP += G[i].GSq*2.*(LPsiDatA[i].re*LPsiDatA[i].re+LPsiDatA[i].im*LPsiDatA[i].im);  // factor 2 due to gamma point symmetry | 
|---|
|  | 64 | } | 
|---|
|  | 65 | /// Gathers partial results by summation from all other coefficients sharing processes. | 
|---|
|  | 66 | MPI_Allreduce ( &LocalSP, &PsiSP, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi); | 
|---|
|  | 67 | /// Multiplies by \a Factor and returns result. | 
|---|
|  | 68 | *T = Factor*PsiSP; | 
|---|
|  | 69 | return(Factor*PsiSP); | 
|---|
|  | 70 | } | 
|---|
|  | 71 |  | 
|---|
|  | 72 | /** Calculates kinetic energy for a given wave function in reciprocal base in case of Riemann tensor use. | 
|---|
|  | 73 | * \param *P Problem at hand | 
|---|
|  | 74 | * \param *RT RiemannTensor structure | 
|---|
|  | 75 | * \param *src replaces reciprocal grid vectors | 
|---|
|  | 76 | * \param *Lap replaces complex Psi wave function coefficients | 
|---|
|  | 77 | * \param *T kinetic eigenvalue, herein result is additionally stored | 
|---|
|  | 78 | * \param Factor Additional factor for return value | 
|---|
|  | 79 | * \sa used in CalculateKineticEnergyUseRT(), compare with EnergyGNSP() | 
|---|
|  | 80 | */ | 
|---|
|  | 81 | static double EnergyLapNSP(const struct Problem *P, const struct RiemannTensor *RT, fftw_complex *src, fftw_complex *Lap, double *T, const double Factor) { | 
|---|
|  | 82 | double LocalSP=0.0,PsiSP; | 
|---|
|  | 83 | int i; | 
|---|
|  | 84 | int s = 0; | 
|---|
|  | 85 | struct LatticeLevel *Lev = RT->LevS; | 
|---|
|  | 86 | if (Lev->GArray[0].GSq == 0.0) { | 
|---|
|  | 87 | LocalSP += src[0].re*Lap[0].re+src[0].im*Lap[0].im; | 
|---|
|  | 88 | s++; | 
|---|
|  | 89 | } | 
|---|
|  | 90 | for (i=s; i < Lev->MaxG; i++) { | 
|---|
|  | 91 | LocalSP += 2.*(src[i].re*Lap[i].re+src[i].im*Lap[i].im); | 
|---|
|  | 92 | } | 
|---|
|  | 93 | MPI_Allreduce ( &LocalSP, &PsiSP, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi); | 
|---|
|  | 94 | *T = Factor*PsiSP; | 
|---|
|  | 95 | return(Factor*PsiSP); | 
|---|
|  | 96 | } | 
|---|
|  | 97 |  | 
|---|
|  | 98 | /** Calculcates Kinetic energy without Riemann tensor. | 
|---|
|  | 99 | * \param *P Problem at hand | 
|---|
|  | 100 | * \param p local psi wave function number | 
|---|
|  | 101 | * \sa EnergyGNSP() | 
|---|
|  | 102 | */ | 
|---|
|  | 103 | static void CalculateKineticEnergyNoRT(struct Problem *P, const int p) | 
|---|
|  | 104 | { | 
|---|
|  | 105 | struct Lattice *Lat = &P->Lat; | 
|---|
|  | 106 | struct Energy *E = Lat->E; | 
|---|
|  | 107 | struct RunStruct *R = &P->R; | 
|---|
|  | 108 | struct LatticeLevel *LevS = R->LevS; | 
|---|
|  | 109 | struct LevelPsi *LPsi = LevS->LPsi; | 
|---|
|  | 110 | struct Psis *Psi = &Lat->Psi; | 
|---|
|  | 111 | const double PsiFactor = Psi->LocalPsiStatus[p].PsiFactor; | 
|---|
|  | 112 | fftw_complex *psi; | 
|---|
|  | 113 | psi = LPsi->LocalPsi[p]; | 
|---|
|  | 114 | E->PsiEnergy[KineticEnergy][p] = EnergyGNSP(P, LevS, psi, &Psi->AddData[p].T, 0.5*PsiFactor); | 
|---|
|  | 115 | } | 
|---|
|  | 116 |  | 
|---|
|  | 117 | /** Calculcates Kinetic energy with Riemann tensor. | 
|---|
|  | 118 | * CalculateRiemannLaplaceS() is called and Lattice->RT.RTLaplaceS used instead | 
|---|
|  | 119 | * of Lattice::Psi. | 
|---|
|  | 120 | * \param *P Problem at hand | 
|---|
|  | 121 | * \param p local psi wave function number | 
|---|
|  | 122 | * \sa EnergyLapNSP() | 
|---|
|  | 123 | */ | 
|---|
|  | 124 | static void CalculateKineticEnergyUseRT(struct Problem *P, const int p) | 
|---|
|  | 125 | { | 
|---|
|  | 126 | struct Lattice *Lat = &P->Lat; | 
|---|
|  | 127 | struct Energy *E = Lat->E; | 
|---|
|  | 128 | struct RunStruct *R = &P->R; | 
|---|
|  | 129 | struct LatticeLevel *LevS = R->LevS; | 
|---|
|  | 130 | struct LevelPsi *LPsi = LevS->LPsi; | 
|---|
|  | 131 | struct Psis *Psi = &Lat->Psi; | 
|---|
|  | 132 | const double PsiFactor = Psi->LocalPsiStatus[p].PsiFactor; | 
|---|
|  | 133 | fftw_complex *psi; | 
|---|
|  | 134 | psi = LPsi->LocalPsi[p]; | 
|---|
|  | 135 | CalculateRiemannLaplaceS(Lat, &Lat->RT, psi, Lat->RT.RTLaplaceS); | 
|---|
|  | 136 | E->PsiEnergy[KineticEnergy][p] = EnergyLapNSP(P, &Lat->RT, psi, Lat->RT.RTLaplaceS, &Psi->AddData[p].T, 0.5*PsiFactor); | 
|---|
|  | 137 | //fprintf(stderr,"CalculateKineticEnergyUseRT: PsiEnergy[KineticEnergy] = %lg\n",E->PsiEnergy[KineticEnergy][p]); | 
|---|
|  | 138 | } | 
|---|
|  | 139 |  | 
|---|
|  | 140 | /** Sums up calculated energies from all processes, calculating Energy::TotalEnergy. | 
|---|
|  | 141 | * Via MPI_Allreduce is Energy::AllLocalPsiEnergy summed up and the sum | 
|---|
|  | 142 | * redistributed back to all processes for the various spin cases. In | 
|---|
|  | 143 | * case of SpinType#SpinUp or SpinType#SpinDown the "other" energy (e.g. down | 
|---|
|  | 144 | * for an up process) is via MPI_SendRecv communicated, and lateron | 
|---|
|  | 145 | * Energy#AllTotalPsiEnergy as the sum of two states generated in each process.<br> | 
|---|
|  | 146 | * Finally, the Energy::TotalEnergy[0] is the sum of Energy::AllTotalPsiEnergy[], | 
|---|
|  | 147 | * Energy::AllTotalDensityEnergy[], - Energy::AllTotalIonsEnergy[GaussSelfEnergy] | 
|---|
|  | 148 | * and Energy::AllTotalIonsEnergy[EwaldEnergy]. | 
|---|
|  | 149 | * Again, as in UpdateEnergyArray(), this is split up completely for PsiTypeTag#UnOccupied | 
|---|
|  | 150 | * and PsiTypeTag#Occupied. | 
|---|
|  | 151 | * \param *P Problem at hand | 
|---|
|  | 152 | */ | 
|---|
|  | 153 | void EnergyAllReduce(struct Problem *P) | 
|---|
|  | 154 | { | 
|---|
|  | 155 | struct Psis *Psi = &P->Lat.Psi; | 
|---|
|  | 156 | struct RunStruct *R = &P->R; | 
|---|
|  | 157 | struct Lattice *Lat = &P->Lat; | 
|---|
|  | 158 | struct Energy *E = P->Lat.E; | 
|---|
|  | 159 | struct OnePsiElement *OnePsiB; | 
|---|
|  | 160 | MPI_Status status; | 
|---|
|  | 161 | int i,j,m; | 
|---|
|  | 162 | double lambda, overlap, lambda2, overlap2; //, part1, part2, tmp; | 
|---|
|  | 163 | MPI_Allreduce(E->AllLocalDensityEnergy, E->AllTotalDensityEnergy, MAXALLDENSITYENERGY, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi ); | 
|---|
|  | 164 | switch (Psi->PsiST) { | 
|---|
|  | 165 | case SpinDouble: | 
|---|
|  | 166 | MPI_Allreduce(E->AllLocalPsiEnergy, E->AllTotalPsiEnergy, MAXALLPSIENERGY, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_PsiT); | 
|---|
|  | 167 | break; | 
|---|
|  | 168 | case SpinUp: | 
|---|
|  | 169 | MPI_Allreduce(E->AllLocalPsiEnergy, E->AllUpPsiEnergy, MAXALLPSIENERGY, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_PsiT); | 
|---|
|  | 170 | MPI_Sendrecv(E->AllUpPsiEnergy, MAXALLPSIENERGY, MPI_DOUBLE, P->Par.me_comm_ST, EnergyTag1, | 
|---|
|  | 171 | E->AllDownPsiEnergy, MAXALLPSIENERGY, MPI_DOUBLE, P->Par.me_comm_ST, EnergyTag2, | 
|---|
|  | 172 | P->Par.comm_STInter, &status ); | 
|---|
|  | 173 | for (i=0; i< MAXALLPSIENERGY; i++) | 
|---|
|  | 174 | E->AllTotalPsiEnergy[i] = E->AllUpPsiEnergy[i] + E->AllDownPsiEnergy[i]; | 
|---|
|  | 175 | break; | 
|---|
|  | 176 | case SpinDown: | 
|---|
|  | 177 | MPI_Allreduce(E->AllLocalPsiEnergy, E->AllDownPsiEnergy, MAXALLPSIENERGY, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_PsiT); | 
|---|
|  | 178 | MPI_Sendrecv(E->AllDownPsiEnergy, MAXALLPSIENERGY, MPI_DOUBLE, P->Par.me_comm_ST, EnergyTag2, | 
|---|
|  | 179 | E->AllUpPsiEnergy, MAXALLPSIENERGY, MPI_DOUBLE, P->Par.me_comm_ST, EnergyTag1, | 
|---|
|  | 180 | P->Par.comm_STInter, &status ); | 
|---|
|  | 181 | for (i=0; i< MAXALLPSIENERGY; i++) | 
|---|
|  | 182 | E->AllTotalPsiEnergy[i] = E->AllUpPsiEnergy[i] + E->AllDownPsiEnergy[i]; | 
|---|
|  | 183 | break; | 
|---|
|  | 184 | } | 
|---|
|  | 185 | switch (R->CurrentMin) { | 
|---|
|  | 186 | case Occupied: | 
|---|
|  | 187 | E->TotalEnergy[0] = E->AllTotalPsiEnergy[KineticEnergy]; | 
|---|
|  | 188 | E->TotalEnergy[0] += E->AllTotalPsiEnergy[NonLocalEnergy] | 
|---|
|  | 189 | ; | 
|---|
|  | 190 | E->TotalEnergy[0] += E->AllTotalDensityEnergy[CorrelationEnergy]+E->AllTotalDensityEnergy[ExchangeEnergy]; | 
|---|
|  | 191 | E->TotalEnergy[0] += E->AllTotalDensityEnergy[PseudoEnergy]; | 
|---|
|  | 192 | E->TotalEnergy[0] += E->AllTotalDensityEnergy[HartreePotentialEnergy]; | 
|---|
|  | 193 | E->TotalEnergy[0] -= E->AllTotalIonsEnergy[GaussSelfEnergy]; | 
|---|
|  | 194 | E->TotalEnergy[0] += E->AllTotalIonsEnergy[EwaldEnergy]; | 
|---|
|  | 195 | //      fprintf(stderr,"(%i) Tot %1.5f ---\t Diff %1.5f\t ---\t Kin %1.5f\tNLErg %1.5f ---\t Corr %1.5f\tXC %1.5f\t Pseudo %1.5f\tHP %1.5f\n", P->Par.me, | 
|---|
|  | 196 | //        E->TotalEnergy[0],(E->TotalEnergy[1]-E->TotalEnergy[0])/fabs(E->TotalEnergy[0]), | 
|---|
|  | 197 | //        E->AllTotalPsiEnergy[KineticEnergy],E->AllTotalPsiEnergy[NonLocalEnergy], | 
|---|
|  | 198 | //        E->AllTotalDensityEnergy[CorrelationEnergy],E->AllTotalDensityEnergy[ExchangeEnergy], | 
|---|
|  | 199 | //        E->AllTotalDensityEnergy[PseudoEnergy],E->AllTotalDensityEnergy[HartreePotentialEnergy]); | 
|---|
|  | 200 | break; | 
|---|
|  | 201 | case UnOccupied: | 
|---|
|  | 202 | E->TotalEnergy[0]  = E->AllTotalPsiEnergy[KineticEnergy]+E->AllTotalPsiEnergy[NonLocalEnergy]; | 
|---|
|  | 203 | E->TotalEnergy[0] += E->AllTotalDensityEnergy[CorrelationEnergy]+E->AllTotalDensityEnergy[ExchangeEnergy]; | 
|---|
|  | 204 | E->TotalEnergy[0] += E->AllTotalDensityEnergy[PseudoEnergy]+E->AllTotalDensityEnergy[HartreePotentialEnergy]; | 
|---|
|  | 205 | break; | 
|---|
|  | 206 | case Perturbed_P0: | 
|---|
|  | 207 | case Perturbed_P1: | 
|---|
|  | 208 | case Perturbed_P2: | 
|---|
|  | 209 | case Perturbed_RxP0: | 
|---|
|  | 210 | case Perturbed_RxP1: | 
|---|
|  | 211 | case Perturbed_RxP2: | 
|---|
|  | 212 | E->TotalEnergy[0]  = E->AllTotalPsiEnergy[Perturbed1_0Energy]+E->AllTotalPsiEnergy[Perturbed0_1Energy]; | 
|---|
|  | 213 | E->parts[0]  = E->AllTotalPsiEnergy[Perturbed1_0Energy]+E->AllTotalPsiEnergy[Perturbed0_1Energy]; | 
|---|
|  | 214 | //fprintf(stderr,"(%i) summed single: AllTotalPsiEnergy[total] = %lg + %lg = %lg\n",P->Par.me,E->AllTotalPsiEnergy[Perturbed1_0Energy],E->AllTotalPsiEnergy[Perturbed0_1Energy], E->TotalEnergy[0]); | 
|---|
|  | 215 | //E->TotalEnergy[0] = 0.; | 
|---|
|  | 216 | m = -1; | 
|---|
|  | 217 | E->parts[1] = E->parts[2] = 0.; | 
|---|
|  | 218 | for (i=0; i < Psi->MaxPsiOfType+P->Par.Max_me_comm_ST_PsiT; i++) {  // go through all wave functions: \sum_k | 
|---|
|  | 219 | OnePsiB = &Psi->AllPsiStatus[i];    // grab OnePsiB | 
|---|
|  | 220 | if (OnePsiB->PsiType == R->CurrentMin) {   // drop all but occupied types | 
|---|
|  | 221 | m++;  // increase m if it is occupied wave function | 
|---|
|  | 222 | lambda = overlap = 0.; | 
|---|
|  | 223 | if (OnePsiB->my_color_comm_ST_Psi == P->Par.my_color_comm_ST_Psi) { // local? | 
|---|
|  | 224 | //fprintf(stderr,"(%i) Lambda[%i] = %lg\n",P->Par.me, m,Lat->Psi.AddData[i].Lambda); | 
|---|
|  | 225 | lambda = Lat->Psi.AddData[OnePsiB->MyLocalNo].Lambda * Lat->Psi.LocalPsiStatus[OnePsiB->MyLocalNo].PsiFactor; | 
|---|
|  | 226 | for (j=0;j<Psi->NoOfPsis;j++) { // over all Psis: \sum_l | 
|---|
|  | 227 | //lambda -= Lat->Psi.lambda[j][i - Psi->TypeStartIndex[R->CurrentMin]]*GradSP(P,R->LevS,R->LevS->LPsi->LocalPsi[j + Psi->TypeStartIndex[R->CurrentMin]],R->LevS->LPsi->LocalPsi[i]); | 
|---|
|  | 228 | overlap -= Lat->Psi.lambda[j][m]*Lat->Psi.Overlap[j][m]; | 
|---|
|  | 229 | } | 
|---|
|  | 230 | // send results to other processes | 
|---|
|  | 231 | } | 
|---|
|  | 232 | //fprintf(stderr,"(%i) before MPI: \tlambda[%i] = %lg\t overlap[%i] = %lg\n",P->Par.me,m,lambda,m,overlap); | 
|---|
|  | 233 | MPI_Allreduce( &lambda, &lambda2, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_PsiT); // lambda is just local | 
|---|
|  | 234 | MPI_Allreduce( &overlap, &overlap2, 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_PsiT); // we just summed up over local m's! | 
|---|
|  | 235 | //fprintf(stderr,"(%i) after MPI: \t lambda[%i] = %lg\t overlap[%i] = %lg\n",P->Par.me, OnePsiB->MyGlobalNo,lambda2, m, overlap2); | 
|---|
|  | 236 | E->TotalEnergy[0] += lambda2; | 
|---|
|  | 237 | E->TotalEnergy[0] += overlap2; | 
|---|
|  | 238 | E->parts[1] += lambda2; | 
|---|
|  | 239 | E->parts[2] += overlap2; | 
|---|
|  | 240 | } | 
|---|
|  | 241 | } | 
|---|
|  | 242 |  | 
|---|
|  | 243 | switch(Psi->PsiST) { | 
|---|
|  | 244 | default: | 
|---|
|  | 245 | lambda = overlap = 0.; | 
|---|
|  | 246 | break; | 
|---|
|  | 247 | case SpinUp: | 
|---|
|  | 248 | MPI_Sendrecv(&E->parts[1], 1, MPI_DOUBLE, P->Par.me_comm_ST, EnergyTag1, | 
|---|
|  | 249 | &lambda, 1, MPI_DOUBLE, P->Par.me_comm_ST, EnergyTag2, P->Par.comm_STInter, &status ); | 
|---|
|  | 250 | E->TotalEnergy[0] += lambda; | 
|---|
|  | 251 | MPI_Sendrecv(&E->parts[2],1, MPI_DOUBLE, P->Par.me_comm_ST, EnergyTag3, | 
|---|
|  | 252 | &overlap, 1, MPI_DOUBLE, P->Par.me_comm_ST, EnergyTag4, P->Par.comm_STInter, &status ); | 
|---|
|  | 253 | E->TotalEnergy[0] += overlap; | 
|---|
|  | 254 | break; | 
|---|
|  | 255 | case SpinDown: | 
|---|
|  | 256 | MPI_Sendrecv(&E->parts[1], 1, MPI_DOUBLE, P->Par.me_comm_ST, EnergyTag2, | 
|---|
|  | 257 | &lambda, 1, MPI_DOUBLE, P->Par.me_comm_ST, EnergyTag1, P->Par.comm_STInter, &status ); | 
|---|
|  | 258 | E->TotalEnergy[0] += lambda; | 
|---|
|  | 259 | MPI_Sendrecv(&E->parts[2],1, MPI_DOUBLE, P->Par.me_comm_ST, EnergyTag4, | 
|---|
|  | 260 | &overlap, 1, MPI_DOUBLE, P->Par.me_comm_ST, EnergyTag3, P->Par.comm_STInter, &status ); | 
|---|
|  | 261 | E->TotalEnergy[0] += overlap; | 
|---|
|  | 262 | break; | 
|---|
|  | 263 | } | 
|---|
|  | 264 | //fprintf(stderr,"(%i) summed single: lambda[total] = %lg\t overlap[total] = %lg\n",P->Par.me,E->parts[1]+lambda, E->parts[2]+overlap); | 
|---|
|  | 265 | break; | 
|---|
|  | 266 | default: | 
|---|
|  | 267 | break; | 
|---|
|  | 268 | } | 
|---|
|  | 269 | } | 
|---|
|  | 270 |  | 
|---|
|  | 271 | /** Initializes Energy Array. | 
|---|
|  | 272 | * Arrays are malloc'd and set to zero, then InitExchangeCorrelationEnergy() | 
|---|
|  | 273 | * called. | 
|---|
|  | 274 | * \param *P Problem at hand | 
|---|
|  | 275 | */ | 
|---|
|  | 276 | void InitEnergyArray(struct Problem *P) | 
|---|
|  | 277 | { | 
|---|
|  | 278 | struct Lattice *Lat = &P->Lat; | 
|---|
|  | 279 | struct Energy *E = Lat->E; | 
|---|
|  | 280 | struct Psis *Psi = &Lat->Psi; | 
|---|
|  | 281 | int i, type, oldtype = P->R.CurrentMin; | 
|---|
|  | 282 | for (type=Occupied;type<Extra;type++) { | 
|---|
|  | 283 | SetCurrentMinState(P, type); | 
|---|
|  | 284 | for (i=0; i<MAXALLPSIENERGY; i++) { | 
|---|
|  | 285 | Lat->Energy[type].PsiEnergy[i] = (double *) | 
|---|
|  | 286 | Malloc(sizeof(double)*Psi->LocalNo,"InitEnergyCalculations: PsiKineticEnergy"); | 
|---|
|  | 287 | SetArrayToDouble0(Lat->Energy[type].PsiEnergy[i], Psi->LocalNo); | 
|---|
|  | 288 | } | 
|---|
|  | 289 | SetArrayToDouble0(E->AllLocalDensityEnergy, MAXALLDENSITYENERGY); | 
|---|
|  | 290 | SetArrayToDouble0(E->AllTotalDensityEnergy, MAXALLDENSITYENERGY); | 
|---|
|  | 291 | SetArrayToDouble0(E->AllTotalIonsEnergy, MAXALLIONSENERGY); | 
|---|
|  | 292 | SetArrayToDouble0(E->TotalEnergy, MAXOLD); | 
|---|
|  | 293 | } | 
|---|
|  | 294 | InitExchangeCorrelationEnergy(P, &P->ExCo); | 
|---|
|  | 295 | SetCurrentMinState(P, oldtype); | 
|---|
|  | 296 | } | 
|---|
|  | 297 |  | 
|---|
|  | 298 | /** Shifts stored total energy values up to MAXOLD. | 
|---|
|  | 299 | * Energy::PsiEnergy, Energy::AllLocalDensityEnergy, Energy::AllTotalDensityEnergy | 
|---|
|  | 300 | * are all set to zero. Energy::TotalEnergy is shifted by one to make | 
|---|
|  | 301 | * place for next value. This is done either for occupied or for the gap energies, | 
|---|
|  | 302 | * stated by \a IncType. | 
|---|
|  | 303 | * \param *P Problem at hand | 
|---|
|  | 304 | */ | 
|---|
|  | 305 | void UpdateEnergyArray(struct Problem *P) | 
|---|
|  | 306 | { | 
|---|
|  | 307 | struct Lattice *Lat = &P->Lat; | 
|---|
|  | 308 | struct RunStruct *R = &P->R; | 
|---|
|  | 309 | struct Energy *E = Lat->E; | 
|---|
|  | 310 | int i; | 
|---|
|  | 311 | for (i=0; i<MAXALLPSIENERGY; i++) | 
|---|
|  | 312 | E->PsiEnergy[i][R->OldActualLocalPsiNo] = 0.0; | 
|---|
|  | 313 | SetArrayToDouble0(E->AllLocalDensityEnergy, MAXALLDENSITYENERGY); | 
|---|
|  | 314 | SetArrayToDouble0(E->AllTotalDensityEnergy, MAXALLDENSITYENERGY); | 
|---|
|  | 315 | for (i=MAXOLD-1; i > 0; i--) | 
|---|
|  | 316 | Lat->Energy[R->CurrentMin].TotalEnergy[i] = Lat->Energy[R->CurrentMin].TotalEnergy[i-1]; | 
|---|
|  | 317 | } | 
|---|
|  | 318 |  | 
|---|
|  | 319 | /** Calculates ion energy. | 
|---|
|  | 320 | * CalculateGaussSelfEnergyNoRT() is called. | 
|---|
|  | 321 | * \param *P Problem at hand | 
|---|
|  | 322 | * \warning CalculateIonsUseRT not implemented | 
|---|
|  | 323 | */ | 
|---|
|  | 324 | void CalculateIonsEnergy(struct Problem *P) | 
|---|
|  | 325 | { | 
|---|
|  | 326 | struct Lattice *Lat = &P->Lat; | 
|---|
|  | 327 | switch (Lat->RT.ActualUse) { | 
|---|
|  | 328 | case inactive: | 
|---|
|  | 329 | case standby: | 
|---|
|  | 330 | CalculateGaussSelfEnergyNoRT(P, &P->PP, &P->Ion); | 
|---|
|  | 331 | break; | 
|---|
|  | 332 | case active: | 
|---|
|  | 333 | Error(SomeError, "CalculateIonsUseRT: Not implemented"); | 
|---|
|  | 334 | break; | 
|---|
|  | 335 | } | 
|---|
|  | 336 | } | 
|---|
|  | 337 |  | 
|---|
|  | 338 | /** Calculates density energy. | 
|---|
|  | 339 | * Depending on RT::ActualUse CalculateXCEnergyNoRT(), CalculateSomeEnergyAndHGNoRT() | 
|---|
|  | 340 | * and CalculateGapEnergy() are called within SpeedMeasure() brackets. | 
|---|
|  | 341 | * Afterwards, CalculateGradientNoRT() for RunStruct::ActualLocalPsiNo. | 
|---|
|  | 342 | * \param *P Problem at hand | 
|---|
|  | 343 | * \param UseInitTime whether SpeedMeasure uses InitLocTime (Init) or LocTime (Update) | 
|---|
|  | 344 | * \warning CalculateSomeEnergyAndHGUseRT not implemented | 
|---|
|  | 345 | * \warning call EnergyAllReduce() afterwards! | 
|---|
|  | 346 | */ | 
|---|
|  | 347 | void CalculateDensityEnergy(struct Problem *P, const int UseInitTime) | 
|---|
|  | 348 | { | 
|---|
|  | 349 | struct Lattice *Lat = &P->Lat; | 
|---|
|  | 350 | struct RunStruct *R = &P->R; | 
|---|
|  | 351 | struct LatticeLevel *LevS = R->LevS; | 
|---|
|  | 352 | switch (Lat->RT.ActualUse) { | 
|---|
|  | 353 | case inactive: | 
|---|
|  | 354 | case standby: | 
|---|
|  | 355 | SpeedMeasure(P, (UseInitTime == 1 ? InitLocTime : LocTime), StartTimeDo); | 
|---|
|  | 356 | CalculateXCEnergyNoRT(P); | 
|---|
|  | 357 | CalculateSomeEnergyAndHGNoRT(P); | 
|---|
|  | 358 | SpeedMeasure(P, (UseInitTime == 1 ? InitLocTime : LocTime), StopTimeDo); | 
|---|
|  | 359 | CalculateGradientNoRT(P, | 
|---|
|  | 360 | LevS->LPsi->LocalPsi[R->ActualLocalPsiNo], | 
|---|
|  | 361 | Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].PsiFactor, | 
|---|
|  | 362 | &Lat->Psi.AddData[R->ActualLocalPsiNo].Lambda, | 
|---|
|  | 363 | P->PP.fnl[R->ActualLocalPsiNo], | 
|---|
|  | 364 | P->Grad.GradientArray[ActualGradient], | 
|---|
|  | 365 | P->Grad.GradientArray[OldActualGradient], | 
|---|
|  | 366 | P->Grad.GradientArray[HcGradient]); | 
|---|
|  | 367 | break; | 
|---|
|  | 368 | case active: | 
|---|
|  | 369 | CalculateXCEnergyUseRT(P); | 
|---|
|  | 370 | /* FIXME - Hier fehlt noch was */ | 
|---|
|  | 371 | Error(SomeError, "CalculateSomeEnergyAndHGUseRT: Not implemented"); | 
|---|
|  | 372 | break; | 
|---|
|  | 373 | } | 
|---|
|  | 374 | /* Achtung danach noch EnergyAllReduce aufrufen */ | 
|---|
|  | 375 | } | 
|---|
|  | 376 |  | 
|---|
|  | 377 | /** Calculation of an additional total energy from unoccupied states. | 
|---|
|  | 378 | * By including additional (unoccupied) orbitals into the minimisation process, | 
|---|
|  | 379 | * which also stand orthogonal on all others, however are minimised in the field | 
|---|
|  | 380 | * of occupied ones (without altering it in a self-consistent manner), a first | 
|---|
|  | 381 | * approximation to the band gap energy can be obtained. The density part of this | 
|---|
|  | 382 | * virtual energy is stored in the PsiTypeTag#UnOccupied part of Lattice#Energy. | 
|---|
|  | 383 | * Note that the band gap is approximated via the eigenvalues of the additional | 
|---|
|  | 384 | * orbitals. This energy here is purely fictious. | 
|---|
|  | 385 | * \param *P Problem at hand | 
|---|
|  | 386 | * \note No RiemannTensor use so far implemented. And mostly copy&paste from | 
|---|
|  | 387 | *        CalculateXCEnergyNoRT() and CalculateSomeEnergyAndHGNoRT(). | 
|---|
|  | 388 | * \bug Understand CoreCorrection part in \f$E_{XC}\f$ | 
|---|
|  | 389 | */ | 
|---|
|  | 390 | void CalculateGapEnergy(struct Problem *P) { | 
|---|
|  | 391 | struct Lattice *Lat = &P->Lat; | 
|---|
|  | 392 | struct Psis *Psi = &Lat->Psi; | 
|---|
|  | 393 | struct Energy *E = Lat->E; | 
|---|
|  | 394 | struct PseudoPot *PP = &P->PP; | 
|---|
|  | 395 | struct RunStruct *R = &P->R; | 
|---|
|  | 396 | struct LatticeLevel *Lev0 = R->Lev0; | 
|---|
|  | 397 | struct LatticeLevel *LevS = R->LevS; | 
|---|
|  | 398 | struct Density *Dens = Lev0->Dens; | 
|---|
|  | 399 | struct ExCor *EC = &P->ExCo; | 
|---|
|  | 400 | struct Ions *I = &P->Ion; | 
|---|
|  | 401 | double SumEc = 0; | 
|---|
|  | 402 | double rs, p = 0.0, pUp = 0.0, pDown = 0.0, zeta, rsUp, rsDown, SumEx=0.0; | 
|---|
|  | 403 | double Factor = R->XCEnergyFactor/Lev0->MaxN; | 
|---|
|  | 404 | fftw_complex vp,rhoe,rhoe_gap; | 
|---|
|  | 405 | fftw_complex rp,rhog; | 
|---|
|  | 406 | double SumEHP,Fac,SumEH,SumEG,SumEPS; | 
|---|
|  | 407 | int g,s=0,it,Index; | 
|---|
|  | 408 | int i; | 
|---|
|  | 409 | fftw_complex *HG = Dens->DensityCArray[HGDensity]; | 
|---|
|  | 410 | SetArrayToDouble0((double *)HG,2*Dens->TotalSize); | 
|---|
|  | 411 |  | 
|---|
| [36f85c] | 412 | //if (isnan(HG[0].re)) { fprintf(stderr,"WARNGING: CalculateGapEnergy(): HG[%i]_%i = NaN!\n", 0, R->ActualLocalPsiNo); Error(SomeError, "NaN-Fehler!"); } | 
|---|
| [a0bcf1] | 413 | SpeedMeasure(P, GapTime, StartTimeDo); | 
|---|
|  | 414 | // === Calculate exchange and correlation energy === | 
|---|
|  | 415 | for (i = 0; i < Dens->LocalSizeR; i++) {  // for each node in radial mesh | 
|---|
|  | 416 | // put (corecorrected) densities in p, pUp, pDown | 
|---|
|  | 417 | p = Dens->DensityArray[TotalDensity][i]; | 
|---|
| [36f85c] | 418 | //if (isnan(p)) { fprintf(stderr,"WARNGING: CalculateGapEnergy(): Dens->DensityArray[TotalUpDensity][%i]_%i = NaN!\n", i, R->ActualLocalPsiNo); Error(SomeError, "NaN-Fehler!"); } | 
|---|
| [a0bcf1] | 419 | switch (Psi->PsiST) { | 
|---|
|  | 420 | case SpinDouble: | 
|---|
|  | 421 | pUp = 0.5*p; | 
|---|
|  | 422 | pDown = 0.5*p; | 
|---|
|  | 423 | break; | 
|---|
|  | 424 | case SpinUp: | 
|---|
|  | 425 | case SpinDown: | 
|---|
|  | 426 | pUp = Dens->DensityArray[TotalUpDensity][i]; | 
|---|
|  | 427 | pDown = Dens->DensityArray[TotalDownDensity][i]; | 
|---|
|  | 428 | break; | 
|---|
|  | 429 | default: | 
|---|
|  | 430 | ; | 
|---|
|  | 431 | } | 
|---|
|  | 432 | if ((p < 0) || (pUp < 0) || (pDown < 0)) { | 
|---|
|  | 433 | /*fprintf(stderr,"index %i pc %g p %g\n",i,Dens->DensityArray[CoreWaveDensity][i],p);*/ | 
|---|
|  | 434 | p = 0.0; | 
|---|
|  | 435 | pUp = 0.0; | 
|---|
|  | 436 | pDown = 0.0; | 
|---|
|  | 437 | } | 
|---|
|  | 438 | rs = Calcrs(EC,p); | 
|---|
|  | 439 | rsUp = Calcrs(EC,pUp); | 
|---|
|  | 440 | rsDown = Calcrs(EC,pDown); | 
|---|
|  | 441 | zeta = CalcZeta(EC,pUp,pDown); | 
|---|
|  | 442 | // Calculation with the densities and summation | 
|---|
|  | 443 | SumEx += CalcSEXr(EC, rsUp, rsDown, pUp, pDown); | 
|---|
|  | 444 | SumEc += CalcSECr(EC, rs, zeta, p); | 
|---|
|  | 445 | } | 
|---|
|  | 446 | E->AllLocalDensityEnergy[CorrelationEnergy] = Factor*SumEc; | 
|---|
|  | 447 | E->AllLocalDensityEnergy[ExchangeEnergy] = Factor*SumEx; | 
|---|
|  | 448 |  | 
|---|
|  | 449 | // === Calculate electrostatic and local pseudopotential energy === | 
|---|
|  | 450 | SumEHP = 0.0; | 
|---|
|  | 451 | SumEH = 0.0; | 
|---|
|  | 452 | SumEG = 0.0; | 
|---|
|  | 453 | SumEPS = 0.0; | 
|---|
|  | 454 | // calculates energy of local pseudopotential | 
|---|
|  | 455 | if (Lev0->GArray[0].GSq == 0.0) { | 
|---|
|  | 456 | Index = Lev0->GArray[0].Index; | 
|---|
|  | 457 | c_re(vp) = 0.0; | 
|---|
|  | 458 | c_im(vp) = 0.0; | 
|---|
|  | 459 | for (it = 0; it < I->Max_Types; it++) { | 
|---|
|  | 460 | c_re(vp) += (c_re(I->I[it].SFactor[0])*PP->phi_ps_loc[it][0]); | 
|---|
|  | 461 | c_im(vp) += (c_im(I->I[it].SFactor[0])*PP->phi_ps_loc[it][0]); | 
|---|
|  | 462 | } | 
|---|
| [36f85c] | 463 | //if (isnan(c_re(Dens->DensityCArray[GapDensity][Index]))) { fprintf(stderr,"WARNGING: CalculateGapEnergy(): Dens->DensityArray[GapDensity][%i]_%i.re = NaN!\n", Index, R->ActualLocalPsiNo); Error(SomeError, "NaN-Fehler!"); } | 
|---|
| [a0bcf1] | 464 | SumEPS += (c_re(Dens->DensityCArray[GapDensity][Index])*c_re(vp) + | 
|---|
|  | 465 | c_im(Dens->DensityCArray[GapDensity][Index])*c_im(vp))*R->HGcFactor; | 
|---|
|  | 466 | s++; | 
|---|
|  | 467 | } | 
|---|
|  | 468 | for (g=s; g < Lev0->MaxG; g++) { | 
|---|
|  | 469 | Index = Lev0->GArray[g].Index; | 
|---|
|  | 470 | c_re(vp) = 0.0; | 
|---|
|  | 471 | c_im(vp) = 0.0; | 
|---|
|  | 472 | c_re(rp) = 0.0; | 
|---|
|  | 473 | c_im(rp) = 0.0; | 
|---|
|  | 474 | Fac = 2.*PI/(Lev0->GArray[g].GSq);  // 4*.. -> 2*...: 1/2 here ! (due to lacking dependence of first n^{tot} (r) on gap psis) | 
|---|
|  | 475 | for (it = 0; it < I->Max_Types; it++) { | 
|---|
|  | 476 | c_re(vp) += (c_re(I->I[it].SFactor[g])*PP->phi_ps_loc[it][g]); | 
|---|
|  | 477 | c_im(vp) += (c_im(I->I[it].SFactor[g])*PP->phi_ps_loc[it][g]); | 
|---|
|  | 478 | c_re(rp) += (c_re(I->I[it].SFactor[g])*PP->FacGauss[it][g]); | 
|---|
|  | 479 | c_im(rp) += (c_im(I->I[it].SFactor[g])*PP->FacGauss[it][g]); | 
|---|
|  | 480 | } | 
|---|
| [36f85c] | 481 | //if (isnan(c_re(Dens->DensityCArray[TotalDensity][Index]))) { fprintf(stderr,"WARNGING: CalculateGapEnergy(): Dens->DensityArray[TotalDensity][%i]_%i.re = NaN!\n", Index, R->ActualLocalPsiNo); Error(SomeError, "NaN-Fehler!"); } | 
|---|
| [a0bcf1] | 482 | c_re(rhog) = c_re(Dens->DensityCArray[TotalDensity][Index])*R->HGcFactor+c_re(rp); | 
|---|
|  | 483 | c_im(rhog) = c_im(Dens->DensityCArray[TotalDensity][Index])*R->HGcFactor+c_im(rp); | 
|---|
|  | 484 | c_re(rhoe) = c_re(Dens->DensityCArray[TotalDensity][Index])*R->HGcFactor; | 
|---|
|  | 485 | c_im(rhoe) = c_im(Dens->DensityCArray[TotalDensity][Index])*R->HGcFactor; | 
|---|
| [36f85c] | 486 | //if (isnan(c_re(Dens->DensityCArray[GapDensity][Index]))) { fprintf(stderr,"WARNGING: CalculateGapEnergy(): Dens->DensityArray[GapDensity][%i]_%i.re = NaN!\n", Index, R->ActualLocalPsiNo); Error(SomeError, "NaN-Fehler!"); } | 
|---|
| [a0bcf1] | 487 | c_re(rhoe_gap) = c_re(Dens->DensityCArray[GapDensity][Index])*R->HGcFactor; | 
|---|
|  | 488 | c_im(rhoe_gap) = c_im(Dens->DensityCArray[GapDensity][Index])*R->HGcFactor; | 
|---|
|  | 489 | //c_re(PP->VCoulombc[g]) = Fac*c_re(rhog); | 
|---|
|  | 490 | //c_im(PP->VCoulombc[g]) = -Fac*c_im(rhog); | 
|---|
|  | 491 | c_re(HG[Index]) = c_re(vp) + Fac * (c_re(Dens->DensityCArray[TotalDensity][Index])*R->HGcFactor+c_re(rp)); | 
|---|
|  | 492 | c_im(HG[Index]) = c_im(vp) + Fac * (c_im(Dens->DensityCArray[TotalDensity][Index])*R->HGcFactor+c_im(rp)); | 
|---|
| [36f85c] | 493 | //if (isnan(c_re(HG[Index]))) { fprintf(stderr,"WARNGING: CalculateGapEnergy(): HG[%i]_%i.re = NaN!\n", Index, R->ActualLocalPsiNo); Error(SomeError, "NaN-Fehler!"); } | 
|---|
|  | 494 | //if (isnan(c_im(HG[Index]))) { fprintf(stderr,"WARNGING: CalculateGapEnergy(): HG[%i]_%i.im = NaN!\n", Index, R->ActualLocalPsiNo); Error(SomeError, "NaN-Fehler!"); } | 
|---|
| [a0bcf1] | 495 | /*if (P->first) */ | 
|---|
|  | 496 | //SumEG += Fac*(c_re(rp)*c_re(rp)+c_im(rp)*c_im(rp));             // Coulomb energy | 
|---|
|  | 497 | // changed: took out gaussian part! rhog -> rhoe | 
|---|
|  | 498 | SumEHP += 2*Fac*(c_re(rhoe)*c_re(rhoe_gap)+c_im(rhoe)*c_im(rhoe_gap));    // E_ES first part | 
|---|
|  | 499 | //SumEH += Fac*(c_re(rhoe)*c_re(rhoe)+c_im(rhoe)*c_im(rhoe)); | 
|---|
|  | 500 | SumEPS += 2.*(c_re(Dens->DensityCArray[GapDensity][Index])*c_re(vp)+ | 
|---|
|  | 501 | c_im(Dens->DensityCArray[GapDensity][Index])*c_im(vp))*R->HGcFactor; | 
|---|
|  | 502 | } | 
|---|
|  | 503 | // | 
|---|
|  | 504 | for (i=0; i<Lev0->MaxDoubleG; i++) { | 
|---|
|  | 505 | HG[Lev0->DoubleG[2*i+1]].re =  HG[Lev0->DoubleG[2*i]].re; | 
|---|
|  | 506 | HG[Lev0->DoubleG[2*i+1]].im = -HG[Lev0->DoubleG[2*i]].im; | 
|---|
|  | 507 | } | 
|---|
|  | 508 | /*if (P->first) */ | 
|---|
|  | 509 | //E->AllLocalDensityEnergy[GaussEnergy] = SumEG*Lat->Volume; | 
|---|
|  | 510 | E->AllLocalDensityEnergy[PseudoEnergy] = SumEPS*Lat->Volume;   // local pseudopotential | 
|---|
|  | 511 | E->AllLocalDensityEnergy[HartreePotentialEnergy] = SumEHP*Lat->Volume;   // Gauss n^Gauss and Hartree n potential | 
|---|
|  | 512 | //E->AllLocalDensityEnergy[HartreeEnergy] = SumEH*Lat->Volume; | 
|---|
|  | 513 | SpeedMeasure(P, GapTime, StopTimeDo); | 
|---|
|  | 514 |  | 
|---|
|  | 515 | // === Calculate Gradient === | 
|---|
| [36f85c] | 516 | //if (isnan(P->R.LevS->LPsi->LocalPsi[P->R.ActualLocalPsiNo][0].re)) { fprintf(stderr,"(%i) WARNING in CalculateGapEnergy(): ActualLocalPsi_%i[%i] = NaN!\n", P->Par.me, P->R.ActualLocalPsiNo, 0); Error(SomeError, "NaN-Fehler!"); } | 
|---|
| [a0bcf1] | 517 | CalculateGradientNoRT(P, | 
|---|
|  | 518 | LevS->LPsi->LocalPsi[R->ActualLocalPsiNo], | 
|---|
|  | 519 | Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].PsiFactor, | 
|---|
|  | 520 | &Lat->Psi.AddData[R->ActualLocalPsiNo].Lambda, | 
|---|
|  | 521 | P->PP.fnl[R->ActualLocalPsiNo], | 
|---|
|  | 522 | P->Grad.GradientArray[ActualGradient], | 
|---|
|  | 523 | P->Grad.GradientArray[OldActualGradient], | 
|---|
|  | 524 | P->Grad.GradientArray[HcGradient]); | 
|---|
| [36f85c] | 525 | //if (isnan(P->Grad.GradientArray[ActualGradient][0].re)) { fprintf(stderr,"(%i) WARNING in CalculateGapEnergy(): ActualGradient_%i[%i] = NaN!\n", P->Par.me, P->R.ActualLocalPsiNo, 0); Error(SomeError, "NaN-Fehler!"); } | 
|---|
| [a0bcf1] | 526 | } | 
|---|
|  | 527 |  | 
|---|
|  | 528 | /** Calculates the energy of a wave function psi. | 
|---|
|  | 529 | * Calculates kinetc and non local energies, taking care of possible | 
|---|
|  | 530 | * Riemann tensor usage. | 
|---|
|  | 531 | * \param *P Problem at hand | 
|---|
|  | 532 | * \param p number of wave function Psi | 
|---|
|  | 533 | * \param UseInitTime Whether speed measuring uses InitLocTime (Init) or LocTime (Update) | 
|---|
|  | 534 | * \sa EnergyGNSP(), EnergyLapNSP() | 
|---|
|  | 535 | * \warning call EnergyAllReduce() afterwards! | 
|---|
|  | 536 | */ | 
|---|
|  | 537 | void CalculatePsiEnergy(struct Problem *P, const int p, const int UseInitTime) | 
|---|
|  | 538 | { | 
|---|
|  | 539 | struct Lattice *Lat = &(P->Lat); | 
|---|
|  | 540 | switch (Lat->RT.ActualUse) { | 
|---|
|  | 541 | case inactive: | 
|---|
|  | 542 | case standby: | 
|---|
|  | 543 | SpeedMeasure(P, (UseInitTime == 1 ? InitLocTime : LocTime), StartTimeDo); | 
|---|
|  | 544 | CalculateKineticEnergyNoRT(P, p); | 
|---|
|  | 545 | SpeedMeasure(P, (UseInitTime == 1 ? InitLocTime : LocTime), StopTimeDo); | 
|---|
|  | 546 | SpeedMeasure(P, (UseInitTime == 1 ? InitNonLocTime : NonLocTime), StartTimeDo); | 
|---|
|  | 547 | CalculateNonLocalEnergyNoRT(P, p); | 
|---|
|  | 548 | SpeedMeasure(P, (UseInitTime == 1 ? InitNonLocTime : NonLocTime), StopTimeDo); | 
|---|
|  | 549 | break; | 
|---|
|  | 550 | case active: | 
|---|
|  | 551 | SpeedMeasure(P, (UseInitTime == 1 ? InitLocTime : LocTime), StartTimeDo); | 
|---|
|  | 552 | CalculateKineticEnergyUseRT(P, p); | 
|---|
|  | 553 | SpeedMeasure(P, (UseInitTime == 1 ? InitLocTime : LocTime), StopTimeDo); | 
|---|
|  | 554 | SpeedMeasure(P, (UseInitTime == 1 ? InitNonLocTime : NonLocTime), StartTimeDo); | 
|---|
|  | 555 | CalculateNonLocalEnergyUseRT(P, p); | 
|---|
|  | 556 | SpeedMeasure(P, (UseInitTime == 1 ? InitNonLocTime : NonLocTime), StopTimeDo); | 
|---|
|  | 557 | break; | 
|---|
|  | 558 | } | 
|---|
|  | 559 | /* Achtung danach noch EnergyAllReduce aufrufen */ | 
|---|
|  | 560 | } | 
|---|
|  | 561 |  | 
|---|
|  | 562 | /** Initialization of wave function energy calculation. | 
|---|
|  | 563 | * For every wave function CalculatePsiEnergy() is called, | 
|---|
|  | 564 | * Energy::AllLocalPsiEnergy is set to sum of these. | 
|---|
|  | 565 | * \param *P Problem at hand | 
|---|
|  | 566 | * \param type minimisation type PsiTypeTag to calculate psi energy for | 
|---|
|  | 567 | * \warning call EnergyAllReduce() afterwards! | 
|---|
|  | 568 | */ | 
|---|
|  | 569 | void InitPsiEnergyCalculation(struct Problem *P, enum PsiTypeTag type) | 
|---|
|  | 570 | { | 
|---|
|  | 571 | struct Lattice *Lat = &(P->Lat); | 
|---|
|  | 572 | int p,i, oldtype = P->R.CurrentMin; | 
|---|
|  | 573 | SetCurrentMinState(P,type); | 
|---|
|  | 574 | for (p=0; p < Lat->Psi.LocalNo; p++) { | 
|---|
|  | 575 | if (P->Lat.Psi.LocalPsiStatus[p].PsiType == P->R.CurrentMin) | 
|---|
|  | 576 | CalculatePsiEnergy(P, p, 1); | 
|---|
|  | 577 | } | 
|---|
|  | 578 | for (i=0; i< MAXALLPSIENERGY; i++) { | 
|---|
|  | 579 | Lat->E->AllLocalPsiEnergy[i] = 0.0; | 
|---|
|  | 580 | for (p=0; p < Lat->Psi.LocalNo; p++) | 
|---|
|  | 581 | if (P->Lat.Psi.LocalPsiStatus[p].PsiType == P->R.CurrentMin) | 
|---|
|  | 582 | Lat->E->AllLocalPsiEnergy[i] += Lat->E->PsiEnergy[i][p]; | 
|---|
|  | 583 | } | 
|---|
|  | 584 | SetCurrentMinState(P,oldtype); | 
|---|
|  | 585 | /* Achtung danach noch EnergyAllReduce aufrufen */ | 
|---|
|  | 586 | } | 
|---|
|  | 587 |  | 
|---|
|  | 588 | /** Updating wave function energy. | 
|---|
|  | 589 | * CalculatePsiEnergy() is called for RunStruct::OldActualLocalPsiNo, | 
|---|
|  | 590 | * Energy::AllLocalPsiEnergy is set to sum of all Psi energies. | 
|---|
|  | 591 | * \param *P Problem at hand | 
|---|
|  | 592 | * \warning call EnergyAllReduce() afterwards! | 
|---|
|  | 593 | */ | 
|---|
|  | 594 | void UpdatePsiEnergyCalculation(struct Problem *P) | 
|---|
|  | 595 | { | 
|---|
|  | 596 | struct Lattice *Lat = &(P->Lat); | 
|---|
|  | 597 | struct RunStruct *R = &P->R; | 
|---|
|  | 598 | int p = R->OldActualLocalPsiNo, i; | 
|---|
|  | 599 | if (P->Lat.Psi.LocalPsiStatus[p].PsiType == P->R.CurrentMin) | 
|---|
|  | 600 | CalculatePsiEnergy(P, p, 0); | 
|---|
|  | 601 | for (i=0; i< MAXALLPSIENERGY; i++) { | 
|---|
|  | 602 | Lat->E->AllLocalPsiEnergy[i] = 0.0; | 
|---|
|  | 603 | for (p=0; p < P->Lat.Psi.LocalNo; p++) | 
|---|
|  | 604 | if (P->Lat.Psi.LocalPsiStatus[p].PsiType == P->R.CurrentMin) | 
|---|
|  | 605 | Lat->E->AllLocalPsiEnergy[i] += Lat->E->PsiEnergy[i][p]; | 
|---|
|  | 606 | } | 
|---|
|  | 607 | /* Achtung danach noch EnergyAllReduce aufrufen */ | 
|---|
|  | 608 | } | 
|---|
|  | 609 |  | 
|---|
|  | 610 | /** Output of energies. | 
|---|
|  | 611 | * Prints either Time, PsiEnergy(Up/Down), DensityEnergy, IonsEnergy, KineticEnergy, | 
|---|
|  | 612 | * TotalEnergy and Temperature to screen or<br> | 
|---|
|  | 613 | * Time, TotalEnergy, NonLocalEnergy, CorrelationEnergy, ExchangeEnergy, | 
|---|
|  | 614 | * PseudoEnergy, HartreePotentialEnergy, GaussSelfEnergy, EwaldEnergy, | 
|---|
|  | 615 | * KineticEnergy and TotalEnergy+KineticEnergy to the energy file | 
|---|
|  | 616 | * \param *P Problem at hand | 
|---|
|  | 617 | * \param doout 1 - print stuff to stderr, 0 - put compact form into energy file | 
|---|
|  | 618 | */ | 
|---|
|  | 619 | void EnergyOutput(struct Problem *P, int doout) | 
|---|
|  | 620 | { | 
|---|
|  | 621 | struct Lattice *Lat = &P->Lat; | 
|---|
|  | 622 | struct RunStruct *R = &P->R; | 
|---|
|  | 623 | struct LatticeLevel *Lev0 = R->Lev0; | 
|---|
|  | 624 | struct LatticeLevel *LevS = R->LevS; | 
|---|
|  | 625 | struct Ions *I = &P->Ion; | 
|---|
|  | 626 | struct Psis *Psi = &Lat->Psi; | 
|---|
|  | 627 | struct FileData *F = &P->Files; | 
|---|
|  | 628 | FILE *eout = NULL; | 
|---|
|  | 629 | FILE *convergence = NULL; | 
|---|
|  | 630 | int i, it; | 
|---|
|  | 631 | if (P->Call.out[LeaderOut] && (P->Par.me == 0) && doout) { | 
|---|
|  | 632 | fprintf(stderr, "Time T:  :\t%e\n",P->R.t); | 
|---|
|  | 633 | fprintf(stderr, "PsiEnergy    :"); | 
|---|
|  | 634 | for (i=0; i<MAXALLPSIENERGY; i++) { | 
|---|
|  | 635 | fprintf(stderr," %e",Lat->Energy[Occupied].AllTotalPsiEnergy[i]); | 
|---|
|  | 636 | } | 
|---|
|  | 637 | fprintf(stderr,"\n"); | 
|---|
|  | 638 | if (Psi->PsiST != SpinDouble) { | 
|---|
|  | 639 | fprintf(stderr, "PsiEnergyUp  :"); | 
|---|
|  | 640 | for (i=0; i<MAXALLPSIENERGY; i++) { | 
|---|
|  | 641 | fprintf(stderr,"\t%e",Lat->Energy[Occupied].AllUpPsiEnergy[i]); | 
|---|
|  | 642 | } | 
|---|
|  | 643 | fprintf(stderr,"\n"); | 
|---|
|  | 644 | fprintf(stderr, "PsiEnergyDown:"); | 
|---|
|  | 645 | for (i=0; i<MAXALLPSIENERGY; i++) { | 
|---|
|  | 646 | fprintf(stderr,"\t%e",Lat->Energy[Occupied].AllDownPsiEnergy[i]); | 
|---|
|  | 647 | } | 
|---|
|  | 648 | fprintf(stderr,"\n"); | 
|---|
|  | 649 | } | 
|---|
|  | 650 | fprintf(stderr, "DensityEnergy:"); | 
|---|
|  | 651 | for (i=0; i<MAXALLDENSITYENERGY; i++) { | 
|---|
|  | 652 | fprintf(stderr,"\t%e",Lat->Energy[Occupied].AllTotalDensityEnergy[i]); | 
|---|
|  | 653 | } | 
|---|
|  | 654 | fprintf(stderr,"\n"); | 
|---|
|  | 655 | fprintf(stderr, "IonsEnergy   :"); | 
|---|
|  | 656 | for (i=0; i<MAXALLIONSENERGY; i++) { | 
|---|
|  | 657 | fprintf(stderr,"\t%e",Lat->Energy[Occupied].AllTotalIonsEnergy[i]); | 
|---|
|  | 658 | } | 
|---|
|  | 659 | fprintf(stderr,"\n"); | 
|---|
|  | 660 | fprintf(stderr, "TotalEnergy  :\t%e\n",Lat->Energy[Occupied].TotalEnergy[0]); | 
|---|
|  | 661 | if (R->DoPerturbation) | 
|---|
|  | 662 | fprintf(stderr, "PerturbedEnergy :\t%e\t%e\t%e\t%e\t%e\t%e\n",Lat->Energy[Perturbed_P0].TotalEnergy[0], Lat->Energy[Perturbed_P1].TotalEnergy[0], Lat->Energy[Perturbed_P2].TotalEnergy[0], Lat->Energy[Perturbed_RxP0].TotalEnergy[0], Lat->Energy[Perturbed_RxP1].TotalEnergy[0], Lat->Energy[Perturbed_RxP2].TotalEnergy[0]); | 
|---|
|  | 663 | if (R->DoUnOccupied) { | 
|---|
|  | 664 | fprintf(stderr, "GapEnergy  :\t%e\t%e\t%e\t%e\n",Lat->Energy[UnOccupied].AllTotalPsiEnergy[KineticEnergy],Lat->Energy[UnOccupied].AllTotalPsiEnergy[NonLocalEnergy], Lat->Energy[UnOccupied].AllTotalDensityEnergy[PseudoEnergy],Lat->Energy[UnOccupied].AllTotalDensityEnergy[HartreePotentialEnergy]); | 
|---|
|  | 665 | fprintf(stderr, "TotalGapEnergy  :\t%e\n",Lat->Energy[UnOccupied].TotalEnergy[0]); | 
|---|
|  | 666 | fprintf(stderr, "BandGap :\t%e\n", Lat->Energy[UnOccupied].bandgap); | 
|---|
|  | 667 | } | 
|---|
|  | 668 | fprintf(stderr, "IonKinEnergy  :\t%e\n",P->Ion.EKin); | 
|---|
|  | 669 | fprintf(stderr, "Temperature  :\t%e\n",P->Ion.ActualTemp); | 
|---|
|  | 670 | } | 
|---|
|  | 671 | if (P->Files.MeOutMes == 0 || doout == 0) return; | 
|---|
|  | 672 | eout = F->EnergyFile; | 
|---|
|  | 673 | if (eout != NULL) { | 
|---|
|  | 674 | if (R->DoUnOccupied) { | 
|---|
|  | 675 | fprintf(eout, "%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\n", | 
|---|
|  | 676 | P->R.t, | 
|---|
|  | 677 | Lat->Energy[Occupied].TotalEnergy[0], Lat->Energy[UnOccupied].TotalEnergy[0], | 
|---|
|  | 678 | Lat->Energy[Occupied].AllTotalPsiEnergy[KineticEnergy], Lat->Energy[Occupied].AllTotalPsiEnergy[NonLocalEnergy], | 
|---|
|  | 679 | Lat->Energy[UnOccupied].AllTotalPsiEnergy[KineticEnergy]+Lat->Energy[UnOccupied].AllTotalPsiEnergy[NonLocalEnergy], | 
|---|
|  | 680 | Lat->Energy[Occupied].AllTotalDensityEnergy[CorrelationEnergy], Lat->Energy[Occupied].AllTotalDensityEnergy[ExchangeEnergy], | 
|---|
|  | 681 | Lat->Energy[Occupied].AllTotalDensityEnergy[PseudoEnergy], Lat->Energy[Occupied].AllTotalDensityEnergy[HartreePotentialEnergy], | 
|---|
|  | 682 | Lat->Energy[UnOccupied].AllTotalDensityEnergy[PseudoEnergy]+Lat->Energy[UnOccupied].AllTotalDensityEnergy[HartreePotentialEnergy], | 
|---|
|  | 683 | -Lat->Energy[Occupied].AllTotalIonsEnergy[GaussSelfEnergy], | 
|---|
|  | 684 | Lat->Energy[Occupied].AllTotalIonsEnergy[EwaldEnergy], | 
|---|
|  | 685 | P->Ion.EKin, | 
|---|
|  | 686 | Lat->Energy[Occupied].TotalEnergy[0]+P->Ion.EKin); | 
|---|
|  | 687 | } else { | 
|---|
|  | 688 | fprintf(eout, "%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\n", | 
|---|
|  | 689 | P->R.t, | 
|---|
|  | 690 | Lat->Energy[Occupied].TotalEnergy[0], | 
|---|
|  | 691 | Lat->Energy[Occupied].AllTotalPsiEnergy[KineticEnergy], Lat->Energy[Occupied].AllTotalPsiEnergy[NonLocalEnergy], | 
|---|
|  | 692 | Lat->Energy[Occupied].AllTotalDensityEnergy[CorrelationEnergy], Lat->Energy[Occupied].AllTotalDensityEnergy[ExchangeEnergy], | 
|---|
|  | 693 | Lat->Energy[Occupied].AllTotalDensityEnergy[PseudoEnergy], Lat->Energy[Occupied].AllTotalDensityEnergy[HartreePotentialEnergy], | 
|---|
|  | 694 | -Lat->Energy[Occupied].AllTotalIonsEnergy[GaussSelfEnergy], | 
|---|
|  | 695 | Lat->Energy[Occupied].AllTotalIonsEnergy[EwaldEnergy], | 
|---|
|  | 696 | P->Ion.EKin, | 
|---|
|  | 697 | Lat->Energy[Occupied].TotalEnergy[0]+P->Ion.EKin); | 
|---|
|  | 698 | } | 
|---|
|  | 699 | fflush(eout); | 
|---|
|  | 700 | } | 
|---|
|  | 701 |  | 
|---|
|  | 702 | // Output for testing convergence | 
|---|
|  | 703 | if (!P->Par.me) { | 
|---|
|  | 704 | if (R->DoPerturbation)  { | 
|---|
|  | 705 | if ((convergence = fopen("pcp.convergence.csv","r")) != NULL) { // only prepend with header if file doesn't exist yet | 
|---|
|  | 706 | fclose(convergence); | 
|---|
|  | 707 | convergence = fopen("pcp.convergence.csv","a"); | 
|---|
|  | 708 | } else { | 
|---|
|  | 709 | convergence = fopen("pcp.convergence.csv","w"); | 
|---|
|  | 710 | if (convergence != NULL) { | 
|---|
|  | 711 | fprintf(convergence,"Ecut\ta.u.\tMaxG\tN0\tN1\tN2\tChi00\tChi11\tChi22\tP0\tP1\tP2\tRxP0\tRxP1\tRxP2\tTE\t"); | 
|---|
|  | 712 | for (it=0; it < I->Max_Types; it++) {  // over all types | 
|---|
|  | 713 | fprintf(convergence,"Sigma00_%s\tSigma11_%s\tSigma22_%s\t",I->I[it].Symbol,I->I[it].Symbol,I->I[it].Symbol); | 
|---|
|  | 714 | fprintf(convergence,"Sigma00_%s_rezi\tSigma11_%s_rezi\tSigma22_%s_rezi\t",I->I[it].Symbol,I->I[it].Symbol,I->I[it].Symbol); | 
|---|
|  | 715 | } | 
|---|
|  | 716 | fprintf(convergence,"Volume\tN^3\tSawStart\t"); | 
|---|
|  | 717 | fprintf(convergence,"Perturbedrxp-0\tPerturbedrxp-1\tPerturbedrxp-2\t"); | 
|---|
|  | 718 | fprintf(convergence,"Perturbedp-0\tPerturbedp-1\tPerturbedp-2\n"); | 
|---|
|  | 719 | } | 
|---|
|  | 720 | } | 
|---|
|  | 721 | if (convergence != NULL) { | 
|---|
|  | 722 | fprintf(convergence,"%e\t%e\t%i\t%i\t%i\t%i\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t%e\t", | 
|---|
|  | 723 | Lat->ECut, | 
|---|
| [36f85c] | 724 | sqrt(Lat->RealBasisSQ[0]), LevS->TotalAllMaxG, Lev0->Plan0.plan->N[0], Lev0->Plan0.plan->N[1], Lev0->Plan0.plan->N[2], | 
|---|
| [a0bcf1] | 725 | I->I[0].chi[0+0*NDIM], I->I[0].chi[1+1*NDIM], I->I[0].chi[2+2*NDIM], | 
|---|
|  | 726 | Lat->Energy[Perturbed_P0].TotalEnergy[0], Lat->Energy[Perturbed_P1].TotalEnergy[0], Lat->Energy[Perturbed_P2].TotalEnergy[0], | 
|---|
|  | 727 | Lat->Energy[Perturbed_RxP0].TotalEnergy[0], Lat->Energy[Perturbed_RxP1].TotalEnergy[0],Lat->Energy[Perturbed_RxP2].TotalEnergy[0], | 
|---|
|  | 728 | Lat->Energy[Occupied].TotalEnergy[0]); | 
|---|
|  | 729 | for (it=0; it < I->Max_Types; it++) {  // over all types | 
|---|
|  | 730 | //fprintf(convergence,"%e\t%e\t%e\t%e\t%e\t%e\t", | 
|---|
|  | 731 | fprintf(convergence,"%e\t%e\t%e\t", | 
|---|
|  | 732 | //I->I[it].sigma[0][0+0*NDIM], I->I[it].sigma[0][1+1*NDIM], I->I[it].sigma[0][2+2*NDIM], | 
|---|
|  | 733 | I->I[it].sigma_rezi[0][0+0*NDIM], I->I[it].sigma_rezi[0][1+1*NDIM], I->I[it].sigma_rezi[0][2+2*NDIM]); | 
|---|
|  | 734 | } | 
|---|
|  | 735 | fprintf(convergence,"%e\t%i\t%e\t",Lat->Volume, Lev0->Plan0.plan->N[0]*Lev0->Plan0.plan->N[1]*Lev0->Plan0.plan->N[2], | 
|---|
|  | 736 | P->Lat.SawtoothStart); | 
|---|
|  | 737 | fprintf(convergence,"%e\t%e\t%e\t",Lat->E[Perturbed_RxP0].AllTotalPsiEnergy[Perturbed1_0Energy],Lat->E[Perturbed_RxP1].AllTotalPsiEnergy[Perturbed1_0Energy],Lat->E[Perturbed_RxP2].AllTotalPsiEnergy[Perturbed1_0Energy]); | 
|---|
|  | 738 | fprintf(convergence,"%e\t%e\t%e\n",Lat->E[Perturbed_P0].AllTotalPsiEnergy[Perturbed1_0Energy],Lat->E[Perturbed_P1].AllTotalPsiEnergy[Perturbed1_0Energy],Lat->E[Perturbed_P2].AllTotalPsiEnergy[Perturbed1_0Energy]); | 
|---|
|  | 739 | fclose(convergence); | 
|---|
|  | 740 | } | 
|---|
|  | 741 | } else { | 
|---|
|  | 742 | if ((convergence = fopen("pcp.convergence.csv","r")) != NULL) { // only prepend with header if file doesn't exist yet | 
|---|
|  | 743 | fclose(convergence); | 
|---|
|  | 744 | convergence = fopen("pcp.convergence.csv","a"); | 
|---|
|  | 745 | } else { | 
|---|
|  | 746 | convergence = fopen("pcp.convergence.csv","w"); | 
|---|
|  | 747 | if (convergence != NULL) | 
|---|
|  | 748 | fprintf(convergence,"Ecut\ta.u.\tMaxG\tN0\tN1\tN2\tTE\tVolume\tN^3\tSawStart\n"); | 
|---|
|  | 749 | } | 
|---|
|  | 750 | if (convergence != NULL) { | 
|---|
|  | 751 | fprintf(convergence,"%e\t%e\t%i\t%i\t%i\t%i\t%e\t%e\t%i\t%e\n", | 
|---|
|  | 752 | Lat->ECut, | 
|---|
| [36f85c] | 753 | sqrt(Lat->RealBasisSQ[0]), LevS->TotalAllMaxG, Lev0->Plan0.plan->N[0], Lev0->Plan0.plan->N[1], Lev0->Plan0.plan->N[2], | 
|---|
| [a0bcf1] | 754 | Lat->Energy[Occupied].TotalEnergy[0], | 
|---|
|  | 755 | Lat->Volume, Lev0->Plan0.plan->N[0]*Lev0->Plan0.plan->N[1]*Lev0->Plan0.plan->N[2], | 
|---|
|  | 756 | P->Lat.SawtoothStart); | 
|---|
|  | 757 | fclose(convergence); | 
|---|
|  | 758 | } | 
|---|
|  | 759 | } | 
|---|
|  | 760 | } | 
|---|
|  | 761 | } | 
|---|