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 | //if (isnan(HG[0].re)) { fprintf(stderr,"WARNGING: CalculateGapEnergy(): HG[%i]_%i = NaN!\n", 0, R->ActualLocalPsiNo); Error(SomeError, "NaN-Fehler!"); }
|
---|
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];
|
---|
418 | //if (isnan(p)) { fprintf(stderr,"WARNGING: CalculateGapEnergy(): Dens->DensityArray[TotalUpDensity][%i]_%i = NaN!\n", i, R->ActualLocalPsiNo); Error(SomeError, "NaN-Fehler!"); }
|
---|
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 | }
|
---|
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!"); }
|
---|
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 | }
|
---|
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!"); }
|
---|
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;
|
---|
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!"); }
|
---|
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));
|
---|
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!"); }
|
---|
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 ===
|
---|
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!"); }
|
---|
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]);
|
---|
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!"); }
|
---|
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,
|
---|
724 | sqrt(Lat->RealBasisSQ[0]), LevS->TotalAllMaxG, Lev0->Plan0.plan->N[0], Lev0->Plan0.plan->N[1], Lev0->Plan0.plan->N[2],
|
---|
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,
|
---|
753 | sqrt(Lat->RealBasisSQ[0]), LevS->TotalAllMaxG, Lev0->Plan0.plan->N[0], Lev0->Plan0.plan->N[1], Lev0->Plan0.plan->N[2],
|
---|
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 | }
|
---|