| 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 <gsl/gsl_randist.h>
 | 
|---|
| 36 | #include "mpi.h"
 | 
|---|
| 37 | #include "data.h"
 | 
|---|
| 38 | #include "errors.h"
 | 
|---|
| 39 | #include "helpers.h"
 | 
|---|
| 40 | #include "init.h"
 | 
|---|
| 41 | #include "opt.h"
 | 
|---|
| 42 | #include "myfft.h"
 | 
|---|
| 43 | #include "gramsch.h"
 | 
|---|
| 44 | #include "output.h"
 | 
|---|
| 45 | #include "energy.h"
 | 
|---|
| 46 | #include "density.h"
 | 
|---|
| 47 | #include "ions.h"
 | 
|---|
| 48 | #include "run.h"
 | 
|---|
| 49 | #include "riemann.h"
 | 
|---|
| 50 | #include "mymath.h"
 | 
|---|
| 51 | #include "pcp.h"
 | 
|---|
| 52 | #include "perturbed.h"
 | 
|---|
| 53 | #include "wannier.h"
 | 
|---|
| 54 | 
 | 
|---|
| 55 | 
 | 
|---|
| 56 | /** Initialization of the (initial) zero and simulation levels in RunStruct structure.
 | 
|---|
| 57 |  * RunStruct::InitLevS is set onto the STANDARTLEVEL in Lattice::Lev[], RunStruct::InitLev0 on
 | 
|---|
| 58 |  * level 0, RunStruct::LevS onto Lattice::MaxLevel-1 (maximum level) and RunStruct::Lev0 onto
 | 
|---|
| 59 |  * Lattice::MaxLevel-2 (one below).
 | 
|---|
| 60 |  * In case of RiemannTensor use an additional Riemann level is intertwined.
 | 
|---|
| 61 |  * \param *P Problem at hand
 | 
|---|
| 62 |  */
 | 
|---|
| 63 | void InitRunLevel(struct Problem *P)
 | 
|---|
| 64 | {
 | 
|---|
| 65 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
| 66 |   struct RunStruct *R = &P->R;
 | 
|---|
| 67 |   struct RiemannTensor *RT = &Lat->RT;
 | 
|---|
| 68 |   int d,i;
 | 
|---|
| 69 | 
 | 
|---|
| 70 |   switch (Lat->RT.Use) {
 | 
|---|
| 71 |   case UseNotRT:
 | 
|---|
| 72 |     R->InitLevSNo = STANDARTLEVEL;
 | 
|---|
| 73 |     R->InitLev0No = 0;
 | 
|---|
| 74 |     R->InitLevS = &P->Lat.Lev[R->InitLevSNo];
 | 
|---|
| 75 |     R->InitLev0 = &P->Lat.Lev[R->InitLev0No];
 | 
|---|
| 76 |     R->LevSNo = Lat->MaxLevel-1;
 | 
|---|
| 77 |     R->Lev0No = Lat->MaxLevel-2;
 | 
|---|
| 78 |     R->LevS = &P->Lat.Lev[R->LevSNo];
 | 
|---|
| 79 |     R->Lev0 = &P->Lat.Lev[R->Lev0No];
 | 
|---|
| 80 |     break;
 | 
|---|
| 81 |   case UseRT:
 | 
|---|
| 82 |     R->InitLevSNo = STANDARTLEVEL;
 | 
|---|
| 83 |     R->InitLev0No = 0;
 | 
|---|
| 84 |     R->InitLevS = &P->Lat.Lev[R->InitLevSNo];
 | 
|---|
| 85 |     R->InitLev0 = &P->Lat.Lev[R->InitLev0No];
 | 
|---|
| 86 | 
 | 
|---|
| 87 |     /*    R->LevSNo = Lat->MaxLevel-1;
 | 
|---|
| 88 |           R->Lev0No = Lat->MaxLevel-2;*/
 | 
|---|
| 89 |     R->LevSNo = Lat->MaxLevel-2;
 | 
|---|
| 90 |     R->Lev0No = Lat->MaxLevel-3;
 | 
|---|
| 91 | 
 | 
|---|
| 92 |     R->LevRNo = P->Lat.RT.RiemannLevel;
 | 
|---|
| 93 |     R->LevRSNo = STANDARTLEVEL;
 | 
|---|
| 94 |     R->LevR0No = 0;
 | 
|---|
| 95 |     R->LevS = &P->Lat.Lev[R->LevSNo];
 | 
|---|
| 96 |     R->Lev0 = &P->Lat.Lev[R->Lev0No];
 | 
|---|
| 97 |     R->LevR = &P->Lat.Lev[R->LevRNo];
 | 
|---|
| 98 |     R->LevRS = &P->Lat.Lev[R->LevRSNo];
 | 
|---|
| 99 |     R->LevR0 = &P->Lat.Lev[R->LevR0No];
 | 
|---|
| 100 |     for (d=0; d<NDIM; d++) {
 | 
|---|
| 101 |       RT->NUpLevRS[d] = 1;
 | 
|---|
| 102 |       for (i=R->LevRNo-1; i >=  R->LevRSNo; i--) 
 | 
|---|
| 103 |                                 RT->NUpLevRS[d] *= Lat->LevelSizes[i];
 | 
|---|
| 104 |       RT->NUpLevR0[d] = 1;
 | 
|---|
| 105 |       for (i=R->LevRNo-1; i >=  R->LevR0No; i--) 
 | 
|---|
| 106 |                                 RT->NUpLevR0[d] *= Lat->LevelSizes[i];
 | 
|---|
| 107 |     }
 | 
|---|
| 108 |     break;
 | 
|---|
| 109 |   }
 | 
|---|
| 110 | }
 | 
|---|
| 111 | 
 | 
|---|
| 112 | 
 | 
|---|
| 113 | /** Initialization of RunStruct structure.
 | 
|---|
| 114 |  * Most of the actual entries in the RunStruct are set to their starter no-nonsense
 | 
|---|
| 115 |  * values (init if LatticeLevel is not STANDARTLEVEL otherwise normal max): FactorDensity,
 | 
|---|
| 116 |  * all Steps, XCEnergyFactor and HGcFactor, current and archived energie values are zeroed.
 | 
|---|
| 117 |  * \param *P problem at hand
 | 
|---|
| 118 |  */
 | 
|---|
| 119 | void InitRun(struct Problem *P)
 | 
|---|
| 120 | {
 | 
|---|
| 121 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
| 122 |   struct RunStruct *R = &P->R;
 | 
|---|
| 123 |   struct Psis *Psi = &Lat->Psi;
 | 
|---|
| 124 |   int i,j;
 | 
|---|
| 125 | 
 | 
|---|
| 126 | #ifndef SHORTSPEED
 | 
|---|
| 127 |   R->MaxMinStepFactor = Psi->AllMaxLocalNo;
 | 
|---|
| 128 | #else
 | 
|---|
| 129 |   R->MaxMinStepFactor = SHORTSPEED;
 | 
|---|
| 130 | #endif
 | 
|---|
| 131 |   if (R->LevSNo == STANDARTLEVEL) {
 | 
|---|
| 132 |     R->ActualMaxMinStep = R->MaxMinStep*R->MaxPsiStep*R->MaxMinStepFactor; 
 | 
|---|
| 133 |     R->ActualRelEpsTotalEnergy = R->RelEpsTotalEnergy;
 | 
|---|
| 134 |     R->ActualRelEpsKineticEnergy = R->RelEpsKineticEnergy;
 | 
|---|
| 135 |     R->ActualMaxMinStopStep = R->MaxMinStopStep;
 | 
|---|
| 136 |     R->ActualMaxMinGapStopStep = R->MaxMinGapStopStep;
 | 
|---|
| 137 |   } else {
 | 
|---|
| 138 |     R->ActualMaxMinStep = R->MaxInitMinStep*R->MaxPsiStep*R->MaxMinStepFactor;
 | 
|---|
| 139 |     R->ActualRelEpsTotalEnergy = R->InitRelEpsTotalEnergy;
 | 
|---|
| 140 |     R->ActualRelEpsKineticEnergy = R->InitRelEpsKineticEnergy;
 | 
|---|
| 141 |     R->ActualMaxMinStopStep = R->InitMaxMinStopStep;
 | 
|---|
| 142 |     R->ActualMaxMinGapStopStep = R->InitMaxMinGapStopStep;
 | 
|---|
| 143 |   }
 | 
|---|
| 144 |   
 | 
|---|
| 145 |   R->FactorDensityR = 1./Lat->Volume;
 | 
|---|
| 146 |   R->FactorDensityC = Lat->Volume;
 | 
|---|
| 147 |   
 | 
|---|
| 148 |   R->OldActualLocalPsiNo = R->ActualLocalPsiNo = 0;
 | 
|---|
| 149 |         R->UseForcesFile = 0;
 | 
|---|
| 150 |   R->UseOldPsi = 1;
 | 
|---|
| 151 |   R->MinStep = 0;
 | 
|---|
| 152 |   R->PsiStep = 0;
 | 
|---|
| 153 |   R->AlphaStep = 0;
 | 
|---|
| 154 |   R->DoCalcCGGauss = 0;
 | 
|---|
| 155 |   R->CurrentMin = Occupied;
 | 
|---|
| 156 | 
 | 
|---|
| 157 |   R->MinStopStep = 0;
 | 
|---|
| 158 |   
 | 
|---|
| 159 |   R->ScanPotential = 0; // in order to deactivate, simply set this to 0
 | 
|---|
| 160 |   R->ScanAtStep = 6;    // must not be set to same as ScanPotential (then gradient is never calculated)
 | 
|---|
| 161 |   R->ScanDelta = 0.01;  // step size on advance
 | 
|---|
| 162 |   R->ScanFlag = 0;      // flag telling that we are scanning
 | 
|---|
| 163 |   
 | 
|---|
| 164 |   //R->DoBrent = 0;   // InitRun() occurs after ReadParameters(), thus this deactivates DoBrent line search
 | 
|---|
| 165 |   
 | 
|---|
| 166 |   /*  R->MaxOuterStep = 1;
 | 
|---|
| 167 |       R->MeanForceEps = 0.0;*/
 | 
|---|
| 168 |   
 | 
|---|
| 169 |   R->NewRStep = 1;
 | 
|---|
| 170 |   /* Factor */
 | 
|---|
| 171 |   R->XCEnergyFactor = 1.0/R->FactorDensityR;
 | 
|---|
| 172 |   R->HGcFactor = 1.0/Lat->Volume;
 | 
|---|
| 173 | 
 | 
|---|
| 174 |   /* Sollte auch geaendert werden */
 | 
|---|
| 175 |   /*Grad->GradientArray[GraSchGradient] = LevS->LPsi->LocalPsi[Psi->LocalNo];*/
 | 
|---|
| 176 | 
 | 
|---|
| 177 |   for (j=Occupied;j<Extra;j++)
 | 
|---|
| 178 |     for (i=0; i < RUNMAXOLD; i++) {
 | 
|---|
| 179 |       R->TE[j][i] = 0;
 | 
|---|
| 180 |       R->KE[j][i] = 0;
 | 
|---|
| 181 |     }
 | 
|---|
| 182 |     
 | 
|---|
| 183 |   R->MinimisationName = (char **) Malloc((perturbations+3)*(sizeof(char *)), "InitRun: *MinimisationName");
 | 
|---|
| 184 |   for (j=Occupied;j<=Extra;j++)
 | 
|---|
| 185 |     R->MinimisationName[j] = (char *) MallocString(6*(sizeof(char)), "InitRun: MinimisationName[]");
 | 
|---|
| 186 |   strncpy(R->MinimisationName[0],"Occ",6); 
 | 
|---|
| 187 |   strncpy(R->MinimisationName[1],"UnOcc",6); 
 | 
|---|
| 188 |   strncpy(R->MinimisationName[2],"P0",6); 
 | 
|---|
| 189 |   strncpy(R->MinimisationName[3],"P1",6); 
 | 
|---|
| 190 |   strncpy(R->MinimisationName[4],"P2",6); 
 | 
|---|
| 191 |   strncpy(R->MinimisationName[5],"RxP0",6); 
 | 
|---|
| 192 |   strncpy(R->MinimisationName[6],"RxP1",6); 
 | 
|---|
| 193 |   strncpy(R->MinimisationName[7],"RxP2",6); 
 | 
|---|
| 194 |   strncpy(R->MinimisationName[8],"Extra",6); 
 | 
|---|
| 195 | }
 | 
|---|
| 196 | 
 | 
|---|
| 197 | /** Re-occupy orbitals according to Fermi (bottom-up energy-wise).
 | 
|---|
| 198 |  * All OnePsiElementAddData#PsiFactor's are set to zero. \a electrons is set to Psi#Use-dependent
 | 
|---|
| 199 |  * Psis#GlobalNo.
 | 
|---|
| 200 |  * Then we go through OnePsiElementAddData#Lambda, find biggest, put one or two electrons into
 | 
|---|
| 201 |  * its PsiFactor, withdraw from \a electrons. Go on as long as there are \a electrons left.
 | 
|---|
| 202 |  * \param *P Problem at hand
 | 
|---|
| 203 |  */
 | 
|---|
| 204 | void OccupyByFermi(struct Problem *P) {
 | 
|---|
| 205 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
| 206 |   struct Psis *Psi = &Lat->Psi;
 | 
|---|
| 207 |   int i, index, electrons = 0;
 | 
|---|
| 208 |   double lambda, electronsperorbit;
 | 
|---|
| 209 |   
 | 
|---|
| 210 |   for (i=0; i< Psi->LocalNo; i++) {// set all PsiFactors to zero
 | 
|---|
| 211 |     Psi->LocalPsiStatus[i].PsiFactor = 0.0;
 | 
|---|
| 212 |     Psi->LocalPsiStatus[i].PsiType = UnOccupied;
 | 
|---|
| 213 |     //Psi->LocalPsiStatus[i].PsiGramSchStatus = (R->DoSeparated) ? NotUsedToOrtho : NotOrthogonal;
 | 
|---|
| 214 |   }
 | 
|---|
| 215 | 
 | 
|---|
| 216 |   electronsperorbit = (Psi->Use == UseSpinUpDown) ? 1 : 2;
 | 
|---|
| 217 |   switch (Psi->PsiST) { // how many electrons may we re-distribute
 | 
|---|
| 218 |     case SpinDouble:
 | 
|---|
| 219 |       electrons = Psi->GlobalNo[PsiMaxNoDouble];
 | 
|---|
| 220 |       break;
 | 
|---|
| 221 |     case SpinUp:
 | 
|---|
| 222 |       electrons = Psi->GlobalNo[PsiMaxNoUp];
 | 
|---|
| 223 |       break;
 | 
|---|
| 224 |     case SpinDown:
 | 
|---|
| 225 |       electrons = Psi->GlobalNo[PsiMaxNoDown];
 | 
|---|
| 226 |       break;
 | 
|---|
| 227 |   } 
 | 
|---|
| 228 |   while (electrons > 0) {
 | 
|---|
| 229 |     lambda = 0.0;
 | 
|---|
| 230 |     index = 0;
 | 
|---|
| 231 |     for (i=0; i< Psi->LocalNo; i++) // seek biggest unoccupied one
 | 
|---|
| 232 |       if ((lambda < Psi->AddData[i].Lambda) && (Psi->LocalPsiStatus[i].PsiFactor == 0.0)) { 
 | 
|---|
| 233 |         index = i;
 | 
|---|
| 234 |         lambda = Psi->AddData[i].Lambda;
 | 
|---|
| 235 |       }
 | 
|---|
| 236 |     Psi->LocalPsiStatus[index].PsiFactor = electronsperorbit; // occupy state
 | 
|---|
| 237 |     Psi->LocalPsiStatus[index].PsiType = Occupied;    
 | 
|---|
| 238 |     electrons--;   // one electron less
 | 
|---|
| 239 |   }
 | 
|---|
| 240 |   for (i=0; i< Psi->LocalNo; i++) // set all PsiFactors to zero
 | 
|---|
| 241 |     if (Psi->LocalPsiStatus[i].PsiType == UnOccupied) Psi->LocalPsiStatus[i].PsiFactor = 1.0;
 | 
|---|
| 242 |     
 | 
|---|
| 243 |   SpeedMeasure(P, DensityTime, StartTimeDo);
 | 
|---|
| 244 |   UpdateDensityCalculation(P);
 | 
|---|
| 245 |   SpeedMeasure(P, DensityTime, StopTimeDo);
 | 
|---|
| 246 |   InitPsiEnergyCalculation(P,Occupied);  // goes through all orbitals calculating kinetic and non-local
 | 
|---|
| 247 |   CalculateDensityEnergy(P, 0);
 | 
|---|
| 248 |   EnergyAllReduce(P);
 | 
|---|
| 249 | //  SetCurrentMinState(P,UnOccupied);
 | 
|---|
| 250 | //  InitPsiEnergyCalculation(P,UnOccupied); /* STANDARTLEVEL */
 | 
|---|
| 251 | //  CalculateGapEnergy(P); /* STANDARTLEVEL */
 | 
|---|
| 252 | //  EnergyAllReduce(P);
 | 
|---|
| 253 | //  SetCurrentMinState(P,Occupied);
 | 
|---|
| 254 | }
 | 
|---|
| 255 | 
 | 
|---|
| 256 | /** Use next local Psi: Update RunStruct::ActualLocalPsiNo.
 | 
|---|
| 257 |  * Increases OnePsiElementAddData::Step, RunStruct::MinStep and RunStruct::PsiStep.
 | 
|---|
| 258 |  * RunStruct::OldActualLocalPsiNo is set to current one and this distributed
 | 
|---|
| 259 |  * (UpdateGramSchOldActualPsiNo()) among process.
 | 
|---|
| 260 |  * Afterwards RunStruct::ActualLocalPsiNo is increased (modulo Psis::LocalNo of
 | 
|---|
| 261 |  * this process) and again distributed (UpdateGramSchActualPsiNo()).
 | 
|---|
| 262 |  * Due to change in the GramSchmidt-Status, GramSch() is called for Orthonormalization.
 | 
|---|
| 263 |  * \param *P Problem at hand#
 | 
|---|
| 264 |  * \param IncType skip types PsiTypeTag#UnOccupied or PsiTypeTag#Occupied we only want next(thus we can handily advance only through either type)
 | 
|---|
| 265 |  */
 | 
|---|
| 266 | void UpdateActualPsiNo(struct Problem *P, enum PsiTypeTag IncType)
 | 
|---|
| 267 | {
 | 
|---|
| 268 |   struct RunStruct *R = &P->R;
 | 
|---|
| 269 |   if (R->CurrentMin != IncType) {
 | 
|---|
| 270 |     SetCurrentMinState(P,IncType);
 | 
|---|
| 271 |     R->PsiStep = R->MaxPsiStep; // force step to next Psi
 | 
|---|
| 272 |   }
 | 
|---|
| 273 |   P->Lat.Psi.AddData[R->ActualLocalPsiNo].Step++;
 | 
|---|
| 274 |   R->MinStep++;
 | 
|---|
| 275 |   R->PsiStep++;
 | 
|---|
| 276 |   if (R->OldActualLocalPsiNo != R->ActualLocalPsiNo) {
 | 
|---|
| 277 |     R->OldActualLocalPsiNo = R->ActualLocalPsiNo;
 | 
|---|
| 278 |     UpdateGramSchOldActualPsiNo(P, &P->Lat.Psi);
 | 
|---|
| 279 |   }
 | 
|---|
| 280 |   if (R->PsiStep >= R->MaxPsiStep) {
 | 
|---|
| 281 |     R->PsiStep=0;
 | 
|---|
| 282 |     do { 
 | 
|---|
| 283 |       R->ActualLocalPsiNo++;
 | 
|---|
| 284 |       R->ActualLocalPsiNo %= P->Lat.Psi.LocalNo;
 | 
|---|
| 285 |     } while (P->Lat.Psi.AllPsiStatus[R->ActualLocalPsiNo].PsiType != IncType);
 | 
|---|
| 286 |     UpdateGramSchActualPsiNo(P, &P->Lat.Psi);
 | 
|---|
| 287 |     //fprintf(stderr,"(%i) ActualLocalNo: %d\n", P->Par.me, R->ActualLocalPsiNo);
 | 
|---|
| 288 |   }
 | 
|---|
| 289 |   if ((R->UseAddGramSch == 1 && (R->OldActualLocalPsiNo != R->ActualLocalPsiNo || P->Lat.Psi.NoOfPsis == 1)) || R->UseAddGramSch == 2) {
 | 
|---|
| 290 |     if (P->Lat.Psi.LocalPsiStatus[R->OldActualLocalPsiNo].PsiGramSchStatus != NotUsedToOrtho) // don't reset by accident last psi of former minimisation run 
 | 
|---|
| 291 |       SetGramSchOldActualPsi(P, &P->Lat.Psi, NotOrthogonal); 
 | 
|---|
| 292 |     SpeedMeasure(P, GramSchTime, StartTimeDo);
 | 
|---|
| 293 |     //OrthogonalizePsis(P);
 | 
|---|
| 294 |     if (R->CurrentMin <= UnOccupied)
 | 
|---|
| 295 |       GramSch(P, R->LevS, &P->Lat.Psi, Orthonormalize);
 | 
|---|
| 296 |     else
 | 
|---|
| 297 |       GramSch(P, R->LevS, &P->Lat.Psi, Orthogonalize); //Orthogonalize
 | 
|---|
| 298 |     SpeedMeasure(P, GramSchTime, StopTimeDo);  
 | 
|---|
| 299 |   }
 | 
|---|
| 300 | }
 | 
|---|
| 301 | 
 | 
|---|
| 302 | /** Resets all OnePsiElement#DoBrent.\
 | 
|---|
| 303 |  * \param *P Problem at hand
 | 
|---|
| 304 |  * \param *Psi pointer to wave functions
 | 
|---|
| 305 |  */
 | 
|---|
| 306 | void ResetBrent(struct Problem *P, struct Psis *Psi) {
 | 
|---|
| 307 |   int i;
 | 
|---|
| 308 |   for (i=0; i< Psi->LocalNo; i++) {// set all PsiFactors to zero
 | 
|---|
| 309 |     //fprintf(stderr,"(%i) DoBrent[%i] = %i\n", P->Par.me, i, Psi->LocalPsiStatus[i].DoBrent);
 | 
|---|
| 310 |     if (Psi->LocalPsiStatus[i].PsiType == Occupied) Psi->LocalPsiStatus[i].DoBrent = 4;
 | 
|---|
| 311 |   }
 | 
|---|
| 312 | }
 | 
|---|
| 313 | 
 | 
|---|
| 314 | /** Sets current minimisation state.
 | 
|---|
| 315 |  * Stores given \a state in RunStruct#CurrentMin and sets pointer Lattice#E accordingly.
 | 
|---|
| 316 |  * \param *P Problem at hand
 | 
|---|
| 317 |  * \param state given PsiTypeTag state
 | 
|---|
| 318 |  */
 | 
|---|
| 319 | void SetCurrentMinState(struct Problem *P, enum PsiTypeTag state) {
 | 
|---|
| 320 |   P->R.CurrentMin = state;
 | 
|---|
| 321 |   P->R.TotalEnergy = &(P->R.TE[state][0]);
 | 
|---|
| 322 |   P->R.KineticEnergy = &(P->R.KE[state][0]);
 | 
|---|
| 323 |   P->R.ActualRelTotalEnergy = &(P->R.ActualRelTE[state][0]);
 | 
|---|
| 324 |   P->R.ActualRelKineticEnergy = &(P->R.ActualRelKE[state][0]);
 | 
|---|
| 325 |   P->Lat.E = &(P->Lat.Energy[state]);  
 | 
|---|
| 326 | }
 | 
|---|
| 327 | /*{  
 | 
|---|
| 328 |   struct RunStruct *R = &P->R;
 | 
|---|
| 329 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
| 330 |   struct Psis *Psi = &Lat->Psi;
 | 
|---|
| 331 |   P->Lat.Psi.AddData[R->ActualLocalPsiNo].Step++;
 | 
|---|
| 332 |   R->MinStep++;
 | 
|---|
| 333 |   R->PsiStep++;
 | 
|---|
| 334 |   if (R->OldActualLocalPsiNo != R->ActualLocalPsiNo) {  // remember old actual local number
 | 
|---|
| 335 |     R->OldActualLocalPsiNo = R->ActualLocalPsiNo;
 | 
|---|
| 336 |     UpdateGramSchOldActualPsiNo(P, &P->Lat.Psi);
 | 
|---|
| 337 |   }
 | 
|---|
| 338 |   if (R->PsiStep >= R->MaxPsiStep) {  // done enough minimisation steps for this orbital?
 | 
|---|
| 339 |     R->PsiStep=0;
 | 
|---|
| 340 |     do {  // step on as long as we are still on a SkipType orbital
 | 
|---|
| 341 |       R->ActualLocalPsiNo++;
 | 
|---|
| 342 |       R->ActualLocalPsiNo %= P->Lat.Psi.LocalNo;
 | 
|---|
| 343 |     } while ((P->Lat.Psi.LocalPsiStatus[R->ActualLocalPsiNo].PsiType == SkipType));
 | 
|---|
| 344 |     UpdateGramSchActualPsiNo(P, &P->Lat.Psi);
 | 
|---|
| 345 |     if (R->UseAddGramSch >= 1) {
 | 
|---|
| 346 |       SetGramSchOldActualPsi(P,Psi,NotOrthogonal);
 | 
|---|
| 347 |       // setze von OldActual bis bla auf nicht orthogonal
 | 
|---|
| 348 |       GramSch(P, R->LevS, &P->Lat.Psi, Orthonormalize);
 | 
|---|
| 349 |     }
 | 
|---|
| 350 |   } else if (R->UseAddGramSch == 2) {
 | 
|---|
| 351 |     SetGramSchOldActualPsi(P, &P->Lat.Psi, NotOrthogonal); 
 | 
|---|
| 352 |     //if (SkipType == UnOccupied)
 | 
|---|
| 353 |       //ResetGramSch(P,Psi);
 | 
|---|
| 354 |     //fprintf(stderr,"UpdateActualPsiNo: GramSch() for %i\n",R->OldActualLocalPsiNo);
 | 
|---|
| 355 |     GramSch(P, R->LevS, &P->Lat.Psi, Orthonormalize);
 | 
|---|
| 356 |   }
 | 
|---|
| 357 | }*/
 | 
|---|
| 358 | 
 | 
|---|
| 359 | /** Upgrades the calculation to the next finer level.
 | 
|---|
| 360 |  * If we are below the initial level, 
 | 
|---|
| 361 |  * ChangePsiAndDensToLevUp() prepares density and Psi coefficients.
 | 
|---|
| 362 |  * Then the level change is made as RunStruct::LevSNo and RunStruct::Lev0No are decreased.
 | 
|---|
| 363 |  * The RunStruct::OldActualLocalPsi is set to current one and both are distributed
 | 
|---|
| 364 |  * (UpdateGramSchActualPsiNo(), UpdateGramSchOldActualPsiNo()).
 | 
|---|
| 365 |  * The PseudoPot'entials adopt the level up by calling ChangePseudoToLevUp().
 | 
|---|
| 366 |  * Now we are prepared to reset Energy::PsiEnergy and local and total density energy and
 | 
|---|
| 367 |  * recalculate them: InitPsiEnergyCalculation(), CalculateDensityEnergy() and CalculateIonsEnergy().
 | 
|---|
| 368 |  * Results are gathered EnergyAllReduce() and the output made EnergyOutput().
 | 
|---|
| 369 |  * Finally, the stop condition are reset for the new level (depending if it's the STANDARTLEVEL or
 | 
|---|
| 370 |  * not).
 | 
|---|
| 371 |  * \param *P Problem at hand
 | 
|---|
| 372 |  * \param *Stop is set to zero if we are below or equal to init level (see CalculateForce())
 | 
|---|
| 373 |  * \sa UpdateToNewWaves() very similar in the procedure, only the update of the Psis and density
 | 
|---|
| 374 |  *     (ChangePsiAndDensToLevUp()) is already made there.
 | 
|---|
| 375 |  * \bug Missing TotalEnergy shifting for other PsiTypeTag's!
 | 
|---|
| 376 |  */
 | 
|---|
| 377 | static void ChangeToLevUp(struct Problem *P, int *Stop)
 | 
|---|
| 378 | {
 | 
|---|
| 379 |   struct RunStruct *R = &P->R;
 | 
|---|
| 380 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
| 381 |   struct Psis *Psi = &Lat->Psi;
 | 
|---|
| 382 |   struct Energy *E = Lat->E;
 | 
|---|
| 383 |   struct RiemannTensor *RT = &Lat->RT;
 | 
|---|
| 384 |   int i;
 | 
|---|
| 385 |   if (R->LevSNo <= R->InitLevSNo) {
 | 
|---|
| 386 |     if (P->Call.out[LeaderOut] && (P->Par.me == 0))
 | 
|---|
| 387 |       fprintf(stderr, "(%i) ChangeLevUp: LevSNo(%i) <= InitLevSNo(%i)\n", P->Par.me, R->LevSNo, R->InitLevSNo);
 | 
|---|
| 388 |     *Stop = 1;
 | 
|---|
| 389 |     return;
 | 
|---|
| 390 |   }
 | 
|---|
| 391 |   if (P->Call.out[LeaderOut] && (P->Par.me == 0))
 | 
|---|
| 392 |     fprintf(stderr, "(0) ChangeLevUp: LevSNo(%i) InitLevSNo(%i)\n", R->LevSNo, R->InitLevSNo); 
 | 
|---|
| 393 |   *Stop = 0;
 | 
|---|
| 394 |   P->Speed.LevUpSteps++;
 | 
|---|
| 395 |   SpeedMeasure(P, SimTime, StopTimeDo);
 | 
|---|
| 396 |   SpeedMeasure(P, InitSimTime, StartTimeDo);
 | 
|---|
| 397 |   SpeedMeasure(P, InitDensityTime, StartTimeDo);
 | 
|---|
| 398 |   ChangePsiAndDensToLevUp(P);
 | 
|---|
| 399 |   SpeedMeasure(P, InitDensityTime, StopTimeDo);
 | 
|---|
| 400 |   R->LevSNo--;
 | 
|---|
| 401 |   R->Lev0No--;
 | 
|---|
| 402 |   if (RT->ActualUse == standby && R->LevSNo == STANDARTLEVEL) {
 | 
|---|
| 403 |     P->Lat.RT.ActualUse = active;
 | 
|---|
| 404 |     CalculateRiemannTensorData(P);
 | 
|---|
| 405 |     Error(SomeError, "Calculate RT: Not further implemented");
 | 
|---|
| 406 |   }
 | 
|---|
| 407 |   R->LevS = &P->Lat.Lev[R->LevSNo];
 | 
|---|
| 408 |   R->Lev0 = &P->Lat.Lev[R->Lev0No];
 | 
|---|
| 409 |   R->OldActualLocalPsiNo = R->ActualLocalPsiNo;
 | 
|---|
| 410 |   UpdateGramSchActualPsiNo(P, &P->Lat.Psi);
 | 
|---|
| 411 |   UpdateGramSchOldActualPsiNo(P, &P->Lat.Psi);
 | 
|---|
| 412 |   ResetBrent(P, &P->Lat.Psi);
 | 
|---|
| 413 |   R->PsiStep=0;
 | 
|---|
| 414 |   R->MinStep=0;
 | 
|---|
| 415 |   P->Grad.GradientArray[GraSchGradient] = R->LevS->LPsi->LocalPsi[Psi->LocalNo];
 | 
|---|
| 416 |   ChangePseudoToLevUp(P);
 | 
|---|
| 417 |   for (i=0; i<MAXALLPSIENERGY; i++) 
 | 
|---|
| 418 |     SetArrayToDouble0(E->PsiEnergy[i], Psi->LocalNo);
 | 
|---|
| 419 |   SetArrayToDouble0(E->AllLocalDensityEnergy, MAXALLDENSITYENERGY);
 | 
|---|
| 420 |   SetArrayToDouble0(E->AllTotalDensityEnergy, MAXALLDENSITYENERGY);
 | 
|---|
| 421 |   for (i=MAXOLD-1; i > 0; i--) {
 | 
|---|
| 422 |     E->TotalEnergy[i] = E->TotalEnergy[i-1];
 | 
|---|
| 423 |     Lat->Energy[UnOccupied].TotalEnergy[i] = Lat->Energy[UnOccupied].TotalEnergy[i-1];
 | 
|---|
| 424 |   }
 | 
|---|
| 425 |   InitPsiEnergyCalculation(P,Occupied);
 | 
|---|
| 426 |   CalculateDensityEnergy(P,1); 
 | 
|---|
| 427 |   CalculateIonsEnergy(P);
 | 
|---|
| 428 |   EnergyAllReduce(P);
 | 
|---|
| 429 | /*  SetCurrentMinState(P,UnOccupied);
 | 
|---|
| 430 |   InitPsiEnergyCalculation(P,UnOccupied);
 | 
|---|
| 431 |   CalculateGapEnergy(P);
 | 
|---|
| 432 |   EnergyAllReduce(P);
 | 
|---|
| 433 |   SetCurrentMinState(P,Occupied);*/
 | 
|---|
| 434 |   EnergyOutput(P,0);
 | 
|---|
| 435 |   if (R->LevSNo == STANDARTLEVEL) {
 | 
|---|
| 436 |     R->ActualMaxMinStep = R->MaxMinStep*R->MaxPsiStep*R->MaxMinStepFactor; 
 | 
|---|
| 437 |     R->ActualRelEpsTotalEnergy = R->RelEpsTotalEnergy;
 | 
|---|
| 438 |     R->ActualRelEpsKineticEnergy = R->RelEpsKineticEnergy;
 | 
|---|
| 439 |     R->ActualMaxMinStopStep = R->MaxMinStopStep;
 | 
|---|
| 440 |     R->ActualMaxMinGapStopStep = R->MaxMinGapStopStep;
 | 
|---|
| 441 |   } else {
 | 
|---|
| 442 |     R->ActualMaxMinStep = R->MaxInitMinStep*R->MaxPsiStep*R->MaxMinStepFactor;
 | 
|---|
| 443 |     R->ActualRelEpsTotalEnergy = R->InitRelEpsTotalEnergy;
 | 
|---|
| 444 |     R->ActualRelEpsKineticEnergy = R->InitRelEpsKineticEnergy;
 | 
|---|
| 445 |     R->ActualMaxMinStopStep = R->InitMaxMinStopStep; 
 | 
|---|
| 446 |     R->ActualMaxMinGapStopStep = R->InitMaxMinGapStopStep; 
 | 
|---|
| 447 |   }
 | 
|---|
| 448 |   R->MinStopStep = 0;
 | 
|---|
| 449 |   SpeedMeasure(P, InitSimTime, StopTimeDo);
 | 
|---|
| 450 |   SpeedMeasure(P, SimTime, StartTimeDo);
 | 
|---|
| 451 |   if (P->Call.out[LeaderOut] && (P->Par.me == 0))
 | 
|---|
| 452 |     fprintf(stderr, "(0) ChangeLevUp: LevSNo(%i) InitLevSNo(%i) Done\n", R->LevSNo, R->InitLevSNo); 
 | 
|---|
| 453 | }
 | 
|---|
| 454 | 
 | 
|---|
| 455 | /** Updates after the wave functions have changed (e.g.\ Ion moved).
 | 
|---|
| 456 |  * Old and current RunStruct::ActualLocalPsiNo are zeroed and distributed among the processes.
 | 
|---|
| 457 |  * InitDensityCalculation() is called, afterwards the pseudo potentials update to the new
 | 
|---|
| 458 |  * wave functions UpdatePseudoToNewWaves().
 | 
|---|
| 459 |  * Energy::AllLocalDensityEnergy, Energy::AllTotalDensityEnergy, Energy::AllTotalIonsEnergy and
 | 
|---|
| 460 |  * Energy::PsiEnergy[i] are set to zero.
 | 
|---|
| 461 |  * We are set to recalculate all of the following energies: Psis InitPsiEnergyCalculation(), density
 | 
|---|
| 462 |  * CalculateDensityEnergy(), ionic CalculateIonsEnergy() and ewald CalculateEwald().
 | 
|---|
| 463 |  * Results are gathered from all processes EnergyAllReduce() and EnergyOutput() is called.
 | 
|---|
| 464 |  * Finally, the various conditons in the RunStruct for stopping the calculation are set: number of
 | 
|---|
| 465 |  * minimisation steps, relative total or kinetic energy change or how often stop condition was
 | 
|---|
| 466 |  * evaluated.
 | 
|---|
| 467 |  * \param *P Problem at hand
 | 
|---|
| 468 |  */
 | 
|---|
| 469 | static void UpdateToNewWaves(struct Problem *P)
 | 
|---|
| 470 | {
 | 
|---|
| 471 |   struct RunStruct *R = &P->R;
 | 
|---|
| 472 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
| 473 |   struct Psis *Psi = &Lat->Psi;
 | 
|---|
| 474 |   struct Energy *E = Lat->E;
 | 
|---|
| 475 |   int i;//,type;
 | 
|---|
| 476 |   R->OldActualLocalPsiNo = R->ActualLocalPsiNo = 0;
 | 
|---|
| 477 |   //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!"); }
 | 
|---|
| 478 |   UpdateGramSchActualPsiNo(P, &P->Lat.Psi);
 | 
|---|
| 479 |   UpdateGramSchOldActualPsiNo(P, &P->Lat.Psi);
 | 
|---|
| 480 |   R->PsiStep=0;
 | 
|---|
| 481 |   R->MinStep=0;
 | 
|---|
| 482 |   SpeedMeasure(P, InitDensityTime, StartTimeDo);
 | 
|---|
| 483 |   //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!"); }
 | 
|---|
| 484 |   InitDensityCalculation(P);
 | 
|---|
| 485 |   SpeedMeasure(P, InitDensityTime, StopTimeDo);
 | 
|---|
| 486 |   UpdatePseudoToNewWaves(P);
 | 
|---|
| 487 |   for (i=0; i<MAXALLPSIENERGY; i++) 
 | 
|---|
| 488 |     SetArrayToDouble0(E->PsiEnergy[i], Psi->LocalNo);
 | 
|---|
| 489 |   SetArrayToDouble0(E->AllLocalDensityEnergy, MAXALLDENSITYENERGY);
 | 
|---|
| 490 |   SetArrayToDouble0(E->AllTotalDensityEnergy, MAXALLDENSITYENERGY);
 | 
|---|
| 491 |   SetArrayToDouble0(E->AllTotalIonsEnergy, MAXALLIONSENERGY);
 | 
|---|
| 492 |   InitPsiEnergyCalculation(P,Occupied);
 | 
|---|
| 493 |   CalculateDensityEnergy(P,1); 
 | 
|---|
| 494 |   CalculateIonsEnergy(P);
 | 
|---|
| 495 |   CalculateEwald(P, 0);
 | 
|---|
| 496 |   EnergyAllReduce(P);
 | 
|---|
| 497 | /*  if (R->DoUnOccupied) {
 | 
|---|
| 498 |           SetCurrentMinState(P,UnOccupied);
 | 
|---|
| 499 |           InitPsiEnergyCalculation(P,UnOccupied); 
 | 
|---|
| 500 |           CalculateGapEnergy(P);        
 | 
|---|
| 501 |           EnergyAllReduce(P);
 | 
|---|
| 502 |   }
 | 
|---|
| 503 |   if (R->DoPerturbation)
 | 
|---|
| 504 |     for(type=Perturbed_P0;type <=Perturbed_RxP2;type++) {
 | 
|---|
| 505 |       SetCurrentMinState(P,type);
 | 
|---|
| 506 |       InitPerturbedEnergyCalculation(P,1);
 | 
|---|
| 507 |       EnergyAllReduce(P);
 | 
|---|
| 508 |     }
 | 
|---|
| 509 |   SetCurrentMinState(P,Occupied);*/
 | 
|---|
| 510 |   E->TotalEnergyOuter[0] = E->TotalEnergy[0];
 | 
|---|
| 511 |   EnergyOutput(P,0);
 | 
|---|
| 512 |   R->ActualMaxMinStep = R->MaxMinStep*R->MaxPsiStep*R->MaxMinStepFactor; 
 | 
|---|
| 513 |   R->ActualRelEpsTotalEnergy = R->RelEpsTotalEnergy;
 | 
|---|
| 514 |   R->ActualRelEpsKineticEnergy = R->RelEpsKineticEnergy;
 | 
|---|
| 515 |   R->ActualMaxMinStopStep = R->MaxMinStopStep;
 | 
|---|
| 516 |   R->ActualMaxMinGapStopStep = R->MaxMinGapStopStep;
 | 
|---|
| 517 |   R->MinStopStep = 0;
 | 
|---|
| 518 | }
 | 
|---|
| 519 | 
 | 
|---|
| 520 | /** Evaluates the stop condition and returns 0 or 1 for occupied states.
 | 
|---|
| 521 |  * Stop is set when:
 | 
|---|
| 522 |  * - SuperStop at best possible point (e.g.\ LevelChange): RunStruct::PsiStep == 0 && SuperStop == 1
 | 
|---|
| 523 |  * - RunStruct::PsiStep && RunStruct::MinStopStep modulo RunStruct::ActualMaxMinStopStep == 0 
 | 
|---|
| 524 |  *    - To many minimisation steps: RunStruct::MinStep > RunStruct::ActualMaxMinStopStep
 | 
|---|
| 525 |  *    - below relative rate of change:
 | 
|---|
| 526 |  *        - Remember old values: Shift all RunStruct::TotalEnergy and RunStruct::KineticEnergy by
 | 
|---|
| 527 |  *          one and transfer current one from Energy::TotalEnergy and Energy::AllTotalPsiEnergy[KineticEnergy].
 | 
|---|
| 528 |  *        - if more than one minimisation step was made, calculate the relative changes of total
 | 
|---|
| 529 |  *          energy and kinetic energy and store them in RunStruct::ActualRelTotalEnergy and
 | 
|---|
| 530 |  *          RunStruct::ActualRelKineticEnergy and check them against the sought for minimum
 | 
|---|
| 531 |  *          values RunStruct::ActualRelEpsTotalEnergy and RunStruct::ActualRelEpsKineticEnergy.
 | 
|---|
| 532 |  * - if RunStruct::PsiStep is zero (default), increase RunStruct::MinStopStep
 | 
|---|
| 533 |  * \param *P Problem at hand
 | 
|---|
| 534 |  * \param SuperStop 1 - external signal: ceasing calculation, 0 - no signal
 | 
|---|
| 535 |  * \return Stop: 1 - stop, 0 - continue
 | 
|---|
| 536 |  */
 | 
|---|
| 537 | int CalculateMinimumStop(struct Problem *P, int SuperStop)
 | 
|---|
| 538 | {
 | 
|---|
| 539 |   int Stop = 0, i;
 | 
|---|
| 540 |   struct RunStruct *R = &P->R;
 | 
|---|
| 541 |   struct Energy *E = P->Lat.E;
 | 
|---|
| 542 |   if (R->PsiStep == 0 && SuperStop) Stop = 1;
 | 
|---|
| 543 |   if (R->PsiStep == 0 && ((R->MinStopStep % R->ActualMaxMinStopStep == 0 && R->CurrentMin != UnOccupied) || (R->MinStopStep % R->ActualMaxMinGapStopStep == 0 && R->CurrentMin == UnOccupied))) {
 | 
|---|
| 544 |     if (R->MinStep >= R->ActualMaxMinStep) Stop = 1;
 | 
|---|
| 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 |       //fprintf(stderr, "(%i) Comparing TE: %lg < %lg\tKE: %lg < %lg?\n", P->Par.me, R->ActualRelTotalEnergy[0], R->ActualRelEpsTotalEnergy, R->ActualRelKineticEnergy[0], R->ActualRelEpsKineticEnergy);
 | 
|---|
| 568 |       if ((R->ActualRelTotalEnergy[0] < R->ActualRelEpsTotalEnergy) &&
 | 
|---|
| 569 |           (R->ActualRelKineticEnergy[0]  < R->ActualRelEpsKineticEnergy))
 | 
|---|
| 570 |         Stop = 1;
 | 
|---|
| 571 |     }
 | 
|---|
| 572 |   }
 | 
|---|
| 573 |   if (R->PsiStep == 0)
 | 
|---|
| 574 |     R->MinStopStep++;
 | 
|---|
| 575 |   if (P->Call.WriteSrcFiles == 2)
 | 
|---|
| 576 |     OutputVisSrcFiles(P, R->CurrentMin);
 | 
|---|
| 577 |   return(Stop);
 | 
|---|
| 578 | }
 | 
|---|
| 579 | 
 | 
|---|
| 580 | /** Evaluates the stop condition and returns 0 or 1 for gap energies.
 | 
|---|
| 581 |  * Stop is set when:
 | 
|---|
| 582 |  * - SuperStop at best possible point (e.g.\ LevelChange): RunStruct::PsiStep == 0 && SuperStop == 1
 | 
|---|
| 583 |  * - RunStruct::PsiStep && RunStruct::MinStopStep modulo RunStruct::ActualMaxMinStopStep == 0 
 | 
|---|
| 584 |  *    - To many minimisation steps: RunStruct::MinStep > RunStruct::ActualMaxMinStopStep
 | 
|---|
| 585 |  *    - below relative rate of change:
 | 
|---|
| 586 |  *        - Remember old values: Shift all RunStruct::TotalEnergy and RunStruct::KineticEnergy by
 | 
|---|
| 587 |  *          one and transfer current one from Energy::TotalEnergy and Energy::AllTotalPsiEnergy[KineticEnergy].
 | 
|---|
| 588 |  *        - if more than one minimisation step was made, calculate the relative changes of total
 | 
|---|
| 589 |  *          energy and kinetic energy and store them in RunStruct::ActualRelTotalEnergy and
 | 
|---|
| 590 |  *          RunStruct::ActualRelKineticEnergy and check them against the sought for minimum
 | 
|---|
| 591 |  *          values RunStruct::ActualRelEpsTotalEnergy and RunStruct::ActualRelEpsKineticEnergy.
 | 
|---|
| 592 |  * - if RunStruct::PsiStep is zero (default), increase RunStruct::MinStopStep
 | 
|---|
| 593 |  * \param *P Problem at hand
 | 
|---|
| 594 |  * \param SuperStop 1 - external signal: ceasing calculation, 0 - no signal
 | 
|---|
| 595 |  * \return Stop: 1 - stop, 0 - continue
 | 
|---|
| 596 |  * \sa CalculateMinimumStop() - same procedure for occupied states
 | 
|---|
| 597 |  *//*
 | 
|---|
| 598 | static double CalculateGapStop(struct Problem *P, int SuperStop)
 | 
|---|
| 599 | {
 | 
|---|
| 600 |   int Stop = 0, i;
 | 
|---|
| 601 |   struct RunStruct *R = &P->R;
 | 
|---|
| 602 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
| 603 |   struct Energy *E = P->Lat.E;
 | 
|---|
| 604 |   if (R->PsiStep == 0 && SuperStop) Stop = 1;
 | 
|---|
| 605 |   if (R->PsiStep == 0 && (R->MinStopStep % R->ActualMaxMinGapStopStep) == 0) {
 | 
|---|
| 606 |     if (R->MinStep >= R->ActualMaxMinStep) Stop = 1;
 | 
|---|
| 607 |     for (i=RUNMAXOLD-1; i > 0; i--) {
 | 
|---|
| 608 |       R->TotalGapEnergy[i] = R->TotalGapEnergy[i-1];
 | 
|---|
| 609 |       R->KineticGapEnergy[i] = R->KineticGapEnergy[i-1];
 | 
|---|
| 610 |     }
 | 
|---|
| 611 |     R->TotalGapEnergy[0] = Lat->Energy[UnOccupied].TotalEnergy[0];
 | 
|---|
| 612 |     R->KineticGapEnergy[0] = E->AllTotalPsiEnergy[GapPsiEnergy];
 | 
|---|
| 613 |     if (R->MinStopStep) {
 | 
|---|
| 614 |       if (R->TotalGapEnergy[1] < MYEPSILON) fprintf(stderr,"CalculateMinimumStop: R->TotalGapEnergy[1] = %lg\n",R->TotalGapEnergy[1]);
 | 
|---|
| 615 |       R->ActualRelTotalGapEnergy[0] = fabs((R->TotalGapEnergy[0]-R->TotalGapEnergy[1])/R->TotalGapEnergy[1]);
 | 
|---|
| 616 |       if (R->KineticGapEnergy[1] < MYEPSILON) fprintf(stderr,"CalculateMinimumStop: R->KineticGapEnergy[1] = %lg\n",R->KineticGapEnergy[1]);
 | 
|---|
| 617 |       R->ActualRelKineticGapEnergy[0] = fabs((R->KineticGapEnergy[0]-R->KineticGapEnergy[1])/R->KineticGapEnergy[1]);
 | 
|---|
| 618 |       if (P->Call.out[LeaderOut] && (P->Par.me == 0))
 | 
|---|
| 619 |         fprintf(stderr, "(%i) -------------------------> ARelTGE: %e\tARelKGE: %e\n", P->Par.me, R->ActualRelTotalGapEnergy[0], R->ActualRelKineticGapEnergy[0]); 
 | 
|---|
| 620 |       if ((R->ActualRelTotalGapEnergy[0] < R->ActualRelEpsTotalGapEnergy) &&
 | 
|---|
| 621 |           (R->ActualRelKineticGapEnergy[0]  < R->ActualRelEpsKineticGapEnergy))
 | 
|---|
| 622 |         Stop = 1;
 | 
|---|
| 623 |     }
 | 
|---|
| 624 |   }
 | 
|---|
| 625 |   if (R->PsiStep == 0)
 | 
|---|
| 626 |     R->MinStopStep++;
 | 
|---|
| 627 | 
 | 
|---|
| 628 |   return(Stop);
 | 
|---|
| 629 | }*/
 | 
|---|
| 630 | 
 | 
|---|
| 631 | #define StepTolerance 1e-4
 | 
|---|
| 632 | 
 | 
|---|
| 633 | static void CalculateEnergy(struct Problem *P) {
 | 
|---|
| 634 |   SpeedMeasure(P, DensityTime, StartTimeDo);
 | 
|---|
| 635 |   UpdateDensityCalculation(P);
 | 
|---|
| 636 |   SpeedMeasure(P, DensityTime, StopTimeDo);
 | 
|---|
| 637 |   UpdatePsiEnergyCalculation(P);
 | 
|---|
| 638 |   CalculateDensityEnergy(P, 0);
 | 
|---|
| 639 |   //CalculateIonsEnergy(P);
 | 
|---|
| 640 |   EnergyAllReduce(P);
 | 
|---|
| 641 | }
 | 
|---|
| 642 | 
 | 
|---|
| 643 | /** Energy functional depending on one parameter \a x (for a certain Psi in a certain conjugate direction).
 | 
|---|
| 644 |  * \param x parameter for the which the function must be minimized
 | 
|---|
| 645 |  * \param *params additional params
 | 
|---|
| 646 |  * \return total energy if Psi is changed according to the given parameter
 | 
|---|
| 647 |  */
 | 
|---|
| 648 | static double fn1 (double x, void * params) {
 | 
|---|
| 649 |   struct Problem *P = (struct Problem *)(params);
 | 
|---|
| 650 |   struct RunStruct *R = &P->R;
 | 
|---|
| 651 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
| 652 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
| 653 |   int ElementSize = (sizeof(fftw_complex) / sizeof(double));
 | 
|---|
| 654 |   int i=R->ActualLocalPsiNo;
 | 
|---|
| 655 |   double ret;
 | 
|---|
| 656 |   
 | 
|---|
| 657 |   //fprintf(stderr,"(%i) Evaluating fnl at %lg ...\n",P->Par.me, x);
 | 
|---|
| 658 |   //TestForOrth(P,R->LevS,P->Grad.GradientArray[GraSchGradient]);
 | 
|---|
| 659 |   CalculateNewWave(P, &x); // also stores Psi to oldPsi
 | 
|---|
| 660 |   //TestGramSch(P,R->LevS,&P->Lat.Psi,Occupied);
 | 
|---|
| 661 |   //fprintf(stderr,"(%i) Testing for orthogonality of %i against ...\n",P->Par.me, R->ActualLocalPsiNo);
 | 
|---|
| 662 |   //TestForOrth(P, LevS, LevS->LPsi->LocalPsi[R->ActualLocalPsiNo]);
 | 
|---|
| 663 |   //UpdateActualPsiNo(P, Occupied);
 | 
|---|
| 664 |   //UpdateEnergyArray(P);
 | 
|---|
| 665 |   CalculateEnergy(P);
 | 
|---|
| 666 |   ret = Lat->E->TotalEnergy[0];
 | 
|---|
| 667 |   memcpy(LevS->LPsi->LocalPsi[i], LevS->LPsi->OldLocalPsi[i], ElementSize*LevS->MaxG*sizeof(double)); // restore old Psi from OldPsi
 | 
|---|
| 668 |   //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);
 | 
|---|
| 669 |   CalculateEnergy(P);
 | 
|---|
| 670 |   //fprintf(stderr,"(%i) fnl(%lg) = %lg\n", P->Par.me, x, ret);
 | 
|---|
| 671 |   return ret;
 | 
|---|
| 672 | }
 | 
|---|
| 673 | 
 | 
|---|
| 674 | #ifdef HAVE_INLINE
 | 
|---|
| 675 | inline void flip(double *a, double *b) {
 | 
|---|
| 676 | #else
 | 
|---|
| 677 | void flip(double *a, double *b) {
 | 
|---|
| 678 | #endif
 | 
|---|
| 679 |   double tmp = *a;
 | 
|---|
| 680 |   *a = *b;
 | 
|---|
| 681 |   *b = tmp;
 | 
|---|
| 682 | }
 | 
|---|
| 683 | 
 | 
|---|
| 684 | 
 | 
|---|
| 685 | /** Minimise PsiType#Occupied orbitals.
 | 
|---|
| 686 |  * It is checked whether CallOptions#ReadSrcFiles is set and thus coefficients for the level have to be
 | 
|---|
| 687 |  * read from file and afterwards initialized.
 | 
|---|
| 688 |  * 
 | 
|---|
| 689 |  * Then follows the main loop, until a stop condition is met:
 | 
|---|
| 690 |  * -# CalculateNewWave()\n
 | 
|---|
| 691 |  *    Over a conjugate gradient method the next (minimal) wave function is sought for.
 | 
|---|
| 692 |  * -# UpdateActualPsiNo()\n
 | 
|---|
| 693 |  *    Switch local Psi to next one.
 | 
|---|
| 694 |  * -# UpdateEnergyArray()\n
 | 
|---|
| 695 |  *    Shift archived energy values to make space for next one.
 | 
|---|
| 696 |  * -# UpdateDensityCalculation(), SpeedMeasure()'d in DensityTime\n
 | 
|---|
| 697 |  *    Calculate TotalLocalDensity of LocalPsis and gather results as TotalDensity.
 | 
|---|
| 698 |  * -# UpdatePsiEnergyCalculation()\n
 | 
|---|
| 699 |  *    Calculate kinetic and non-local energy contributons from the Psis.
 | 
|---|
| 700 |  * -# CalculateDensityEnergy()\n
 | 
|---|
| 701 |  *    Calculate remaining energy contributions from the Density and adds \f$V_xc\f$ onto DensityTypes#HGDensity.
 | 
|---|
| 702 |  * -# CalculateIonsEnergy()\n
 | 
|---|
| 703 |  *    Calculate the Gauss self energy of the Ions.
 | 
|---|
| 704 |  * -# EnergyAllReduce()\n
 | 
|---|
| 705 |  *    Gather PsiEnergy results from all processes and sum up together with all other contributions to TotalEnergy.
 | 
|---|
| 706 |  * -# CheckCPULIM()\n
 | 
|---|
| 707 |  *    Check if external signal has been received (e.g. end of time slit on cluster), break operation at next possible moment.
 | 
|---|
| 708 |  * -# CalculateMinimumStop()\n
 | 
|---|
| 709 |  *    Evaluates stop condition if desired precision or steps or ... have been reached. Otherwise go to
 | 
|---|
| 710 |  *    CalculateNewWave().
 | 
|---|
| 711 |  * 
 | 
|---|
| 712 |  * Before return orthonormality is tested.
 | 
|---|
| 713 |  * \param *P Problem at hand
 | 
|---|
| 714 |  * \param *Stop flag to determine if epsilon stop conditions have met
 | 
|---|
| 715 |  * \param *SuperStop flag to determinte whether external signal's required end of calculations
 | 
|---|
| 716 |  * \bug ResetGramSch() not allowed after reading orthonormal values from file
 | 
|---|
| 717 |  */
 | 
|---|
| 718 | static void MinimiseOccupied(struct Problem *P, int *Stop, int *SuperStop)
 | 
|---|
| 719 | {
 | 
|---|
| 720 |   struct RunStruct *R = &P->R;
 | 
|---|
| 721 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
| 722 |   struct Psis *Psi = &Lat->Psi;
 | 
|---|
| 723 |   //struct FileData *F = &P->Files;
 | 
|---|
| 724 | //  int i;
 | 
|---|
| 725 | //  double norm;
 | 
|---|
| 726 |   //double dEdt0,ddEddt0,HartreeddEddt0,XCddEddt0, d[4], D[4],ConDirHConDir;
 | 
|---|
| 727 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
| 728 |   int ElementSize = (sizeof(fftw_complex) / sizeof(double));
 | 
|---|
| 729 |   int iter = 0, status, max_iter=10;
 | 
|---|
| 730 |   const gsl_min_fminimizer_type *T;
 | 
|---|
| 731 |   gsl_min_fminimizer *s;
 | 
|---|
| 732 |   double m, a, b;
 | 
|---|
| 733 |   double f_m = 0., f_a, f_b;
 | 
|---|
| 734 |   double dcos, dsin;
 | 
|---|
| 735 |   int g;
 | 
|---|
| 736 |   fftw_complex *ConDir = P->Grad.GradientArray[ConDirGradient];
 | 
|---|
| 737 |   fftw_complex *source = NULL, *oldsource = NULL; 
 | 
|---|
| 738 |   gsl_function F;
 | 
|---|
| 739 |   F.function = &fn1;
 | 
|---|
| 740 |   F.params = (void *) P;
 | 
|---|
| 741 |   T = gsl_min_fminimizer_brent;
 | 
|---|
| 742 |   s = gsl_min_fminimizer_alloc (T);
 | 
|---|
| 743 |   int DoBrent, StartLocalPsiNo;
 | 
|---|
| 744 |  
 | 
|---|
| 745 |   ResetBrent(P,Psi);
 | 
|---|
| 746 |   *Stop = 0;
 | 
|---|
| 747 |   if (P->Call.ReadSrcFiles) {
 | 
|---|
| 748 |     if (!ReadSrcPsiDensity(P,Occupied,1, R->LevSNo)) {  // if file for level exists and desired, read from file
 | 
|---|
| 749 |       P->Call.ReadSrcFiles = 0; // -r was bogus, remove it, have to start anew
 | 
|---|
| 750 |       if(P->Call.out[MinOut]) fprintf(stderr,"(%i) Re-initializing, files are missing/corrupted...\n", P->Par.me);
 | 
|---|
| 751 |       InitPsisValue(P, Psi->TypeStartIndex[Occupied], Psi->TypeStartIndex[Occupied+1]);  // initialize perturbed array for this run
 | 
|---|
| 752 |       ResetGramSchTagType(P, Psi, Occupied, NotOrthogonal); // loaded values are orthonormal
 | 
|---|
| 753 |     } else {
 | 
|---|
| 754 |       SpeedMeasure(P, InitSimTime, StartTimeDo);  
 | 
|---|
| 755 |       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]);
 | 
|---|
| 756 |       ReadSrcPsiDensity(P, Occupied, 0, R->LevSNo);
 | 
|---|
| 757 |       //ResetGramSchTagType(P, Psi, Occupied, IsOrthonormal); // loaded values are orthonormal
 | 
|---|
| 758 |       // note: this did not work and is currently not clear why not (as TestGramSch says: OK, but minimisation goes awry without the following GramSch)
 | 
|---|
| 759 |     }
 | 
|---|
| 760 |     SpeedMeasure(P, InitGramSchTime, StartTimeDo);  
 | 
|---|
| 761 |     GramSch(P, R->LevS, Psi, Orthonormalize);
 | 
|---|
| 762 |     SpeedMeasure(P, InitGramSchTime, StopTimeDo);  
 | 
|---|
| 763 |     SpeedMeasure(P, InitDensityTime, StartTimeDo);
 | 
|---|
| 764 |     InitDensityCalculation(P);
 | 
|---|
| 765 |     SpeedMeasure(P, InitDensityTime, StopTimeDo);
 | 
|---|
| 766 |     InitPsiEnergyCalculation(P, Occupied);  // go through all orbitals calculating kinetic and non-local
 | 
|---|
| 767 |     StartLocalPsiNo = R->ActualLocalPsiNo;
 | 
|---|
| 768 |     do { // otherwise OnePsiElementAddData#Lambda is calculated only for current Psi not for all
 | 
|---|
| 769 |       CalculateDensityEnergy(P, 0);
 | 
|---|
| 770 |       UpdateActualPsiNo(P, Occupied);
 | 
|---|
| 771 |     } while (R->ActualLocalPsiNo != StartLocalPsiNo);
 | 
|---|
| 772 |     CalculateIonsEnergy(P);
 | 
|---|
| 773 |     EnergyAllReduce(P);
 | 
|---|
| 774 |     SpeedMeasure(P, InitSimTime, StopTimeDo);  
 | 
|---|
| 775 |     R->LevS->Step++;
 | 
|---|
| 776 |     EnergyOutput(P,0);
 | 
|---|
| 777 |   } 
 | 
|---|
| 778 |   if (P->Call.ReadSrcFiles != 1) {  // otherwise minimise oneself
 | 
|---|
| 779 |     if(P->Call.out[LeaderOut]) fprintf(stderr,"(%i)Beginning minimisation of type %s ...\n", P->Par.me, R->MinimisationName[Occupied]);
 | 
|---|
| 780 |     while (*Stop != 1) {  // loop testing condition over all Psis
 | 
|---|
| 781 |       // in the following loop, we have two cases:
 | 
|---|
| 782 |       // 1) still far away and just guessing: Use the normal CalculateNewWave() to improve Psi
 | 
|---|
| 783 |       // 2) closer (DoBrent=-1): use brent line search instead
 | 
|---|
| 784 |       // and due to these two cases, we also have two ifs inside each in order to catch stepping from one case
 | 
|---|
| 785 |       // to the other - due to decreasing DoBrent and/or stepping to the next Psi (which may not yet be DoBrent==1)
 | 
|---|
| 786 | 
 | 
|---|
| 787 |       // case 1)
 | 
|---|
| 788 |       if (Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent != 1) {
 | 
|---|
| 789 |         //SetArrayToDouble0((double *)LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo],LevS->MaxG*2);
 | 
|---|
| 790 |         if (R->DoBrent == 1) {
 | 
|---|
| 791 |           memcpy(LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo], LevS->LPsi->LocalPsi[R->ActualLocalPsiNo], ElementSize*LevS->MaxG*sizeof(double)); // restore old Psi from OldPsi
 | 
|---|
| 792 |           //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);
 | 
|---|
| 793 |           f_m = P->Lat.E->TotalEnergy[0]; // grab first value
 | 
|---|
| 794 |           m = 0.;
 | 
|---|
| 795 |         }
 | 
|---|
| 796 |         CalculateNewWave(P,NULL);
 | 
|---|
| 797 |         if ((R->DoBrent == 1) && (fabs(Lat->E->delta[0]) < M_PI/4.)) 
 | 
|---|
| 798 |           Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent--;
 | 
|---|
| 799 |         if (Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent != 1) {
 | 
|---|
| 800 |           UpdateActualPsiNo(P, Occupied);
 | 
|---|
| 801 |           UpdateEnergyArray(P);
 | 
|---|
| 802 |           CalculateEnergy(P); // just to get a sensible delta
 | 
|---|
| 803 |           if ((R->ActualLocalPsiNo != R->OldActualLocalPsiNo) && (Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent == 1)) {
 | 
|---|
| 804 |              R->OldActualLocalPsiNo = R->ActualLocalPsiNo;
 | 
|---|
| 805 |             // if we stepped on to a new Psi, which is already down at DoBrent=1 unlike the last one,
 | 
|---|
| 806 |             // then an up-to-date gradient is missing for the following Brent line search
 | 
|---|
| 807 |             if(P->Call.out[MinOut]) fprintf(stderr,"(%i) We stepped on to a new Psi, which is already in the Brent regime ...re-calc delta\n", P->Par.me);
 | 
|---|
| 808 |             memcpy(LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo], LevS->LPsi->LocalPsi[R->ActualLocalPsiNo], ElementSize*LevS->MaxG*sizeof(double)); // restore old Psi from OldPsi
 | 
|---|
| 809 |             //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);
 | 
|---|
| 810 |             f_m = P->Lat.E->TotalEnergy[0]; // grab first value
 | 
|---|
| 811 |             m = 0.;
 | 
|---|
| 812 |             DoBrent = Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent;
 | 
|---|
| 813 |             Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent = 2;
 | 
|---|
| 814 |             CalculateNewWave(P,NULL);
 | 
|---|
| 815 |             Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent = DoBrent;
 | 
|---|
| 816 |           }
 | 
|---|
| 817 |           //fprintf(stderr,"(%i) fnl(%lg) = %lg\n", P->Par.me, m, f_m);
 | 
|---|
| 818 |         } 
 | 
|---|
| 819 |       }
 | 
|---|
| 820 |       
 | 
|---|
| 821 |       // case 2)
 | 
|---|
| 822 |       if (Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent == 1) {
 | 
|---|
| 823 |         R->PsiStep=R->MaxPsiStep;  // no more fresh gradients from this point for current ActualLocalPsiNo
 | 
|---|
| 824 |         a = b = 0.5*fabs(Lat->E->delta[0]);
 | 
|---|
| 825 |         // we have a meaningful first minimum guess from above CalculateNewWave() resp. from end of this if of last step: Lat->E->delta[0]
 | 
|---|
| 826 |         source = LevS->LPsi->LocalPsi[R->ActualLocalPsiNo];
 | 
|---|
| 827 |         oldsource = LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo];
 | 
|---|
| 828 |         //SetArrayToDouble0((double *)source,LevS->MaxG*2);
 | 
|---|
| 829 |         do { 
 | 
|---|
| 830 |           a -= fabs(Lat->E->delta[0]) == 0 ? 0.1 : fabs(Lat->E->delta[0]);
 | 
|---|
| 831 |           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)
 | 
|---|
| 832 |           dcos = cos(a);
 | 
|---|
| 833 |           dsin = sin(a);
 | 
|---|
| 834 |           for (g = 0; g < LevS->MaxG; g++) {  // Here all coefficients are updated for the new found wave function
 | 
|---|
| 835 |             //if (isnan(ConDir[g].re)) { fprintf(stderr,"WARNGING: CalculateLineSearch(): ConDir_%i(%i) = NaN!\n", R->ActualLocalPsiNo, g); Error(SomeError, "NaN-Fehler!"); }
 | 
|---|
| 836 |             c_re(source[g]) = c_re(oldsource[g])*dcos + c_re(ConDir[g])*dsin;
 | 
|---|
| 837 |             c_im(source[g]) = c_im(oldsource[g])*dcos + c_im(ConDir[g])*dsin;
 | 
|---|
| 838 |           }
 | 
|---|
| 839 |           CalculateEnergy(P);
 | 
|---|
| 840 |           f_a = P->Lat.E->TotalEnergy[0]; // grab second value at left border
 | 
|---|
| 841 |           //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]);
 | 
|---|
| 842 |         } while (f_a < f_m);
 | 
|---|
| 843 | 
 | 
|---|
| 844 |         //SetArrayToDouble0((double *)source,LevS->MaxG*2);
 | 
|---|
| 845 |         do {
 | 
|---|
| 846 |           b += fabs(Lat->E->delta[0]) == 0 ? 0.1 : fabs(Lat->E->delta[0]);
 | 
|---|
| 847 |           if (b > M_PI/2.) b = M_PI/2.;
 | 
|---|
| 848 |           dcos = cos(b);
 | 
|---|
| 849 |           dsin = sin(b);
 | 
|---|
| 850 |           for (g = 0; g < LevS->MaxG; g++) {  // Here all coefficients are updated for the new found wave function
 | 
|---|
| 851 |             //if (isnan(ConDir[g].re)) { fprintf(stderr,"WARNGING: CalculateLineSearch(): ConDir_%i(%i) = NaN!\n", R->ActualLocalPsiNo, g); Error(SomeError, "NaN-Fehler!"); }
 | 
|---|
| 852 |             c_re(source[g]) = c_re(oldsource[g])*dcos + c_re(ConDir[g])*dsin;
 | 
|---|
| 853 |             c_im(source[g]) = c_im(oldsource[g])*dcos + c_im(ConDir[g])*dsin;
 | 
|---|
| 854 |           }
 | 
|---|
| 855 |           CalculateEnergy(P);
 | 
|---|
| 856 |           f_b = P->Lat.E->TotalEnergy[0]; // grab second value at left border
 | 
|---|
| 857 |           //fprintf(stderr,"(%i) fnl(%lg) = %lg\n", P->Par.me, b, f_b);
 | 
|---|
| 858 |         } while (f_b < f_m);
 | 
|---|
| 859 |         
 | 
|---|
| 860 |         memcpy(source, oldsource, ElementSize*LevS->MaxG*sizeof(double)); // restore old Psi from OldPsi
 | 
|---|
| 861 |         //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);
 | 
|---|
| 862 |         CalculateEnergy(P);
 | 
|---|
| 863 | 
 | 
|---|
| 864 |         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);
 | 
|---|
| 865 |         iter=0; 
 | 
|---|
| 866 |         gsl_min_fminimizer_set_with_values (s, &F, m, f_m, a, f_a, b, f_b);
 | 
|---|
| 867 |         if(P->Call.out[ValueOut]) fprintf (stderr,"(%i) using %s method\n",P->Par.me, gsl_min_fminimizer_name (s));
 | 
|---|
| 868 |         if(P->Call.out[ValueOut]) fprintf (stderr,"(%i) %5s [%9s, %9s] %9s %9s\n",P->Par.me, "iter", "lower", "upper", "min", "err(est)");
 | 
|---|
| 869 |         if(P->Call.out[ValueOut]) fprintf (stderr,"(%i) %5d [%.7f, %.7f] %.7f %.7f\n",P->Par.me, iter, a, b, m, b - a);
 | 
|---|
| 870 |         do {
 | 
|---|
| 871 |           iter++;
 | 
|---|
| 872 |           status = gsl_min_fminimizer_iterate (s);
 | 
|---|
| 873 |        
 | 
|---|
| 874 |           m = gsl_min_fminimizer_x_minimum (s);
 | 
|---|
| 875 |           a = gsl_min_fminimizer_x_lower (s);
 | 
|---|
| 876 |           b = gsl_min_fminimizer_x_upper (s);
 | 
|---|
| 877 |        
 | 
|---|
| 878 |           status = gsl_min_test_interval (a, b, 0.001, 0.0);
 | 
|---|
| 879 |        
 | 
|---|
| 880 |           if (status == GSL_SUCCESS)
 | 
|---|
| 881 |             if(P->Call.out[ValueOut]) fprintf (stderr,"(%i) Converged:\n",P->Par.me);
 | 
|---|
| 882 |        
 | 
|---|
| 883 |           if(P->Call.out[ValueOut]) fprintf (stderr,"(%i) %5d [%.7f, %.7f] %.7f %.7f\n",P->Par.me,
 | 
|---|
| 884 |             iter, a, b, m, b - a);
 | 
|---|
| 885 |         } while (status == GSL_CONTINUE && iter < max_iter);
 | 
|---|
| 886 |         CalculateNewWave(P,&m);
 | 
|---|
| 887 |         TestGramSch(P,LevS,Psi,Occupied);
 | 
|---|
| 888 |         UpdateActualPsiNo(P, Occupied); // step on due setting to MaxPsiStep further above
 | 
|---|
| 889 |         UpdateEnergyArray(P);
 | 
|---|
| 890 |         CalculateEnergy(P);
 | 
|---|
| 891 |         //fprintf(stderr,"(%i) Final value for Psi %i: %lg\n", P->Par.me, R->ActualLocalPsiNo, P->Lat.E->TotalEnergy[0]);
 | 
|---|
| 892 |         R->MinStopStep =  R->ActualMaxMinStopStep; // check stop condition every time
 | 
|---|
| 893 |         if (*SuperStop != 1)
 | 
|---|
| 894 |           *SuperStop = CheckCPULIM(P);
 | 
|---|
| 895 |         *Stop = CalculateMinimumStop(P, *SuperStop);
 | 
|---|
| 896 |         R->OldActualLocalPsiNo = R->ActualLocalPsiNo;
 | 
|---|
| 897 |         if (Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent == 1) { // new wave function means new gradient!
 | 
|---|
| 898 |           DoBrent = Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent;
 | 
|---|
| 899 |           Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent = 2;
 | 
|---|
| 900 |           //SetArrayToDouble0((double *)LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo],LevS->MaxG*2);
 | 
|---|
| 901 |           memcpy(LevS->LPsi->OldLocalPsi[R->ActualLocalPsiNo], LevS->LPsi->LocalPsi[R->ActualLocalPsiNo], ElementSize*LevS->MaxG*sizeof(double)); // restore old Psi from OldPsi
 | 
|---|
| 902 |           //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);
 | 
|---|
| 903 |           f_m = P->Lat.E->TotalEnergy[0]; // grab first value
 | 
|---|
| 904 |           m = 0.;
 | 
|---|
| 905 |           CalculateNewWave(P,NULL);
 | 
|---|
| 906 |           Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent = DoBrent;
 | 
|---|
| 907 |         }
 | 
|---|
| 908 |       }
 | 
|---|
| 909 | 
 | 
|---|
| 910 |       if (Lat->Psi.LocalPsiStatus[R->ActualLocalPsiNo].DoBrent != 1) { // otherwise the following checks eliminiate stop=1 from above
 | 
|---|
| 911 |         if (*SuperStop != 1)
 | 
|---|
| 912 |           *SuperStop = CheckCPULIM(P);
 | 
|---|
| 913 |         *Stop = CalculateMinimumStop(P, *SuperStop);
 | 
|---|
| 914 |       }
 | 
|---|
| 915 |       /*EnergyOutput(P, Stop);*/
 | 
|---|
| 916 |       P->Speed.Steps++;
 | 
|---|
| 917 |       R->LevS->Step++;
 | 
|---|
| 918 |       /*ControlNativeDensity(P);*/
 | 
|---|
| 919 |       //fprintf(stderr,"(%i) Stop %i\n",P->Par.me, Stop);
 | 
|---|
| 920 |     }
 | 
|---|
| 921 |     if (*SuperStop == 1) OutputVisSrcFiles(P, Occupied); // is now done after localization (ComputeMLWF())
 | 
|---|
| 922 |   }
 | 
|---|
| 923 |   TestGramSch(P,R->LevS,Psi, Occupied);
 | 
|---|
| 924 | }
 | 
|---|
| 925 | 
 | 
|---|
| 926 | /** Minimisation of the PsiTagType#UnOccupied orbitals in the field of the occupied ones.
 | 
|---|
| 927 |  * Assuming RunStruct#ActualLocalPsiNo is currenlty still an occupied wave function, we stop onward to the first
 | 
|---|
| 928 |  * unoccupied and reset RunStruct#OldActualLocalPsiNo. Then it is checked whether CallOptions#ReadSrcFiles is set
 | 
|---|
| 929 |  * and thus coefficients for the level have to be read from file and afterwards initialized.
 | 
|---|
| 930 |  * 
 | 
|---|
| 931 |  * Then follows the main loop, until a stop condition is met:
 | 
|---|
| 932 |  * -# CalculateNewWave()\n
 | 
|---|
| 933 |  *    Over a conjugate gradient method the next (minimal) wave function is sought for.
 | 
|---|
| 934 |  * -# UpdateActualPsiNo()\n
 | 
|---|
| 935 |  *    Switch local Psi to next one.
 | 
|---|
| 936 |  * -# UpdateEnergyArray()\n
 | 
|---|
| 937 |  *    Shift archived energy values to make space for next one.
 | 
|---|
| 938 |  * -# UpdateDensityCalculation(), SpeedMeasure()'d in DensityTime\n
 | 
|---|
| 939 |  *    Calculate TotalLocalDensity of LocalPsis and gather results as TotalDensity.
 | 
|---|
| 940 |  * -# UpdatePsiEnergyCalculation()\n
 | 
|---|
| 941 |  *    Calculate kinetic and non-local energy contributons from the Psis.
 | 
|---|
| 942 |  * -# CalculateGapEnergy()\n
 | 
|---|
| 943 |  *    Calculate Gap energies (Hartreepotential, Pseudo) and the gradient.
 | 
|---|
| 944 |  * -# EnergyAllReduce()\n
 | 
|---|
| 945 |  *    Gather PsiEnergy results from all processes and sum up together with all other contributions to TotalEnergy.
 | 
|---|
| 946 |  * -# CheckCPULIM()\n
 | 
|---|
| 947 |  *    Check if external signal has been received (e.g. end of time slit on cluster), break operation at next possible moment.
 | 
|---|
| 948 |  * -# CalculateMinimumStop()\n
 | 
|---|
| 949 |  *    Evaluates stop condition if desired precision or steps or ... have been reached. Otherwise go to
 | 
|---|
| 950 |  *    CalculateNewWave().
 | 
|---|
| 951 |  * 
 | 
|---|
| 952 |  * Afterwards, the coefficients are written to file by OutputVisSrcFiles() if desired. Orthonormality is tested, we step
 | 
|---|
| 953 |  * back to the occupied wave functions and the densities are re-initialized. 
 | 
|---|
| 954 |  * \param *P Problem at hand
 | 
|---|
| 955 |  * \param *Stop flag to determine if epsilon stop conditions have met
 | 
|---|
| 956 |  * \param *SuperStop flag to determinte whether external signal's required end of calculations
 | 
|---|
| 957 |  */
 | 
|---|
| 958 | static void MinimiseUnoccupied (struct Problem *P, int *Stop, int *SuperStop) {
 | 
|---|
| 959 |   struct RunStruct *R = &P->R;
 | 
|---|
| 960 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
| 961 |   struct Psis *Psi = &Lat->Psi;
 | 
|---|
| 962 |   int StartLocalPsiNo;
 | 
|---|
| 963 | 
 | 
|---|
| 964 |   *Stop = 0;
 | 
|---|
| 965 |   R->PsiStep = R->MaxPsiStep; // in case it's zero from CalculateForce()
 | 
|---|
| 966 |   UpdateActualPsiNo(P, UnOccupied); // step on to next unoccupied one
 | 
|---|
| 967 |   R->OldActualLocalPsiNo = R->ActualLocalPsiNo; // reset, otherwise OldActualLocalPsiNo still points to occupied wave function
 | 
|---|
| 968 |   UpdateGramSchOldActualPsiNo(P,Psi);
 | 
|---|
| 969 |   if (P->Call.ReadSrcFiles && ReadSrcPsiDensity(P,UnOccupied,1, R->LevSNo)) {
 | 
|---|
| 970 |     SpeedMeasure(P, InitSimTime, StartTimeDo);  
 | 
|---|
| 971 |     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]);
 | 
|---|
| 972 |     ReadSrcPsiDensity(P, UnOccupied, 0, R->LevSNo);
 | 
|---|
| 973 |     if (P->Call.ReadSrcFiles != 2) {
 | 
|---|
| 974 |       ResetGramSchTagType(P, Psi, UnOccupied, IsOrthonormal); // loaded values are orthonormal
 | 
|---|
| 975 |       SpeedMeasure(P, DensityTime, StartTimeDo);
 | 
|---|
| 976 |       InitDensityCalculation(P);
 | 
|---|
| 977 |       SpeedMeasure(P, DensityTime, StopTimeDo);
 | 
|---|
| 978 |       InitPsiEnergyCalculation(P,UnOccupied);  // go through all orbitals calculating kinetic and non-local
 | 
|---|
| 979 |       //CalculateDensityEnergy(P, 0);
 | 
|---|
| 980 |       StartLocalPsiNo = R->ActualLocalPsiNo;
 | 
|---|
| 981 |       do { // otherwise OnePsiElementAddData#Lambda is calculated only for current Psi not for all
 | 
|---|
| 982 |         CalculateGapEnergy(P);
 | 
|---|
| 983 |         UpdateActualPsiNo(P, Occupied);
 | 
|---|
| 984 |       } while (R->ActualLocalPsiNo != StartLocalPsiNo);
 | 
|---|
| 985 |       EnergyAllReduce(P);
 | 
|---|
| 986 |     }
 | 
|---|
| 987 |     SpeedMeasure(P, InitSimTime, StopTimeDo);  
 | 
|---|
| 988 |   }
 | 
|---|
| 989 |   if (P->Call.ReadSrcFiles != 1) {
 | 
|---|
| 990 |     SpeedMeasure(P, InitSimTime, StartTimeDo);  
 | 
|---|
| 991 |     ResetGramSchTagType(P, Psi, UnOccupied, NotOrthogonal);
 | 
|---|
| 992 |     SpeedMeasure(P, GramSchTime, StartTimeDo);  
 | 
|---|
| 993 |     GramSch(P, R->LevS, Psi, Orthonormalize);
 | 
|---|
| 994 |     SpeedMeasure(P, GramSchTime, StopTimeDo);  
 | 
|---|
| 995 |     SpeedMeasure(P, InitDensityTime, StartTimeDo);
 | 
|---|
| 996 |     InitDensityCalculation(P);
 | 
|---|
| 997 |     SpeedMeasure(P, InitDensityTime, StopTimeDo);
 | 
|---|
| 998 |     InitPsiEnergyCalculation(P,UnOccupied);  // go through all orbitals calculating kinetic and non-local
 | 
|---|
| 999 |     //CalculateDensityEnergy(P, 0);
 | 
|---|
| 1000 |     CalculateGapEnergy(P);
 | 
|---|
| 1001 |     EnergyAllReduce(P);
 | 
|---|
| 1002 |     SpeedMeasure(P, InitSimTime, StopTimeDo);  
 | 
|---|
| 1003 |     R->LevS->Step++;
 | 
|---|
| 1004 |     EnergyOutput(P,0);
 | 
|---|
| 1005 |     if(P->Call.out[LeaderOut]) fprintf(stderr,"(%i)Beginning minimisation of type %s ...\n", P->Par.me, R->MinimisationName[R->CurrentMin]);
 | 
|---|
| 1006 |     while (*Stop != 1) {
 | 
|---|
| 1007 |       CalculateNewWave(P,NULL);
 | 
|---|
| 1008 |       UpdateActualPsiNo(P, UnOccupied);
 | 
|---|
| 1009 |       /* New */
 | 
|---|
| 1010 |       UpdateEnergyArray(P);
 | 
|---|
| 1011 |       SpeedMeasure(P, DensityTime, StartTimeDo);
 | 
|---|
| 1012 |       UpdateDensityCalculation(P);
 | 
|---|
| 1013 |       SpeedMeasure(P, DensityTime, StopTimeDo);
 | 
|---|
| 1014 |       UpdatePsiEnergyCalculation(P);
 | 
|---|
| 1015 |       //CalculateDensityEnergy(P, 0);
 | 
|---|
| 1016 |       CalculateGapEnergy(P);  //calculates XC, HGDensity, afterwards gradient, where V_xc is added upon HGDensity
 | 
|---|
| 1017 |       EnergyAllReduce(P);
 | 
|---|
| 1018 |       if (*SuperStop != 1)
 | 
|---|
| 1019 |         *SuperStop = CheckCPULIM(P);
 | 
|---|
| 1020 |       *Stop = CalculateMinimumStop(P, *SuperStop);
 | 
|---|
| 1021 |       /*EnergyOutput(P, Stop);*/
 | 
|---|
| 1022 |       P->Speed.Steps++;
 | 
|---|
| 1023 |       R->LevS->Step++;
 | 
|---|
| 1024 |       /*ControlNativeDensity(P);*/
 | 
|---|
| 1025 |     }
 | 
|---|
| 1026 |     OutputVisSrcFiles(P, UnOccupied);
 | 
|---|
| 1027 | //    if (!TestReadnWriteSrcDensity(P,UnOccupied))
 | 
|---|
| 1028 | //      Error(SomeError,"TestReadnWriteSrcDensity failed!");
 | 
|---|
| 1029 |   }
 | 
|---|
| 1030 |   TestGramSch(P,R->LevS,Psi, UnOccupied);
 | 
|---|
| 1031 |   ResetGramSchTagType(P, Psi, UnOccupied, NotUsedToOrtho);
 | 
|---|
| 1032 |   // re-calculate Occupied values (in preparation for perturbed ones)
 | 
|---|
| 1033 |   UpdateActualPsiNo(P, Occupied); // step on to next occupied one
 | 
|---|
| 1034 |   SpeedMeasure(P, DensityTime, StartTimeDo);
 | 
|---|
| 1035 |   InitDensityCalculation(P);  // re-init densities to occupied standard
 | 
|---|
| 1036 |   SpeedMeasure(P, DensityTime, StopTimeDo);
 | 
|---|
| 1037 | //  InitPsiEnergyCalculation(P,Occupied);
 | 
|---|
| 1038 | //  CalculateDensityEnergy(P, 0);
 | 
|---|
| 1039 | //  EnergyAllReduce(P);
 | 
|---|
| 1040 | }
 | 
|---|
| 1041 | 
 | 
|---|
| 1042 | 
 | 
|---|
| 1043 | /** Calculate the forces.
 | 
|---|
| 1044 |  * From RunStruct::LevSNo downto RunStruct::InitLevSNo the following routines are called in a loop:
 | 
|---|
| 1045 |  * -# In case of RunStruct#DoSeparated another loop begins for the unoccupied states with some reinitalization
 | 
|---|
| 1046 |  *    before and afterwards. The loop however is much the same as the one above.
 | 
|---|
| 1047 |  * -# ChangeToLevUp()\n
 | 
|---|
| 1048 |  *    Repeat the loop or when the above stop is reached, the level is changed and the loop repeated.
 | 
|---|
| 1049 |  * 
 | 
|---|
| 1050 |  * Afterwards comes the actual force and energy calculation by calling:
 | 
|---|
| 1051 |  * -# ControlNativeDensity()\n
 | 
|---|
| 1052 |  *    Checks if the density still reproduces particle number.
 | 
|---|
| 1053 |  * -# CalculateIonLocalForce(), SpeedMeasure()'d in LocFTime\n
 | 
|---|
| 1054 |  *    Calculale local part of force acting on Ions.
 | 
|---|
| 1055 |  * -# CalculateIonNonLocalForce(), SpeedMeasure()'d in NonLocFTime\n
 | 
|---|
| 1056 |  *    Calculale local part of force acting on Ions.
 | 
|---|
| 1057 |  * -# CalculateEwald()\n
 | 
|---|
| 1058 |  *    Calculate Ewald force acting on Ions.
 | 
|---|
| 1059 |  * -# CalculateIonForce()\n
 | 
|---|
| 1060 |  *    Sum up those three contributions.
 | 
|---|
| 1061 |  * -# CorrectForces()\n
 | 
|---|
| 1062 |  *    Shifts center of gravity of all forces for each Ion, so that the cell itself remains at rest.
 | 
|---|
| 1063 |  * -# GetOuterStop()
 | 
|---|
| 1064 |  *    Calculates a mean force per Ion.
 | 
|---|
| 1065 |  * \param *P Problem at hand
 | 
|---|
| 1066 |  * \return 1 - cpulim received, break operation, 0 - continue as normal
 | 
|---|
| 1067 |  */
 | 
|---|
| 1068 | int CalculateForce(struct Problem *P)
 | 
|---|
| 1069 | {
 | 
|---|
| 1070 |   struct RunStruct *R = &P->R;
 | 
|---|
| 1071 |   struct Lattice *Lat = &P->Lat;
 | 
|---|
| 1072 |   struct Psis *Psi = &Lat->Psi;
 | 
|---|
| 1073 |   struct LatticeLevel *LevS = R->LevS;
 | 
|---|
| 1074 |   struct FileData *F = &P->Files;
 | 
|---|
| 1075 |   struct Ions *I = &P->Ion;
 | 
|---|
| 1076 |   int Stop=0, SuperStop = 0, OuterStop = 0;
 | 
|---|
| 1077 |   //int i, j;
 | 
|---|
| 1078 |   SpeedMeasure(P, SimTime, StartTimeDo);
 | 
|---|
| 1079 |   if ((F->DoOutVis == 2) || (P->Call.ForcesFile == NULL)) {  // if we want to draw those pretty density pictures, we have to solve the ground state in any case
 | 
|---|
| 1080 |     while ((R->LevSNo > R->InitLevSNo) || (!Stop && R->LevSNo == R->InitLevSNo)) {
 | 
|---|
| 1081 |       // occupied
 | 
|---|
| 1082 |       R->PsiStep = R->MaxPsiStep; // reset in-Psi-minimisation-counter, so that we really advance to the next wave function
 | 
|---|
| 1083 |       R->OldActualLocalPsiNo = R->ActualLocalPsiNo; // reset OldActualLocalPsiNo, as it might still point to a perturbed wave function from last level
 | 
|---|
| 1084 |       UpdateGramSchOldActualPsiNo(P,Psi);
 | 
|---|
| 1085 |       ControlNativeDensity(P);
 | 
|---|
| 1086 |       MinimiseOccupied(P, &Stop, &SuperStop);
 | 
|---|
| 1087 |       if (!I->StructOpt) {
 | 
|---|
| 1088 |         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)
 | 
|---|
| 1089 |           SpeedMeasure(P, WannierTime, StartTimeDo);
 | 
|---|
| 1090 |           ComputeMLWF(P);   // localization of orbitals
 | 
|---|
| 1091 |           SpeedMeasure(P, WannierTime, StopTimeDo);
 | 
|---|
| 1092 |           OutputVisSrcFiles(P, Occupied); // rewrite now localized orbitals
 | 
|---|
| 1093 |     //      if (!TestReadnWriteSrcDensity(P,Occupied))
 | 
|---|
| 1094 |     //        Error(SomeError,"TestReadnWriteSrcDensity failed!");
 | 
|---|
| 1095 |         }
 | 
|---|
| 1096 |       
 | 
|---|
| 1097 | //      // plot psi cuts
 | 
|---|
| 1098 | //      for (i=0; i < Psi->MaxPsiOfType; i++)  // go through all wave functions (here without the extra ones for each process)
 | 
|---|
| 1099 | //        if ((Psi->AllPsiStatus[i].PsiType == Occupied) && (Psi->AllPsiStatus[i].my_color_comm_ST_Psi == P->Par.my_color_comm_ST_Psi))
 | 
|---|
| 1100 | //          for (j=0;j<NDIM;j++) {
 | 
|---|
| 1101 | //              //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]);
 | 
|---|
| 1102 | //              CalculateOneDensityR(Lat, R->LevS, R->Lev0->Dens, R->LevS->LPsi->LocalPsi[Psi->AllPsiStatus[i].MyLocalNo], R->Lev0->Dens->DensityArray[ActualDensity], R->FactorDensityR, 0);
 | 
|---|
| 1103 | //              PlotSrcPlane(P, j, Lat->Psi.AddData[Psi->AllPsiStatus[i].MyLocalNo].WannierCentre[j], Psi->AllPsiStatus[i].MyGlobalNo, R->Lev0->Dens->DensityArray[ActualDensity]);
 | 
|---|
| 1104 | //            }
 | 
|---|
| 1105 |           
 | 
|---|
| 1106 |         // unoccupied calc 
 | 
|---|
| 1107 |         if (R->DoUnOccupied) {
 | 
|---|
| 1108 |           MinimiseUnoccupied(P, &Stop, &SuperStop);
 | 
|---|
| 1109 |         }
 | 
|---|
| 1110 |         // hamiltonian
 | 
|---|
| 1111 |         CalculateHamiltonian(P);  // lambda_{kl} needed (and for bandgap after UnOccupied)
 | 
|---|
| 1112 | 
 | 
|---|
| 1113 |         //TestSawtooth(P, 0);
 | 
|---|
| 1114 |         //TestSawtooth(P, 1);
 | 
|---|
| 1115 |         //TestSawtooth(P, 2);
 | 
|---|
| 1116 |                 
 | 
|---|
| 1117 |         // perturbed calc
 | 
|---|
| 1118 |         if ((R->DoPerturbation)) { // && R->LevSNo <= R->InitLevSNo) {
 | 
|---|
| 1119 |           AllocCurrentDensity(R->Lev0->Dens);// lock current density arrays
 | 
|---|
| 1120 |           MinimisePerturbed(P, &Stop, &SuperStop); // herein InitDensityCalculation() is called, thus no need to call it beforehand
 | 
|---|
| 1121 | 
 | 
|---|
| 1122 |           SpeedMeasure(P, CurrDensTime, StartTimeDo);
 | 
|---|
| 1123 |           if (SuperStop != 1) {
 | 
|---|
| 1124 |             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
 | 
|---|
| 1125 |               R->DoFullCurrent = 1; // set to 1 if it was 2 but Check...() yielded necessity
 | 
|---|
| 1126 |               //debug(P,"Filling with Delta j ...");
 | 
|---|
| 1127 |               FillDeltaCurrentDensity(P);
 | 
|---|
| 1128 |             }
 | 
|---|
| 1129 |           }
 | 
|---|
| 1130 |           SpeedMeasure(P, CurrDensTime, StopTimeDo);
 | 
|---|
| 1131 |           TestCurrent(P,0);
 | 
|---|
| 1132 |           TestCurrent(P,1);
 | 
|---|
| 1133 |           TestCurrent(P,2);
 | 
|---|
| 1134 |           if (F->DoOutCurr && R->Lev0->LevelNo == 0)  // only output in uppermost level)
 | 
|---|
| 1135 |             OutputCurrentDensity(P);
 | 
|---|
| 1136 |           if (R->VectorPlane != -1)
 | 
|---|
| 1137 |             PlotVectorPlane(P,R->VectorPlane,R->VectorCut);
 | 
|---|
| 1138 |           CalculateMagneticSusceptibility(P);
 | 
|---|
| 1139 |           debug(P,"Normal calculation of shielding over R-space");
 | 
|---|
| 1140 |           CalculateMagneticMoment(P);
 | 
|---|
| 1141 |           CalculateChemicalShieldingByReciprocalCurrentDensity(P);
 | 
|---|
| 1142 |           SpeedMeasure(P, CurrDensTime, StopTimeDo);
 | 
|---|
| 1143 |           DisAllocCurrentDensity(R->Lev0->Dens);    // unlock current density arrays
 | 
|---|
| 1144 |         }  // end of if perturbation
 | 
|---|
| 1145 |         InitDensityCalculation(P);  // all unperturbed(!) wave functions've "changed" from ComputeMLWF(), thus reinit density
 | 
|---|
| 1146 |       } else  // end of if StructOpt or MaxOuterStep
 | 
|---|
| 1147 |                 OutputVisSrcFiles(P, Occupied); // in structopt or MD write for every level
 | 
|---|
| 1148 | 
 | 
|---|
| 1149 |       if ((!I->StructOpt) && (!R->MaxOuterStep))  // print intermediate levels energy results if we don't do MD or StructOpt
 | 
|---|
| 1150 |             EnergyOutput(P, 1);
 | 
|---|
| 1151 |       // next level
 | 
|---|
| 1152 |       ChangeToLevUp(P, &Stop);
 | 
|---|
| 1153 |       //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!"); }      
 | 
|---|
| 1154 |       LevS = R->LevS; // re-set pointer that's changed from LevUp
 | 
|---|
| 1155 |     }
 | 
|---|
| 1156 |           SpeedMeasure(P, SimTime, StopTimeDo);
 | 
|---|
| 1157 |           ControlNativeDensity(P);
 | 
|---|
| 1158 |           TestGramSch(P,LevS,Psi, Occupied);
 | 
|---|
| 1159 |           // necessary for correct ionic forces ...
 | 
|---|
| 1160 |                 SpeedMeasure(P, LocFTime, StartTimeDo);
 | 
|---|
| 1161 |                 CalculateIonLocalForce(P);
 | 
|---|
| 1162 |                 SpeedMeasure(P, LocFTime, StopTimeDo);
 | 
|---|
| 1163 |                 SpeedMeasure(P, NonLocFTime, StartTimeDo);
 | 
|---|
| 1164 |                 CalculateIonNonLocalForce(P);
 | 
|---|
| 1165 |                 SpeedMeasure(P, NonLocFTime, StopTimeDo);
 | 
|---|
| 1166 |                 CalculateEwald(P, 1);
 | 
|---|
| 1167 |                 CalculateIonForce(P);
 | 
|---|
| 1168 |   }
 | 
|---|
| 1169 |   if (P->Call.ForcesFile != NULL) { // if we parse forces from file, values are written over (in case of DoOutVis)
 | 
|---|
| 1170 |     fprintf(stderr, "Parsing Forces from file.\n");
 | 
|---|
| 1171 |     ParseIonForce(P); 
 | 
|---|
| 1172 |     //CalculateIonForce(P);
 | 
|---|
| 1173 |   }
 | 
|---|
| 1174 |   CorrectForces(P);
 | 
|---|
| 1175 |   // ... on output of densities
 | 
|---|
| 1176 |   if (F->DoOutOrbitals) { // output of each orbital
 | 
|---|
| 1177 |     debug(P,"OutputVisAllOrbital");
 | 
|---|
| 1178 |     OutputVisAllOrbital(P,0,1,Occupied);
 | 
|---|
| 1179 |   }
 | 
|---|
| 1180 |   //OutputNorm(P);
 | 
|---|
| 1181 |   //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);
 | 
|---|
| 1182 |   //OutputVis(P, P->R.Lev0->Dens->DensityArray[TotalDensity]);
 | 
|---|
| 1183 |   /*TestGramSch(P, R->LevS, &P->Lat.Psi); */
 | 
|---|
| 1184 |   GetOuterStop(P);
 | 
|---|
| 1185 |   //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); 
 | 
|---|
| 1186 |   if (SuperStop) OuterStop = 1;
 | 
|---|
| 1187 |   return OuterStop;
 | 
|---|
| 1188 | }
 | 
|---|
| 1189 | 
 | 
|---|
| 1190 | /** Checks whether the given positions \a *v have changed wrt stored in IonData structure.
 | 
|---|
| 1191 |  * \param *P Problem at hand
 | 
|---|
| 1192 |  * \param *v gsl_vector storing new positions
 | 
|---|
| 1193 |  */
 | 
|---|
| 1194 | int CheckForChangedPositions(struct Problem *P, const gsl_vector *v)
 | 
|---|
| 1195 | {
 | 
|---|
| 1196 |   struct Ions *I = &P->Ion;
 | 
|---|
| 1197 |   int is,ia,k, index=0;
 | 
|---|
| 1198 |   int diff = 0;
 | 
|---|
| 1199 |   double *R_ion;
 | 
|---|
| 1200 |   for (is=0; is < I->Max_Types; is++) // for all elements
 | 
|---|
| 1201 |     for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {  // for all ions of element
 | 
|---|
| 1202 |       R_ion = &I->I[is].R[NDIM*ia];
 | 
|---|
| 1203 |       for (k=0;k<NDIM;k++) { // for all dimensions
 | 
|---|
| 1204 |         if (fabs(R_ion[k] - gsl_vector_get (v, index++)) > MYEPSILON)
 | 
|---|
| 1205 |           diff++;
 | 
|---|
| 1206 |       }      
 | 
|---|
| 1207 |     }
 | 
|---|
| 1208 |   return diff;  
 | 
|---|
| 1209 | }
 | 
|---|
| 1210 | 
 | 
|---|
| 1211 | /** Wrapper for CalculateForce() for simplex minimisation of total energy.
 | 
|---|
| 1212 |  * \param *v vector with degrees of freedom
 | 
|---|
| 1213 |  * \param *params additional arguments, here Problem at hand
 | 
|---|
| 1214 |  */
 | 
|---|
| 1215 | double StructOpt_func(const gsl_vector *v, void *params)
 | 
|---|
| 1216 | {
 | 
|---|
| 1217 |   struct Problem *P = (struct Problem *)params;
 | 
|---|
| 1218 |   struct RunStruct *R = &P->R;
 | 
|---|
| 1219 |   struct Ions *I = &P->Ion;
 | 
|---|
| 1220 |   struct Energy *E = P->Lat.E;
 | 
|---|
| 1221 |   int i;
 | 
|---|
| 1222 |   double *R_ion, *R_old, *R_old_old;//, *FIon;
 | 
|---|
| 1223 |   //double norm = 0.;
 | 
|---|
| 1224 |   int is,ia,k,index = 0;
 | 
|---|
| 1225 |   int OuterStop;
 | 
|---|
| 1226 |   double diff = 0., tmp;
 | 
|---|
| 1227 |   debug (P, "StructOpt_func");
 | 
|---|
| 1228 |   if (CheckForChangedPositions(P,v)) {
 | 
|---|
| 1229 |     // update ion positions from vector coordinates
 | 
|---|
| 1230 |     for (is=0; is < I->Max_Types; is++) // for all elements
 | 
|---|
| 1231 |       for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {  // for all ions of element
 | 
|---|
| 1232 |         R_ion = &I->I[is].R[NDIM*ia];
 | 
|---|
| 1233 |         R_old = &I->I[is].R_old[NDIM*ia];
 | 
|---|
| 1234 |         R_old_old = &I->I[is].R_old_old[NDIM*ia];
 | 
|---|
| 1235 |         tmp = 0.;
 | 
|---|
| 1236 |         for (k=0;k<NDIM;k++) { // for all dimensions
 | 
|---|
| 1237 |           R_old_old[k] = R_old[k];
 | 
|---|
| 1238 |           R_old[k] = R_ion[k];
 | 
|---|
| 1239 |           tmp += (R_ion[k]-gsl_vector_get (v, index))*(R_ion[k]-gsl_vector_get (v, index));
 | 
|---|
| 1240 |           R_ion[k] = gsl_vector_get (v, index++);        
 | 
|---|
| 1241 |         }
 | 
|---|
| 1242 |         diff += sqrt(tmp);
 | 
|---|
| 1243 |       }  
 | 
|---|
| 1244 |     if (P->Call.out[ValueOut]) fprintf(stderr,"(%i) Summed Difference to former position %lg\n", P->Par.me, diff);
 | 
|---|
| 1245 |     // recalculate ionic forces (do electronic minimisation)
 | 
|---|
| 1246 |     R->OuterStep++;
 | 
|---|
| 1247 |     R->NewRStep++;
 | 
|---|
| 1248 |     UpdateWaveAfterIonMove(P);
 | 
|---|
| 1249 |     for (i=MAXOLD-1; i > 0; i--)    // store away old energies
 | 
|---|
| 1250 |       E->TotalEnergyOuter[i] = E->TotalEnergyOuter[i-1];  
 | 
|---|
| 1251 |     UpdateToNewWaves(P);
 | 
|---|
| 1252 |     E->TotalEnergyOuter[0] = E->TotalEnergy[0];
 | 
|---|
| 1253 |     OuterStop = CalculateForce(P);
 | 
|---|
| 1254 |     //UpdateIonsU(P);
 | 
|---|
| 1255 |     //CorrectVelocity(P);
 | 
|---|
| 1256 |     //CalculateEnergyIonsU(P);
 | 
|---|
| 1257 |   /*  if ((P->R.ScaleTempStep > 0) && ((R->OuterStep-1) % P->R.ScaleTempStep == 0))
 | 
|---|
| 1258 |       ScaleTemp(P);*/
 | 
|---|
| 1259 |     if ((R->OuterStep-1) % P->R.OutSrcStep == 0) 
 | 
|---|
| 1260 |       OutputVisSrcFiles(P, Occupied);
 | 
|---|
| 1261 |     if ((R->OuterStep-1) % P->R.OutVisStep == 0) {      
 | 
|---|
| 1262 |   /*      // recalculate density for the specific wave function ...
 | 
|---|
| 1263 |         CalculateOneDensityR(Lat, LevS, Dens0, PsiDat, Dens0->DensityArray[ActualDensity], R->FactorDensityR, 0);
 | 
|---|
| 1264 |         // ... and output (wherein ActualDensity is used instead of TotalDensity)
 | 
|---|
| 1265 |         OutputVis(P);
 | 
|---|
| 1266 |         OutputIonForce(P);
 | 
|---|
| 1267 |         EnergyOutput(P, 1);*/
 | 
|---|
| 1268 |     }
 | 
|---|
| 1269 |   }
 | 
|---|
| 1270 |   if (P->Par.me == 0) fprintf(stderr,"(%i) TE %e\n",P->Par.me, E->TotalEnergy[0]);
 | 
|---|
| 1271 |   return E->TotalEnergy[0];
 | 
|---|
| 1272 | }
 | 
|---|
| 1273 | 
 | 
|---|
| 1274 | /** Wrapper for CalculateForce() for simplex minimisation of ionic forces.
 | 
|---|
| 1275 |  * \param *v vector with degrees of freedom
 | 
|---|
| 1276 |  * \param *params additional arguments, here Problem at hand
 | 
|---|
| 1277 |  */
 | 
|---|
| 1278 | double StructOpt_f(const gsl_vector *v, void *params)
 | 
|---|
| 1279 | {
 | 
|---|
| 1280 |   struct Problem *P = (struct Problem *)params;
 | 
|---|
| 1281 |   struct RunStruct *R = &P->R;
 | 
|---|
| 1282 |   struct Ions *I = &P->Ion;
 | 
|---|
| 1283 |   struct Energy *E = P->Lat.E;
 | 
|---|
| 1284 |   int i;
 | 
|---|
| 1285 |   double *R_ion, *R_old, *R_old_old;//, *FIon;
 | 
|---|
| 1286 |   //double norm = 0.;
 | 
|---|
| 1287 |   int is,ia,k,index = 0;
 | 
|---|
| 1288 |   int OuterStop;
 | 
|---|
| 1289 |   double diff = 0., tmp;
 | 
|---|
| 1290 |   //debug (P, "StructOpt_f");
 | 
|---|
| 1291 |   if (CheckForChangedPositions(P,v)) {
 | 
|---|
| 1292 |     // update ion positions from vector coordinates
 | 
|---|
| 1293 |     for (is=0; is < I->Max_Types; is++) // for all elements
 | 
|---|
| 1294 |       for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {  // for all ions of element
 | 
|---|
| 1295 |         R_ion = &I->I[is].R[NDIM*ia];
 | 
|---|
| 1296 |         R_old = &I->I[is].R_old[NDIM*ia];
 | 
|---|
| 1297 |         R_old_old = &I->I[is].R_old_old[NDIM*ia];
 | 
|---|
| 1298 |         tmp = 0.;
 | 
|---|
| 1299 |         for (k=0;k<NDIM;k++) { // for all dimensions
 | 
|---|
| 1300 |           R_old_old[k] = R_old[k];
 | 
|---|
| 1301 |           R_old[k] = R_ion[k];
 | 
|---|
| 1302 |           tmp += (R_ion[k]-gsl_vector_get (v, index))*(R_ion[k]-gsl_vector_get (v, index));
 | 
|---|
| 1303 |           R_ion[k] = gsl_vector_get (v, index++);        
 | 
|---|
| 1304 |         }
 | 
|---|
| 1305 |         diff += sqrt(tmp);
 | 
|---|
| 1306 |       }  
 | 
|---|
| 1307 |     if (P->Call.out[ValueOut]) fprintf(stderr,"(%i) Summed Difference to former position %lg\n", P->Par.me, diff);
 | 
|---|
| 1308 |     // recalculate ionic forces (do electronic minimisation)
 | 
|---|
| 1309 |     //R->OuterStep++;
 | 
|---|
| 1310 |     R->NewRStep++;
 | 
|---|
| 1311 |     UpdateWaveAfterIonMove(P);
 | 
|---|
| 1312 |     for (i=MAXOLD-1; i > 0; i--)    // store away old energies
 | 
|---|
| 1313 |       E->TotalEnergyOuter[i] = E->TotalEnergyOuter[i-1];  
 | 
|---|
| 1314 |     UpdateToNewWaves(P);
 | 
|---|
| 1315 |     E->TotalEnergyOuter[0] = E->TotalEnergy[0];
 | 
|---|
| 1316 |     OuterStop = CalculateForce(P);
 | 
|---|
| 1317 |     //UpdateIonsU(P);
 | 
|---|
| 1318 |     //CorrectVelocity(P);
 | 
|---|
| 1319 |     //CalculateEnergyIonsU(P);
 | 
|---|
| 1320 |   /*  if ((P->R.ScaleTempStep > 0) && ((R->OuterStep-1) % P->R.ScaleTempStep == 0))
 | 
|---|
| 1321 |       ScaleTemp(P);*/
 | 
|---|
| 1322 |     if ((R->OuterStep-1) % P->R.OutSrcStep == 0) 
 | 
|---|
| 1323 |       OutputVisSrcFiles(P, Occupied);
 | 
|---|
| 1324 |     /*if ((R->OuterStep-1) % P->R.OutVisStep == 0) {      
 | 
|---|
| 1325 |         // recalculate density for the specific wave function ...
 | 
|---|
| 1326 |         CalculateOneDensityR(Lat, LevS, Dens0, PsiDat, Dens0->DensityArray[ActualDensity], R->FactorDensityR, 0);
 | 
|---|
| 1327 |         // ... and output (wherein ActualDensity is used instead of TotalDensity)
 | 
|---|
| 1328 |         OutputVis(P);
 | 
|---|
| 1329 |         OutputIonForce(P);
 | 
|---|
| 1330 |         EnergyOutput(P, 1);
 | 
|---|
| 1331 |     }*/
 | 
|---|
| 1332 |   }
 | 
|---|
| 1333 |   GetOuterStop(P);
 | 
|---|
| 1334 |   //if (P->Call.out[LeaderOut] && (P->Par.me == 0)) fprintf(stderr,"(%i) Absolute Force summed over all Ions %e\n",P->Par.me, norm);
 | 
|---|
| 1335 |   return R->MeanForce[0];
 | 
|---|
| 1336 |   //if (P->Call.out[LeaderOut] && (P->Par.me == 0)) fprintf(stderr,"(%i) Struct_optf returning: %lg\n",P->Par.me,E->TotalEnergy[0]); 
 | 
|---|
| 1337 |   //return E->TotalEnergy[0];
 | 
|---|
| 1338 | }
 | 
|---|
| 1339 | 
 | 
|---|
| 1340 | void StructOpt_df(const gsl_vector *v, void *params, gsl_vector *df) 
 | 
|---|
| 1341 | {
 | 
|---|
| 1342 |   struct Problem *P = (struct Problem *)params;
 | 
|---|
| 1343 |   struct Ions *I = &P->Ion;
 | 
|---|
| 1344 |   double *FIon;
 | 
|---|
| 1345 |   int is,ia,k, index=0;
 | 
|---|
| 1346 |   //debug (P, "StructOpt_df");
 | 
|---|
| 1347 |   // look through coordinate vector if positions have changed sind last StructOpt_f call
 | 
|---|
| 1348 |   if (CheckForChangedPositions(P,v)) {// if so, recalc to update forces
 | 
|---|
| 1349 |     debug (P, "Calling StructOpt_f to update");
 | 
|---|
| 1350 |     StructOpt_f(v, params);
 | 
|---|
| 1351 |   }
 | 
|---|
| 1352 |   for (is=0; is < I->Max_Types; is++) // for all elements
 | 
|---|
| 1353 |     for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {  // for all ions of element
 | 
|---|
| 1354 |       FIon = &I->I[is].FIon[NDIM*ia];
 | 
|---|
| 1355 |       for (k=0;k<NDIM;k++) { // for all dimensions
 | 
|---|
| 1356 |         gsl_vector_set (df, index++, FIon[k]);
 | 
|---|
| 1357 |       }      
 | 
|---|
| 1358 |     } 
 | 
|---|
| 1359 |   if (P->Call.out[LeaderOut] && (P->Par.me == 0)) {
 | 
|---|
| 1360 |     fprintf(stderr,"(%i) Struct_Optdf returning",P->Par.me); 
 | 
|---|
| 1361 |     gsl_vector_fprintf(stderr, df, "%lg");
 | 
|---|
| 1362 |   } 
 | 
|---|
| 1363 | }
 | 
|---|
| 1364 | 
 | 
|---|
| 1365 | void StructOpt_fdf (const gsl_vector *x, void *params, double *f, gsl_vector *df)
 | 
|---|
| 1366 | {
 | 
|---|
| 1367 |   *f = StructOpt_f(x, params);
 | 
|---|
| 1368 |   StructOpt_df(x, params, df);
 | 
|---|
| 1369 | }
 | 
|---|
| 1370 | 
 | 
|---|
| 1371 | 
 | 
|---|
| 1372 | /** CG implementation for the structure optimization.
 | 
|---|
| 1373 |  * We follow the example from the GSL manual.
 | 
|---|
| 1374 |  * \param *P Problem at hand
 | 
|---|
| 1375 |  */
 | 
|---|
| 1376 | void UpdateIon_PRCG(struct Problem *P)
 | 
|---|
| 1377 | {
 | 
|---|
| 1378 |   //struct RunStruct *Run = &P->R;
 | 
|---|
| 1379 |   struct Ions *I = &P->Ion;
 | 
|---|
| 1380 |   size_t np = NDIM*I->Max_TotalIons;  // d.o.f = number of ions times number of dimensions
 | 
|---|
| 1381 |   int is, ia, k, index;
 | 
|---|
| 1382 |   double *R;
 | 
|---|
| 1383 |  
 | 
|---|
| 1384 |   const gsl_multimin_fdfminimizer_type *T;
 | 
|---|
| 1385 |   gsl_multimin_fdfminimizer *s;
 | 
|---|
| 1386 |   gsl_vector *x;
 | 
|---|
| 1387 |   gsl_multimin_function_fdf minex_func;
 | 
|---|
| 1388 | 
 | 
|---|
| 1389 |   size_t iter = 0;
 | 
|---|
| 1390 |   int status;
 | 
|---|
| 1391 | 
 | 
|---|
| 1392 |   /* Starting point */
 | 
|---|
| 1393 |   x = gsl_vector_alloc (np);
 | 
|---|
| 1394 |   //fprintf(stderr,"(%i) d.o.f. = %i\n", P->Par.me, (int)np);
 | 
|---|
| 1395 | 
 | 
|---|
| 1396 |   index=0;
 | 
|---|
| 1397 |   for (is=0; is < I->Max_Types; is++) // for all elements
 | 
|---|
| 1398 |     for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {  // for all ions of element
 | 
|---|
| 1399 |       R = &I->I[is].R[NDIM*ia];
 | 
|---|
| 1400 |       for (k=0;k<NDIM;k++) // for all dimensions
 | 
|---|
| 1401 |         gsl_vector_set (x, index++, R[k]);      
 | 
|---|
| 1402 |     }
 | 
|---|
| 1403 | 
 | 
|---|
| 1404 |   /* Initialize method and iterate */
 | 
|---|
| 1405 |   minex_func.f = &StructOpt_f;
 | 
|---|
| 1406 |   minex_func.df = &StructOpt_df;
 | 
|---|
| 1407 |   minex_func.fdf = &StructOpt_fdf;
 | 
|---|
| 1408 |   minex_func.n = np;
 | 
|---|
| 1409 |   minex_func.params = (void *)P;
 | 
|---|
| 1410 |   
 | 
|---|
| 1411 |   T = gsl_multimin_fdfminimizer_conjugate_pr;
 | 
|---|
| 1412 |   s = gsl_multimin_fdfminimizer_alloc (T, np);
 | 
|---|
| 1413 | 
 | 
|---|
| 1414 |   gsl_multimin_fdfminimizer_set (s, &minex_func, x, 0.1, 0.001);
 | 
|---|
| 1415 | 
 | 
|---|
| 1416 |   fprintf(stderr,"(%i) Commencing Structure optimization with PRCG: dof %d\n", P->Par.me,(int)np);
 | 
|---|
| 1417 |   do {
 | 
|---|
| 1418 |     iter++;
 | 
|---|
| 1419 |     status = gsl_multimin_fdfminimizer_iterate(s);
 | 
|---|
| 1420 | 
 | 
|---|
| 1421 |     if (status)
 | 
|---|
| 1422 |       break;
 | 
|---|
| 1423 |     
 | 
|---|
| 1424 |     status = gsl_multimin_test_gradient (s->gradient, 1e-2);
 | 
|---|
| 1425 |        
 | 
|---|
| 1426 |     if (status == GSL_SUCCESS)
 | 
|---|
| 1427 |       if (P->Par.me == 0) fprintf (stderr,"(%i) converged to minimum at\n", P->Par.me);
 | 
|---|
| 1428 | 
 | 
|---|
| 1429 |     if (P->Call.out[NormalOut]) fprintf(stderr,"(%i) Commencing '%s' step %i ... \n",P->Par.me, gsl_multimin_fdfminimizer_name(s), P->R.StructOptStep);
 | 
|---|
| 1430 |     if ((P->Call.out[NormalOut]) && (P->Par.me == 0)) fprintf (stderr, "(%i) %5d %10.5f\n", P->Par.me, (int)iter, s->f);
 | 
|---|
| 1431 |     //gsl_vector_fprintf(stderr, s->dx, "%lg");
 | 
|---|
| 1432 |     OutputVis(P, P->R.Lev0->Dens->DensityArray[TotalDensity]);
 | 
|---|
| 1433 |     OutputIonCoordinates(P, 0);
 | 
|---|
| 1434 |     P->R.StructOptStep++;
 | 
|---|
| 1435 |   } while ((status == GSL_CONTINUE) && (P->R.StructOptStep < P->R.MaxStructOptStep));
 | 
|---|
| 1436 | 
 | 
|---|
| 1437 |   gsl_vector_free(x);
 | 
|---|
| 1438 |   gsl_multimin_fdfminimizer_free (s);
 | 
|---|
| 1439 | }
 | 
|---|
| 1440 | 
 | 
|---|
| 1441 | /** Simplex implementation for the structure optimization.
 | 
|---|
| 1442 |  * We follow the example from the GSL manual.
 | 
|---|
| 1443 |  * \param *P Problem at hand
 | 
|---|
| 1444 |  */
 | 
|---|
| 1445 | void UpdateIon_Simplex(struct Problem *P)
 | 
|---|
| 1446 | {
 | 
|---|
| 1447 |   struct RunStruct *Run = &P->R;
 | 
|---|
| 1448 |   struct Ions *I = &P->Ion;
 | 
|---|
| 1449 |   size_t np = NDIM*I->Max_TotalIons;  // d.o.f = number of ions times number of dimensions
 | 
|---|
| 1450 |   int is, ia, k, index;
 | 
|---|
| 1451 |   double *R;
 | 
|---|
| 1452 |  
 | 
|---|
| 1453 |   const gsl_multimin_fminimizer_type *T;
 | 
|---|
| 1454 |   gsl_multimin_fminimizer *s;
 | 
|---|
| 1455 |   gsl_vector *x, *ss;
 | 
|---|
| 1456 |   gsl_multimin_function minex_func;
 | 
|---|
| 1457 | 
 | 
|---|
| 1458 |   size_t iter = 0;
 | 
|---|
| 1459 |   int status;
 | 
|---|
| 1460 |   double size;
 | 
|---|
| 1461 | 
 | 
|---|
| 1462 |   ss = gsl_vector_alloc (np);
 | 
|---|
| 1463 |   gsl_vector_set_all(ss, .2);
 | 
|---|
| 1464 |   /* Starting point */
 | 
|---|
| 1465 |   x = gsl_vector_alloc (np);
 | 
|---|
| 1466 |   //fprintf(stderr,"(%i) d.o.f. = %i\n", P->Par.me, (int)np);
 | 
|---|
| 1467 | 
 | 
|---|
| 1468 |   index=0;
 | 
|---|
| 1469 |   for (is=0; is < I->Max_Types; is++) // for all elements
 | 
|---|
| 1470 |     for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {  // for all ions of element
 | 
|---|
| 1471 |       R = &I->I[is].R[NDIM*ia];
 | 
|---|
| 1472 |       for (k=0;k<NDIM;k++) // for all dimensions
 | 
|---|
| 1473 |         gsl_vector_set (x, index++, R[k]);      
 | 
|---|
| 1474 |     }
 | 
|---|
| 1475 | 
 | 
|---|
| 1476 |   /* Initialize method and iterate */
 | 
|---|
| 1477 |   minex_func.f = &StructOpt_f;
 | 
|---|
| 1478 |   minex_func.n = np;
 | 
|---|
| 1479 |   minex_func.params = (void *)P;
 | 
|---|
| 1480 |   
 | 
|---|
| 1481 |   T = gsl_multimin_fminimizer_nmsimplex;
 | 
|---|
| 1482 |   s = gsl_multimin_fminimizer_alloc (T, np);
 | 
|---|
| 1483 | 
 | 
|---|
| 1484 |   gsl_multimin_fminimizer_set (s, &minex_func, x, ss);
 | 
|---|
| 1485 | 
 | 
|---|
| 1486 |   fprintf(stderr,"(%i) Commencing Structure optimization with NM simplex: dof %d\n", P->Par.me, (int)np);
 | 
|---|
| 1487 |   do {
 | 
|---|
| 1488 |     iter++;
 | 
|---|
| 1489 |     status = gsl_multimin_fminimizer_iterate(s);
 | 
|---|
| 1490 | 
 | 
|---|
| 1491 |     if (status)
 | 
|---|
| 1492 |       break;
 | 
|---|
| 1493 |     
 | 
|---|
| 1494 |     size = gsl_multimin_fminimizer_size (s);
 | 
|---|
| 1495 |     status = gsl_multimin_test_size (size, 1e-4);
 | 
|---|
| 1496 |        
 | 
|---|
| 1497 |     if (status == GSL_SUCCESS)
 | 
|---|
| 1498 |       if (P->Par.me == 0) fprintf (stderr,"(%i) converged to minimum at\n", P->Par.me);
 | 
|---|
| 1499 | 
 | 
|---|
| 1500 |     if (P->Call.out[MinOut]) fprintf(stderr,"(%i) Commencing '%s' step %i ... \n",P->Par.me, gsl_multimin_fminimizer_name(s), P->R.StructOptStep);
 | 
|---|
| 1501 |     if ((P->Call.out[MinOut]) && (P->Par.me == 0)) fprintf (stderr, "(%i) %5d %10.5f %10.5f\n", P->Par.me, (int)iter, s->fval, size);
 | 
|---|
| 1502 |     OutputVis(P, P->R.Lev0->Dens->DensityArray[TotalDensity]);
 | 
|---|
| 1503 |     OutputIonCoordinates(P, 0);
 | 
|---|
| 1504 |     P->R.StructOptStep++;
 | 
|---|
| 1505 |   } while ((status == GSL_CONTINUE) && (Run->OuterStep < Run->MaxOuterStep));
 | 
|---|
| 1506 | 
 | 
|---|
| 1507 |   gsl_vector_free(x);
 | 
|---|
| 1508 |   gsl_vector_free(ss);
 | 
|---|
| 1509 |   gsl_multimin_fminimizer_free (s);
 | 
|---|
| 1510 | }
 | 
|---|
| 1511 | 
 | 
|---|
| 1512 | /** Implementation of various thermostats.
 | 
|---|
| 1513 |  * All these thermostats apply an additional force which has the following forms:
 | 
|---|
| 1514 |  * -# Woodcock
 | 
|---|
| 1515 |  *  \f$p_i \rightarrow \sqrt{\frac{T_0}{T}} \cdot p_i\f$
 | 
|---|
| 1516 |  * -# Gaussian
 | 
|---|
| 1517 |  *  \f$ \frac{ \sum_i \frac{p_i}{m_i} \frac{\partial V}{\partial q_i}} {\sum_i \frac{p^2_i}{m_i}} \cdot p_i\f$
 | 
|---|
| 1518 |  * -# Langevin
 | 
|---|
| 1519 |  *  \f$p_{i,n} \rightarrow \sqrt{1-\alpha^2} p_{i,0} + \alpha p_r\f$  
 | 
|---|
| 1520 |  * -# Berendsen
 | 
|---|
| 1521 |  *  \f$p_i \rightarrow \left [ 1+ \frac{\delta t}{\tau_T} \left ( \frac{T_0}{T} \right ) \right ]^{\frac{1}{2}} \cdot p_i\f$
 | 
|---|
| 1522 |  * -# Nose-Hoover
 | 
|---|
| 1523 |  *  \f$\zeta p_i \f$ with \f$\frac{\partial \zeta}{\partial t} = \frac{1}{M_s} \left ( \sum^N_{i=1} \frac{p_i^2}{m_i} - g k_B T \right )\f$
 | 
|---|
| 1524 |  * These Thermostats either simply rescale the velocities, thus Thermostats() should be called after UpdateIonsU(), and/or
 | 
|---|
| 1525 |  * have a constraint force acting additionally on the ions. In the latter case, the ion speeds have to be modified
 | 
|---|
| 1526 |  * belatedly and the constraint force set.
 | 
|---|
| 1527 |  * \param *P Problem at hand
 | 
|---|
| 1528 |  * \param i which of the thermostats to take: 0 - none, 1 - Woodcock, 2 - Gaussian, 3 - Langevin, 4 - Berendsen, 5 - Nose-Hoover
 | 
|---|
| 1529 |  * \sa InitThermostat()
 | 
|---|
| 1530 |  */
 | 
|---|
| 1531 | void Thermostats(struct Problem *P, enum thermostats i)
 | 
|---|
| 1532 | {
 | 
|---|
| 1533 |   struct FileData *Files = &P->Files;
 | 
|---|
| 1534 |   struct Ions *I = &P->Ion;
 | 
|---|
| 1535 |   int is, ia, d;
 | 
|---|
| 1536 |   double *U;
 | 
|---|
| 1537 |   double a, ekin = 0.;
 | 
|---|
| 1538 |   double E = 0., F = 0.;
 | 
|---|
| 1539 |   double delta_alpha = 0.;
 | 
|---|
| 1540 |   const int delta_t = P->R.delta_t;
 | 
|---|
| 1541 |   double ScaleTempFactor;
 | 
|---|
| 1542 |   double sigma;
 | 
|---|
| 1543 |   gsl_rng * r;
 | 
|---|
| 1544 |   const gsl_rng_type * T;
 | 
|---|
| 1545 |   
 | 
|---|
| 1546 |   // calculate current temperature
 | 
|---|
| 1547 |   CalculateEnergyIonsU(P); // Temperature now in I->ActualTemp
 | 
|---|
| 1548 |   ScaleTempFactor = P->R.TargetTemp/I->ActualTemp;
 | 
|---|
| 1549 |   //if ((P->Par.me == 0) && (I->ActualTemp < MYEPSILON)) fprintf(stderr,"Thermostat: (1) I->ActualTemp = %lg",I->ActualTemp);
 | 
|---|
| 1550 |   if (Files->MeOutMes) fprintf(Files->TemperatureFile, "%d\t%lg",P->R.OuterStep, I->ActualTemp);
 | 
|---|
| 1551 |     
 | 
|---|
| 1552 |   // differentating between the various thermostats
 | 
|---|
| 1553 |   switch(i) {
 | 
|---|
| 1554 |      case None:
 | 
|---|
| 1555 |       debug(P, "Applying no thermostat...");
 | 
|---|
| 1556 |       break;
 | 
|---|
| 1557 |      case Woodcock:
 | 
|---|
| 1558 |       if ((P->R.ScaleTempStep > 0) && ((P->R.OuterStep-1) % P->R.ScaleTempStep == 0)) {
 | 
|---|
| 1559 |         debug(P, "Applying Woodcock thermostat...");
 | 
|---|
| 1560 |         for (is=0; is < I->Max_Types; is++) {
 | 
|---|
| 1561 |           a = 0.5*I->I[is].IonMass;
 | 
|---|
| 1562 |           for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
 | 
|---|
| 1563 |             U = &I->I[is].U[NDIM*ia];
 | 
|---|
| 1564 |             if (I->I[is].IMT[ia] == MoveIon) // even FixedIon moves, only not by other's forces
 | 
|---|
| 1565 |               for (d=0; d<NDIM; d++) {
 | 
|---|
| 1566 |                 U[d] *= sqrt(ScaleTempFactor);
 | 
|---|
| 1567 |                 ekin += 0.5*I->I[is].IonMass * U[d]*U[d];
 | 
|---|
| 1568 |               }
 | 
|---|
| 1569 |           }
 | 
|---|
| 1570 |         }
 | 
|---|
| 1571 |       }
 | 
|---|
| 1572 |       break;
 | 
|---|
| 1573 |      case Gaussian:
 | 
|---|
| 1574 |       debug(P, "Applying Gaussian thermostat...");
 | 
|---|
| 1575 |       for (is=0; is < I->Max_Types; is++) { // sum up constraint constant
 | 
|---|
| 1576 |         for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
 | 
|---|
| 1577 |           U = &I->I[is].U[NDIM*ia];
 | 
|---|
| 1578 |           if (I->I[is].IMT[ia] == MoveIon) // even FixedIon moves, only not by other's forces
 | 
|---|
| 1579 |             for (d=0; d<NDIM; d++) {
 | 
|---|
| 1580 |               F += U[d] * I->I[is].FIon[d+NDIM*ia]; 
 | 
|---|
| 1581 |               E += U[d]*U[d]*I->I[is].IonMass;
 | 
|---|
| 1582 |             }
 | 
|---|
| 1583 |         }
 | 
|---|
| 1584 |       }
 | 
|---|
| 1585 |       if (P->Call.out[ValueOut]) fprintf(stderr, "(%i) Gaussian Least Constraint constant is %lg\n", P->Par.me, F/E);
 | 
|---|
| 1586 |       for (is=0; is < I->Max_Types; is++) { // apply constraint constant on constraint force and on velocities
 | 
|---|
| 1587 |         for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
 | 
|---|
| 1588 |           U = &I->I[is].U[NDIM*ia];
 | 
|---|
| 1589 |           if (I->I[is].IMT[ia] == MoveIon) // even FixedIon moves, only not by other's forces
 | 
|---|
| 1590 |             for (d=0; d<NDIM; d++) {
 | 
|---|
| 1591 |               I->I[is].FConstraint[d+NDIM*ia] = (F/E) * (U[d]*I->I[is].IonMass);
 | 
|---|
| 1592 |               U[d] += delta_t/I->I[is].IonMass * (I->I[is].FConstraint[d+NDIM*ia]);
 | 
|---|
| 1593 |               ekin += 0.5*I->I[is].IonMass * U[d]*U[d];
 | 
|---|
| 1594 |             }
 | 
|---|
| 1595 |         }
 | 
|---|
| 1596 |       }
 | 
|---|
| 1597 |       break;
 | 
|---|
| 1598 |      case Langevin:
 | 
|---|
| 1599 |       debug(P, "Applying Langevin thermostat...");
 | 
|---|
| 1600 |       // init random number generator
 | 
|---|
| 1601 |       gsl_rng_env_setup();
 | 
|---|
| 1602 |       T = gsl_rng_default;
 | 
|---|
| 1603 |       r = gsl_rng_alloc (T);
 | 
|---|
| 1604 |       // Go through each ion
 | 
|---|
| 1605 |       for (is=0; is < I->Max_Types; is++) {
 | 
|---|
| 1606 |         sigma  = sqrt(P->R.TargetTemp/I->I[is].IonMass); // sigma = (k_b T)/m (Hartree/atomicmass = atomiclength/atomictime)
 | 
|---|
| 1607 |         for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
 | 
|---|
| 1608 |           U = &I->I[is].U[NDIM*ia];
 | 
|---|
| 1609 |           // throw a dice to determine whether it gets hit by a heat bath particle
 | 
|---|
| 1610 |           if (((((rand()/(double)RAND_MAX))*P->R.TempFrequency) < 1.)) {  // (I->I[is].IMT[ia] == MoveIon) &&  even FixedIon moves, only not by other's forces
 | 
|---|
| 1611 |             if (P->Par.me == 0) fprintf(stderr,"(%i) Particle %i,%i was hit (sigma %lg): %lg -> ", P->Par.me, is, ia, sigma, sqrt(U[0]*U[0]+U[1]*U[1]+U[2]*U[2]));
 | 
|---|
| 1612 |             // pick three random numbers from a Boltzmann distribution around the desired temperature T for each momenta axis
 | 
|---|
| 1613 |             for (d=0; d<NDIM; d++) {
 | 
|---|
| 1614 |               U[d] = gsl_ran_gaussian (r, sigma);
 | 
|---|
| 1615 |             }
 | 
|---|
| 1616 |             if (P->Par.me == 0) fprintf(stderr,"%lg\n", sqrt(U[0]*U[0]+U[1]*U[1]+U[2]*U[2]));
 | 
|---|
| 1617 |           }
 | 
|---|
| 1618 |           for (d=0; d<NDIM; d++)
 | 
|---|
| 1619 |             ekin += 0.5*I->I[is].IonMass * U[d]*U[d];
 | 
|---|
| 1620 |         }
 | 
|---|
| 1621 |       }
 | 
|---|
| 1622 |       break;
 | 
|---|
| 1623 |      case Berendsen:
 | 
|---|
| 1624 |       debug(P, "Applying Berendsen-VanGunsteren thermostat...");
 | 
|---|
| 1625 |       for (is=0; is < I->Max_Types; is++) {
 | 
|---|
| 1626 |         for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
 | 
|---|
| 1627 |           U = &I->I[is].U[NDIM*ia];
 | 
|---|
| 1628 |           if (I->I[is].IMT[ia] == MoveIon) // even FixedIon moves, only not by other's forces
 | 
|---|
| 1629 |             for (d=0; d<NDIM; d++) {
 | 
|---|
| 1630 |               U[d] *= sqrt(1+(P->R.delta_t/P->R.TempFrequency)*(ScaleTempFactor-1));
 | 
|---|
| 1631 |               ekin += 0.5*I->I[is].IonMass * U[d]*U[d];
 | 
|---|
| 1632 |             }
 | 
|---|
| 1633 |         }
 | 
|---|
| 1634 |       }
 | 
|---|
| 1635 |       break;
 | 
|---|
| 1636 |      case NoseHoover:
 | 
|---|
| 1637 |       debug(P, "Applying Nose-Hoover thermostat...");
 | 
|---|
| 1638 |       // dynamically evolve alpha (the additional degree of freedom)
 | 
|---|
| 1639 |       delta_alpha = 0.;
 | 
|---|
| 1640 |       for (is=0; is < I->Max_Types; is++) { // sum up constraint constant
 | 
|---|
| 1641 |         for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
 | 
|---|
| 1642 |           U = &I->I[is].U[NDIM*ia];
 | 
|---|
| 1643 |           if (I->I[is].IMT[ia] == MoveIon) // even FixedIon moves, only not by other's forces
 | 
|---|
| 1644 |             for (d=0; d<NDIM; d++) {
 | 
|---|
| 1645 |               delta_alpha += U[d]*U[d]*I->I[is].IonMass;
 | 
|---|
| 1646 |             }
 | 
|---|
| 1647 |         }
 | 
|---|
| 1648 |       }
 | 
|---|
| 1649 |       delta_alpha = (delta_alpha - (3.*I->Max_TotalIons+1.) * P->R.TargetTemp)/(P->R.HooverMass*Units2Electronmass);
 | 
|---|
| 1650 |       P->R.alpha += delta_alpha*delta_t;
 | 
|---|
| 1651 |       if (P->Par.me == 0) fprintf(stderr,"(%i) alpha = %lg * %i = %lg\n", P->Par.me, delta_alpha, delta_t, P->R.alpha);
 | 
|---|
| 1652 |       // apply updated alpha as additional force
 | 
|---|
| 1653 |       for (is=0; is < I->Max_Types; is++) { // apply constraint constant on constraint force and on velocities
 | 
|---|
| 1654 |         for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
 | 
|---|
| 1655 |           U = &I->I[is].U[NDIM*ia];
 | 
|---|
| 1656 |           if (I->I[is].IMT[ia] == MoveIon) // even FixedIon moves, only not by other's forces
 | 
|---|
| 1657 |             for (d=0; d<NDIM; d++) {
 | 
|---|
| 1658 |               I->I[is].FConstraint[d+NDIM*ia] = - P->R.alpha * (U[d] * I->I[is].IonMass);
 | 
|---|
| 1659 |               U[d] += delta_t/I->I[is].IonMass * (I->I[is].FConstraint[d+NDIM*ia]);
 | 
|---|
| 1660 |               ekin += (0.5*I->I[is].IonMass) * U[d]*U[d];
 | 
|---|
| 1661 |             }
 | 
|---|
| 1662 |         }
 | 
|---|
| 1663 |       }
 | 
|---|
| 1664 |       break;
 | 
|---|
| 1665 |   }    
 | 
|---|
| 1666 |   I->EKin = ekin;
 | 
|---|
| 1667 |   I->ActualTemp = (2./(3.*I->Max_TotalIons)*I->EKin);    
 | 
|---|
| 1668 |   //if ((P->Par.me == 0) && (I->ActualTemp < MYEPSILON)) fprintf(stderr,"Thermostat: (2) I->ActualTemp = %lg",I->ActualTemp);
 | 
|---|
| 1669 |   if (Files->MeOutMes) { fprintf(Files->TemperatureFile, "\t%lg\n", I->ActualTemp); fflush(Files->TemperatureFile); }
 | 
|---|
| 1670 | }
 | 
|---|
| 1671 | 
 | 
|---|
| 1672 | /** Does the Molecular Dynamics Calculations.
 | 
|---|
| 1673 |  * All of the following is SpeedMeasure()'d in SimTime.
 | 
|---|
| 1674 |  * Initialization by calling:
 | 
|---|
| 1675 |  * -# CorrectVelocity()\n
 | 
|---|
| 1676 |  *    Shifts center of gravity of Ions momenta, so that the cell itself remains at rest.
 | 
|---|
| 1677 |  * -# CalculateEnergyIonsU(), SpeedMeasure()'d in TimeTypes#InitSimTime\n
 | 
|---|
| 1678 |  *    Calculates kinetic energy of "movable" Ions.
 | 
|---|
| 1679 |  * -# CalculateForce()\n
 | 
|---|
| 1680 |  *    Does the minimisation, calculates densities, then energies and finally the forces.
 | 
|---|
| 1681 |  * -# OutputVisSrcFiles()\n
 | 
|---|
| 1682 |  *    If desired, so-far made calculations are stored to file for later restarting.
 | 
|---|
| 1683 |  * -# OutputIonForce()\n
 | 
|---|
| 1684 |  *    Write ion forces to file.
 | 
|---|
| 1685 |  * -# EnergyOutput()\n
 | 
|---|
| 1686 |  *    Write calculated energies to screen or file.
 | 
|---|
| 1687 |  * 
 | 
|---|
| 1688 |  * The simulation phase begins: 
 | 
|---|
| 1689 |  * -# UpdateIonsR()\n
 | 
|---|
| 1690 |  *    Move Ions according to the calculated force.
 | 
|---|
| 1691 |  * -# UpdateWaveAfterIonMove()\n
 | 
|---|
| 1692 |  *    Update wave functions by averaging LocalPsi coefficients after the Ions have been shifted.
 | 
|---|
| 1693 |  * -# UpdateToNewWaves()\n
 | 
|---|
| 1694 |  *    Update after wave functions have changed.
 | 
|---|
| 1695 |  * -# CalculateForce()\n
 | 
|---|
| 1696 |  *    Does the minimisation, calculates densities, then energies and finally the forces.
 | 
|---|
| 1697 |  * -# UpdateIonsU()\n
 | 
|---|
| 1698 |  *    Change ion's velocities according to the calculated acting force.
 | 
|---|
| 1699 |  * -# CorrectVelocity()\n
 | 
|---|
| 1700 |  *    Shifts center of gravity of Ions momenta, so that the cell itself remains at rest.
 | 
|---|
| 1701 |  * -# CalculateEnergyIonsU()\n
 | 
|---|
| 1702 |  *    Calculates kinetic energy of "movable" Ions.
 | 
|---|
| 1703 |  * -# ScaleTemp()\n
 | 
|---|
| 1704 |  *    The temperature is scaled, so the systems energy remains constant (they must not gain momenta out of nothing)
 | 
|---|
| 1705 |  * -# OutputVisSrcFiles()\n
 | 
|---|
| 1706 |  *    If desired, so-far made calculations are stored to file for later restarting.
 | 
|---|
| 1707 |  * -# OutputVis()\n
 | 
|---|
| 1708 |  *    Visulization data for OpenDX is written at certain steps if desired.
 | 
|---|
| 1709 |  * -# OutputIonForce()\n
 | 
|---|
| 1710 |  *    Write ion forces to file.
 | 
|---|
| 1711 |  * -# EnergyOutput()\n
 | 
|---|
| 1712 |  *    Write calculated energies to screen or file.
 | 
|---|
| 1713 |  * 
 | 
|---|
| 1714 |  * After the ground state is found:
 | 
|---|
| 1715 |  * -# CalculateUnOccupied()\n
 | 
|---|
| 1716 |  *    Energies of unoccupied orbitals - that have been left out completely so far -
 | 
|---|
| 1717 |  *    are calculated.
 | 
|---|
| 1718 |  * -# TestGramSch()\n
 | 
|---|
| 1719 |  *    Test if orbitals are still orthogonal.
 | 
|---|
| 1720 |  * -# CalculateHamiltonian()\n
 | 
|---|
| 1721 |  *    Construct Hamiltonian and calculate Eigenvalues.
 | 
|---|
| 1722 |  * -# ComputeMLWF()\n
 | 
|---|
| 1723 |  *    Localize orbital wave functions.
 | 
|---|
| 1724 |  * 
 | 
|---|
| 1725 |  * \param *P Problem at hand
 | 
|---|
| 1726 |  */
 | 
|---|
| 1727 | void CalculateMD(struct Problem *P)
 | 
|---|
| 1728 | {
 | 
|---|
| 1729 |   struct RunStruct *R = &P->R;
 | 
|---|
| 1730 |   struct Ions *I = &P->Ion;
 | 
|---|
| 1731 |   struct Energy *E = P->Lat.E;
 | 
|---|
| 1732 |   int OuterStop = 0;
 | 
|---|
| 1733 |   int i;
 | 
|---|
| 1734 |   
 | 
|---|
| 1735 |   SpeedMeasure(P, SimTime, StartTimeDo);
 | 
|---|
| 1736 |   // initial calculations (bring density on BO surface and output start energies, coordinates, densities, ...)
 | 
|---|
| 1737 |   SpeedMeasure(P, InitSimTime, StartTimeDo);
 | 
|---|
| 1738 |   R->OuterStep = 0;
 | 
|---|
| 1739 |   CorrectVelocity(P);
 | 
|---|
| 1740 |   CalculateEnergyIonsU(P);
 | 
|---|
| 1741 |   OuterStop = CalculateForce(P);
 | 
|---|
| 1742 |   //R->OuterStep++;
 | 
|---|
| 1743 |   P->Speed.InitSteps++;
 | 
|---|
| 1744 |   SpeedMeasure(P, InitSimTime, StopTimeDo);
 | 
|---|
| 1745 | 
 | 
|---|
| 1746 |   OutputIonCoordinates(P, 1);
 | 
|---|
| 1747 |   OutputVis(P, P->R.Lev0->Dens->DensityArray[TotalDensity]);
 | 
|---|
| 1748 |   OutputIonForce(P);
 | 
|---|
| 1749 |   EnergyOutput(P, 1);
 | 
|---|
| 1750 |   
 | 
|---|
| 1751 |   // if desired perform beforehand a structure relaxation/optimization
 | 
|---|
| 1752 |   if (I->StructOpt) {
 | 
|---|
| 1753 |     debug(P,"Commencing minimisation on ionic structure ...");
 | 
|---|
| 1754 |     R->StructOptStep = 0;
 | 
|---|
| 1755 |     //UpdateIon_PRCG(P);
 | 
|---|
| 1756 |     //UpdateIon_Simplex(P);
 | 
|---|
| 1757 |     while ((R->MeanForce[0] > 1e-4) && (R->StructOptStep < R->MaxStructOptStep)) {
 | 
|---|
| 1758 |       R->StructOptStep++; 
 | 
|---|
| 1759 |       OutputIonCoordinates(P, 1);
 | 
|---|
| 1760 |       UpdateIons(P); 
 | 
|---|
| 1761 |       UpdateWaveAfterIonMove(P);
 | 
|---|
| 1762 |       for (i=MAXOLD-1; i > 0; i--)    // store away old energies
 | 
|---|
| 1763 |         E->TotalEnergyOuter[i] = E->TotalEnergyOuter[i-1];  
 | 
|---|
| 1764 |       UpdateToNewWaves(P);
 | 
|---|
| 1765 |       E->TotalEnergyOuter[0] = E->TotalEnergy[0]; 
 | 
|---|
| 1766 |       OuterStop = CalculateForce(P);
 | 
|---|
| 1767 |       CalculateEnergyIonsU(P);
 | 
|---|
| 1768 |       if ((R->StructOptStep-1) % P->R.OutSrcStep == 0) 
 | 
|---|
| 1769 |         OutputVisSrcFiles(P, Occupied);
 | 
|---|
| 1770 |       if ((R->StructOptStep-1) % P->R.OutVisStep == 0) {      
 | 
|---|
| 1771 |         OutputVis(P, P->R.Lev0->Dens->DensityArray[TotalDensity]);
 | 
|---|
| 1772 |         OutputIonForce(P);
 | 
|---|
| 1773 |         EnergyOutput(P, 1);
 | 
|---|
| 1774 |       }
 | 
|---|
| 1775 |       if (P->Par.me == 0) fprintf(stderr,"(%i) Mean force is %lg\n", P->Par.me, R->MeanForce[0]); 
 | 
|---|
| 1776 |     }
 | 
|---|
| 1777 |     OutputIonCoordinates(P, 1);
 | 
|---|
| 1778 |   }
 | 
|---|
| 1779 |   if (I->StructOpt && !OuterStop) {
 | 
|---|
| 1780 |     I->StructOpt = 0;
 | 
|---|
| 1781 |     OuterStop = CalculateForce(P);
 | 
|---|
| 1782 |   }
 | 
|---|
| 1783 |   
 | 
|---|
| 1784 |   // and now begin with the molecular dynamics simulation
 | 
|---|
| 1785 |   debug(P,"Commencing MD simulation ...");
 | 
|---|
| 1786 |   while (!OuterStop && R->OuterStep < R->MaxOuterStep) {
 | 
|---|
| 1787 |     R->OuterStep++;
 | 
|---|
| 1788 |     if (P->Par.me == 0) {
 | 
|---|
| 1789 |       if (R->OuterStep > 1) fprintf(stderr,"\b\b\b\b\b\b\b\b\b\b\b\b");
 | 
|---|
| 1790 |       fprintf(stderr,"Time: %f fs\r", R->t*Atomictime2Femtoseconds);
 | 
|---|
| 1791 |       fflush(stderr);
 | 
|---|
| 1792 |     }
 | 
|---|
| 1793 |     OuterStop = CalculateForce(P);
 | 
|---|
| 1794 |     P->R.t += P->R.delta_t;   // increase current time by delta_t
 | 
|---|
| 1795 |     R->NewRStep++;
 | 
|---|
| 1796 | 
 | 
|---|
| 1797 |     UpdateIonsU(P);
 | 
|---|
| 1798 |     CorrectVelocity(P);
 | 
|---|
| 1799 |     Thermostats(P, I->Thermostat);
 | 
|---|
| 1800 |     CalculateEnergyIonsU(P);
 | 
|---|
| 1801 | 
 | 
|---|
| 1802 |     UpdateIonsR(P);
 | 
|---|
| 1803 |     OutputIonCoordinates(P, 1);
 | 
|---|
| 1804 | 
 | 
|---|
| 1805 |     UpdateWaveAfterIonMove(P);
 | 
|---|
| 1806 |     for (i=MAXOLD-1; i > 0; i--)    // store away old energies
 | 
|---|
| 1807 |       E->TotalEnergyOuter[i] = E->TotalEnergyOuter[i-1];  
 | 
|---|
| 1808 |     UpdateToNewWaves(P);
 | 
|---|
| 1809 |     E->TotalEnergyOuter[0] = E->TotalEnergy[0]; 
 | 
|---|
| 1810 |     //if ((P->R.ScaleTempStep > 0) && ((R->OuterStep-1) % P->R.ScaleTempStep == 0))
 | 
|---|
| 1811 |     //  ScaleTemp(P);
 | 
|---|
| 1812 |     if ((R->OuterStep-1) % P->R.OutSrcStep == 0) 
 | 
|---|
| 1813 |       OutputVisSrcFiles(P, Occupied);
 | 
|---|
| 1814 |     if ((R->OuterStep-1) % P->R.OutVisStep == 0) {      
 | 
|---|
| 1815 |       OutputVis(P, P->R.Lev0->Dens->DensityArray[TotalDensity]);
 | 
|---|
| 1816 |       OutputIonForce(P);
 | 
|---|
| 1817 |       EnergyOutput(P, 1);
 | 
|---|
| 1818 |     }
 | 
|---|
| 1819 |     ResetForces(P);
 | 
|---|
| 1820 |   }
 | 
|---|
| 1821 |   SpeedMeasure(P, SimTime, StopTimeDo);
 | 
|---|
| 1822 |   CloseOutputFiles(P);
 | 
|---|
| 1823 | }
 | 
|---|