source: pcp/src/run.c@ 4931e0

Last change on this file since 4931e0 was 4931e0, checked in by Frederik Heber <heber@…>, 17 years ago

verbosity levels added to various fprintf

  • Property mode set to 100644
File size: 65.8 KB
Line 
1/** \file run.c
2 * Initialization of levels and calculation super-functions.
3 *
4 * Most important functions herein are CalculateForce() and CalculateMD(), which calls various
5 * functions in order to perfom the Molecular Dynamics simulation. MinimiseOccupied() and MinimiseUnOccupied()
6 * call various functions to perform the actual minimisation for the occupied and unoccupied wave functions.
7 * CalculateMinimumStop() evaluates the stop condition for desired precision or step count (or external signals).
8 *
9 * Minor functions are ChangeToLevUp() (which takes the calculation to the next finer level),
10 * UpdateActualPsiNo() (next Psi is minimized and an additional orthonormalization takes place) and UpdateToNewWaves()
11 * (which reinitializes density calculations after the wave functions have changed due to the ionic motion).
12 * OccupyByFermi() re-occupies orbitals according to Fermi distribution if calculated with additional orbitals.
13 * InitRun() and InitRunLevel() prepare the RunStruct with starting values. UpdateIon_PRCG() implements a CG
14 * algorithm to minimize the ionic forces and thus optimize the structure.
15 *
16 *
17 Project: ParallelCarParrinello
18 \author Jan Hamaekers
19 \date 2000
20
21 File: run.c
22 $Id: run.c,v 1.101.2.2 2007-04-21 13:01:13 foo Exp $
23*/
24
25#include <signal.h>
26#include <stdlib.h>
27#include <stdio.h>
28#include <string.h>
29#include <math.h>
30#include <gsl/gsl_multimin.h>
31#include <gsl/gsl_vector.h>
32#include <gsl/gsl_errno.h>
33#include <gsl/gsl_math.h>
34#include <gsl/gsl_min.h>
35#include "mpi.h"
36#include "data.h"
37#include "errors.h"
38#include "helpers.h"
39#include "init.h"
40#include "opt.h"
41#include "myfft.h"
42#include "gramsch.h"
43#include "output.h"
44#include "energy.h"
45#include "density.h"
46#include "ions.h"
47#include "run.h"
48#include "riemann.h"
49#include "mymath.h"
50#include "pcp.h"
51#include "perturbed.h"
52#include "wannier.h"
53
54
55/** Initialization of the (initial) zero and simulation levels in RunStruct structure.
56 * RunStruct::InitLevS is set onto the STANDARTLEVEL in Lattice::Lev[], RunStruct::InitLev0 on
57 * level 0, RunStruct::LevS onto Lattice::MaxLevel-1 (maximum level) and RunStruct::Lev0 onto
58 * Lattice::MaxLevel-2 (one below).
59 * In case of RiemannTensor use an additional Riemann level is intertwined.
60 * \param *P Problem at hand
61 */
62void InitRunLevel(struct Problem *P)
63{
64 struct Lattice *Lat = &P->Lat;
65 struct RunStruct *R = &P->R;
66 struct RiemannTensor *RT = &Lat->RT;
67 int d,i;
68
69 switch (Lat->RT.Use) {
70 case UseNotRT:
71 R->InitLevSNo = STANDARTLEVEL;
72 R->InitLev0No = 0;
73 R->InitLevS = &P->Lat.Lev[R->InitLevSNo];
74 R->InitLev0 = &P->Lat.Lev[R->InitLev0No];
75 R->LevSNo = Lat->MaxLevel-1;
76 R->Lev0No = Lat->MaxLevel-2;
77 R->LevS = &P->Lat.Lev[R->LevSNo];
78 R->Lev0 = &P->Lat.Lev[R->Lev0No];
79 break;
80 case UseRT:
81 R->InitLevSNo = STANDARTLEVEL;
82 R->InitLev0No = 0;
83 R->InitLevS = &P->Lat.Lev[R->InitLevSNo];
84 R->InitLev0 = &P->Lat.Lev[R->InitLev0No];
85
86 /* R->LevSNo = Lat->MaxLevel-1;
87 R->Lev0No = Lat->MaxLevel-2;*/
88 R->LevSNo = Lat->MaxLevel-2;
89 R->Lev0No = Lat->MaxLevel-3;
90
91 R->LevRNo = P->Lat.RT.RiemannLevel;
92 R->LevRSNo = STANDARTLEVEL;
93 R->LevR0No = 0;
94 R->LevS = &P->Lat.Lev[R->LevSNo];
95 R->Lev0 = &P->Lat.Lev[R->Lev0No];
96 R->LevR = &P->Lat.Lev[R->LevRNo];
97 R->LevRS = &P->Lat.Lev[R->LevRSNo];
98 R->LevR0 = &P->Lat.Lev[R->LevR0No];
99 for (d=0; d<NDIM; d++) {
100 RT->NUpLevRS[d] = 1;
101 for (i=R->LevRNo-1; i >= R->LevRSNo; i--)
102 RT->NUpLevRS[d] *= Lat->LevelSizes[i];
103 RT->NUpLevR0[d] = 1;
104 for (i=R->LevRNo-1; i >= R->LevR0No; i--)
105 RT->NUpLevR0[d] *= Lat->LevelSizes[i];
106 }
107 break;
108 }
109}
110
111
112/** Initialization of RunStruct structure.
113 * Most of the actual entries in the RunStruct are set to their starter no-nonsense
114 * values (init if LatticeLevel is not STANDARTLEVEL otherwise normal max): FactorDensity,
115 * all Steps, XCEnergyFactor and HGcFactor, current and archived energie values are zeroed.
116 * \param *P problem at hand
117 */
118void InitRun(struct Problem *P)
119{
120 struct Lattice *Lat = &P->Lat;
121 struct RunStruct *R = &P->R;
122 struct Psis *Psi = &Lat->Psi;
123 int i,j;
124
125#ifndef SHORTSPEED
126 R->MaxMinStepFactor = Psi->AllMaxLocalNo;
127#else
128 R->MaxMinStepFactor = SHORTSPEED;
129#endif
130 if (R->LevSNo == STANDARTLEVEL) {
131 R->ActualMaxMinStep = R->MaxMinStep*R->MaxPsiStep*R->MaxMinStepFactor;
132 R->ActualRelEpsTotalEnergy = R->RelEpsTotalEnergy;
133 R->ActualRelEpsKineticEnergy = R->RelEpsKineticEnergy;
134 R->ActualMaxMinStopStep = R->MaxMinStopStep;
135 R->ActualMaxMinGapStopStep = R->MaxMinGapStopStep;
136 } else {
137 R->ActualMaxMinStep = R->MaxInitMinStep*R->MaxPsiStep*R->MaxMinStepFactor;
138 R->ActualRelEpsTotalEnergy = R->InitRelEpsTotalEnergy;
139 R->ActualRelEpsKineticEnergy = R->InitRelEpsKineticEnergy;
140 R->ActualMaxMinStopStep = R->InitMaxMinStopStep;
141 R->ActualMaxMinGapStopStep = R->InitMaxMinGapStopStep;
142 }
143
144 R->FactorDensityR = 1./Lat->Volume;
145 R->FactorDensityC = Lat->Volume;
146
147 R->OldActualLocalPsiNo = R->ActualLocalPsiNo = 0;
148 R->UseOldPsi = 1;
149 R->MinStep = 0;
150 R->PsiStep = 0;
151 R->AlphaStep = 0;
152 R->DoCalcCGGauss = 0;
153 R->CurrentMin = Occupied;
154
155 R->MinStopStep = 0;
156
157 R->ScanPotential = 0; // in order to deactivate, simply set this to 0
158 R->ScanAtStep = 6; // must not be set to same as ScanPotential (then gradient is never calculated)
159 R->ScanDelta = 0.01; // step size on advance
160 R->ScanFlag = 0; // flag telling that we are scanning
161
162 //R->DoBrent = 0; // InitRun() occurs after ReadParameters(), thus this deactivates DoBrent line search
163
164 /* R->MaxOuterStep = 1;
165 R->MeanForceEps = 0.0;*/
166
167 R->NewRStep = 1;
168 /* Factor */
169 R->XCEnergyFactor = 1.0/R->FactorDensityR;
170 R->HGcFactor = 1.0/Lat->Volume;
171
172 /* Sollte auch geaendert werden */
173 /*Grad->GradientArray[GraSchGradient] = LevS->LPsi->LocalPsi[Psi->LocalNo];*/
174
175 for (j=Occupied;j<Extra;j++)
176 for (i=0; i < RUNMAXOLD; i++) {
177 R->TE[j][i] = 0;
178 R->KE[j][i] = 0;
179 }
180
181 R->MinimisationName = (char **) Malloc((perturbations+3)*(sizeof(char *)), "InitRun: *MinimisationName");
182 for (j=Occupied;j<=Extra;j++)
183 R->MinimisationName[j] = (char *) MallocString(6*(sizeof(char)), "InitRun: MinimisationName[]");
184 strncpy(R->MinimisationName[0],"Occ",6);
185 strncpy(R->MinimisationName[1],"UnOcc",6);
186 strncpy(R->MinimisationName[2],"P0",6);
187 strncpy(R->MinimisationName[3],"P1",6);
188 strncpy(R->MinimisationName[4],"P2",6);
189 strncpy(R->MinimisationName[5],"RxP0",6);
190 strncpy(R->MinimisationName[6],"RxP1",6);
191 strncpy(R->MinimisationName[7],"RxP2",6);
192 strncpy(R->MinimisationName[8],"Extra",6);
193}
194
195/** Re-occupy orbitals according to Fermi (bottom-up energy-wise).
196 * All OnePsiElementAddData#PsiFactor's are set to zero. \a electrons is set to Psi#Use-dependent
197 * Psis#GlobalNo.
198 * Then we go through OnePsiElementAddData#Lambda, find biggest, put one or two electrons into
199 * its PsiFactor, withdraw from \a electrons. Go on as long as there are \a electrons left.
200 * \param *P Problem at hand
201 */
202void OccupyByFermi(struct Problem *P) {
203 struct Lattice *Lat = &P->Lat;
204 struct Psis *Psi = &Lat->Psi;
205 int i, index, electrons = 0;
206 double lambda, electronsperorbit;
207
208 for (i=0; i< Psi->LocalNo; i++) {// set all PsiFactors to zero
209 Psi->LocalPsiStatus[i].PsiFactor = 0.0;
210 Psi->LocalPsiStatus[i].PsiType = UnOccupied;
211 //Psi->LocalPsiStatus[i].PsiGramSchStatus = (R->DoSeparated) ? NotUsedToOrtho : NotOrthogonal;
212 }
213
214 electronsperorbit = (Psi->Use == UseSpinUpDown) ? 1 : 2;
215 switch (Psi->PsiST) { // how many electrons may we re-distribute
216 case SpinDouble:
217 electrons = Psi->GlobalNo[PsiMaxNoDouble];
218 break;
219 case SpinUp:
220 electrons = Psi->GlobalNo[PsiMaxNoUp];
221 break;
222 case SpinDown:
223 electrons = Psi->GlobalNo[PsiMaxNoDown];
224 break;
225 }
226 while (electrons > 0) {
227 lambda = 0.0;
228 index = 0;
229 for (i=0; i< Psi->LocalNo; i++) // seek biggest unoccupied one
230 if ((lambda < Psi->AddData[i].Lambda) && (Psi->LocalPsiStatus[i].PsiFactor == 0.0)) {
231 index = i;
232 lambda = Psi->AddData[i].Lambda;
233 }
234 Psi->LocalPsiStatus[index].PsiFactor = electronsperorbit; // occupy state
235 Psi->LocalPsiStatus[index].PsiType = Occupied;
236 electrons--; // one electron less
237 }
238 for (i=0; i< Psi->LocalNo; i++) // set all PsiFactors to zero
239 if (Psi->LocalPsiStatus[i].PsiType == UnOccupied) Psi->LocalPsiStatus[i].PsiFactor = 1.0;
240
241 SpeedMeasure(P, DensityTime, StartTimeDo);
242 UpdateDensityCalculation(P);
243 SpeedMeasure(P, DensityTime, StopTimeDo);
244 InitPsiEnergyCalculation(P,Occupied); // goes through all orbitals calculating kinetic and non-local
245 CalculateDensityEnergy(P, 0);
246 EnergyAllReduce(P);
247// SetCurrentMinState(P,UnOccupied);
248// InitPsiEnergyCalculation(P,UnOccupied); /* STANDARTLEVEL */
249// CalculateGapEnergy(P); /* STANDARTLEVEL */
250// EnergyAllReduce(P);
251// SetCurrentMinState(P,Occupied);
252}
253
254/** Use next local Psi: Update RunStruct::ActualLocalPsiNo.
255 * Increases OnePsiElementAddData::Step, RunStruct::MinStep and RunStruct::PsiStep.
256 * RunStruct::OldActualLocalPsiNo is set to current one and this distributed
257 * (UpdateGramSchOldActualPsiNo()) among process.
258 * Afterwards RunStruct::ActualLocalPsiNo is increased (modulo Psis::LocalNo of
259 * this process) and again distributed (UpdateGramSchActualPsiNo()).
260 * Due to change in the GramSchmidt-Status, GramSch() is called for Orthonormalization.
261 * \param *P Problem at hand#
262 * \param IncType skip types PsiTypeTag#UnOccupied or PsiTypeTag#Occupied we only want next(thus we can handily advance only through either type)
263 */
264void UpdateActualPsiNo(struct Problem *P, enum PsiTypeTag IncType)
265{
266 struct RunStruct *R = &P->R;
267 if (R->CurrentMin != IncType) {
268 SetCurrentMinState(P,IncType);
269 R->PsiStep = R->MaxPsiStep; // force step to next Psi
270 }
271 P->Lat.Psi.AddData[R->ActualLocalPsiNo].Step++;
272 R->MinStep++;
273 R->PsiStep++;
274 if (R->OldActualLocalPsiNo != R->ActualLocalPsiNo) {
275 R->OldActualLocalPsiNo = R->ActualLocalPsiNo;
276 UpdateGramSchOldActualPsiNo(P, &P->Lat.Psi);
277 }
278 if (R->PsiStep >= R->MaxPsiStep) {
279 R->PsiStep=0;
280 do {
281 R->ActualLocalPsiNo++;
282 R->ActualLocalPsiNo %= P->Lat.Psi.LocalNo;
283 } while (P->Lat.Psi.AllPsiStatus[R->ActualLocalPsiNo].PsiType != IncType);
284 UpdateGramSchActualPsiNo(P, &P->Lat.Psi);
285 //fprintf(stderr,"(%i) ActualLocalNo: %d\n", P->Par.me, R->ActualLocalPsiNo);
286 }
287 if ((R->UseAddGramSch == 1 && (R->OldActualLocalPsiNo != R->ActualLocalPsiNo || P->Lat.Psi.NoOfPsis == 1)) || R->UseAddGramSch == 2) {
288 if (P->Lat.Psi.LocalPsiStatus[R->OldActualLocalPsiNo].PsiGramSchStatus != NotUsedToOrtho) // don't reset by accident last psi of former minimisation run
289 SetGramSchOldActualPsi(P, &P->Lat.Psi, NotOrthogonal);
290 SpeedMeasure(P, GramSchTime, StartTimeDo);
291 if (R->CurrentMin <= UnOccupied)
292 GramSch(P, R->LevS, &P->Lat.Psi, Orthonormalize);
293 else
294 GramSch(P, R->LevS, &P->Lat.Psi, Orthogonalize); //Orthogonalize
295 SpeedMeasure(P, GramSchTime, StopTimeDo);
296 }
297}
298
299/** Resets all OnePsiElement#DoBrent.\
300 * \param *P Problem at hand
301 * \param *Psi pointer to wave functions
302 */
303void ResetBrent(struct Problem *P, struct Psis *Psi) {
304 int i;
305 for (i=0; i< Psi->LocalNo; i++) {// set all PsiFactors to zero
306 //fprintf(stderr,"(%i) DoBrent[%i] = %i\n", P->Par.me, i, Psi->LocalPsiStatus[i].DoBrent);
307 if (Psi->LocalPsiStatus[i].PsiType == Occupied) Psi->LocalPsiStatus[i].DoBrent = 4;
308 }
309}
310
311/** Sets current minimisation state.
312 * Stores given \a state in RunStruct#CurrentMin and sets pointer Lattice#E accordingly.
313 * \param *P Problem at hand
314 * \param state given PsiTypeTag state
315 */
316void SetCurrentMinState(struct Problem *P, enum PsiTypeTag state) {
317 P->R.CurrentMin = state;
318 P->R.TotalEnergy = &(P->R.TE[state][0]);
319 P->R.KineticEnergy = &(P->R.KE[state][0]);
320 P->R.ActualRelTotalEnergy = &(P->R.ActualRelTE[state][0]);
321 P->R.ActualRelKineticEnergy = &(P->R.ActualRelKE[state][0]);
322 P->Lat.E = &(P->Lat.Energy[state]);
323}
324/*{
325 struct RunStruct *R = &P->R;
326 struct Lattice *Lat = &P->Lat;
327 struct Psis *Psi = &Lat->Psi;
328 P->Lat.Psi.AddData[R->ActualLocalPsiNo].Step++;
329 R->MinStep++;
330 R->PsiStep++;
331 if (R->OldActualLocalPsiNo != R->ActualLocalPsiNo) { // remember old actual local number
332 R->OldActualLocalPsiNo = R->ActualLocalPsiNo;
333 UpdateGramSchOldActualPsiNo(P, &P->Lat.Psi);
334 }
335 if (R->PsiStep >= R->MaxPsiStep) { // done enough minimisation steps for this orbital?
336 R->PsiStep=0;
337 do { // step on as long as we are still on a SkipType orbital
338 R->ActualLocalPsiNo++;
339 R->ActualLocalPsiNo %= P->Lat.Psi.LocalNo;
340 } while ((P->Lat.Psi.LocalPsiStatus[R->ActualLocalPsiNo].PsiType == SkipType));
341 UpdateGramSchActualPsiNo(P, &P->Lat.Psi);
342 if (R->UseAddGramSch >= 1) {
343 SetGramSchOldActualPsi(P,Psi,NotOrthogonal);
344 // setze von OldActual bis bla auf nicht orthogonal
345 GramSch(P, R->LevS, &P->Lat.Psi, Orthonormalize);
346 }
347 } else if (R->UseAddGramSch == 2) {
348 SetGramSchOldActualPsi(P, &P->Lat.Psi, NotOrthogonal);
349 //if (SkipType == UnOccupied)
350 //ResetGramSch(P,Psi);
351 //fprintf(stderr,"UpdateActualPsiNo: GramSch() for %i\n",R->OldActualLocalPsiNo);
352 GramSch(P, R->LevS, &P->Lat.Psi, Orthonormalize);
353 }
354}*/
355
356/** Upgrades the calculation to the next finer level.
357 * If we are below the initial level,
358 * ChangePsiAndDensToLevUp() prepares density and Psi coefficients.
359 * Then the level change is made as RunStruct::LevSNo and RunStruct::Lev0No are decreased.
360 * The RunStruct::OldActualLocalPsi is set to current one and both are distributed
361 * (UpdateGramSchActualPsiNo(), UpdateGramSchOldActualPsiNo()).
362 * The PseudoPot'entials adopt the level up by calling ChangePseudoToLevUp().
363 * Now we are prepared to reset Energy::PsiEnergy and local and total density energy and
364 * recalculate them: InitPsiEnergyCalculation(), CalculateDensityEnergy() and CalculateIonsEnergy().
365 * Results are gathered EnergyAllReduce() and the output made EnergyOutput().
366 * Finally, the stop condition are reset for the new level (depending if it's the STANDARTLEVEL or
367 * not).
368 * \param *P Problem at hand
369 * \param *Stop is set to zero if we are below or equal to init level (see CalculateForce())
370 * \sa UpdateToNewWaves() very similar in the procedure, only the update of the Psis and density
371 * (ChangePsiAndDensToLevUp()) is already made there.
372 * \bug Missing TotalEnergy shifting for other PsiTypeTag's!
373 */
374static void ChangeToLevUp(struct Problem *P, int *Stop)
375{
376 struct RunStruct *R = &P->R;
377 struct Lattice *Lat = &P->Lat;
378 struct Psis *Psi = &Lat->Psi;
379 struct Energy *E = Lat->E;
380 struct RiemannTensor *RT = &Lat->RT;
381 int i;
382 if (R->LevSNo <= R->InitLevSNo) {
383 if (P->Call.out[LeaderOut] && (P->Par.me == 0))
384 fprintf(stderr, "(%i) ChangeLevUp: LevSNo(%i) <= InitLevSNo(%i)\n", P->Par.me, R->LevSNo, R->InitLevSNo);
385 *Stop = 1;
386 return;
387 }
388 if (P->Call.out[LeaderOut] && (P->Par.me == 0))
389 fprintf(stderr, "(0) ChangeLevUp: LevSNo(%i) InitLevSNo(%i)\n", R->LevSNo, R->InitLevSNo);
390 *Stop = 0;
391 P->Speed.LevUpSteps++;
392 SpeedMeasure(P, SimTime, StopTimeDo);
393 SpeedMeasure(P, InitSimTime, StartTimeDo);
394 SpeedMeasure(P, InitDensityTime, StartTimeDo);
395 ChangePsiAndDensToLevUp(P);
396 SpeedMeasure(P, InitDensityTime, StopTimeDo);
397 R->LevSNo--;
398 R->Lev0No--;
399 if (RT->ActualUse == standby && R->LevSNo == STANDARTLEVEL) {
400 P->Lat.RT.ActualUse = active;
401 CalculateRiemannTensorData(P);
402 Error(SomeError, "Calculate RT: Not further implemented");
403 }
404 R->LevS = &P->Lat.Lev[R->LevSNo];
405 R->Lev0 = &P->Lat.Lev[R->Lev0No];
406 R->OldActualLocalPsiNo = R->ActualLocalPsiNo;
407 UpdateGramSchActualPsiNo(P, &P->Lat.Psi);
408 UpdateGramSchOldActualPsiNo(P, &P->Lat.Psi);
409 ResetBrent(P, &P->Lat.Psi);
410 R->PsiStep=0;
411 R->MinStep=0;
412 P->Grad.GradientArray[GraSchGradient] = R->LevS->LPsi->LocalPsi[Psi->LocalNo];
413 ChangePseudoToLevUp(P);
414 for (i=0; i<MAXALLPSIENERGY; i++)
415 SetArrayToDouble0(E->PsiEnergy[i], Psi->LocalNo);
416 SetArrayToDouble0(E->AllLocalDensityEnergy, MAXALLDENSITYENERGY);
417 SetArrayToDouble0(E->AllTotalDensityEnergy, MAXALLDENSITYENERGY);
418 for (i=MAXOLD-1; i > 0; i--) {
419 E->TotalEnergy[i] = E->TotalEnergy[i-1];
420 Lat->Energy[UnOccupied].TotalEnergy[i] = Lat->Energy[UnOccupied].TotalEnergy[i-1];
421 }
422 InitPsiEnergyCalculation(P,Occupied);
423 CalculateDensityEnergy(P,1);
424 CalculateIonsEnergy(P);
425 EnergyAllReduce(P);
426/* SetCurrentMinState(P,UnOccupied);
427 InitPsiEnergyCalculation(P,UnOccupied);
428 CalculateGapEnergy(P);
429 EnergyAllReduce(P);
430 SetCurrentMinState(P,Occupied);*/
431 EnergyOutput(P,0);
432 if (R->LevSNo == STANDARTLEVEL) {
433 R->ActualMaxMinStep = R->MaxMinStep*R->MaxPsiStep*R->MaxMinStepFactor;
434 R->ActualRelEpsTotalEnergy = R->RelEpsTotalEnergy;
435 R->ActualRelEpsKineticEnergy = R->RelEpsKineticEnergy;
436 R->ActualMaxMinStopStep = R->MaxMinStopStep;
437 R->ActualMaxMinGapStopStep = R->MaxMinGapStopStep;
438 } else {
439 R->ActualMaxMinStep = R->MaxInitMinStep*R->MaxPsiStep*R->MaxMinStepFactor;
440 R->ActualRelEpsTotalEnergy = R->InitRelEpsTotalEnergy;
441 R->ActualRelEpsKineticEnergy = R->InitRelEpsKineticEnergy;
442 R->ActualMaxMinStopStep = R->InitMaxMinStopStep;
443 R->ActualMaxMinGapStopStep = R->InitMaxMinGapStopStep;
444 }
445 R->MinStopStep = 0;
446 SpeedMeasure(P, InitSimTime, StopTimeDo);
447 SpeedMeasure(P, SimTime, StartTimeDo);
448 if (P->Call.out[LeaderOut] && (P->Par.me == 0))
449 fprintf(stderr, "(0) ChangeLevUp: LevSNo(%i) InitLevSNo(%i) Done\n", R->LevSNo, R->InitLevSNo);
450}
451
452/** Updates after the wave functions have changed (e.g.\ Ion moved).
453 * Old and current RunStruct::ActualLocalPsiNo are zeroed and distributed among the processes.
454 * InitDensityCalculation() is called, afterwards the pseudo potentials update to the new
455 * wave functions UpdatePseudoToNewWaves().
456 * Energy::AllLocalDensityEnergy, Energy::AllTotalDensityEnergy, Energy::AllTotalIonsEnergy and
457 * Energy::PsiEnergy[i] are set to zero.
458 * We are set to recalculate all of the following energies: Psis InitPsiEnergyCalculation(), density
459 * CalculateDensityEnergy(), ionic CalculateIonsEnergy() and ewald CalculateEwald().
460 * Results are gathered from all processes EnergyAllReduce() and EnergyOutput() is called.
461 * Finally, the various conditons in the RunStruct for stopping the calculation are set: number of
462 * minimisation steps, relative total or kinetic energy change or how often stop condition was
463 * evaluated.
464 * \param *P Problem at hand
465 */
466static void UpdateToNewWaves(struct Problem *P)
467{
468 struct RunStruct *R = &P->R;
469 struct Lattice *Lat = &P->Lat;
470 struct Psis *Psi = &Lat->Psi;
471 struct Energy *E = Lat->E;
472 int i,type;
473 R->OldActualLocalPsiNo = R->ActualLocalPsiNo = 0;
474 //if (isnan((double)R->LevS->LPsi->LocalPsi[R->OldActualLocalPsiNo][0].re)) { fprintf(stderr,"(%i) WARNING in UpdateGramSchActualPsiNo(): LPsi->LocalPsi[%i]_[%i] = NaN!\n", P->Par.me, R->OldActualLocalPsiNo, 0); Error(SomeError, "NaN-Fehler!"); }
475 UpdateGramSchActualPsiNo(P, &P->Lat.Psi);
476 UpdateGramSchOldActualPsiNo(P, &P->Lat.Psi);
477 R->PsiStep=0;
478 R->MinStep=0;
479 SpeedMeasure(P, InitDensityTime, StartTimeDo);
480 //if (isnan((double)R->LevS->LPsi->LocalPsi[R->OldActualLocalPsiNo][0].re)) { fprintf(stderr,"(%i) WARNING in Update../InitDensityCalculation(): LPsi->LocalPsi[%i]_[%i] = NaN!\n", P->Par.me, R->OldActualLocalPsiNo, 0); Error(SomeError, "NaN-Fehler!"); }
481 InitDensityCalculation(P);
482 SpeedMeasure(P, InitDensityTime, StopTimeDo);
483 UpdatePseudoToNewWaves(P);
484 for (i=0; i<MAXALLPSIENERGY; i++)
485 SetArrayToDouble0(E->PsiEnergy[i], Psi->LocalNo);
486 SetArrayToDouble0(E->AllLocalDensityEnergy, MAXALLDENSITYENERGY);
487 SetArrayToDouble0(E->AllTotalDensityEnergy, MAXALLDENSITYENERGY);
488 SetArrayToDouble0(E->AllTotalIonsEnergy, MAXALLIONSENERGY);
489 InitPsiEnergyCalculation(P,Occupied);
490 CalculateDensityEnergy(P,1);
491 CalculateIonsEnergy(P);
492 CalculateEwald(P, 0);
493 EnergyAllReduce(P);
494 if (R->DoUnOccupied) {
495 SetCurrentMinState(P,UnOccupied);
496 InitPsiEnergyCalculation(P,UnOccupied); /* STANDARTLEVEL */
497 CalculateGapEnergy(P); /* STANDARTLEVEL */
498 EnergyAllReduce(P);
499 }
500 if (R->DoPerturbation)
501 for(type=Perturbed_P0;type <=Perturbed_RxP2;type++) {
502 SetCurrentMinState(P,type);
503 InitPerturbedEnergyCalculation(P,1); /* STANDARTLEVEL */
504 EnergyAllReduce(P);
505 }
506 SetCurrentMinState(P,Occupied);
507 E->TotalEnergyOuter[0] = E->TotalEnergy[0];
508 EnergyOutput(P,0);
509 R->ActualMaxMinStep = R->MaxMinStep*R->MaxPsiStep*R->MaxMinStepFactor;
510 R->ActualRelEpsTotalEnergy = R->RelEpsTotalEnergy;
511 R->ActualRelEpsKineticEnergy = R->RelEpsKineticEnergy;
512 R->ActualMaxMinStopStep = R->MaxMinStopStep;
513 R->ActualMaxMinGapStopStep = R->MaxMinGapStopStep;
514 R->MinStopStep = 0;
515}
516
517/** Evaluates the stop condition and returns 0 or 1 for occupied states.
518 * Stop is set when:
519 * - SuperStop at best possible point (e.g.\ LevelChange): RunStruct::PsiStep == 0 && SuperStop == 1
520 * - RunStruct::PsiStep && RunStruct::MinStopStep modulo RunStruct::ActualMaxMinStopStep == 0
521 * - To many minimisation steps: RunStruct::MinStep > RunStruct::ActualMaxMinStopStep
522 * - below relative rate of change:
523 * - Remember old values: Shift all RunStruct::TotalEnergy and RunStruct::KineticEnergy by
524 * one and transfer current one from Energy::TotalEnergy and Energy::AllTotalPsiEnergy[KineticEnergy].
525 * - if more than one minimisation step was made, calculate the relative changes of total
526 * energy and kinetic energy and store them in RunStruct::ActualRelTotalEnergy and
527 * RunStruct::ActualRelKineticEnergy and check them against the sought for minimum
528 * values RunStruct::ActualRelEpsTotalEnergy and RunStruct::ActualRelEpsKineticEnergy.
529 * - if RunStruct::PsiStep is zero (default), increase RunStruct::MinStopStep
530 * \param *P Problem at hand
531 * \param SuperStop 1 - external signal: ceasing calculation, 0 - no signal
532 * \return Stop: 1 - stop, 0 - continue
533 */
534int CalculateMinimumStop(struct Problem *P, int SuperStop)
535{
536 int Stop = 0, i;
537 struct RunStruct *R = &P->R;
538 struct Energy *E = P->Lat.E;
539 if (R->PsiStep == 0 && SuperStop) Stop = 1;
540 if (R->PsiStep == 0 && ((R->MinStopStep % R->ActualMaxMinStopStep == 0 && R->CurrentMin != UnOccupied) || (R->MinStopStep % R->ActualMaxMinGapStopStep == 0 && R->CurrentMin == UnOccupied))) {
541// if (R->MinStep >= R->ActualMaxMinStep) {
542// Stop = 1;
543// fprintf(stderr,"(%i) MinStep %i >= %i MaxMinStep.\n", P->Par.me, R->MinStep, R->ActualMaxMinStep);
544// }
545 for (i=RUNMAXOLD-1; i > 0; i--) {
546 R->TotalEnergy[i] = R->TotalEnergy[i-1];
547 R->KineticEnergy[i] = R->KineticEnergy[i-1];
548 }
549 R->TotalEnergy[0] = E->TotalEnergy[0];
550 R->KineticEnergy[0] = E->AllTotalPsiEnergy[KineticEnergy];
551 if (R->MinStopStep) {
552 //if (R->TotalEnergy[1] < MYEPSILON) fprintf(stderr,"CalculateMinimumStop: R->TotalEnergy[1] = %lg\n",R->TotalEnergy[1]);
553 R->ActualRelTotalEnergy[0] = fabs((R->TotalEnergy[0]-R->TotalEnergy[1])/R->TotalEnergy[1]);
554 //if (R->KineticEnergy[1] < MYEPSILON) fprintf(stderr,"CalculateMinimumStop: R->KineticEnergy[1] = %lg\n",R->KineticEnergy[1]);
555 //if (R->CurrentMin < Perturbed_P0)
556 R->ActualRelKineticEnergy[0] = fabs((R->KineticEnergy[0]-R->KineticEnergy[1])/R->KineticEnergy[1]);
557 //else R->ActualRelKineticEnergy[0] = 0.;
558 if (P->Call.out[LeaderOut] && (P->Par.me == 0))
559 switch (R->CurrentMin) {
560 default:
561 fprintf(stderr, "ARelTE: %e\tARelKE: %e\n", R->ActualRelTotalEnergy[0], R->ActualRelKineticEnergy[0]);
562 break;
563 case UnOccupied:
564 fprintf(stderr, "ARelTGE: %e\tARelKGE: %e\n", R->ActualRelTotalEnergy[0], R->ActualRelKineticEnergy[0]);
565 break;
566 }
567 if ((R->ActualRelTotalEnergy[0] < R->ActualRelEpsTotalEnergy) &&
568 (R->ActualRelKineticEnergy[0] < R->ActualRelEpsKineticEnergy))
569 Stop = 1;
570 }
571 }
572 if (R->PsiStep == 0)
573 R->MinStopStep++;
574 if (P->Call.WriteSrcFiles == 2)
575 OutputVisSrcFiles(P, R->CurrentMin);
576 return(Stop);
577}
578
579/** Evaluates the stop condition and returns 0 or 1 for gap energies.
580 * Stop is set when:
581 * - SuperStop at best possible point (e.g.\ LevelChange): RunStruct::PsiStep == 0 && SuperStop == 1
582 * - RunStruct::PsiStep && RunStruct::MinStopStep modulo RunStruct::ActualMaxMinStopStep == 0
583 * - To many minimisation steps: RunStruct::MinStep > RunStruct::ActualMaxMinStopStep
584 * - below relative rate of change:
585 * - Remember old values: Shift all RunStruct::TotalEnergy and RunStruct::KineticEnergy by
586 * one and transfer current one from Energy::TotalEnergy and Energy::AllTotalPsiEnergy[KineticEnergy].
587 * - if more than one minimisation step was made, calculate the relative changes of total
588 * energy and kinetic energy and store them in RunStruct::ActualRelTotalEnergy and
589 * RunStruct::ActualRelKineticEnergy and check them against the sought for minimum
590 * values RunStruct::ActualRelEpsTotalEnergy and RunStruct::ActualRelEpsKineticEnergy.
591 * - if RunStruct::PsiStep is zero (default), increase RunStruct::MinStopStep
592 * \param *P Problem at hand
593 * \param SuperStop 1 - external signal: ceasing calculation, 0 - no signal
594 * \return Stop: 1 - stop, 0 - continue
595 * \sa CalculateMinimumStop() - same procedure for occupied states
596 *//*
597static double CalculateGapStop(struct Problem *P, int SuperStop)
598{
599 int Stop = 0, i;
600 struct RunStruct *R = &P->R;
601 struct Lattice *Lat = &P->Lat;
602 struct Energy *E = P->Lat.E;
603 if (R->PsiStep == 0 && SuperStop) Stop = 1;
604 if (R->PsiStep == 0 && (R->MinStopStep % R->ActualMaxMinGapStopStep) == 0) {
605 if (R->MinStep >= R->ActualMaxMinStep) Stop = 1;
606 for (i=RUNMAXOLD-1; i > 0; i--) {
607 R->TotalGapEnergy[i] = R->TotalGapEnergy[i-1];
608 R->KineticGapEnergy[i] = R->KineticGapEnergy[i-1];
609 }
610 R->TotalGapEnergy[0] = Lat->Energy[UnOccupied].TotalEnergy[0];
611 R->KineticGapEnergy[0] = E->AllTotalPsiEnergy[GapPsiEnergy];
612 if (R->MinStopStep) {
613 if (R->TotalGapEnergy[1] < MYEPSILON) fprintf(stderr,"CalculateMinimumStop: R->TotalGapEnergy[1] = %lg\n",R->TotalGapEnergy[1]);
614 R->ActualRelTotalGapEnergy[0] = fabs((R->TotalGapEnergy[0]-R->TotalGapEnergy[1])/R->TotalGapEnergy[1]);
615 if (R->KineticGapEnergy[1] < MYEPSILON) fprintf(stderr,"CalculateMinimumStop: R->KineticGapEnergy[1] = %lg\n",R->KineticGapEnergy[1]);
616 R->ActualRelKineticGapEnergy[0] = fabs((R->KineticGapEnergy[0]-R->KineticGapEnergy[1])/R->KineticGapEnergy[1]);
617 if (P->Call.out[LeaderOut] && (P->Par.me == 0))
618 fprintf(stderr, "(%i) -------------------------> ARelTGE: %e\tARelKGE: %e\n", P->Par.me, R->ActualRelTotalGapEnergy[0], R->ActualRelKineticGapEnergy[0]);
619 if ((R->ActualRelTotalGapEnergy[0] < R->ActualRelEpsTotalGapEnergy) &&
620 (R->ActualRelKineticGapEnergy[0] < R->ActualRelEpsKineticGapEnergy))
621 Stop = 1;
622 }
623 }
624 if (R->PsiStep == 0)
625 R->MinStopStep++;
626
627 return(Stop);
628}*/
629
630#define StepTolerance 1e-4
631
632static void CalculateEnergy(struct Problem *P) {
633 SpeedMeasure(P, DensityTime, StartTimeDo);
634 UpdateDensityCalculation(P);
635 SpeedMeasure(P, DensityTime, StopTimeDo);
636 UpdatePsiEnergyCalculation(P);
637 CalculateDensityEnergy(P, 0);
638 //CalculateIonsEnergy(P);
639 EnergyAllReduce(P);
640}
641
642/** Energy functional depending on one parameter \a x (for a certain Psi in a certain conjugate direction).
643 * \param x parameter for the which the function must be minimized
644 * \param *params additional params
645 * \return total energy if Psi is changed according to the given parameter
646 */
647static double fn1 (double x, void * params) {
648 struct Problem *P = (struct Problem *)(params);
649 struct RunStruct *R = &P->R;
650 struct Lattice *Lat = &P->Lat;
651 struct LatticeLevel *LevS = R->LevS;
652 int ElementSize = (sizeof(fftw_complex) / sizeof(double));
653 int i=R->ActualLocalPsiNo;
654 double ret;
655
656 //fprintf(stderr,"(%i) Evaluating fnl at %lg ...\n",P->Par.me, x);
657 //TestForOrth(P,R->LevS,P->Grad.GradientArray[GraSchGradient]);
658 CalculateNewWave(P, &x); // also stores Psi to oldPsi
659 //TestGramSch(P,R->LevS,&P->Lat.Psi,Occupied);
660 //fprintf(stderr,"(%i) Testing for orthogonality of %i against ...\n",P->Par.me, R->ActualLocalPsiNo);
661 //TestForOrth(P, LevS, LevS->LPsi->LocalPsi[R->ActualLocalPsiNo]);
662 //UpdateActualPsiNo(P, Occupied);
663 //UpdateEnergyArray(P);
664 CalculateEnergy(P);
665 ret = Lat->E->TotalEnergy[0];
666 memcpy(LevS->LPsi->LocalPsi[i], LevS->LPsi->OldLocalPsi[i], ElementSize*LevS->MaxG*sizeof(double)); // restore old Psi from OldPsi
667 //fprintf(stderr,"(%i) Psi %i at %p retrieved from OldPsi at %p: Old[0] %lg+i%lg\n", P->Par.me, R->ActualLocalPsiNo, LevS->LPsi->LocalPsi[R->ActualLocalPsiNo], LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo], LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo][0].re, LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo][0].im);
668 CalculateEnergy(P);
669 //fprintf(stderr,"(%i) fnl(%lg) = %lg\n", P->Par.me, x, ret);
670 return ret;
671}
672
673#ifdef HAVE_INLINE
674inline void flip(double *a, double *b) {
675#else
676void flip(double *a, double *b) {
677#endif
678 double tmp = *a;
679 *a = *b;
680 *b = tmp;
681}
682
683
684/** Minimise PsiType#Occupied orbitals.
685 * It is checked whether CallOptions#ReadSrcFiles is set and thus coefficients for the level have to be
686 * read from file and afterwards initialized.
687 *
688 * Then follows the main loop, until a stop condition is met:
689 * -# CalculateNewWave()\n
690 * Over a conjugate gradient method the next (minimal) wave function is sought for.
691 * -# UpdateActualPsiNo()\n
692 * Switch local Psi to next one.
693 * -# UpdateEnergyArray()\n
694 * Shift archived energy values to make space for next one.
695 * -# UpdateDensityCalculation(), SpeedMeasure()'d in DensityTime\n
696 * Calculate TotalLocalDensity of LocalPsis and gather results as TotalDensity.
697 * -# UpdatePsiEnergyCalculation()\n
698 * Calculate kinetic and non-local energy contributons from the Psis.
699 * -# CalculateDensityEnergy()\n
700 * Calculate remaining energy contributions from the Density and adds \f$V_xc\f$ onto DensityTypes#HGDensity.
701 * -# CalculateIonsEnergy()\n
702 * Calculate the Gauss self energy of the Ions.
703 * -# EnergyAllReduce()\n
704 * Gather PsiEnergy results from all processes and sum up together with all other contributions to TotalEnergy.
705 * -# CheckCPULIM()\n
706 * Check if external signal has been received (e.g. end of time slit on cluster), break operation at next possible moment.
707 * -# CalculateMinimumStop()\n
708 * Evaluates stop condition if desired precision or steps or ... have been reached. Otherwise go to
709 * CalculateNewWave().
710 *
711 * Before return orthonormality is tested.
712 * \param *P Problem at hand
713 * \param *Stop flag to determine if epsilon stop conditions have met
714 * \param *SuperStop flag to determinte whether external signal's required end of calculations
715 */
716static void MinimiseOccupied(struct Problem *P, int *Stop, int *SuperStop)
717{
718 struct RunStruct *R = &P->R;
719 struct Lattice *Lat = &P->Lat;
720 struct Psis *Psi = &Lat->Psi;
721 //struct FileData *F = &P->Files;
722// int i;
723// double norm;
724 //double dEdt0,ddEddt0,HartreeddEddt0,XCddEddt0, d[4], D[4],ConDirHConDir;
725 struct LatticeLevel *LevS = R->LevS;
726 int ElementSize = (sizeof(fftw_complex) / sizeof(double));
727 int iter = 0, status, max_iter=10;
728 const gsl_min_fminimizer_type *T;
729 gsl_min_fminimizer *s;
730 double m, a, b;
731 double f_m = 0., f_a, f_b;
732 double dcos, dsin;
733 int g;
734 fftw_complex *ConDir = P->Grad.GradientArray[ConDirGradient];
735 fftw_complex *source = NULL, *oldsource = NULL;
736 gsl_function F;
737 F.function = &fn1;
738 F.params = (void *) P;
739 T = gsl_min_fminimizer_brent;
740 s = gsl_min_fminimizer_alloc (T);
741 int DoBrent, StartLocalPsiNo;
742
743 ResetBrent(P,Psi);
744 *Stop = 0;
745 if (P->Call.ReadSrcFiles) {
746 if (!ReadSrcPsiDensity(P,Occupied,1, R->LevSNo)) { // if file for level exists and desired, read from file
747 P->Call.ReadSrcFiles = 0; // -r was bogus, remove it, have to start anew
748 if(P->Call.out[MinOut]) fprintf(stderr,"(%i) Re-initializing, files are missing/corrupted...\n", P->Par.me);
749 InitPsisValue(P, Psi->TypeStartIndex[Occupied], Psi->TypeStartIndex[Occupied+1]); // initialize perturbed array for this run
750 ResetGramSchTagType(P, Psi, Occupied, NotOrthogonal); // loaded values are orthonormal
751 SpeedMeasure(P, InitGramSchTime, StartTimeDo);
752 GramSch(P, R->LevS, Psi, Orthonormalize);
753 SpeedMeasure(P, InitGramSchTime, StopTimeDo);
754 } else {
755 SpeedMeasure(P, InitSimTime, StartTimeDo);
756 if(P->Call.out[MinOut]) fprintf(stderr,"(%i) Reading from file...\n", P->Par.me);
757 ReadSrcPsiDensity(P, Occupied, 0, R->LevSNo);
758 ResetGramSchTagType(P, Psi, Occupied, IsOrthonormal); // loaded values are orthonormal
759 }
760 SpeedMeasure(P, InitDensityTime, StartTimeDo);
761 InitDensityCalculation(P);
762 SpeedMeasure(P, InitDensityTime, StopTimeDo);
763 InitPsiEnergyCalculation(P, Occupied); // go through all orbitals calculating kinetic and non-local
764 StartLocalPsiNo = R->ActualLocalPsiNo;
765 do { // otherwise OnePsiElementAddData#Lambda is calculated only for current Psi not for all
766 CalculateDensityEnergy(P, 0);
767 UpdateActualPsiNo(P, Occupied);
768 } while (R->ActualLocalPsiNo != StartLocalPsiNo);
769 CalculateIonsEnergy(P);
770 EnergyAllReduce(P);
771 SpeedMeasure(P, InitSimTime, StopTimeDo);
772 R->LevS->Step++;
773 EnergyOutput(P,0);
774 }
775 if (P->Call.ReadSrcFiles != 1) { // otherwise minimise oneself
776 if(P->Call.out[LeaderOut]) fprintf(stderr,"(%i)Beginning minimisation of type %s ...\n", P->Par.me, R->MinimisationName[Occupied]);
777 while (*Stop != 1) { // loop testing condition over all Psis
778 // in the following loop, we have two cases:
779 // 1) still far away and just guessing: Use the normal CalculateNewWave() to improve Psi
780 // 2) closer (DoBrent=-1): use brent line search instead
781 // and due to these two cases, we also have two ifs inside each in order to catch stepping from one case
782 // to the other - due to decreasing DoBrent and/or stepping to the next Psi (which may not yet be DoBrent==1)
783
784 // case 1)
785 if (Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent != 1) {
786 //SetArrayToDouble0((double *)LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo],LevS->MaxG*2);
787 memcpy(LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo], LevS->LPsi->LocalPsi[R->ActualLocalPsiNo], ElementSize*LevS->MaxG*sizeof(double)); // restore old Psi from OldPsi
788 //fprintf(stderr,"(%i) Psi %i at %p stored in OldPsi at %p: Old[0] %lg+i%lg\n", P->Par.me, R->ActualLocalPsiNo, LevS->LPsi->LocalPsi[R->ActualLocalPsiNo], LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo], LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo][0].re, LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo][0].im);
789 f_m = P->Lat.E->TotalEnergy[0]; // grab first value
790 m = 0.;
791 CalculateNewWave(P,NULL);
792 if ((R->DoBrent == 1) && (fabs(Lat->E->delta[0]) < M_PI/4.))
793 Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent--;
794 if (Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent != 1) {
795 UpdateActualPsiNo(P, Occupied);
796 UpdateEnergyArray(P);
797 CalculateEnergy(P); // just to get a sensible delta
798 if ((R->ActualLocalPsiNo != R->OldActualLocalPsiNo) && (Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent == 1)) {
799 R->OldActualLocalPsiNo = R->ActualLocalPsiNo;
800 // if we stepped on to a new Psi, which is already down at DoBrent=1 unlike the last one,
801 // then an up-to-date gradient is missing for the following Brent line search
802 if(P->Call.out[LeaderOut]) fprintf(stderr,"(%i) We stepped on to a new Psi, which is already in the Brent regime ...re-calc delta\n", P->Par.me);
803 memcpy(LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo], LevS->LPsi->LocalPsi[R->ActualLocalPsiNo], ElementSize*LevS->MaxG*sizeof(double)); // restore old Psi from OldPsi
804 //fprintf(stderr,"(%i) Psi %i at %p stored in OldPsi at %p: Old[0] %lg+i%lg\n", P->Par.me, R->ActualLocalPsiNo, LevS->LPsi->LocalPsi[R->ActualLocalPsiNo], LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo], LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo][0].re, LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo][0].im);
805 f_m = P->Lat.E->TotalEnergy[0]; // grab first value
806 m = 0.;
807 DoBrent = Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent;
808 Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent = 2;
809 CalculateNewWave(P,NULL);
810 Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent = DoBrent;
811 }
812 //fprintf(stderr,"(%i) fnl(%lg) = %lg\n", P->Par.me, m, f_m);
813 }
814 }
815
816 // case 2)
817 if (Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent == 1) {
818 R->PsiStep=R->MaxPsiStep; // no more fresh gradients from this point for current ActualLocalPsiNo
819 a = b = 0.5*fabs(Lat->E->delta[0]);
820 // we have a meaningful first minimum guess from above CalculateNewWave() resp. from end of this if of last step: Lat->E->delta[0]
821 source = LevS->LPsi->LocalPsi[R->ActualLocalPsiNo];
822 oldsource = LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo];
823 //SetArrayToDouble0((double *)source,LevS->MaxG*2);
824 do {
825 a -= fabs(Lat->E->delta[0]) == 0 ? 0.1 : fabs(Lat->E->delta[0]);
826 if (a < -M_PI/2.) a = -M_PI/2.;// for this to work we need the pre-estimation which leads us into a nice regime (without gradient being the better _initial_ guess for a Psi)
827 dcos = cos(a);
828 dsin = sin(a);
829 for (g = 0; g < LevS->MaxG; g++) { // Here all coefficients are updated for the new found wave function
830 //if (isnan(ConDir[g].re)) { fprintf(stderr,"WARNGING: CalculateLineSearch(): ConDir_%i(%i) = NaN!\n", R->ActualLocalPsiNo, g); Error(SomeError, "NaN-Fehler!"); }
831 c_re(source[g]) = c_re(oldsource[g])*dcos + c_re(ConDir[g])*dsin;
832 c_im(source[g]) = c_im(oldsource[g])*dcos + c_im(ConDir[g])*dsin;
833 }
834 CalculateEnergy(P);
835 f_a = P->Lat.E->TotalEnergy[0]; // grab second value at left border
836 //fprintf(stderr,"(%i) fnl(%lg) = %lg, Check ConDir[0] = %lg+i%lg, source[0] = %lg+i%lg, oldsource[0] = %lg+i%lg, TotDens[0] = %lg\n", P->Par.me, a, f_a, ConDir[0].re, ConDir[0].im, source[0].re, source[0].im, oldsource[0].re, oldsource[0].im, R->Lev0->Dens->DensityArray[TotalDensity][0]);
837 } while (f_a < f_m);
838
839 //SetArrayToDouble0((double *)source,LevS->MaxG*2);
840 do {
841 b += fabs(Lat->E->delta[0]) == 0 ? 0.1 : fabs(Lat->E->delta[0]);
842 if (b > M_PI/2.) b = M_PI/2.;
843 dcos = cos(b);
844 dsin = sin(b);
845 for (g = 0; g < LevS->MaxG; g++) { // Here all coefficients are updated for the new found wave function
846 //if (isnan(ConDir[g].re)) { fprintf(stderr,"WARNGING: CalculateLineSearch(): ConDir_%i(%i) = NaN!\n", R->ActualLocalPsiNo, g); Error(SomeError, "NaN-Fehler!"); }
847 c_re(source[g]) = c_re(oldsource[g])*dcos + c_re(ConDir[g])*dsin;
848 c_im(source[g]) = c_im(oldsource[g])*dcos + c_im(ConDir[g])*dsin;
849 }
850 CalculateEnergy(P);
851 f_b = P->Lat.E->TotalEnergy[0]; // grab second value at left border
852 //fprintf(stderr,"(%i) fnl(%lg) = %lg\n", P->Par.me, b, f_b);
853 } while (f_b < f_m);
854
855 memcpy(source, oldsource, ElementSize*LevS->MaxG*sizeof(double)); // restore old Psi from OldPsi
856 //fprintf(stderr,"(%i) Psi %i at %p retrieved from OldPsi at %p: Old[0] %lg+i%lg\n", P->Par.me, R->ActualLocalPsiNo, LevS->LPsi->LocalPsi[R->ActualLocalPsiNo], LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo], LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo][0].re, LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo][0].im);
857 CalculateEnergy(P);
858
859 if(P->Call.out[ValueOut]) fprintf(stderr,"(%i) Preparing brent with f(a) (%lg,%lg)\t f(b) (%lg,%lg)\t f(m) (%lg,%lg) ...\n", P->Par.me,a,f_a,b,f_b,m,f_m);
860 iter=0;
861 gsl_min_fminimizer_set_with_values (s, &F, m, f_m, a, f_a, b, f_b);
862 if(P->Call.out[ValueOut]) fprintf (stderr,"(%i) using %s method\n",P->Par.me, gsl_min_fminimizer_name (s));
863 if(P->Call.out[ValueOut]) fprintf (stderr,"(%i) %5s [%9s, %9s] %9s %9s\n",P->Par.me, "iter", "lower", "upper", "min", "err(est)");
864 if(P->Call.out[ValueOut]) fprintf (stderr,"(%i) %5d [%.7f, %.7f] %.7f %.7f\n",P->Par.me, iter, a, b, m, b - a);
865 do {
866 iter++;
867 status = gsl_min_fminimizer_iterate (s);
868
869 m = gsl_min_fminimizer_x_minimum (s);
870 a = gsl_min_fminimizer_x_lower (s);
871 b = gsl_min_fminimizer_x_upper (s);
872
873 status = gsl_min_test_interval (a, b, 0.001, 0.0);
874
875 if (status == GSL_SUCCESS)
876 if(P->Call.out[ValueOut]) fprintf (stderr,"(%i) Converged:\n",P->Par.me);
877
878 if(P->Call.out[ValueOut]) fprintf (stderr,"(%i) %5d [%.7f, %.7f] %.7f %.7f\n",P->Par.me,
879 iter, a, b, m, b - a);
880 } while (status == GSL_CONTINUE && iter < max_iter);
881 CalculateNewWave(P,&m);
882 TestGramSch(P,LevS,Psi,Occupied);
883 UpdateActualPsiNo(P, Occupied); // step on due setting to MaxPsiStep further above
884 UpdateEnergyArray(P);
885 CalculateEnergy(P);
886 //fprintf(stderr,"(%i) Final value for Psi %i: %lg\n", P->Par.me, R->ActualLocalPsiNo, P->Lat.E->TotalEnergy[0]);
887 R->MinStopStep = R->ActualMaxMinStopStep; // check stop condition every time
888 if (*SuperStop != 1)
889 *SuperStop = CheckCPULIM(P);
890 *Stop = CalculateMinimumStop(P, *SuperStop);
891 R->OldActualLocalPsiNo = R->ActualLocalPsiNo;
892 if (Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent == 1) { // new wave function means new gradient!
893 DoBrent = Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent;
894 Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent = 2;
895 //SetArrayToDouble0((double *)LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo],LevS->MaxG*2);
896 memcpy(LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo], LevS->LPsi->LocalPsi[R->ActualLocalPsiNo], ElementSize*LevS->MaxG*sizeof(double)); // restore old Psi from OldPsi
897 //fprintf(stderr,"(%i) Psi %i at %p stored in OldPsi at %p: Old[0] %lg+i%lg\n", P->Par.me, R->ActualLocalPsiNo, LevS->LPsi->LocalPsi[R->ActualLocalPsiNo], LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo], LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo][0].re, LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo][0].im);
898 f_m = P->Lat.E->TotalEnergy[0]; // grab first value
899 m = 0.;
900 CalculateNewWave(P,NULL);
901 Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent = DoBrent;
902 }
903 }
904
905 if (Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent != 1) { // otherwise the following checks eliminiate stop=1 from above
906 if (*SuperStop != 1)
907 *SuperStop = CheckCPULIM(P);
908 *Stop = CalculateMinimumStop(P, *SuperStop);
909 }
910 /*EnergyOutput(P, Stop);*/
911 P->Speed.Steps++;
912 R->LevS->Step++;
913 /*ControlNativeDensity(P);*/
914 //fprintf(stderr,"(%i) Stop %i\n",P->Par.me, Stop);
915 }
916 //OutputVisSrcFiles(P, Occupied); // is now done after localization (ComputeMLWF())
917 }
918 TestGramSch(P,R->LevS,Psi, Occupied);
919}
920
921/** Minimisation of the PsiTagType#UnOccupied orbitals in the field of the occupied ones.
922 * Assuming RunStruct#ActualLocalPsiNo is currenlty still an occupied wave function, we stop onward to the first
923 * unoccupied and reset RunStruct#OldActualLocalPsiNo. Then it is checked whether CallOptions#ReadSrcFiles is set
924 * and thus coefficients for the level have to be read from file and afterwards initialized.
925 *
926 * Then follows the main loop, until a stop condition is met:
927 * -# CalculateNewWave()\n
928 * Over a conjugate gradient method the next (minimal) wave function is sought for.
929 * -# UpdateActualPsiNo()\n
930 * Switch local Psi to next one.
931 * -# UpdateEnergyArray()\n
932 * Shift archived energy values to make space for next one.
933 * -# UpdateDensityCalculation(), SpeedMeasure()'d in DensityTime\n
934 * Calculate TotalLocalDensity of LocalPsis and gather results as TotalDensity.
935 * -# UpdatePsiEnergyCalculation()\n
936 * Calculate kinetic and non-local energy contributons from the Psis.
937 * -# CalculateGapEnergy()\n
938 * Calculate Gap energies (Hartreepotential, Pseudo) and the gradient.
939 * -# EnergyAllReduce()\n
940 * Gather PsiEnergy results from all processes and sum up together with all other contributions to TotalEnergy.
941 * -# CheckCPULIM()\n
942 * Check if external signal has been received (e.g. end of time slit on cluster), break operation at next possible moment.
943 * -# CalculateMinimumStop()\n
944 * Evaluates stop condition if desired precision or steps or ... have been reached. Otherwise go to
945 * CalculateNewWave().
946 *
947 * Afterwards, the coefficients are written to file by OutputVisSrcFiles() if desired. Orthonormality is tested, we step
948 * back to the occupied wave functions and the densities are re-initialized.
949 * \param *P Problem at hand
950 * \param *Stop flag to determine if epsilon stop conditions have met
951 * \param *SuperStop flag to determinte whether external signal's required end of calculations
952 */
953static void MinimiseUnoccupied (struct Problem *P, int *Stop, int *SuperStop) {
954 struct RunStruct *R = &P->R;
955 struct Lattice *Lat = &P->Lat;
956 struct Psis *Psi = &Lat->Psi;
957 int StartLocalPsiNo;
958
959 *Stop = 0;
960 R->PsiStep = R->MaxPsiStep; // in case it's zero from CalculateForce()
961 UpdateActualPsiNo(P, UnOccupied); // step on to next unoccupied one
962 R->OldActualLocalPsiNo = R->ActualLocalPsiNo; // reset, otherwise OldActualLocalPsiNo still points to occupied wave function
963 UpdateGramSchOldActualPsiNo(P,Psi);
964 if (P->Call.ReadSrcFiles && ReadSrcPsiDensity(P,UnOccupied,1, R->LevSNo)) {
965 SpeedMeasure(P, InitSimTime, StartTimeDo);
966 if(P->Call.out[MinOut]) fprintf(stderr, "(%i) Re-initializing %s psi array from source file of recent calculation\n", P->Par.me, R->MinimisationName[R->CurrentMin]);
967 ReadSrcPsiDensity(P, UnOccupied, 0, R->LevSNo);
968 if (P->Call.ReadSrcFiles != 2) {
969 ResetGramSchTagType(P, Psi, UnOccupied, IsOrthonormal); // loaded values are orthonormal
970 SpeedMeasure(P, DensityTime, StartTimeDo);
971 InitDensityCalculation(P);
972 SpeedMeasure(P, DensityTime, StopTimeDo);
973 InitPsiEnergyCalculation(P,UnOccupied); // go through all orbitals calculating kinetic and non-local
974 //CalculateDensityEnergy(P, 0);
975 StartLocalPsiNo = R->ActualLocalPsiNo;
976 do { // otherwise OnePsiElementAddData#Lambda is calculated only for current Psi not for all
977 CalculateGapEnergy(P);
978 UpdateActualPsiNo(P, Occupied);
979 } while (R->ActualLocalPsiNo != StartLocalPsiNo);
980 EnergyAllReduce(P);
981 }
982 SpeedMeasure(P, InitSimTime, StopTimeDo);
983 }
984 if (P->Call.ReadSrcFiles != 1) {
985 SpeedMeasure(P, InitSimTime, StartTimeDo);
986 ResetGramSchTagType(P, Psi, UnOccupied, NotOrthogonal);
987 SpeedMeasure(P, GramSchTime, StartTimeDo);
988 GramSch(P, R->LevS, Psi, Orthonormalize);
989 SpeedMeasure(P, GramSchTime, StopTimeDo);
990 SpeedMeasure(P, InitDensityTime, StartTimeDo);
991 InitDensityCalculation(P);
992 SpeedMeasure(P, InitDensityTime, StopTimeDo);
993 InitPsiEnergyCalculation(P,UnOccupied); // go through all orbitals calculating kinetic and non-local
994 //CalculateDensityEnergy(P, 0);
995 CalculateGapEnergy(P);
996 EnergyAllReduce(P);
997 SpeedMeasure(P, InitSimTime, StopTimeDo);
998 R->LevS->Step++;
999 EnergyOutput(P,0);
1000 if(P->Call.out[LeaderOut]) fprintf(stderr,"(%i)Beginning minimisation of type %s ...\n", P->Par.me, R->MinimisationName[R->CurrentMin]);
1001 while (*Stop != 1) {
1002 CalculateNewWave(P,NULL);
1003 UpdateActualPsiNo(P, UnOccupied);
1004 /* New */
1005 UpdateEnergyArray(P);
1006 SpeedMeasure(P, DensityTime, StartTimeDo);
1007 UpdateDensityCalculation(P);
1008 SpeedMeasure(P, DensityTime, StopTimeDo);
1009 UpdatePsiEnergyCalculation(P);
1010 //CalculateDensityEnergy(P, 0);
1011 CalculateGapEnergy(P); //calculates XC, HGDensity, afterwards gradient, where V_xc is added upon HGDensity
1012 EnergyAllReduce(P);
1013 if (*SuperStop != 1)
1014 *SuperStop = CheckCPULIM(P);
1015 *Stop = CalculateMinimumStop(P, *SuperStop);
1016 /*EnergyOutput(P, Stop);*/
1017 P->Speed.Steps++;
1018 R->LevS->Step++;
1019 /*ControlNativeDensity(P);*/
1020 }
1021 OutputVisSrcFiles(P, UnOccupied);
1022// if (!TestReadnWriteSrcDensity(P,UnOccupied))
1023// Error(SomeError,"TestReadnWriteSrcDensity failed!");
1024 }
1025 TestGramSch(P,R->LevS,Psi, UnOccupied);
1026 ResetGramSchTagType(P, Psi, UnOccupied, NotUsedToOrtho);
1027 // re-calculate Occupied values (in preparation for perturbed ones)
1028 UpdateActualPsiNo(P, Occupied); // step on to next occupied one
1029 SpeedMeasure(P, DensityTime, StartTimeDo);
1030 InitDensityCalculation(P); // re-init densities to occupied standard
1031 SpeedMeasure(P, DensityTime, StopTimeDo);
1032// InitPsiEnergyCalculation(P,Occupied);
1033// CalculateDensityEnergy(P, 0);
1034// EnergyAllReduce(P);
1035}
1036
1037
1038/** Calculate the forces.
1039 * From RunStruct::LevSNo downto RunStruct::InitLevSNo the following routines are called in a loop:
1040 * -# In case of RunStruct#DoSeparated another loop begins for the unoccupied states with some reinitalization
1041 * before and afterwards. The loop however is much the same as the one above.
1042 * -# ChangeToLevUp()\n
1043 * Repeat the loop or when the above stop is reached, the level is changed and the loop repeated.
1044 *
1045 * Afterwards comes the actual force and energy calculation by calling:
1046 * -# ControlNativeDensity()\n
1047 * Checks if the density still reproduces particle number.
1048 * -# CalculateIonLocalForce(), SpeedMeasure()'d in LocFTime\n
1049 * Calculale local part of force acting on Ions.
1050 * -# CalculateIonNonLocalForce(), SpeedMeasure()'d in NonLocFTime\n
1051 * Calculale local part of force acting on Ions.
1052 * -# CalculateEwald()\n
1053 * Calculate Ewald force acting on Ions.
1054 * -# CalculateIonForce()\n
1055 * Sum up those three contributions.
1056 * -# CorrectForces()\n
1057 * Shifts center of gravity of all forces for each Ion, so that the cell itself remains at rest.
1058 * -# GetOuterStop()
1059 * Calculates a mean force per Ion.
1060 * \param *P Problem at hand
1061 * \return 1 - cpulim received, break operation, 0 - continue as normal
1062 */
1063int CalculateForce(struct Problem *P)
1064{
1065 struct RunStruct *R = &P->R;
1066 struct Lattice *Lat = &P->Lat;
1067 struct Psis *Psi = &Lat->Psi;
1068 struct LatticeLevel *LevS = R->LevS;
1069 struct FileData *F = &P->Files;
1070 struct Ions *I = &P->Ion;
1071 int Stop=0, SuperStop = 0, OuterStop = 0;
1072 //int i, j;
1073 while ((R->LevSNo > R->InitLevSNo) || (!Stop && R->LevSNo == R->InitLevSNo)) {
1074 // occupied
1075 R->PsiStep = R->MaxPsiStep; // reset in-Psi-minimisation-counter, so that we really advance to the next wave function
1076 R->OldActualLocalPsiNo = R->ActualLocalPsiNo; // reset OldActualLocalPsiNo, as it might still point to a perturbed wave function from last level
1077 UpdateGramSchOldActualPsiNo(P,Psi);
1078 MinimiseOccupied(P, &Stop, &SuperStop);
1079 if (!I->StructOpt) {
1080 if ((P->Call.ReadSrcFiles != 1) || (!ParseWannierFile(P))) { // only localize and store if they have just been minimised (hence don't come solely from file), otherwise read stored values from file (if possible)
1081 SpeedMeasure(P, WannierTime, StartTimeDo);
1082 ComputeMLWF(P); // localization of orbitals
1083 SpeedMeasure(P, WannierTime, StopTimeDo);
1084 OutputVisSrcFiles(P, Occupied); // rewrite now localized orbitals
1085 // if (!TestReadnWriteSrcDensity(P,Occupied))
1086 // Error(SomeError,"TestReadnWriteSrcDensity failed!");
1087 }
1088
1089// // plot psi cuts
1090// for (i=0; i < Psi->MaxPsiOfType; i++) // go through all wave functions (here without the extra ones for each process)
1091// if ((Psi->AllPsiStatus[i].PsiType == Occupied) && (Psi->AllPsiStatus[i].my_color_comm_ST_Psi == P->Par.my_color_comm_ST_Psi))
1092// for (j=0;j<NDIM;j++) {
1093// //fprintf(stderr,"(%i) Plotting Psi %i/%i cut axis %i at coordinate %lg \n",P->Par.me, i, Psi->AllPsiStatus[i].MyGlobalNo, j, Lat->Psi.AddData[Psi->AllPsiStatus[i].MyLocalNo].WannierCentre[j]);
1094// CalculateOneDensityR(Lat, R->LevS, R->Lev0->Dens, R->LevS->LPsi->LocalPsi[Psi->AllPsiStatus[i].MyLocalNo], R->Lev0->Dens->DensityArray[ActualDensity], R->FactorDensityR, 0);
1095// PlotSrcPlane(P, j, Lat->Psi.AddData[Psi->AllPsiStatus[i].MyLocalNo].WannierCentre[j], Psi->AllPsiStatus[i].MyGlobalNo, R->Lev0->Dens->DensityArray[ActualDensity]);
1096// }
1097
1098 // unoccupied calc
1099 if (R->DoUnOccupied) {
1100 MinimiseUnoccupied(P, &Stop, &SuperStop);
1101 }
1102 // hamiltonian
1103 CalculateHamiltonian(P); // lambda_{kl} needed (and for bandgap after UnOccupied)
1104
1105 // perturbed calc
1106 if ((R->DoPerturbation)) { // && R->LevSNo <= R->InitLevSNo) {
1107 AllocCurrentDensity(R->Lev0->Dens);// lock current density arrays
1108 MinimisePerturbed(P, &Stop, &SuperStop); // herein InitDensityCalculation() is called, thus no need to call it beforehand
1109
1110 SpeedMeasure(P, CurrDensTime, StartTimeDo);
1111 if (SuperStop != 1) {
1112 if ((R->DoFullCurrent == 1) || ((R->DoFullCurrent == 2) && (CheckOrbitalOverlap(P) == 1))) { //test to check whether orbitals have mutual overlap and thus \\DeltaJ_{xc} must not be dropped
1113 R->DoFullCurrent = 1; // set to 1 if it was 2 but Check...() yielded necessity
1114 debug(P,"Filling with Delta j ...");
1115 FillDeltaCurrentDensity(P);
1116 }// else
1117 //debug(P,"There is no overlap between orbitals.");
1118 //debug(P,"Filling with j ...");
1119 //FillCurrentDensity(P);
1120 }
1121 SpeedMeasure(P, CurrDensTime, StopTimeDo);
1122 TestCurrent(P,0);
1123 TestCurrent(P,1);
1124 TestCurrent(P,2);
1125 if (F->DoOutCurr) {
1126 debug(P,"OutputCurrentDensity");
1127 OutputCurrentDensity(P);
1128 }
1129 if (R->VectorPlane != -1) {
1130 debug(P,"PlotVectorPlane");
1131 PlotVectorPlane(P,R->VectorPlane,R->VectorCut);
1132 }
1133 fprintf(stderr,"(%i) ECut [L%i] = %e Ht\n", P->Par.me, R->Lev0->LevelNo, pow(2*M_PI*M_PI/Lat->Volume*R->Lev0->TotalAllMaxG, 2./3.));
1134 debug(P,"Calculation of magnetic susceptibility");
1135 CalculateMagneticSusceptibility(P);
1136 debug(P,"Normal calculation of shielding over R-space");
1137 CalculateChemicalShielding(P);
1138 debug(P,"Reciprocal calculation of shielding over G-space");
1139 CalculateChemicalShieldingByReciprocalCurrentDensity(P);
1140 SpeedMeasure(P, CurrDensTime, StopTimeDo);
1141 DisAllocCurrentDensity(R->Lev0->Dens); // unlock current density arrays
1142 } else {
1143 InitDensityCalculation(P); // all unperturbed(!) wave functions've "changed" from ComputeMLWF(), thus reinit density
1144 }
1145 //fprintf(stderr,"(%i) DoubleG: %p, CArray[22]: %p, OldLocalPsi: %p\n", P->Par.me, R->LevS->DoubleG, R->Lev0->Dens->DensityCArray[22], R->LevS->LPsi->OldLocalPsi);
1146 }
1147
1148// if (!I->StructOpt && R->DoPerturbation) {
1149// InitDensityCalculation(P); // most of the density array were used during FillCurrentDensity(), thus reinit density
1150// }
1151
1152 // next level
1153 ChangeToLevUp(P, &Stop);
1154 //if (isnan(LevS->LPsi->LocalPsi[R->ActualLocalPsiNo][0].re)) { fprintf(stderr,"(%i) WARNING in ChangeToLevUp(): LPsi->LocalPsi[%i]_[%i] = NaN!\n", P->Par.me, R->ActualLocalPsiNo, 0); Error(SomeError, "NaN-Fehler!"); }
1155 LevS = R->LevS; // re-set pointer that's changed from LevUp
1156 }
1157 //fprintf(stderr,"(%i) DoubleG: %p, CArray[22]: %p, OldLocalPsi: %p\n", P->Par.me, R->LevS->DoubleG, R->Lev0->Dens->DensityCArray[22], R->LevS->LPsi->OldLocalPsi);
1158 // necessary for correct ionic forces ...
1159 SpeedMeasure(P, LocFTime, StartTimeDo);
1160 CalculateIonLocalForce(P);
1161 SpeedMeasure(P, LocFTime, StopTimeDo);
1162 SpeedMeasure(P, NonLocFTime, StartTimeDo);
1163 CalculateIonNonLocalForce(P);
1164 SpeedMeasure(P, NonLocFTime, StopTimeDo);
1165 CalculateEwald(P, 0);
1166 CalculateIonForce(P);
1167 CorrectForces(P);
1168 // ... on output of densities
1169 if (F->DoOutOrbitals) { // output of each orbital
1170 debug(P,"OutputVisAllOrbital");
1171 OutputVisAllOrbital(P,0,1,Occupied);
1172 }
1173
1174 OutputNorm(stderr, P);
1175 //fprintf(stderr,"(%i) DoubleG: %p, CArray[22]: %p, OldLocalPsi: %p\n", P->Par.me, R->LevS->DoubleG, R->Lev0->Dens->DensityCArray[22], R->LevS->LPsi->OldLocalPsi);
1176 OutputVis(P, P->R.Lev0->Dens->DensityArray[TotalDensity]);
1177 TestGramSch(P,LevS,Psi, -1);
1178 SpeedMeasure(P, SimTime, StopTimeDo);
1179 /*TestGramSch(P, R->LevS, &P->Lat.Psi); */
1180 ControlNativeDensity(P);
1181 SpeedMeasure(P, LocFTime, StartTimeDo);
1182 CalculateIonLocalForce(P);
1183 SpeedMeasure(P, LocFTime, StopTimeDo);
1184 SpeedMeasure(P, NonLocFTime, StartTimeDo);
1185 CalculateIonNonLocalForce(P);
1186 SpeedMeasure(P, NonLocFTime, StopTimeDo);
1187 CalculateEwald(P, 0);
1188 CalculateIonForce(P);
1189 CorrectForces(P);
1190 GetOuterStop(P);
1191 //fprintf(stderr,"(%i) DoubleG: %p, CArray[22]: %p, OldLocalPsi: %p\n", P->Par.me, R->LevS->DoubleG, R->Lev0->Dens->DensityCArray[22], R->LevS->LPsi->OldLocalPsi);
1192 if (SuperStop) OuterStop = 1;
1193 return OuterStop;
1194}
1195
1196/** Wrapper for CalculateForce() for simplex minimisation of ionic forces.
1197 * \param *v vector with degrees of freedom
1198 * \param *params additional arguments, here Problem at hand
1199 */
1200double my_f(const gsl_vector *v, void *params)
1201{
1202 struct Problem *P = (struct Problem *)params;
1203 struct RunStruct *R = &P->R;
1204 struct Ions *I = &P->Ion;
1205 struct Energy *E = P->Lat.E;
1206 int i;
1207 double *R_ion, *R_old, *R_old_old, *FIon;
1208 double norm = 0.;
1209 int is,ia,k,index;
1210 int OuterStop;
1211 // update ion positions from vector coordinates
1212 index=0;
1213 for (is=0; is < I->Max_Types; is++) // for all elements
1214 for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) { // for all ions of element
1215 R_ion = &I->I[is].R[NDIM*ia];
1216 R_old = &I->I[is].R_old[NDIM*ia];
1217 R_old_old = &I->I[is].R_old_old[NDIM*ia];
1218 for (k=0;k<NDIM;k++) { // for all dimensions
1219 R_old_old[k] = R_old[k];
1220 R_old[k] = R_ion[k];
1221 R_ion[k] = gsl_vector_get (v, index++);
1222 }
1223 }
1224 // recalculate ionic forces (do electronic minimisation)
1225 R->OuterStep++;
1226 if (P->Call.out[NormalOut]) fprintf(stderr,"(%i) Commencing Fletcher-Reeves step %i ... \n",P->Par.me, R->OuterStep);
1227 R->NewRStep++;
1228 OutputIonCoordinates(P);
1229 UpdateWaveAfterIonMove(P);
1230 for (i=MAXOLD-1; i > 0; i--) // store away old energies
1231 E->TotalEnergyOuter[i] = E->TotalEnergyOuter[i-1];
1232 UpdateToNewWaves(P);
1233 E->TotalEnergyOuter[0] = E->TotalEnergy[0];
1234 OuterStop = CalculateForce(P);
1235 UpdateIonsU(P);
1236 CorrectVelocity(P);
1237 CalculateEnergyIonsU(P);
1238/* if ((P->R.ScaleTempStep > 0) && ((R->OuterStep-1) % P->R.ScaleTempStep == 0))
1239 ScaleTemp(P);*/
1240 if ((R->OuterStep-1) % P->R.OutSrcStep == 0)
1241 OutputVisSrcFiles(P, Occupied);
1242 if ((R->OuterStep-1) % P->R.OutVisStep == 0) {
1243/* // recalculate density for the specific wave function ...
1244 CalculateOneDensityR(Lat, LevS, Dens0, PsiDat, Dens0->DensityArray[ActualDensity], R->FactorDensityR, 0);
1245 // ... and output (wherein ActualDensity is used instead of TotalDensity)
1246 OutputVis(P);
1247 OutputIonForce(P);
1248 EnergyOutput(P, 1);*/
1249 }
1250 // sum up mean force
1251 for (is=0; is < I->Max_Types; is++)
1252 for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
1253 FIon = &I->I[is].FIon[NDIM*ia];
1254 norm += sqrt(RSP3(FIon,FIon));
1255 }
1256 if (P->Par.me == 0) fprintf(stderr,"(%i) Mean Force over all Ions %e\n",P->Par.me, norm);
1257 return norm;
1258}
1259
1260void my_df(const gsl_vector *v, void *params, gsl_vector *df)
1261{
1262 struct Problem *P = (struct Problem *)params;
1263 struct Ions *I = &P->Ion;
1264 double *FIon;
1265 int is,ia,k, index=0;
1266 for (is=0; is < I->Max_Types; is++) // for all elements
1267 for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) { // for all ions of element
1268 FIon = &I->I[is].FIon[NDIM*ia];
1269 for (k=0;k<NDIM;k++) { // for all dimensions
1270 gsl_vector_set (df, index++, FIon[k]);
1271 }
1272 }
1273}
1274
1275void my_fdf (const gsl_vector *x, void *params, double *f, gsl_vector *df)
1276{
1277 *f = my_f(x, params);
1278 my_df(x, params, df);
1279}
1280
1281
1282/** CG implementation for the structure optimization.
1283 * We follow the example from the GSL manual.
1284 * \param *P Problem at hand
1285 */
1286void UpdateIon_PRCG(struct Problem *P)
1287{
1288 struct RunStruct *Run = &P->R;
1289 struct Ions *I = &P->Ion;
1290 size_t np = NDIM*I->Max_TotalIons; // d.o.f = number of ions times number of dimensions
1291 int is, ia, k, index;
1292 double *R;
1293
1294 const gsl_multimin_fdfminimizer_type *T;
1295 gsl_multimin_fdfminimizer *s;
1296 gsl_vector *x;
1297 gsl_multimin_function_fdf minex_func;
1298
1299 size_t iter = 0;
1300 int status;
1301
1302 /* Starting point */
1303 x = gsl_vector_alloc (np);
1304
1305 index=0;
1306 for (is=0; is < I->Max_Types; is++) // for all elements
1307 for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) { // for all ions of element
1308 R = &I->I[is].R[NDIM*ia];
1309 for (k=0;k<NDIM;k++) // for all dimensions
1310 gsl_vector_set (x, index++, R[k]);
1311 }
1312
1313 /* Initialize method and iterate */
1314 minex_func.f = &my_f;
1315 minex_func.df = &my_df;
1316 minex_func.fdf = &my_fdf;
1317 minex_func.n = np;
1318 minex_func.params = (void *)P;
1319
1320 T = gsl_multimin_fdfminimizer_conjugate_pr;
1321 s = gsl_multimin_fdfminimizer_alloc (T, np);
1322
1323 gsl_multimin_fdfminimizer_set (s, &minex_func, x, 0.1, 1e-4);
1324
1325 do {
1326 iter++;
1327 status = gsl_multimin_fdfminimizer_iterate(s);
1328
1329 if (status)
1330 break;
1331
1332 status = gsl_multimin_test_gradient (s->gradient, 1e-4);
1333
1334 if (status == GSL_SUCCESS)
1335 if (P->Par.me == 0) fprintf (stderr,"(%i) converged to minimum at\n", P->Par.me);
1336
1337 //if (P->Call.out[NormalOut]) fprintf(stderr,"(%i) Commencing '%s' step %i ... \n",P->Par.me, gsl_multimin_fdfminimizer_name(s), P->R.StructOptStep);
1338 if ((P->Call.out[NormalOut]) && (P->Par.me == 0)) fprintf (stderr, "(%i) %5d %10.5f\n", P->Par.me, (int)iter, s->f);
1339 } while (status == GSL_CONTINUE && iter < Run->MaxOuterStep);
1340
1341 gsl_vector_free(x);
1342 gsl_multimin_fdfminimizer_free (s);
1343}
1344
1345/** Does the Molecular Dynamics Calculations.
1346 * All of the following is SpeedMeasure()'d in SimTime.
1347 * Initialization by calling:
1348 * -# CorrectVelocity()\n
1349 * Shifts center of gravity of Ions momenta, so that the cell itself remains at rest.
1350 * -# CalculateEnergyIonsU(), SpeedMeasure()'d in TimeTypes#InitSimTime\n
1351 * Calculates kinetic energy of "movable" Ions.
1352 * -# CalculateForce()\n
1353 * Does the minimisation, calculates densities, then energies and finally the forces.
1354 * -# OutputVisSrcFiles()\n
1355 * If desired, so-far made calculations are stored to file for later restarting.
1356 * -# OutputIonForce()\n
1357 * Write ion forces to file.
1358 * -# EnergyOutput()\n
1359 * Write calculated energies to screen or file.
1360 *
1361 * The simulation phase begins:
1362 * -# UpdateIonsR()\n
1363 * Move Ions according to the calculated force.
1364 * -# UpdateWaveAfterIonMove()\n
1365 * Update wave functions by averaging LocalPsi coefficients after the Ions have been shifted.
1366 * -# UpdateToNewWaves()\n
1367 * Update after wave functions have changed.
1368 * -# CalculateForce()\n
1369 * Does the minimisation, calculates densities, then energies and finally the forces.
1370 * -# UpdateIonsU()\n
1371 * Change ion's velocities according to the calculated acting force.
1372 * -# CorrectVelocity()\n
1373 * Shifts center of gravity of Ions momenta, so that the cell itself remains at rest.
1374 * -# CalculateEnergyIonsU()\n
1375 * Calculates kinetic energy of "movable" Ions.
1376 * -# ScaleTemp()\n
1377 * The temperature is scaled, so the systems energy remains constant (they must not gain momenta out of nothing)
1378 * -# OutputVisSrcFiles()\n
1379 * If desired, so-far made calculations are stored to file for later restarting.
1380 * -# OutputVis()\n
1381 * Visulization data for OpenDX is written at certain steps if desired.
1382 * -# OutputIonForce()\n
1383 * Write ion forces to file.
1384 * -# EnergyOutput()\n
1385 * Write calculated energies to screen or file.
1386 *
1387 * After the ground state is found:
1388 * -# CalculateUnOccupied()\n
1389 * Energies of unoccupied orbitals - that have been left out completely so far -
1390 * are calculated.
1391 * -# TestGramSch()\n
1392 * Test if orbitals are still orthogonal.
1393 * -# CalculateHamiltonian()\n
1394 * Construct Hamiltonian and calculate Eigenvalues.
1395 * -# ComputeMLWF()\n
1396 * Localize orbital wave functions.
1397 *
1398 * \param *P Problem at hand
1399 */
1400void CalculateMD(struct Problem *P)
1401{
1402 struct RunStruct *R = &P->R;
1403 struct Ions *I = &P->Ion;
1404 int OuterStop = 0;
1405 SpeedMeasure(P, SimTime, StartTimeDo);
1406 SpeedMeasure(P, InitSimTime, StartTimeDo);
1407 R->OuterStep = 0;
1408 CorrectVelocity(P);
1409 CalculateEnergyIonsU(P);
1410 OuterStop = CalculateForce(P);
1411 R->OuterStep++;
1412 P->Speed.InitSteps++;
1413 SpeedMeasure(P, InitSimTime, StopTimeDo);
1414 OutputIonForce(P);
1415 EnergyOutput(P, 1);
1416 if (R->MaxOuterStep > 0) {
1417 debug(P,"Commencing Fletcher-Reeves minimisation on ionic structure ...");
1418 UpdateIon_PRCG(P);
1419 }
1420 if (I->StructOpt && !OuterStop) {
1421 I->StructOpt = 0;
1422 OuterStop = CalculateForce(P);
1423 }
1424 /* while (!OuterStop && R->OuterStep <= R->MaxOuterStep) {
1425 R->OuterStep++;
1426 if (P->Call.out[NormalOut]) fprintf(stderr,"(%i) Commencing MD steps %i ... \n",P->Par.me, R->OuterStep);
1427 P->R.t += P->R.delta_t; // increase current time by delta_t
1428 R->NewRStep++;
1429 if (P->Ion.StructOpt == 1) {
1430 UpdateIons(P);
1431 OutputIonCoordinates(P);
1432 } else {
1433 UpdateIonsR(P);
1434 }
1435 UpdateWaveAfterIonMove(P);
1436 for (i=MAXOLD-1; i > 0; i--) // store away old energies
1437 E->TotalEnergyOuter[i] = E->TotalEnergyOuter[i-1];
1438 UpdateToNewWaves(P);
1439 E->TotalEnergyOuter[0] = E->TotalEnergy[0];
1440 OuterStop = CalculateForce(P);
1441 UpdateIonsU(P);
1442 CorrectVelocity(P);
1443 CalculateEnergyIonsU(P);
1444 if ((P->R.ScaleTempStep > 0) && ((R->OuterStep-1) % P->R.ScaleTempStep == 0))
1445 ScaleTemp(P);
1446 if ((R->OuterStep-1) % P->R.OutSrcStep == 0)
1447 OutputVisSrcFiles(P, Occupied);
1448 if ((R->OuterStep-1) % P->R.OutVisStep == 0) {
1449 // recalculate density for the specific wave function ...
1450 //CalculateOneDensityR(Lat, LevS, Dens0, PsiDat, Dens0->DensityArray[ActualDensity], R->FactorDensityR, 0);
1451 // ... and output (wherein ActualDensity is used instead of TotalDensity)
1452 //OutputVis(P);
1453 //OutputIonForce(P);
1454 //EnergyOutput(P, 1);
1455 }
1456 }*/
1457 SpeedMeasure(P, SimTime, StopTimeDo);
1458 // hack to output each orbital before and after spread-minimisation
1459/* if (P->Files.MeOutVis) P->Files.OutputPosType = (enum ModeType *) Realloc(P->Files.OutputPosType,sizeof(enum ModeType)*(P->Files.OutVisStep+P->Lat.Psi.MaxPsiOfType*2),"OutputVis");
1460 OutputVisAllOrbital(P, 0, 2, Occupied);
1461 CalculateHamiltonian(P);
1462 if (P->Files.MeOutVis) P->Files.OutVisStep -= (P->Lat.Psi.MaxPsiOfType)*2;
1463 OutputVisAllOrbital(P, 1, 2, Occupied);*/
1464 CloseOutputFiles(P);
1465}
Note: See TracBrowser for help on using the repository browser.