| [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 | }
 | 
|---|