[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 |
|
---|
| 412 | SpeedMeasure(P, GapTime, StartTimeDo);
|
---|
| 413 | // === Calculate exchange and correlation energy ===
|
---|
| 414 | for (i = 0; i < Dens->LocalSizeR; i++) { // for each node in radial mesh
|
---|
| 415 | // put (corecorrected) densities in p, pUp, pDown
|
---|
| 416 | p = Dens->DensityArray[TotalDensity][i];
|
---|
| 417 | switch (Psi->PsiST) {
|
---|
| 418 | case SpinDouble:
|
---|
| 419 | pUp = 0.5*p;
|
---|
| 420 | pDown = 0.5*p;
|
---|
| 421 | break;
|
---|
| 422 | case SpinUp:
|
---|
| 423 | case SpinDown:
|
---|
| 424 | pUp = Dens->DensityArray[TotalUpDensity][i];
|
---|
| 425 | pDown = Dens->DensityArray[TotalDownDensity][i];
|
---|
| 426 | break;
|
---|
| 427 | default:
|
---|
| 428 | ;
|
---|
| 429 | }
|
---|
| 430 | if ((p < 0) || (pUp < 0) || (pDown < 0)) {
|
---|
| 431 | /*fprintf(stderr,"index %i pc %g p %g\n",i,Dens->DensityArray[CoreWaveDensity][i],p);*/
|
---|
| 432 | p = 0.0;
|
---|
| 433 | pUp = 0.0;
|
---|
| 434 | pDown = 0.0;
|
---|
| 435 | }
|
---|
| 436 | rs = Calcrs(EC,p);
|
---|
| 437 | rsUp = Calcrs(EC,pUp);
|
---|
| 438 | rsDown = Calcrs(EC,pDown);
|
---|
| 439 | zeta = CalcZeta(EC,pUp,pDown);
|
---|
| 440 | // Calculation with the densities and summation
|
---|
| 441 | SumEx += CalcSEXr(EC, rsUp, rsDown, pUp, pDown);
|
---|
| 442 | SumEc += CalcSECr(EC, rs, zeta, p);
|
---|
| 443 | }
|
---|
| 444 | E->AllLocalDensityEnergy[CorrelationEnergy] = Factor*SumEc;
|
---|
| 445 | E->AllLocalDensityEnergy[ExchangeEnergy] = Factor*SumEx;
|
---|
| 446 |
|
---|
| 447 | // === Calculate electrostatic and local pseudopotential energy ===
|
---|
| 448 | SumEHP = 0.0;
|
---|
| 449 | SumEH = 0.0;
|
---|
| 450 | SumEG = 0.0;
|
---|
| 451 | SumEPS = 0.0;
|
---|
| 452 | // calculates energy of local pseudopotential
|
---|
| 453 | if (Lev0->GArray[0].GSq == 0.0) {
|
---|
| 454 | Index = Lev0->GArray[0].Index;
|
---|
| 455 | c_re(vp) = 0.0;
|
---|
| 456 | c_im(vp) = 0.0;
|
---|
| 457 | for (it = 0; it < I->Max_Types; it++) {
|
---|
| 458 | c_re(vp) += (c_re(I->I[it].SFactor[0])*PP->phi_ps_loc[it][0]);
|
---|
| 459 | c_im(vp) += (c_im(I->I[it].SFactor[0])*PP->phi_ps_loc[it][0]);
|
---|
| 460 | }
|
---|
| 461 | SumEPS += (c_re(Dens->DensityCArray[GapDensity][Index])*c_re(vp) +
|
---|
| 462 | c_im(Dens->DensityCArray[GapDensity][Index])*c_im(vp))*R->HGcFactor;
|
---|
| 463 | s++;
|
---|
| 464 | }
|
---|
| 465 | for (g=s; g < Lev0->MaxG; g++) {
|
---|
| 466 | Index = Lev0->GArray[g].Index;
|
---|
| 467 | c_re(vp) = 0.0;
|
---|
| 468 | c_im(vp) = 0.0;
|
---|
| 469 | c_re(rp) = 0.0;
|
---|
| 470 | c_im(rp) = 0.0;
|
---|
| 471 | Fac = 2.*PI/(Lev0->GArray[g].GSq); // 4*.. -> 2*...: 1/2 here ! (due to lacking dependence of first n^{tot} (r) on gap psis)
|
---|
| 472 | for (it = 0; it < I->Max_Types; it++) {
|
---|
| 473 | c_re(vp) += (c_re(I->I[it].SFactor[g])*PP->phi_ps_loc[it][g]);
|
---|
| 474 | c_im(vp) += (c_im(I->I[it].SFactor[g])*PP->phi_ps_loc[it][g]);
|
---|
| 475 | c_re(rp) += (c_re(I->I[it].SFactor[g])*PP->FacGauss[it][g]);
|
---|
| 476 | c_im(rp) += (c_im(I->I[it].SFactor[g])*PP->FacGauss[it][g]);
|
---|
| 477 | }
|
---|
| 478 | c_re(rhog) = c_re(Dens->DensityCArray[TotalDensity][Index])*R->HGcFactor+c_re(rp);
|
---|
| 479 | c_im(rhog) = c_im(Dens->DensityCArray[TotalDensity][Index])*R->HGcFactor+c_im(rp);
|
---|
| 480 | c_re(rhoe) = c_re(Dens->DensityCArray[TotalDensity][Index])*R->HGcFactor;
|
---|
| 481 | c_im(rhoe) = c_im(Dens->DensityCArray[TotalDensity][Index])*R->HGcFactor;
|
---|
| 482 | c_re(rhoe_gap) = c_re(Dens->DensityCArray[GapDensity][Index])*R->HGcFactor;
|
---|
| 483 | c_im(rhoe_gap) = c_im(Dens->DensityCArray[GapDensity][Index])*R->HGcFactor;
|
---|
| 484 | //c_re(PP->VCoulombc[g]) = Fac*c_re(rhog);
|
---|
| 485 | //c_im(PP->VCoulombc[g]) = -Fac*c_im(rhog);
|
---|
| 486 | c_re(HG[Index]) = c_re(vp) + Fac * (c_re(Dens->DensityCArray[TotalDensity][Index])*R->HGcFactor+c_re(rp));
|
---|
| 487 | c_im(HG[Index]) = c_im(vp) + Fac * (c_im(Dens->DensityCArray[TotalDensity][Index])*R->HGcFactor+c_im(rp));
|
---|
| 488 | /*if (P->first) */
|
---|
| 489 | //SumEG += Fac*(c_re(rp)*c_re(rp)+c_im(rp)*c_im(rp)); // Coulomb energy
|
---|
| 490 | // changed: took out gaussian part! rhog -> rhoe
|
---|
| 491 | SumEHP += 2*Fac*(c_re(rhoe)*c_re(rhoe_gap)+c_im(rhoe)*c_im(rhoe_gap)); // E_ES first part
|
---|
| 492 | //SumEH += Fac*(c_re(rhoe)*c_re(rhoe)+c_im(rhoe)*c_im(rhoe));
|
---|
| 493 | SumEPS += 2.*(c_re(Dens->DensityCArray[GapDensity][Index])*c_re(vp)+
|
---|
| 494 | c_im(Dens->DensityCArray[GapDensity][Index])*c_im(vp))*R->HGcFactor;
|
---|
| 495 | }
|
---|
| 496 | //
|
---|
| 497 | for (i=0; i<Lev0->MaxDoubleG; i++) {
|
---|
| 498 | HG[Lev0->DoubleG[2*i+1]].re = HG[Lev0->DoubleG[2*i]].re;
|
---|
| 499 | HG[Lev0->DoubleG[2*i+1]].im = -HG[Lev0->DoubleG[2*i]].im;
|
---|
| 500 | }
|
---|
| 501 | /*if (P->first) */
|
---|
| 502 | //E->AllLocalDensityEnergy[GaussEnergy] = SumEG*Lat->Volume;
|
---|
| 503 | E->AllLocalDensityEnergy[PseudoEnergy] = SumEPS*Lat->Volume; // local pseudopotential
|
---|
| 504 | E->AllLocalDensityEnergy[HartreePotentialEnergy] = SumEHP*Lat->Volume; // Gauss n^Gauss and Hartree n potential
|
---|
| 505 | //E->AllLocalDensityEnergy[HartreeEnergy] = SumEH*Lat->Volume;
|
---|
| 506 | SpeedMeasure(P, GapTime, StopTimeDo);
|
---|
| 507 |
|
---|
| 508 | // === Calculate Gradient ===
|
---|
| 509 | CalculateGradientNoRT(P,
|
---|
| 510 | LevS->LPsi->LocalPsi[R->ActualLocalPsiNo],
|
---|
| 511 | Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].PsiFactor,
|
---|
| 512 | &Lat->Psi.AddData[R->ActualLocalPsiNo].Lambda,
|
---|
| 513 | P->PP.fnl[R->ActualLocalPsiNo],
|
---|
| 514 | P->Grad.GradientArray[ActualGradient],
|
---|
| 515 | P->Grad.GradientArray[OldActualGradient],
|
---|
| 516 | P->Grad.GradientArray[HcGradient]);
|
---|
| 517 | }
|
---|
| 518 |
|
---|
| 519 | /** Calculates the energy of a wave function psi.
|
---|
| 520 | * Calculates kinetc and non local energies, taking care of possible
|
---|
| 521 | * Riemann tensor usage.
|
---|
| 522 | * \param *P Problem at hand
|
---|
| 523 | * \param p number of wave function Psi
|
---|
| 524 | * \param UseInitTime Whether speed measuring uses InitLocTime (Init) or LocTime (Update)
|
---|
| 525 | * \sa EnergyGNSP(), EnergyLapNSP()
|
---|
| 526 | * \warning call EnergyAllReduce() afterwards!
|
---|
| 527 | */
|
---|
| 528 | void CalculatePsiEnergy(struct Problem *P, const int p, const int UseInitTime)
|
---|
| 529 | {
|
---|
| 530 | struct Lattice *Lat = &(P->Lat);
|
---|
| 531 | switch (Lat->RT.ActualUse) {
|
---|
| 532 | case inactive:
|
---|
| 533 | case standby:
|
---|
| 534 | SpeedMeasure(P, (UseInitTime == 1 ? InitLocTime : LocTime), StartTimeDo);
|
---|
| 535 | CalculateKineticEnergyNoRT(P, p);
|
---|
| 536 | SpeedMeasure(P, (UseInitTime == 1 ? InitLocTime : LocTime), StopTimeDo);
|
---|
| 537 | SpeedMeasure(P, (UseInitTime == 1 ? InitNonLocTime : NonLocTime), StartTimeDo);
|
---|
| 538 | CalculateNonLocalEnergyNoRT(P, p);
|
---|
| 539 | SpeedMeasure(P, (UseInitTime == 1 ? InitNonLocTime : NonLocTime), StopTimeDo);
|
---|
| 540 | break;
|
---|
| 541 | case active:
|
---|
| 542 | SpeedMeasure(P, (UseInitTime == 1 ? InitLocTime : LocTime), StartTimeDo);
|
---|
| 543 | CalculateKineticEnergyUseRT(P, p);
|
---|
| 544 | SpeedMeasure(P, (UseInitTime == 1 ? InitLocTime : LocTime), StopTimeDo);
|
---|
| 545 | SpeedMeasure(P, (UseInitTime == 1 ? InitNonLocTime : NonLocTime), StartTimeDo);
|
---|
| 546 | CalculateNonLocalEnergyUseRT(P, p);
|
---|
| 547 | SpeedMeasure(P, (UseInitTime == 1 ? InitNonLocTime : NonLocTime), StopTimeDo);
|
---|
| 548 | break;
|
---|
| 549 | }
|
---|
| 550 | /* Achtung danach noch EnergyAllReduce aufrufen */
|
---|
| 551 | }
|
---|
| 552 |
|
---|
| 553 | /** Initialization of wave function energy calculation.
|
---|
| 554 | * For every wave function CalculatePsiEnergy() is called,
|
---|
| 555 | * Energy::AllLocalPsiEnergy is set to sum of these.
|
---|
| 556 | * \param *P Problem at hand
|
---|
| 557 | * \param type minimisation type PsiTypeTag to calculate psi energy for
|
---|
| 558 | * \warning call EnergyAllReduce() afterwards!
|
---|
| 559 | */
|
---|
| 560 | void InitPsiEnergyCalculation(struct Problem *P, enum PsiTypeTag type)
|
---|
| 561 | {
|
---|
| 562 | struct Lattice *Lat = &(P->Lat);
|
---|
| 563 | int p,i, oldtype = P->R.CurrentMin;
|
---|
| 564 | SetCurrentMinState(P,type);
|
---|
| 565 | for (p=0; p < Lat->Psi.LocalNo; p++) {
|
---|
| 566 | if (P->Lat.Psi.LocalPsiStatus[p].PsiType == P->R.CurrentMin)
|
---|
| 567 | CalculatePsiEnergy(P, p, 1);
|
---|
| 568 | }
|
---|
| 569 | for (i=0; i< MAXALLPSIENERGY; i++) {
|
---|
| 570 | Lat->E->AllLocalPsiEnergy[i] = 0.0;
|
---|
| 571 | for (p=0; p < Lat->Psi.LocalNo; p++)
|
---|
| 572 | if (P->Lat.Psi.LocalPsiStatus[p].PsiType == P->R.CurrentMin)
|
---|
| 573 | Lat->E->AllLocalPsiEnergy[i] += Lat->E->PsiEnergy[i][p];
|
---|
| 574 | }
|
---|
| 575 | SetCurrentMinState(P,oldtype);
|
---|
| 576 | /* Achtung danach noch EnergyAllReduce aufrufen */
|
---|
| 577 | }
|
---|
| 578 |
|
---|
| 579 | /** Updating wave function energy.
|
---|
| 580 | * CalculatePsiEnergy() is called for RunStruct::OldActualLocalPsiNo,
|
---|
| 581 | * Energy::AllLocalPsiEnergy is set to sum of all Psi energies.
|
---|
| 582 | * \param *P Problem at hand
|
---|
| 583 | * \warning call EnergyAllReduce() afterwards!
|
---|
| 584 | */
|
---|
| 585 | void UpdatePsiEnergyCalculation(struct Problem *P)
|
---|
| 586 | {
|
---|
| 587 | struct Lattice *Lat = &(P->Lat);
|
---|
| 588 | struct RunStruct *R = &P->R;
|
---|
| 589 | int p = R->OldActualLocalPsiNo, i;
|
---|
| 590 | if (P->Lat.Psi.LocalPsiStatus[p].PsiType == P->R.CurrentMin)
|
---|
| 591 | CalculatePsiEnergy(P, p, 0);
|
---|
| 592 | for (i=0; i< MAXALLPSIENERGY; i++) {
|
---|
| 593 | Lat->E->AllLocalPsiEnergy[i] = 0.0;
|
---|
| 594 | for (p=0; p < P->Lat.Psi.LocalNo; p++)
|
---|
| 595 | if (P->Lat.Psi.LocalPsiStatus[p].PsiType == P->R.CurrentMin)
|
---|
| 596 | Lat->E->AllLocalPsiEnergy[i] += Lat->E->PsiEnergy[i][p];
|
---|
| 597 | }
|
---|
| 598 | /* Achtung danach noch EnergyAllReduce aufrufen */
|
---|
| 599 | }
|
---|
| 600 |
|
---|
| 601 | /** Output of energies.
|
---|
| 602 | * Prints either Time, PsiEnergy(Up/Down), DensityEnergy, IonsEnergy, KineticEnergy,
|
---|
| 603 | * TotalEnergy and Temperature to screen or<br>
|
---|
| 604 | * Time, TotalEnergy, NonLocalEnergy, CorrelationEnergy, ExchangeEnergy,
|
---|
| 605 | * PseudoEnergy, HartreePotentialEnergy, GaussSelfEnergy, EwaldEnergy,
|
---|
| 606 | * KineticEnergy and TotalEnergy+KineticEnergy to the energy file
|
---|
| 607 | * \param *P Problem at hand
|
---|
| 608 | * \param doout 1 - print stuff to stderr, 0 - put compact form into energy file
|
---|
| 609 | */
|
---|
| 610 | void EnergyOutput(struct Problem *P, int doout)
|
---|
| 611 | {
|
---|
| 612 | struct Lattice *Lat = &P->Lat;
|
---|
| 613 | struct RunStruct *R = &P->R;
|
---|
| 614 | struct LatticeLevel *Lev0 = R->Lev0;
|
---|
| 615 | struct LatticeLevel *LevS = R->LevS;
|
---|
| 616 | struct Ions *I = &P->Ion;
|
---|
| 617 | struct Psis *Psi = &Lat->Psi;
|
---|
| 618 | struct FileData *F = &P->Files;
|
---|
| 619 | FILE *eout = NULL;
|
---|
| 620 | FILE *convergence = NULL;
|
---|
| 621 | int i, it;
|
---|
| 622 | if (P->Call.out[LeaderOut] && (P->Par.me == 0) && doout) {
|
---|
| 623 | fprintf(stderr, "Time T: :\t%e\n",P->R.t);
|
---|
| 624 | fprintf(stderr, "PsiEnergy :");
|
---|
| 625 | for (i=0; i<MAXALLPSIENERGY; i++) {
|
---|
| 626 | fprintf(stderr," %e",Lat->Energy[Occupied].AllTotalPsiEnergy[i]);
|
---|
| 627 | }
|
---|
| 628 | fprintf(stderr,"\n");
|
---|
| 629 | if (Psi->PsiST != SpinDouble) {
|
---|
| 630 | fprintf(stderr, "PsiEnergyUp :");
|
---|
| 631 | for (i=0; i<MAXALLPSIENERGY; i++) {
|
---|
| 632 | fprintf(stderr,"\t%e",Lat->Energy[Occupied].AllUpPsiEnergy[i]);
|
---|
| 633 | }
|
---|
| 634 | fprintf(stderr,"\n");
|
---|
| 635 | fprintf(stderr, "PsiEnergyDown:");
|
---|
| 636 | for (i=0; i<MAXALLPSIENERGY; i++) {
|
---|
| 637 | fprintf(stderr,"\t%e",Lat->Energy[Occupied].AllDownPsiEnergy[i]);
|
---|
| 638 | }
|
---|
| 639 | fprintf(stderr,"\n");
|
---|
| 640 | }
|
---|
| 641 | fprintf(stderr, "DensityEnergy:");
|
---|
| 642 | for (i=0; i<MAXALLDENSITYENERGY; i++) {
|
---|
| 643 | fprintf(stderr,"\t%e",Lat->Energy[Occupied].AllTotalDensityEnergy[i]);
|
---|
| 644 | }
|
---|
| 645 | fprintf(stderr,"\n");
|
---|
| 646 | fprintf(stderr, "IonsEnergy :");
|
---|
| 647 | for (i=0; i<MAXALLIONSENERGY; i++) {
|
---|
| 648 | fprintf(stderr,"\t%e",Lat->Energy[Occupied].AllTotalIonsEnergy[i]);
|
---|
| 649 | }
|
---|
| 650 | fprintf(stderr,"\n");
|
---|
| 651 | fprintf(stderr, "TotalEnergy :\t%e\n",Lat->Energy[Occupied].TotalEnergy[0]);
|
---|
| 652 | if (R->DoPerturbation)
|
---|
| 653 | 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]);
|
---|
| 654 | if (R->DoUnOccupied) {
|
---|
| 655 | 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]);
|
---|
| 656 | fprintf(stderr, "TotalGapEnergy :\t%e\n",Lat->Energy[UnOccupied].TotalEnergy[0]);
|
---|
| 657 | fprintf(stderr, "BandGap :\t%e\n", Lat->Energy[UnOccupied].bandgap);
|
---|
| 658 | }
|
---|
| 659 | fprintf(stderr, "IonKinEnergy :\t%e\n",P->Ion.EKin);
|
---|
| 660 | fprintf(stderr, "Temperature :\t%e\n",P->Ion.ActualTemp);
|
---|
| 661 | }
|
---|
| 662 | if (P->Files.MeOutMes == 0 || doout == 0) return;
|
---|
| 663 | eout = F->EnergyFile;
|
---|
| 664 | if (eout != NULL) {
|
---|
| 665 | if (R->DoUnOccupied) {
|
---|
| 666 | 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",
|
---|
| 667 | P->R.t,
|
---|
| 668 | Lat->Energy[Occupied].TotalEnergy[0], Lat->Energy[UnOccupied].TotalEnergy[0],
|
---|
| 669 | Lat->Energy[Occupied].AllTotalPsiEnergy[KineticEnergy], Lat->Energy[Occupied].AllTotalPsiEnergy[NonLocalEnergy],
|
---|
| 670 | Lat->Energy[UnOccupied].AllTotalPsiEnergy[KineticEnergy]+Lat->Energy[UnOccupied].AllTotalPsiEnergy[NonLocalEnergy],
|
---|
| 671 | Lat->Energy[Occupied].AllTotalDensityEnergy[CorrelationEnergy], Lat->Energy[Occupied].AllTotalDensityEnergy[ExchangeEnergy],
|
---|
| 672 | Lat->Energy[Occupied].AllTotalDensityEnergy[PseudoEnergy], Lat->Energy[Occupied].AllTotalDensityEnergy[HartreePotentialEnergy],
|
---|
| 673 | Lat->Energy[UnOccupied].AllTotalDensityEnergy[PseudoEnergy]+Lat->Energy[UnOccupied].AllTotalDensityEnergy[HartreePotentialEnergy],
|
---|
| 674 | -Lat->Energy[Occupied].AllTotalIonsEnergy[GaussSelfEnergy],
|
---|
| 675 | Lat->Energy[Occupied].AllTotalIonsEnergy[EwaldEnergy],
|
---|
| 676 | P->Ion.EKin,
|
---|
| 677 | Lat->Energy[Occupied].TotalEnergy[0]+P->Ion.EKin);
|
---|
| 678 | } else {
|
---|
| 679 | 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",
|
---|
| 680 | P->R.t,
|
---|
| 681 | Lat->Energy[Occupied].TotalEnergy[0],
|
---|
| 682 | Lat->Energy[Occupied].AllTotalPsiEnergy[KineticEnergy], Lat->Energy[Occupied].AllTotalPsiEnergy[NonLocalEnergy],
|
---|
| 683 | Lat->Energy[Occupied].AllTotalDensityEnergy[CorrelationEnergy], Lat->Energy[Occupied].AllTotalDensityEnergy[ExchangeEnergy],
|
---|
| 684 | Lat->Energy[Occupied].AllTotalDensityEnergy[PseudoEnergy], Lat->Energy[Occupied].AllTotalDensityEnergy[HartreePotentialEnergy],
|
---|
| 685 | -Lat->Energy[Occupied].AllTotalIonsEnergy[GaussSelfEnergy],
|
---|
| 686 | Lat->Energy[Occupied].AllTotalIonsEnergy[EwaldEnergy],
|
---|
| 687 | P->Ion.EKin,
|
---|
| 688 | Lat->Energy[Occupied].TotalEnergy[0]+P->Ion.EKin);
|
---|
| 689 | }
|
---|
| 690 | fflush(eout);
|
---|
| 691 | }
|
---|
| 692 |
|
---|
| 693 | // Output for testing convergence
|
---|
| 694 | if (!P->Par.me) {
|
---|
| 695 | if (R->DoPerturbation) {
|
---|
| 696 | if ((convergence = fopen("pcp.convergence.csv","r")) != NULL) { // only prepend with header if file doesn't exist yet
|
---|
| 697 | fclose(convergence);
|
---|
| 698 | convergence = fopen("pcp.convergence.csv","a");
|
---|
| 699 | } else {
|
---|
| 700 | convergence = fopen("pcp.convergence.csv","w");
|
---|
| 701 | if (convergence != NULL) {
|
---|
| 702 | fprintf(convergence,"Ecut\ta.u.\tMaxG\tN0\tN1\tN2\tChi00\tChi11\tChi22\tP0\tP1\tP2\tRxP0\tRxP1\tRxP2\tTE\t");
|
---|
| 703 | for (it=0; it < I->Max_Types; it++) { // over all types
|
---|
| 704 | fprintf(convergence,"Sigma00_%s\tSigma11_%s\tSigma22_%s\t",I->I[it].Symbol,I->I[it].Symbol,I->I[it].Symbol);
|
---|
| 705 | fprintf(convergence,"Sigma00_%s_rezi\tSigma11_%s_rezi\tSigma22_%s_rezi\t",I->I[it].Symbol,I->I[it].Symbol,I->I[it].Symbol);
|
---|
| 706 | }
|
---|
| 707 | fprintf(convergence,"Volume\tN^3\tSawStart\t");
|
---|
| 708 | fprintf(convergence,"Perturbedrxp-0\tPerturbedrxp-1\tPerturbedrxp-2\t");
|
---|
| 709 | fprintf(convergence,"Perturbedp-0\tPerturbedp-1\tPerturbedp-2\n");
|
---|
| 710 | }
|
---|
| 711 | }
|
---|
| 712 | if (convergence != NULL) {
|
---|
| 713 | 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",
|
---|
| 714 | Lat->ECut,
|
---|
| 715 | Lat->RealBasisQ[0], LevS->TotalAllMaxG, Lev0->Plan0.plan->N[0], Lev0->Plan0.plan->N[1], Lev0->Plan0.plan->N[2],
|
---|
| 716 | I->I[0].chi[0+0*NDIM], I->I[0].chi[1+1*NDIM], I->I[0].chi[2+2*NDIM],
|
---|
| 717 | Lat->Energy[Perturbed_P0].TotalEnergy[0], Lat->Energy[Perturbed_P1].TotalEnergy[0], Lat->Energy[Perturbed_P2].TotalEnergy[0],
|
---|
| 718 | Lat->Energy[Perturbed_RxP0].TotalEnergy[0], Lat->Energy[Perturbed_RxP1].TotalEnergy[0],Lat->Energy[Perturbed_RxP2].TotalEnergy[0],
|
---|
| 719 | Lat->Energy[Occupied].TotalEnergy[0]);
|
---|
| 720 | for (it=0; it < I->Max_Types; it++) { // over all types
|
---|
| 721 | //fprintf(convergence,"%e\t%e\t%e\t%e\t%e\t%e\t",
|
---|
| 722 | fprintf(convergence,"%e\t%e\t%e\t",
|
---|
| 723 | //I->I[it].sigma[0][0+0*NDIM], I->I[it].sigma[0][1+1*NDIM], I->I[it].sigma[0][2+2*NDIM],
|
---|
| 724 | 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]);
|
---|
| 725 | }
|
---|
| 726 | 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],
|
---|
| 727 | P->Lat.SawtoothStart);
|
---|
| 728 | 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]);
|
---|
| 729 | 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]);
|
---|
| 730 | fclose(convergence);
|
---|
| 731 | }
|
---|
| 732 | } else {
|
---|
| 733 | if ((convergence = fopen("pcp.convergence.csv","r")) != NULL) { // only prepend with header if file doesn't exist yet
|
---|
| 734 | fclose(convergence);
|
---|
| 735 | convergence = fopen("pcp.convergence.csv","a");
|
---|
| 736 | } else {
|
---|
| 737 | convergence = fopen("pcp.convergence.csv","w");
|
---|
| 738 | if (convergence != NULL)
|
---|
| 739 | fprintf(convergence,"Ecut\ta.u.\tMaxG\tN0\tN1\tN2\tTE\tVolume\tN^3\tSawStart\n");
|
---|
| 740 | }
|
---|
| 741 | if (convergence != NULL) {
|
---|
| 742 | fprintf(convergence,"%e\t%e\t%i\t%i\t%i\t%i\t%e\t%e\t%i\t%e\n",
|
---|
| 743 | Lat->ECut,
|
---|
| 744 | Lat->RealBasisQ[0], LevS->TotalAllMaxG, Lev0->Plan0.plan->N[0], Lev0->Plan0.plan->N[1], Lev0->Plan0.plan->N[2],
|
---|
| 745 | Lat->Energy[Occupied].TotalEnergy[0],
|
---|
| 746 | Lat->Volume, Lev0->Plan0.plan->N[0]*Lev0->Plan0.plan->N[1]*Lev0->Plan0.plan->N[2],
|
---|
| 747 | P->Lat.SawtoothStart);
|
---|
| 748 | fclose(convergence);
|
---|
| 749 | }
|
---|
| 750 | }
|
---|
| 751 | }
|
---|
| 752 | }
|
---|