source: pcp/src/init.c@ 515271

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

HashGArray(): Little comment change

  • Property mode set to 100644
File size: 97.3 KB
Line 
1/** \file init.c
2 * Initialization and Readin of parameter files.
3 * Initialization Init() is split up into various parts:
4 * lattice InitLattice(), first lattice level InitLatticeLevel0(), remaining lattice level InitOtherLevel(),
5 * wave functions InitPsis() and their values InitPsisValue() and distribution among the processes InitPsiGroupNo(),
6 * Many parts are found in their respective files such as for densities density.c and energies or
7 * GramSchmidt gramsch.c.\n
8 * Reading of the parameter file is done in ReadParameters() by parsing the file with ParseForParameter(), CreateMainname()
9 * separates the path from the main programme file.\n
10 * There remain some special routines used during initialization: splitting grid vector index on level change SplitIndex(),
11 * calculating the grid vector index GetIndex(), sort criteria on squared grid vector norm GetKeyOneG(), testing whether G's
12 * norm is below the energy cutoff TestG, or discerning wethers it's stored only half as often due to symmetry TestGDouble().
13 * Also due to density being calculated on a higher level there are certain factors that can be pulled out which can be
14 * precalculated CreatePosFacForG().
15 *
16 Project: ParallelCarParrinello
17 \author Jan Hamaekers, Frederik Heber
18 \date 2000, 2006
19
20 File: init.c
21 $Id: init.c,v 1.97 2007-04-10 14:34:08 foo Exp $
22*/
23
24#include <stdlib.h>
25#include <stdio.h>
26#include <math.h>
27#include <string.h>
28
29// use double precision fft when we have it
30#ifdef HAVE_CONFIG_H
31#include <config.h>
32#endif
33
34#ifdef HAVE_DFFTW_H
35#include "dfftw.h"
36#else
37#include "fftw.h"
38#endif
39
40#include "data.h"
41#include "helpers.h"
42#include "errors.h"
43#include "init.h"
44#include "mergesort2.h"
45#include "myfft.h"
46#include "gramsch.h"
47#include "density.h"
48#include "riemann.h"
49#include "output.h"
50#include "energy.h"
51#include "mymath.h"
52#include "pseudo.h"
53#include "ions.h"
54
55/** Splits the index of a reciprocal grid vector by the number of nodes per dimension.
56 * \param Index current index of the grid vector
57 * \param nx number of nodes in x direction
58 * \param nz number of nodes in z direction
59 * \param *x return value (Index % nx)
60 * \param *y return value (Index / nx / nz)
61 * \param *z return value (Index / nx % nz)
62 */
63static void SplitIndex(int Index, const int nx, const int nz, int *x, int *y, int *z) {
64 if ((nx == 0) || (nz == 0)) fprintf(stderr,"SplitIndex: nx = %d, nz == %d",nx,nz);
65 *x = Index % nx;
66 Index /= nx;
67 *z = Index % nz;
68 *y = Index / nz;
69}
70
71/** Prepare mainname (and mainpath).
72 * Extracts the path specified from the config file on command line by hopping along the path delimiters,
73 * this becomes Files::mainpath, including the filename itself it becomes Files::mainname.
74 * \param *P Problem at hand
75 * \param filename pointer to file name string
76 */
77void CreateMainname(struct Problem *const P, const char* const filename)
78{
79 char *dummy;
80 char *token;
81 char *token2;
82 const char delimiters[] = "/";
83 int stop = 0;
84 int setit = 0;
85 dummy = (char*) /* Kopie von filename */
86 Malloc(strlen(filename)+1, "PrecreateMainname - dummy");
87 sprintf(dummy,"%s",filename);
88 P->Files.mainname = (char*) /* Speicher fuer P->Files.mainname */
89 Malloc(strlen(filename)+strlen(P->Files.filename)+2, "CreateMainname - P->Files.mainname");
90 P->Files.mainname[0] = 0;
91 /* Jetzt mit strtok mainname vorbereiten */
92 if (dummy) {
93 if (dummy[0] == '/') setit = 1; // remember there was delimiter at the very beginning
94 token = strtok(dummy, delimiters);
95 do {
96 token2 = strtok(0, delimiters); // a subsequent call of strtok to the end of this path piece (between token and token2)
97 if (token2) { // if it's not the last piece
98 if (setit) strcat(P->Files.mainname,"/");
99 setit = 1; // afterwards always replace the delimiters in the target string
100 strcat(P->Files.mainname, token); // copy the path piece
101 token = token2; // and go to next section
102 } else {
103 stop = 1;
104 }
105 } while (!stop);
106 }
107 if (setit) strcat(P->Files.mainname,"/");
108 if (dummy) Free(dummy, "CreateMainname: dummy");
109 P->Files.mainpath = (char*) /* Speicher fuer P->Files.mainname */
110 Malloc(strlen(P->Files.mainname)+10, "CreateMainname - P->Files.mainpath");
111 sprintf(P->Files.mainpath, "%s" ,P->Files.mainname);
112 if (P->Call.out[ReadOut]) fprintf(stderr,"(%i) CreateMainame: mainpath: %s\t", P->Par.me, P->Files.mainpath);
113 //strcat(P->Files.mainname, P->Files.filename); /* mainname fertigstellen */
114 strcpy(P->Files.mainname, P->Files.filename);
115 if (P->Call.out[ReadOut]) fprintf(stderr,"mainname: %s\n", P->Files.mainname);
116}
117
118/** Initializing Lattice structure.
119 * Calculates unit cell's volume, (transposed) reciprocal base Lattice::ReciBasis
120 * and square-rooted Lattice::ReciBasisSQ, preparation of LatticeLevel structure,
121 * NFields depends on use of RiemannTensor, calculates the orthonormal reciprocal
122 * base and thus how many mesh points for the ECut constraint are at least necessary.
123 * \param *P Problem at hand
124 * \return 0 - everything went alright, 1 - some problem (volume is zero)
125 */
126static int InitLattice(struct Problem *const P) {
127 struct Lattice *const Lat = &P->Lat;
128 double factor = 2.*PI;
129 double h[NDIM_NDIM];
130 double V[NDIM];
131 double NormV;
132 int AddNFactor = Lat->AddNFactor = P->Call.AddNFactor;
133 int i,j,UpDummy;
134 int MaxG[NDIM], N[NDIM], NFactor, Lev1N[NDIM];
135 struct LatticeLevel *Lev0;
136 int RL=-1;
137 // Volume
138 if (P->Call.out[NormalOut]) fprintf(stderr, "(%i)InitLattice\n", P->Par.me);
139 Lat->Volume = RDET3(Lat->RealBasis);
140 if (P->Call.out[ValueOut]) fprintf(stderr,"Volume = %g\n",Lat->Volume);
141 if (Lat->Volume == 0.0) {
142 return(1);
143 }
144 // square-rooted and normal reciprocal (transposed) Base
145 for (i=0; i < NDIM_NDIM; i++) h[i] = Lat->RealBasis[i];
146 RTranspose3(h);
147 RMatReci3(Lat->ReciBasis, h);
148 for (i=0; i < NDIM_NDIM; i++) Lat->ReciBasis[i] *= factor; // SM(Lat->ReciBasis, factor, NDIM_NDIM);
149 for (i=0; i < NDIM; i++) {
150 Lat->ReciBasisSQ[i] = RNORMSQ3(&(Lat->ReciBasis[i*NDIM]));
151 Lat->RealBasisSQ[i] = RNORMSQ3(&(Lat->RealBasis[i*NDIM]));
152 Lat->RealBasisQ[i] = sqrt(Lat->RealBasisSQ[i]);
153 }
154 // Prepares LatticeLevels
155 Lat->Lev = (struct LatticeLevel *)
156 Malloc(Lat->MaxLevel*sizeof(struct LatticeLevel),"InitLattice: Lat->Lev");
157 for (i=0; i < Lat->MaxLevel; i++)
158 Lat->Lev[i].Step = 0;
159 Lev0 = Lat->Lev; // short for &(Lat->Lev[0])
160 Lat->LevelSizes = (int *)
161 Malloc(sizeof(int)*Lat->MaxLevel,"InitLattice: LevelSizes");
162 Lat->LevelSizes[0] = P->Lat.Lev0Factor;
163 for (i=1; i < Lat->MaxLevel-1; i++) Lat->LevelSizes[i] = 2;
164 if (Lat->RT.Use == UseRT) {
165 RL = Lat->RT.RiemannLevel;
166 Lat->LevelSizes[RL-1] = P->Lat.LevRFactor;
167 }
168 Lat->LevelSizes[Lat->MaxLevel-1] = 1;
169 // NFields are next ... depending on use of RiemannTensor
170 Lat->MaxNoOfnFields = (int *)
171 Malloc(sizeof(int)*Lat->MaxLevel,"InitLattice: MaxNoOfnFields");;
172 Lat->NFields = (int **)
173 Malloc(sizeof(int*)*Lat->MaxLevel,"InitLattice: NFields");
174 switch (Lat->RT.Use) {
175 case UseNotRT:
176 for (i=0; i<Lat->MaxLevel; i++) {
177 if (i==0) {
178 Lat->MaxNoOfnFields[i] = 1;
179 Lat->NFields[i] = (int *)
180 Malloc(sizeof(int)*Lat->MaxNoOfnFields[i],"InitLattice: NFields");
181 Lat->NFields[i][FFTNF1] = 1;
182 } else {
183 Lat->MaxNoOfnFields[i] = 2;
184 Lat->NFields[i] = (int *)
185 Malloc(sizeof(int)*Lat->MaxNoOfnFields[i],"InitLattice: NFields");
186 Lat->NFields[i][FFTNF1] = 1;
187 Lat->NFields[i][FFTNFUp] = Lat->LevelSizes[i-1]*Lat->LevelSizes[i-1]*Lat->LevelSizes[i-1];
188 }
189 }
190 break;
191 case UseRT:
192 for (i=0; i<Lat->MaxLevel; i++) {
193 switch (i) {
194 case 0:
195 Lat->MaxNoOfnFields[i] = 2;
196 Lat->NFields[i] = (int *)
197 Malloc(sizeof(int)*Lat->MaxNoOfnFields[i],"InitLattice: NFields");
198 Lat->NFields[i][FFTNF1] = 1;
199 Lat->NFields[i][FFTNF0Vec] = NDIM;
200 break;
201 case STANDARTLEVEL:
202 Lat->MaxNoOfnFields[i] = 4;
203 Lat->NFields[i] = (int *)
204 Malloc(sizeof(int)*Lat->MaxNoOfnFields[i],"InitLattice: NFields");
205 Lat->NFields[i][FFTNF1] = 1;
206 Lat->NFields[i][FFTNFUp] = Lat->LevelSizes[0]*Lat->LevelSizes[0]*Lat->LevelSizes[0];
207 Lat->NFields[i][FFTNFSVecUp] = Lat->NFields[i][FFTNFUp]*NDIM;
208 Lat->NFields[i][FFTNFSVec] = NDIM;
209 break;
210 default:
211 if (i == RL) {
212 Lat->MaxNoOfnFields[i] = 5;
213 Lat->NFields[i] = (int *)
214 Malloc(sizeof(int)*Lat->MaxNoOfnFields[i],"InitLattice: NFields");
215 Lat->NFields[i][FFTNF1] = 1;
216 Lat->NFields[i][FFTNFUp] = Lat->LevelSizes[i-1]*Lat->LevelSizes[i-1]*Lat->LevelSizes[i-1];
217 UpDummy = 1;
218 for (j=RL-1; j >= STANDARTLEVEL; j--)
219 UpDummy *= Lat->LevelSizes[j]*Lat->LevelSizes[j]*Lat->LevelSizes[j];
220 /* UpDummy RL -> S */
221 Lat->NFields[i][FFTNFRMatVecUpS] = UpDummy*NDIM_NDIM*NDIM;
222
223 UpDummy = 1;
224 for (j=RL-1; j >= 0; j--)
225 UpDummy *= Lat->LevelSizes[j]*Lat->LevelSizes[j]*Lat->LevelSizes[j];
226 /* UpDummy RL -> 0 */
227 Lat->NFields[i][FFTNFRMatUp0] = UpDummy*NDIM_NDIM;
228 Lat->NFields[i][FFTNFRVecUp0] = UpDummy*NDIM;
229 } else {
230 Lat->MaxNoOfnFields[i] = 2;
231 Lat->NFields[i] = (int *)
232 Malloc(sizeof(int)*Lat->MaxNoOfnFields[i],"InitLattice: NFields");
233 Lat->NFields[i][FFTNF1] = 1;
234 Lat->NFields[i][FFTNFUp] = Lat->LevelSizes[i-1]*Lat->LevelSizes[i-1]*Lat->LevelSizes[i-1];
235 }
236 break;
237 }
238 }
239 break;
240 }
241 if (P->Call.out[ValueOut]) {
242 for (i=0; i<Lat->MaxLevel; i++) {
243 fprintf(stderr,"NFields[%i] =",i);
244 for (j=0; j<Lat->MaxNoOfnFields[i]; j++) {
245 fprintf(stderr," %i",Lat->NFields[i][j]);
246 }
247 fprintf(stderr,"\n");
248 }
249 }
250 // calculate mesh points per dimension from ECut constraints for 0th level
251 for (i=0; i< NDIM; i++) { // by vector product creates orthogonal reciprocal base vectors, takes norm, ...
252 VP3(V, &Lat->ReciBasis[NDIM*((i+1)%NDIM)], &Lat->ReciBasis[NDIM*((i+2)%NDIM)]);
253 NormV = sqrt(RNORMSQ3(V));
254 if (fabs(NormV) < MYEPSILON) fprintf(stderr,"InitLattice: NormV = %lg",NormV);
255 for (j=0;j<NDIM;j++) V[j] /= NormV;
256 Lat->ReciBasisO[i] = fabs(RSP3(V,&Lat->ReciBasis[NDIM*i]));
257 Lat->ReciBasisOSQ[i] = Lat->ReciBasisO[i]*Lat->ReciBasisO[i];
258 if (P->Call.out[ValueOut]) fprintf(stderr,"G[%i] = (%g ,%g ,%g) GSQ[%i] = %g GOSQ[%i] = %g\n",i,Lat->ReciBasis[i*NDIM+0],Lat->ReciBasis[i*NDIM+1],Lat->ReciBasis[i*NDIM+2],i,Lat->ReciBasisSQ[i],i,Lat->ReciBasisOSQ[i]);
259 if (Lat->ReciBasisOSQ[i] < MYEPSILON) fprintf(stderr,"InitLattice: Lat->ReciBasisOSQ[i] = %lg",Lat->ReciBasisOSQ[i]);
260 MaxG[i] = floor(sqrt(2.*Lat->ECut/Lat->ReciBasisOSQ[i]));
261 N[i] = 2*MaxG[i]+2;
262 NFactor = ( i==2 ? 2 : 1)*P->Par.proc[PEGamma]; /* TESTINIT */
263 for (j=1; j < Lat->MaxLevel; j++) NFactor *= Lat->LevelSizes[j];
264 if (AddNFactor == 0) fprintf(stderr,"InitLattice: AddNFactor = %d",AddNFactor);
265 NFactor *= AddNFactor;
266 Lev0->N[i] = NFactor*ceil((double)N[i]/(double)NFactor);
267 Lev1N[i] = Lev0->N[i];
268 Lev0->N[i] *= Lat->LevelSizes[0];
269 }
270 if (P->Call.out[LeaderOut] && P->Par.me == 0) fprintf(stderr,"MaxG[] = %i %i %i -> N[] = %i %i %i -> Lev1->N[] %i %i %i -> Lev0->N[] %i %i %i\n",MaxG[0],MaxG[1],MaxG[2],N[0],N[1],N[2],Lev1N[0],Lev1N[1],Lev1N[2],Lev0->N[0],Lev0->N[1],Lev0->N[2]);
271 if (P->Files.MeOutMes)
272 fprintf(P->Files.SpeedFile,"\nMaxG[] = %i %i %i -> N[] = %i %i %i -> Lev1->N[] %i %i %i -> Lev0->N[] %i %i %i\n",MaxG[0],MaxG[1],MaxG[2],N[0],N[1],N[2],Lev1N[0],Lev1N[1],Lev1N[2],Lev0->N[0],Lev0->N[1],Lev0->N[2]);
273 Lat->E = &Lat->Energy[Occupied];
274
275 if (P->Call.out[ValueOut]) {
276 fprintf(stderr,"(%i) Lat->Realbasis = \n",P->Par.me);
277 for (i=0; i < NDIM_NDIM; i++) {
278 fprintf(stderr,"%lg ",Lat->RealBasis[i]);
279 if (i%NDIM == NDIM-1) fprintf(stderr,"\n");
280 }
281 fprintf(stderr,"(%i) Lat->RealbasisQ = ",P->Par.me);
282 for (i=0; i < NDIM; i++)
283 fprintf(stderr,"%lg ",Lat->RealBasisQ[i]);
284 fprintf(stderr,"\n");
285 }
286
287 return(0);
288}
289
290/** Test if a reciprocal grid vector is still within the energy cutoff Lattice::ECut.
291 * The vector is generated with the given coefficients, its norm calculated and compared
292 * with twice the ECut.
293 * \param *Lat Lattice containing the reciprocal basis vectors and ECut
294 * \param g1 first coefficient
295 * \param g2 second coefficient
296 * \param g3 third coefficient
297 * \param *GSq return value for norm of the vector
298 * \param G return array of NDIM for the vector
299 * \return 0 - vector ok, 1 - norm is bigger than twice the energy cutoff
300 */
301static int TestG(struct Lattice *Lat, int g1, int g2, int g3, double *GSq, double G[NDIM]) {
302 G[0] = g1*Lat->ReciBasis[0]+g2*Lat->ReciBasis[3]+g3*Lat->ReciBasis[6];
303 G[1] = g1*Lat->ReciBasis[1]+g2*Lat->ReciBasis[4]+g3*Lat->ReciBasis[7];
304 G[2] = g1*Lat->ReciBasis[2]+g2*Lat->ReciBasis[5]+g3*Lat->ReciBasis[8];
305 *GSq = RNORMSQ3(G);
306 if (0.5*(*GSq) <= Lat->ECut) return (1);
307 return (0);
308}
309
310/** Specifies which DoubleGType a certain combination of coefficients is.
311 * Basically, on the (gz=0)-plane the gy half is DoubleGUse, the lower DoubleGNotUse (including
312 * the (gx>=0)-line)
313 * \param gx x coefficient of reciprocal grid vector
314 * \param gy y coefficient of reciprocal grid vector
315 * \param gz z coefficient of reciprocal grid vector
316 * \return DoubleG0 : if all coefficients are zero <br>
317 * DoubleGUse : if gz is zero, and gx is strictly positive and gy positive or vice versa <br>
318 * DoubleGNotUse: if gz is zero, and gx is (strictly) positive and gy (strictly) negative or vice versa <br>
319 * DoubleGNot : if gz is not equal to zero
320 */
321static enum DoubleGType TestGDouble(int gx, int gy, int gz) {
322 if (gx == 0 && gy == 0 && gz == 0) return DoubleG0;
323 if (gz == 0) {
324 if (gx > 0) {
325 if (gy >= 0) return DoubleGUse;
326 else return DoubleGNotUse;
327 } else {
328 if (gy > 0) return DoubleGUse;
329 else return DoubleGNotUse;
330 }
331 }
332 return DoubleGNot;
333}
334
335/** Returns squared product of the reciprocal vector as a sort criteria.
336 * \param *a OneGData structure array containing the grid vectors
337 * \param i i-th reciprocal vector
338 * \param *Args not used, specified for contingency
339 * \return a[i].OneGData::GSq
340 */
341static double GetKeyOneG(void *a, int i, void *Args) {
342 return(((struct OneGData *)a)[i].GSq);
343}
344
345/** Returns component of reciprocal vector as a sort criteria.
346 * \param *a OneGData structure array containing the grid vectors
347 * \param i i-th reciprocal vector
348 * \param *Args specifies index
349 * \return a[i].OneGData::G[Args]
350 */
351static double GetKeyOneG2(void *a, int i, void *Args) {
352 //fprintf(stderr,"G[%i] = %e\n", *(int *)Args,((struct OneGData *)a)[i].G[*(int *)Args] );
353 return(((struct OneGData *)a)[i].G[*(int *)Args]);
354}
355
356/** Copies each entry of OneGData from \a b to \a a.
357 * \param *a destination reciprocal grid vector
358 * \param i i-th grid vector of \a a
359 * \param *b source reciprocal grid vector
360 * \param j j-th vector of \a b
361 */
362static void CopyElementOneG(void *a, int i, void *b, int j) {
363 ((struct OneGData *)a)[i].Index = ((struct OneGData *)b)[j].Index;
364 ((struct OneGData *)a)[i].GlobalIndex = ((struct OneGData *)b)[j].GlobalIndex;
365 ((struct OneGData *)a)[i].GSq = ((struct OneGData *)b)[j].GSq;
366 ((struct OneGData *)a)[i].G[0] = ((struct OneGData *)b)[j].G[0];
367 ((struct OneGData *)a)[i].G[1] = ((struct OneGData *)b)[j].G[1];
368 ((struct OneGData *)a)[i].G[2] = ((struct OneGData *)b)[j].G[2];
369}
370
371/** Calculates the index of a reciprocal grid vector by its components.
372 * \param *plan
373 * \param *LPlan LevelPlan structure
374 * \param gx first component
375 * \param gy second component
376 * \param gz third component
377 * \return index
378 */
379static int GetIndex(struct fft_plan_3d *plan, struct LevelPlan *LPlan, int gx, int gy, int gz) {
380 int x = (gx < 0 ? gx+LPlan->N[0] : gx);
381 int y = (gy < 0 ? gy+LPlan->N[1] : gy);
382 int Y = y/LPlan->LevelFactor;
383 int YY = y%LPlan->LevelFactor;
384 int z = (gz < 0 ? gz+LPlan->N[2]/2+1 : gz);
385 int Z = z/LPlan->LevelFactor;
386 int ZZ = z%LPlan->LevelFactor;
387 int pwIndex = Z+(plan->NLSR[2]/2+1)*Y;
388 int i=0,pwy,pwz,iz;
389 for (i=0; i < plan->LocalMaxpw; i++)
390 if (plan->Localpw[i].Index == pwIndex) {
391 pwz = i%(plan->NLSR[2]/2+1);
392 if (pwz == plan->NLSR[2]/2) {
393 iz = LPlan->N[2]/2;
394 } else {
395 iz = pwz*LPlan->LevelFactor+ZZ;
396 }
397 pwy = i/(plan->NLSR[2]/2+1);
398 return (x+LPlan->N[0]*(iz+LPlan->nz*(pwy*LPlan->LevelFactor+YY)));
399 }
400 return -1;
401}
402
403/** Builds a hash table and sets a global index for GArray.
404 * The global index is needed in order to initalise the wave functions randomly but solely dependent
405 * on the seed value, not on the number of coefficient sharing processes! The creation of the G vectors
406 * is checked whether there were duplicates or not by sorting the vectors.
407 * \param *P Problem at hand
408 * \param *Lat Pointer to Lattice structure
409 * \param *Lev Pointer to LatticeLevel structure, containing GArray
410 */
411static void HashGArray(struct Problem *P, struct Lattice *Lat, struct LatticeLevel *Lev)
412{
413 int index, i, g, dupes;
414 int myPE, MaxPE;
415 struct OneGData *GlobalGArray, *GlobalGArray_sort;
416 double **G, **G_send;
417 int base = 0;
418 int MaxG = 0;
419 int AllMaxG = 0;
420 MPI_Comm_size(P->Par.comm_ST_Psi, &MaxPE); // Determines the size of the group associated with a communictor
421 MPI_Comm_rank(P->Par.comm_ST_Psi, &myPE); // Determines the rank of the calling process in the communicator
422
423 // first gather GArray from all coefficient sharing processes into one array
424 // get maximum number of G in one process
425 for (i=0;i<MaxPE; i++) { // go through every process
426 if (MaxG < Lev->AllMaxG[i])
427 MaxG = Lev->AllMaxG[i];
428 AllMaxG += Lev->AllMaxG[i];
429 }
430 GlobalGArray = (struct OneGData *) Malloc(AllMaxG*(sizeof(struct OneGData)),"HashGArray: GlobalGArray");
431 GlobalGArray_sort = (struct OneGData *) Malloc(AllMaxG*(sizeof(struct OneGData)),"HashGArray: GlobalGArray");
432 G = (double **) Malloc(NDIM*(sizeof(double)),"HashGArray: G");
433 G_send = (double **) Malloc(NDIM*(sizeof(double)),"HashGArray: G_send");
434 for (i=0;i<NDIM;i++) {
435 G[i] = (double *) Malloc(MaxPE*MaxG*(sizeof(double)),"HashGArray: G[i]");
436 G_send[i] = (double *) Malloc(MaxG*(sizeof(double)),"HashGArray: G_send[i]");
437 }
438 // fill send array
439 for (index=0;index<NDIM;index++) {
440 for (i=0;i<Lev->MaxG;i++)
441 G_send[index][i] = Lev->GArray[i].G[index];
442 for (;i<MaxG;i++)
443 G_send[index][i] = 0.;
444 }
445
446 // gather among all processes
447 MPI_Allgather(G_send[0], MaxG, MPI_DOUBLE, G[0], MaxG, MPI_DOUBLE, P->Par.comm_ST_Psi);
448 MPI_Allgather(G_send[1], MaxG, MPI_DOUBLE, G[1], MaxG, MPI_DOUBLE, P->Par.comm_ST_Psi);
449 MPI_Allgather(G_send[2], MaxG, MPI_DOUBLE, G[2], MaxG, MPI_DOUBLE, P->Par.comm_ST_Psi);
450 // fill gathered results into GlobalGArray
451 //if (P->Call.out[LeaderOut])
452 fprintf(stderr,"(%i) MaxPE %i / myPE %i, AllMaxG %i / MaxG %i / Lev->MaxG %i, TotalAllMaxG %i, ECut %lg\n", P->Par.me, MaxPE, myPE, AllMaxG, MaxG, Lev->MaxG, Lev->TotalAllMaxG, Lev->ECut/4.); // Ecut is in Rydberg
453 base = 0;
454 for (i=0;i<MaxPE; i++) { // go through every process
455 for (g=0;g<Lev->AllMaxG[i];g++) { // through every G of above process
456 for (index=0;index<NDIM;index++)
457 GlobalGArray[base+g].G[index] = G[index][MaxG*i+g];
458 GlobalGArray[base+g].GlobalIndex = i;
459 GlobalGArray[base+g].Index = g;
460 //if (P->Call.out[LeaderOut]) fprintf(stderr,"(%i) GlobalGArray[%i+%i].G[index] = (%e,%e,%e), .index = %i, myPE = %i\n",P->Par.me, base, g, GlobalGArray[base+g].G[0], GlobalGArray[base+g].G[1], GlobalGArray[base+g].G[2], GlobalGArray[base+g].Index, GlobalGArray[base+g].GlobalIndex);
461 }
462 base += Lev->AllMaxG[i];
463 }
464
465 // then sort array
466 // sort by x coordinate
467 index = 0;
468 naturalmergesort(GlobalGArray,GlobalGArray_sort,0,AllMaxG-1,&GetKeyOneG2,&index,&CopyElementOneG);
469 //if (P->Call.out[LeaderOut]) fprintf(stderr,"\n\n");
470 base = 0;
471 //for (g=0;g<AllMaxG;g++) // through every G of above process
472 //if (P->Call.out[LeaderOut]) fprintf(stderr,"(%i) GlobalGArray_sort[%i].G[index] = (%e,%e,%e), .index = %i, myPE= %i\n",P->Par.me, g, GlobalGArray_sort[g].G[0], GlobalGArray_sort[g].G[1], GlobalGArray_sort[g].G[2], GlobalGArray_sort[g].Index, GlobalGArray[base+g].GlobalIndex);
473 // sort by y coordinate
474 //if (P->Call.out[LeaderOut]) fprintf(stderr,"\n\n");
475 index = 1;
476 base = 0;
477 for (g=0;g<AllMaxG;g++) { // through every G of above process
478 if (GlobalGArray[base].G[index-1] != GlobalGArray[g].G[index-1]) {
479 naturalmergesort(GlobalGArray_sort,GlobalGArray,base,g-1,&GetKeyOneG2,&index,&CopyElementOneG);
480 base = g;
481 }
482 }
483 if (base != AllMaxG-1) naturalmergesort(GlobalGArray_sort,GlobalGArray,base,AllMaxG-1,&GetKeyOneG2,&index,&CopyElementOneG); // last section
484 base = 0;
485 //for (g=0;g<AllMaxG;g++) // through every G of above process
486 //if (P->Call.out[LeaderOut]) fprintf(stderr,"(%i) GlobalGArray[%i].G[index] = (%e,%e,%e), .index = %i, myPE= %i\n",P->Par.me, g, GlobalGArray[g].G[0], GlobalGArray[g].G[1], GlobalGArray[g].G[2], GlobalGArray[g].Index, GlobalGArray[base+g].GlobalIndex);
487 // sort by z coordinate
488 index = 2;
489 base = 0;
490 for (g=0;g<AllMaxG;g++) { // through every G of above process
491 if (GlobalGArray[base].G[index-1] != GlobalGArray[g].G[index-1]) {
492 naturalmergesort(GlobalGArray,GlobalGArray_sort,base,g-1,&GetKeyOneG2,&index,&CopyElementOneG);
493 base = g;
494 }
495 }
496 if (base != AllMaxG-1) naturalmergesort(GlobalGArray,GlobalGArray_sort,base,AllMaxG-1,&GetKeyOneG2,&index,&CopyElementOneG); // last section
497 base = 0;
498 //for (g=0;g<AllMaxG;g++) // through every G of above process
499 //if (P->Call.out[LeaderOut]) fprintf(stderr,"(%i) GlobalGArray_sort[%i].G = (%e,%e,%e), myPE = %i, index = %i\n", P->Par.me, g, GlobalGArray_sort[g].G[0], GlobalGArray_sort[g].G[1], GlobalGArray_sort[g].G[2], GlobalGArray_sort[g].GlobalIndex, GlobalGArray_sort[g].Index);
500
501
502 // now index 'em through and build the hash table
503 for (g=0;g<AllMaxG;g++) {// through every G of above process
504 Lev->HashG[g].i = GlobalGArray_sort[g].Index;
505 Lev->HashG[g].myPE = GlobalGArray_sort[g].GlobalIndex;
506 //if (P->Call.out[LeaderOut]) fprintf(stderr,"(%i) HashG[%i]: i %i, myPE %i\n",P->Par.me, g, Lev->HashG[g].i, Lev->HashG[g].myPE);
507 }
508
509 // find the dupes
510 dupes = 0;
511 for (g=0;g<AllMaxG-1;g++) // through every G of above process
512 if ((GlobalGArray_sort[g].G[0] == GlobalGArray_sort[g+1].G[0]) &&
513 (GlobalGArray_sort[g].G[1] == GlobalGArray_sort[g+1].G[1]) &&
514 (GlobalGArray_sort[g].G[2] == GlobalGArray_sort[g+1].G[2])) {
515 dupes++;
516 if (P->Call.out[LeaderOut]) fprintf(stderr,"(%i) (i, myPE): (%i,%i) and (%i,%i) are duplicate!\n",P->Par.me, GlobalGArray_sort[g].Index, GlobalGArray_sort[g].GlobalIndex, GlobalGArray_sort[g+1].Index, GlobalGArray_sort[g+1].GlobalIndex);
517 }
518 if (P->Call.out[LeaderOut]) {
519 if (dupes) fprintf(stderr,"(%i) %i duplicates in GArrays overall in Lev[%i]\n",P->Par.me, dupes, Lev->LevelNo);
520 else fprintf(stderr,"(%i) There were no duplicate G vectors in Lev[%i] \n",P->Par.me, Lev->LevelNo);
521 }
522
523 Free(GlobalGArray, "HashGArray: GlobalGArray");
524 Free(GlobalGArray_sort, "HashGArray: GlobalGArray_sort");
525 for (i=0;i<NDIM;i++) {
526 Free(G[i], "HashGArray: G[i]");
527 Free(G_send[i], "HashGArray: G_send[i]");
528 }
529 Free(G, "HashGArray: G");
530 Free(G_send, "HashGArray: G_send");
531}
532
533/** Initialization of zeroth lattice level.
534 * Creates each possible reciprocal grid vector, first counting them all (LatticeLevel::MaxG and LatticeLevel::MaxDoubleG),
535 * then allocating memory in LatticeLevel::GArray, creating and storing them all. Afterwards, these are sorted.
536 * LatticeLevel::MaxG is gathered from all processes and LatticeLevel::AllMaxG calculated
537 *\param *P Problem at hand
538 */
539static void InitLatticeLevel0(struct Problem *const P) {
540 struct Lattice *Lat = &P->Lat;
541 struct LatticeLevel *Lev0 = Lat->Lev; // short for &(Lat->Lev[0])
542 struct RPlans *RPs = &Lev0->Plan0;
543 double GSq=0;
544 double ECut = Lat->ECut;
545 double G[NDIM];
546 int x,ly,y,z,Index,d,Y,Z,iY,iZ,iy,iz,lz,X,i,yY,k,AllMaxG;
547
548 if (P->Call.out[NormalOut]) fprintf(stderr, "(%i)InitLatticeLevel0\n", P->Par.me);
549 Lat->ECut *= Lat->LevelSizes[0]*Lat->LevelSizes[0];
550 Lat->plan = fft_3d_create_plan(P, P->Par.comm_ST_Psi, Lat->ECut, Lat->MaxLevel, Lat->LevelSizes, Lat->ReciBasisOSQ, Lev0->N, Lat->MaxNoOfnFields, Lat->NFields);
551 RPs->plan = &Lat->plan->Levplan[0];
552 RPs->cdata = Lat->plan->local_data;
553 RPs->rdata = (fftw_real *)Lat->plan->local_data;
554 for (d=0; d < NDIM; d++) {
555 Lev0->NUp[d] = 1;
556 Lev0->NUp0[d] = 1;
557 Lev0->NUp1[d] = 0;
558 }
559 Lev0->MaxN = Lev0->N[0]*Lev0->N[1]*Lev0->N[2];
560 Lev0->PosFactorUp = NULL;
561 Lev0->LevelNo = 0;
562 Lev0->MaxG = 0;
563 Lev0->MaxDoubleG = 0;
564 Lev0->MaxNUp = 0;
565 // goes through each possible reciprocal grid vector, counting them (for MaxG and MaxDoubleG)
566 for (i = 0; i < Lat->plan->LocalMaxpw; i++) {
567 Index = Lat->plan->Localpw[i].Index;
568 Z = Index%(Lat->plan->NLSR[2]/2+1);
569 Y = Index/(Lat->plan->NLSR[2]/2+1);
570 for (ly = 0; ly < RPs->plan->LevelFactor; ly++) {
571 yY = ly + RPs->plan->LevelFactor*Y;
572 if (Z==Lat->plan->NLSR[2]/2) { // if it's the last possible one
573 z = RPs->plan->N[2]/2;
574 for (X=0; X < RPs->plan->N[0]; X++) {
575 x = ( X >= RPs->plan->N[0]/2+1 ? X - RPs->plan->N[0] : X);
576 y = ( yY >= RPs->plan->N[1]/2+1 ? yY - RPs->plan->N[1] : yY);
577 if (TestG(&P->Lat, x, y, z, &GSq, G)) Lev0->MaxG++;
578 }
579 } else {
580 for (z=(Z)*RPs->plan->LevelFactor; z < (Z+1)*RPs->plan->LevelFactor; z++)
581 for (X=0; X < RPs->plan->N[0]; X++) {
582 x = ( X >= RPs->plan->N[0]/2+1 ? X - RPs->plan->N[0] : X);
583 y = ( yY >= RPs->plan->N[1]/2+1 ? yY - RPs->plan->N[1] : yY);
584 if (TestG(&P->Lat, x, y, z, &GSq, G)) {
585 switch (TestGDouble(x,y,z)) {
586 case DoubleGNot:
587 Lev0->MaxG++;
588 break;
589 case DoubleG0:
590 Lev0->MaxG++;
591 break;
592 case DoubleGUse:
593 Lev0->MaxG++;
594 Lev0->MaxDoubleG++;
595 break;
596 case DoubleGNotUse:
597 break;
598 }
599 }
600 }
601 }
602 }
603 }
604 if (P->Call.out[PsiOut]) fprintf(stderr,"(%i) (%i,%i) Lev0->MaxG %i MaxDoubleG %i\n", P->Par.mytid, P->Par.mypos[PEPsi], P->Par.mypos[PEGamma], Lev0->MaxG, Lev0->MaxDoubleG);
605 // then allocate memory for all these vectors
606 Lev0->GArray = (struct OneGData *)
607 Malloc(Lev0->MaxG*sizeof(struct OneGData),"InitLevel0: Lev0->GArray");
608 Lat->GArrayForSort = (struct OneGData *)
609 Malloc(Lev0->MaxG*sizeof(struct OneGData),"InitLevel0: Lat->GArrayForSort");
610 if (Lev0->MaxDoubleG) {
611 Lev0->DoubleG = (int *)
612 Malloc(2*sizeof(int)*Lev0->MaxDoubleG,"InitLevel0: Lev0->DoubleG");
613 } else {
614 Lev0->DoubleG = NULL;
615 }
616 Lev0->MaxDoubleG = 0;
617 Lev0->MaxG = 0;
618 Lev0->ECut = 0;
619 Lev0->G0 = -1;
620 // and generate them again, this time noting them down in GArray
621 for (i = 0; i < Lat->plan->LocalMaxpw; i++) {
622 Index = Lat->plan->Localpw[i].Index;
623 Z = Index%(Lat->plan->NLSR[2]/2+1);
624 Y = Index/(Lat->plan->NLSR[2]/2+1);
625 iZ = i%(Lat->plan->NLSR[2]/2+1);
626 iY = i/(Lat->plan->NLSR[2]/2+1);
627 for (ly = 0; ly < RPs->plan->LevelFactor; ly++) {
628 yY = ly + RPs->plan->LevelFactor*Y;
629 iy = ly + RPs->plan->LevelFactor*iY;
630 if (Z==Lat->plan->NLSR[2]/2) {
631 z = RPs->plan->N[2]/2;
632 iz = RPs->plan->N[2]/2;
633 for (X=0; X < RPs->plan->N[0]; X++) {
634 x = ( X >= RPs->plan->N[0]/2+1 ? X - RPs->plan->N[0] : X);
635 y = ( yY >= RPs->plan->N[1]/2+1 ? yY - RPs->plan->N[1] : yY);
636 if (TestG(&P->Lat, x, y, z, &GSq, G)) {
637 Index = X+RPs->plan->N[0]*(iz+RPs->plan->nz*(iy));
638 Lev0->GArray[Lev0->MaxG].Index = Index;
639 Lev0->GArray[Lev0->MaxG].GlobalIndex = 0;
640 Lev0->GArray[Lev0->MaxG].GSq = GSq;
641 Lev0->GArray[Lev0->MaxG].G[0] = G[0];
642 Lev0->GArray[Lev0->MaxG].G[1] = G[1];
643 Lev0->GArray[Lev0->MaxG].G[2] = G[2];
644 if (GSq > Lev0->ECut) Lev0->ECut = GSq;
645 Lev0->MaxG++;
646 }
647 }
648 } else {
649 for (lz=0; lz < RPs->plan->LevelFactor; lz++) {
650 iz = iZ*RPs->plan->LevelFactor+lz;
651 z = Z*RPs->plan->LevelFactor+lz;
652 for (X=0; X < RPs->plan->N[0]; X++) {
653 x = ( X >= RPs->plan->N[0]/2+1 ? X - RPs->plan->N[0] : X);
654 y = ( yY >= RPs->plan->N[1]/2+1 ? yY - RPs->plan->N[1] : yY);
655 if (TestG(&P->Lat, x, y, z, &GSq, G)) {
656 switch (TestGDouble(x,y,z)) {
657 case DoubleGNot:
658 Index = X+RPs->plan->N[0]*(iz+RPs->plan->nz*(iy));
659 Lev0->GArray[Lev0->MaxG].Index = Index;
660 Lev0->GArray[Lev0->MaxG].GlobalIndex = 0;
661 Lev0->GArray[Lev0->MaxG].GSq = GSq;
662 Lev0->GArray[Lev0->MaxG].G[0] = G[0];
663 Lev0->GArray[Lev0->MaxG].G[1] = G[1];
664 Lev0->GArray[Lev0->MaxG].G[2] = G[2];
665 if (GSq > Lev0->ECut) Lev0->ECut = GSq;
666 Lev0->MaxG++;
667 break;
668 case DoubleG0:
669 Index = X+RPs->plan->N[0]*(iz+RPs->plan->nz*(iy));
670 Lev0->GArray[Lev0->MaxG].Index = Index;
671 Lev0->GArray[Lev0->MaxG].GlobalIndex = 0;
672 Lev0->GArray[Lev0->MaxG].GSq = GSq;
673 Lev0->GArray[Lev0->MaxG].G[0] = G[0];
674 Lev0->GArray[Lev0->MaxG].G[1] = G[1];
675 Lev0->GArray[Lev0->MaxG].G[2] = G[2];
676 if (GSq > Lev0->ECut) Lev0->ECut = GSq;
677 Lev0->MaxG++;
678 Lev0->G0 = Index;
679 break;
680 case DoubleGUse:
681 Index = X+RPs->plan->N[0]*(iz+RPs->plan->nz*(iy));
682 Lev0->GArray[Lev0->MaxG].Index = Index;
683 Lev0->GArray[Lev0->MaxG].GlobalIndex = 0;
684 Lev0->GArray[Lev0->MaxG].GSq = GSq;
685 Lev0->GArray[Lev0->MaxG].G[0] = G[0];
686 Lev0->GArray[Lev0->MaxG].G[1] = G[1];
687 Lev0->GArray[Lev0->MaxG].G[2] = G[2];
688 if (GSq > Lev0->ECut) Lev0->ECut = GSq;
689 Lev0->DoubleG[2*Lev0->MaxDoubleG] = Index;
690 Lev0->DoubleG[2*Lev0->MaxDoubleG+1] = GetIndex(Lat->plan,RPs->plan,-x,-y,-z);
691 if (Lev0->DoubleG[2*Lev0->MaxDoubleG+1] < 0) Error(SomeError,"InitLevel0: Lev0->DoubleG[2*Lev->MaxDoubleG+1]");
692 Lev0->MaxG++;
693 Lev0->MaxDoubleG++;
694 break;
695 case DoubleGNotUse:
696 break;
697 }
698
699 }
700 }
701 }
702 }
703 }
704 }
705 Lev0->ECut *= 0.5;
706 naturalmergesort(Lev0->GArray,Lat->GArrayForSort,0,Lev0->MaxG-1,&GetKeyOneG,NULL,&CopyElementOneG);
707 MPI_Allreduce(&Lev0->ECut , &ECut, 1, MPI_DOUBLE, MPI_MAX, P->Par.comm_ST_Psi );
708 if (P->Call.out[PsiOut]) fprintf(stderr,"(%i) (%i,%i) Lev0->ECut %g (%g) %g\n", P->Par.mytid, P->Par.mypos[PEPsi], P->Par.mypos[PEGamma], Lev0->ECut, ECut, ECut - Lat->ECut);
709 Lev0->ECut = Lat->ECut;
710 if (ECut > Lat->ECut) Error(SomeError,"InitLevel0: ECut > Lat->ECut");
711 Lev0->AllMaxG = (int *)
712 Malloc(sizeof(int)*P->Par.Max_me_comm_ST_Psi,"InitLevel0: AllMaxG");
713 MPI_Allgather ( &Lev0->MaxG, 1, MPI_INT,
714 Lev0->AllMaxG, 1, MPI_INT, P->Par.comm_ST_Psi );
715 AllMaxG = 0;
716 for (k=0; k<P->Par.Max_me_comm_ST_Psi; k++) AllMaxG += Lev0->AllMaxG[k];
717 if (P->Call.out[NormalOut]) {
718 fprintf(stderr,"(%i) Lev0->AllMaxG %i -> RealAllMaxG %i\n", P->Par.mytid, AllMaxG, 2*AllMaxG-1);
719 }
720 Lev0->TotalAllMaxG = AllMaxG;
721 Lev0->TotalRealAllMaxG = 2*AllMaxG-1;
722 Lev0->HashG = (struct GDataHash *)
723 Malloc(AllMaxG*sizeof(struct GDataHash),"InitLevel0: Lev0->HashG");
724
725 HashGArray(P,Lat,Lev0);
726}
727
728/** Precalculate Position Factors LatticeLevel::PosFactorUp.
729 * Due to the finer resolution of the densities certain transformations are necessary.
730 * One position factor can be pulled out and pre-calculated
731 * \f[
732 * P_p(G) = \exp(i2\pi \sum^3_{j=1} \frac{g_j p_j}{2N_j} )
733 * \f]
734 * where \f$N_j\f$ is RPlans::plan::N, p is the position vector and G the reciprocal
735 * grid vector, j goes up to NDIM (here 3)
736 * \param *P Problem at hand
737 * \param *Lat Lattice structure
738 * \param *Lev LatticeLevel structure
739 * \param *RPsUp RPlans structure
740 * \param g number of reciprocal grid points
741 * \param x number of mesh points in x direction (in the upper level)
742 * \param y number of mesh points in y direction (in the upper level)
743 * \param z number of mesh points in z direction (in the upper level)
744 */
745static void CreatePosFacForG(struct Problem *P, struct Lattice *Lat, const struct LatticeLevel
746 *Lev, const struct RPlans *RPsUp, int g, int x, int y, int z)
747{
748 double posfacreal[NDIM];
749 struct RiemannTensor *RT = &Lat->RT;
750 struct RunStruct *R = &P->R;
751 int pos[NDIM];
752 for (pos[0]=0; pos[0] < Lev->NUp[0]; pos[0]++) {
753 for (pos[1]=0; pos[1] < Lev->NUp[1]; pos[1]++) {
754 for (pos[2]=0; pos[2] < Lev->NUp[2]; pos[2]++) {
755 posfacreal[0] = (x*pos[0])/(double)(RPsUp->plan->N[0]);
756 posfacreal[1] = (y*pos[1])/(double)(RPsUp->plan->N[1]);
757 posfacreal[2] = (z*pos[2])/(double)(RPsUp->plan->N[2]);
758 Lev->PosFactorUp[pos[2]+Lev->NUp[2]*(pos[1]+Lev->NUp[1]*(pos[0]+Lev->NUp[0]*g))].re = cos(2.*PI*(posfacreal[0]+posfacreal[1]+posfacreal[2]));
759 Lev->PosFactorUp[pos[2]+Lev->NUp[2]*(pos[1]+Lev->NUp[1]*(pos[0]+Lev->NUp[0]*g))].im = sin(2.*PI*(posfacreal[0]+posfacreal[1]+posfacreal[2]));
760 }
761 }
762 }
763 if (RT->Use == UseRT) {
764 if (Lev->LevelNo == R->LevRNo) {
765 for (pos[0]=0; pos[0] < RT->NUpLevRS[0]; pos[0]++) {
766 for (pos[1]=0; pos[1] < RT->NUpLevRS[1]; pos[1]++) {
767 for (pos[2]=0; pos[2] < RT->NUpLevRS[2]; pos[2]++) {
768 posfacreal[0] = (x*pos[0])/(double)(Lat->Lev[R->LevRSNo].N[0]);
769 posfacreal[1] = (y*pos[1])/(double)(Lat->Lev[R->LevRSNo].N[1]);
770 posfacreal[2] = (z*pos[2])/(double)(Lat->Lev[R->LevRSNo].N[2]);
771 RT->PosFactor[RTPFRtoS][pos[2]+RT->NUpLevRS[2]*(pos[1]+RT->NUpLevRS[1]*(pos[0]+RT->NUpLevRS[0]*g))].re = cos(2.*PI*(posfacreal[0]+posfacreal[1]+posfacreal[2]));
772 RT->PosFactor[RTPFRtoS][pos[2]+RT->NUpLevRS[2]*(pos[1]+RT->NUpLevRS[1]*(pos[0]+RT->NUpLevRS[0]*g))].im = sin(2.*PI*(posfacreal[0]+posfacreal[1]+posfacreal[2]));
773 }
774 }
775 }
776 for (pos[0]=0; pos[0] < RT->NUpLevR0[0]; pos[0]++) {
777 for (pos[1]=0; pos[1] < RT->NUpLevR0[1]; pos[1]++) {
778 for (pos[2]=0; pos[2] < RT->NUpLevR0[2]; pos[2]++) {
779 posfacreal[0] = (x*pos[0])/(double)(Lat->Lev[R->LevR0No].N[0]);
780 posfacreal[1] = (y*pos[1])/(double)(Lat->Lev[R->LevR0No].N[1]);
781 posfacreal[2] = (z*pos[2])/(double)(Lat->Lev[R->LevR0No].N[2]);
782 RT->PosFactor[RTPFRto0][pos[2]+RT->NUpLevR0[2]*(pos[1]+RT->NUpLevR0[1]*(pos[0]+RT->NUpLevR0[0]*g))].re = cos(2.*PI*(posfacreal[0]+posfacreal[1]+posfacreal[2]));
783 RT->PosFactor[RTPFRto0][pos[2]+RT->NUpLevR0[2]*(pos[1]+RT->NUpLevR0[1]*(pos[0]+RT->NUpLevR0[0]*g))].im = sin(2.*PI*(posfacreal[0]+posfacreal[1]+posfacreal[2]));
784 }
785 }
786 }
787 }
788 }
789}
790
791/** Initialization of first to Lattice::MaxLevel LatticeLevel's.
792 * Sets numbers and ratios of mesh points (maximum (LatticeLevel::MaxN, LatticeLevel::MaxNUp), per dimension
793 * (LatticeLevel::N[], LatticeLevel::NUp[])) for the respective levels and its upper level. LatticeLevel::LevelNo and
794 * RPlans are set from LevelPlan[], number of reciprocal grid vectors is recounted (LatticeLevel::MaxG,
795 * LatticeLevel::MaxDoubleG), then they are created, stored (LatticeLevel::GArray) and their position factor
796 * (LatticeLevel::PosFactorUp) recalculated. MaxG is gathered from all processes in LatticeLevel::AllMaxG and
797 * LatticeLevel::TotalAllMaxG generated by summing these up.
798 * \param *P Problem at hand
799 * \sa InitLatticeLevel0()
800 */
801static void InitOtherLevel(struct Problem *const P) {
802 struct Lattice *Lat = &P->Lat;
803 struct LatticeLevel *Lev;
804 struct LatticeLevel *LevUp;
805 struct RPlans *RPs;
806 struct RPlans *RPsUp;
807 double GSq=0,ECut=0;
808 int lx,x,ly,y,z,Index,Y,YY,Z,ZZ,lz,I,k,AllMaxG;
809 int d,MaxGUp,i;
810 for (i=1; i < P->Lat.MaxLevel; i++) { // for each level
811 Lev = &Lat->Lev[i];
812 LevUp = &Lat->Lev[i-1];
813 RPs = &Lev->Plan0;
814 RPsUp = &LevUp->Plan0;
815 // set number of mesh points
816 for (d=0; d < NDIM; d++) { // for each dimension
817 Lev->NUp[d] = Lat->LevelSizes[i-1];
818 Lev->NUp0[d] = LevUp->NUp0[d]*Lev->NUp[d];
819 Lev->NUp1[d] = (i == STANDARTLEVEL ? 1 : LevUp->NUp1[d]*Lev->NUp[d]);
820 Lev->N[d] = LevUp->N[d]/Lev->NUp[d];
821 }
822 Lev->MaxN = Lev->N[0]*Lev->N[1]*Lev->N[2];
823 Lev->MaxNUp = Lev->NUp[0]*Lev->NUp[1]*Lev->NUp[2];
824 if (P->Call.out[NormalOut]) fprintf(stderr, "(%i)InitLatticeLevel %i\tN[] = %i %i %i\n",P->Par.me, i,Lev->N[0],Lev->N[1],Lev->N[2]);
825 // fft plan and its data
826 RPs->plan = &Lat->plan->Levplan[i];
827 RPs->cdata = Lat->plan->local_data;
828 RPs->rdata = (fftw_real *)Lat->plan->local_data;
829 Lev->LevelNo = i;
830 // recount MaxG, MaxDoubleG by creating all g vectors
831 Lev->MaxG=0;
832 Lev->MaxDoubleG = 0;
833 for (MaxGUp=0; MaxGUp < LevUp->MaxG; MaxGUp++) {
834 SplitIndex(LevUp->GArray[MaxGUp].Index,RPsUp->plan->N[0],RPsUp->plan->nz,&lx,&ly,&lz);
835 Y = ly/RPsUp->plan->LevelFactor;
836 YY = ly%RPsUp->plan->LevelFactor;
837 Z = lz/RPsUp->plan->LevelFactor;
838 ZZ = lz%RPsUp->plan->LevelFactor;
839 Index = Lat->plan->Localpw[Z+(Lat->plan->NLSR[2]/2+1)*(Y)].Index;
840 ly = YY+RPsUp->plan->LevelFactor*(Index/(Lat->plan->NLSR[2]/2+1));
841 z = ZZ+RPsUp->plan->LevelFactor*(Index%(Lat->plan->NLSR[2]/2+1));
842 x = ( lx >= RPsUp->plan->N[0]/2+1 ? lx-RPsUp->plan->N[0] : lx);
843 y = ( ly >= RPsUp->plan->N[1]/2+1 ? ly-RPsUp->plan->N[1] : ly);
844 if ((x%Lev->NUp[0] == 0) && (y%Lev->NUp[1] == 0) && (z%Lev->NUp[2] == 0)) {
845 switch (TestGDouble(x/Lev->NUp[0],y/Lev->NUp[1],z/Lev->NUp[2])) {
846 case DoubleGNot:
847 Lev->MaxG++;
848 break;
849 case DoubleG0:
850 Lev->MaxG++;
851 break;
852 case DoubleGUse:
853 Lev->MaxG++;
854 Lev->MaxDoubleG++;
855 break;
856 case DoubleGNotUse:
857 Lev->MaxG--;
858 break;
859 }
860 }
861 }
862 if (P->Call.out[PsiOut]) fprintf(stderr,"(%i) (%i,%i) Lev%i->MaxG %i MaxDoubleG %i\n", P->Par.mytid, P->Par.mypos[PEPsi], P->Par.mypos[PEGamma], i, Lev->MaxG, Lev->MaxDoubleG);
863 Lev->PosFactorUp = (fftw_complex *) Malloc(sizeof(fftw_complex)*Lev->MaxG*Lev->NUp[0]*Lev->NUp[1]*Lev->NUp[2], "InitLatticeLevel: PosFactors");
864 if (Lat->RT.Use == UseRT) {
865 if (Lev->LevelNo == Lat->RT.RiemannLevel) {
866 Lat->RT.PosFactor[RTPFRtoS] = (fftw_complex *)
867 Malloc(sizeof(fftw_complex)*Lev->MaxG*Lev->NUp1[0]*Lev->NUp1[1]*Lev->NUp1[2], "InitLatticeLevel: RTPosFactors1");
868 Lat->RT.PosFactor[RTPFRto0] = (fftw_complex *)
869 Malloc(sizeof(fftw_complex)*Lev->MaxG*Lev->NUp0[0]*Lev->NUp0[1]*Lev->NUp0[2], "InitLatticeLevel: RTPosFactors0");
870 }
871 }
872 // now create the G vectors and store them
873 Lev->GArray = (struct OneGData *)
874 Malloc(Lev->MaxG*sizeof(struct OneGData),"InitLevel: Lev->GArray");
875 if (Lev->MaxDoubleG) {
876 Lev->DoubleG = (int *)
877 Malloc(2*sizeof(int)*Lev->MaxDoubleG,"InitLevel: Lev0->DoubleG");
878 } else {
879 Lev->DoubleG = NULL;
880 }
881 Lev->MaxDoubleG = 0;
882 Lev->MaxG=0;
883 Lev->ECut = 0;
884 Lev->G0 = -1;
885 for (MaxGUp=0; MaxGUp < LevUp->MaxG; MaxGUp++) {
886 SplitIndex(LevUp->GArray[MaxGUp].Index,RPsUp->plan->N[0],RPsUp->plan->nz,&lx,&ly,&lz);
887 Index = lx/Lev->NUp[0]+RPs->plan->N[0]*(lz/Lev->NUp[2]+RPs->plan->nz*(ly/Lev->NUp[1]));
888 Y = ly/RPsUp->plan->LevelFactor;
889 YY = ly%RPsUp->plan->LevelFactor;
890 Z = lz/RPsUp->plan->LevelFactor;
891 ZZ = lz%RPsUp->plan->LevelFactor;
892 I = Lat->plan->Localpw[Z+(Lat->plan->NLSR[2]/2+1)*(Y)].Index;
893 ly = YY+RPsUp->plan->LevelFactor*(I/(Lat->plan->NLSR[2]/2+1));
894 z = ZZ+RPsUp->plan->LevelFactor*(I%(Lat->plan->NLSR[2]/2+1));
895 x = ( lx >= RPsUp->plan->N[0]/2+1 ? lx-RPsUp->plan->N[0] : lx);
896 y = ( ly >= RPsUp->plan->N[1]/2+1 ? ly-RPsUp->plan->N[1] : ly);
897 if ((x%Lev->NUp[0] == 0) && (y%Lev->NUp[1] == 0) && (z%Lev->NUp[2] == 0)) {
898 switch (TestGDouble(x/Lev->NUp[0],y/Lev->NUp[1],z/Lev->NUp[2])) {
899 case DoubleGNot:
900 TestG(&P->Lat, x/Lev->NUp[0], y/Lev->NUp[1], z/Lev->NUp[2], &GSq, Lev->GArray[Lev->MaxG].G);
901 Lev->GArray[Lev->MaxG].Index = Index;
902 Lev->GArray[Lev->MaxG].GlobalIndex = 0;
903 Lev->GArray[Lev->MaxG].GSq = GSq;
904 if (GSq > Lev->ECut) Lev->ECut = GSq;
905 CreatePosFacForG(P, Lat, Lev, RPsUp, Lev->MaxG, x/Lev->NUp[0], y/Lev->NUp[1], z/Lev->NUp[2]);
906 Lev->MaxG++;
907 break;
908 case DoubleG0:
909 TestG(&P->Lat, x/Lev->NUp[0], y/Lev->NUp[1], z/Lev->NUp[2], &GSq, Lev->GArray[Lev->MaxG].G);
910 Lev->GArray[Lev->MaxG].Index = Index;
911 Lev->GArray[Lev->MaxG].GlobalIndex = 0;
912 Lev->GArray[Lev->MaxG].GSq = GSq;
913 if (GSq > Lev->ECut) Lev->ECut = GSq;
914 CreatePosFacForG(P, Lat, Lev, RPsUp, Lev->MaxG, x/Lev->NUp[0], y/Lev->NUp[1], z/Lev->NUp[2]);
915 Lev->MaxG++;
916 Lev->G0 = Index;
917 break;
918 case DoubleGUse:
919 TestG(&P->Lat, x/Lev->NUp[0], y/Lev->NUp[1], z/Lev->NUp[2], &GSq, Lev->GArray[Lev->MaxG].G);
920 Lev->GArray[Lev->MaxG].Index = Index;
921 Lev->GArray[Lev->MaxG].GlobalIndex = 0;
922 Lev->GArray[Lev->MaxG].GSq = GSq;
923 if (GSq > Lev->ECut) Lev->ECut = GSq;
924 CreatePosFacForG(P, Lat, Lev, RPsUp, Lev->MaxG, x/Lev->NUp[0], y/Lev->NUp[1], z/Lev->NUp[2]);
925 Lev->DoubleG[2*Lev->MaxDoubleG] = Index;
926 Lev->DoubleG[2*Lev->MaxDoubleG+1] = GetIndex(Lat->plan,RPs->plan,-(x/Lev->NUp[0]),-(y/Lev->NUp[1]),-(z/Lev->NUp[2]));
927 if (Lev->DoubleG[2*Lev->MaxDoubleG+1] < 0) Error(SomeError,"Lev->DoubleG[2*Lev->MaxDoubleG+1]");
928 CreatePosFacForG(P, Lat, Lev, RPsUp, Lev->MaxG, x/Lev->NUp[0], y/Lev->NUp[1], z/Lev->NUp[2]);
929 Lev->MaxG++;
930 Lev->MaxDoubleG++;
931 break;
932 case DoubleGNotUse:
933 break;
934 }
935 }
936 }
937 Lev->ECut *= 0.5;
938 MPI_Allreduce(&Lev->ECut , &ECut, 1, MPI_DOUBLE, MPI_MAX, P->Par.comm_ST_Psi );
939 if (P->Call.out[PsiOut]) fprintf(stderr,"(%i) (%i,%i) Lev%i->ECut %g (%g) %g\n", P->Par.mytid, P->Par.mypos[PEPsi], P->Par.mypos[PEGamma], i, Lev->ECut, ECut, ECut - Lat->ECut/(Lev->NUp0[0]*Lev->NUp0[0]));
940 Lev->ECut = Lat->ECut/(Lev->NUp0[0]*Lev->NUp0[0]);
941 if (ECut > Lev->ECut) Error(SomeError,"InitLevel: ECut > Lat->ECut");
942 Lev->AllMaxG = (int *)
943 Malloc(sizeof(int)*P->Par.Max_me_comm_ST_Psi,"InitLevel: AllMaxG");
944 MPI_Allgather ( &Lev->MaxG, 1, MPI_INT,
945 Lev->AllMaxG, 1, MPI_INT, P->Par.comm_ST_Psi );
946 AllMaxG = 0;
947 for (k=0; k<P->Par.Max_me_comm_ST_Psi; k++) AllMaxG += Lev->AllMaxG[k];
948 if (P->Call.out[NormalOut]) {
949 fprintf(stderr,"(%i) Lev%i->AllMaxG %i -> RealAllMaxG %i\n", P->Par.mytid, i, AllMaxG, 2*AllMaxG-1);
950 }
951 Lev->TotalAllMaxG = AllMaxG;
952 Lev->TotalRealAllMaxG = 2*AllMaxG-1;
953 Lev->HashG = (struct GDataHash *)
954 Malloc(AllMaxG*sizeof(struct GDataHash),"InitLevel0: Lev0->HashG");
955 HashGArray(P, Lat, Lev);
956 }
957}
958
959/** Sets the Spin group number for each process.
960 * First of all, SpinUps and SpinDowns Psis are completely separated (they have their own communicator groups).
961 * Psis::PsiGroup is then just the rank in this Psi group, where Psis::MaxPsiGroup is the number of participating
962 * processes. Afterwards, depending on the SpinType Psis:PsiST is set and Psis::LocalNo calculated by modulo of
963 * global number of Psis and the number of Psi groups, e.g. 18 psis, 5 processes, make 3 times 4 Psis per process
964 * and 2 times 3 Psis per process. Finally, the maximum of all the local number of Psis is taken and stored in
965 * Psis::AllMaxLocalNo.
966 * \param *P Problem at hand
967 */
968static void InitPsiGroupNo(struct Problem *const P) {
969 struct Lattice *Lat = &P->Lat;
970 struct Psis *Psi = &Lat->Psi;
971 int i, r, r1, NoPsis = 0, type;
972 MPI_Status status;
973 int AllMaxLocalNoUp, AllMaxLocalNoDown;
974 if (P->Call.out[NormalOut]) fprintf(stderr, "(%i)InitPsisGroupNo\n", P->Par.me);
975 Psi->MaxPsiGroup = P->Par.Max_my_color_comm_ST_Psi;
976 Psi->PsiGroup = P->Par.my_color_comm_ST_Psi;
977 // now discern between the different spin cases
978 switch (Psi->Use) {
979 case UseSpinDouble:
980 NoPsis = Psi->GlobalNo[PsiMaxNoDouble];
981 if (P->Call.out[NormalOut]) fprintf(stderr, "(%i) PsiGlobalNo %i = %i + %i\n", P->Par.me, Psi->GlobalNo[PsiMaxNo], NoPsis, Psi->GlobalNo[PsiMaxAdd]);
982 Psi->PsiST = SpinDouble; // set SpinType
983 break;
984 case UseSpinUpDown:
985 if (P->Call.out[NormalOut]) fprintf(stderr, "(%i) PsiGlobalNo %i = (%i+%i) + (%i+%i)\n", P->Par.me, Psi->GlobalNo[PsiMaxNo], Psi->GlobalNo[PsiMaxNoUp], Psi->GlobalNo[PsiMaxAdd], Psi->GlobalNo[PsiMaxNoDown], Psi->GlobalNo[PsiMaxAdd]);
986 // depending on my spin type (up or down) ...
987 switch (P->Par.my_color_comm_ST) {
988 case ((int)SpinUp) - 1:
989 Psi->PsiST = SpinUp;
990 NoPsis = Psi->GlobalNo[PsiMaxNoUp];
991 break;
992 case ((int)SpinDown) -1:
993 Psi->PsiST = SpinDown;
994 NoPsis = Psi->GlobalNo[PsiMaxNoDown];
995 break;
996 }
997 break;
998 }
999 Psi->LocalNo = (NoPsis + P->Lat.Psi.GlobalNo[PsiMaxAdd]) / Psi->MaxPsiGroup; // local number of Psis per process
1000 r = (NoPsis + P->Lat.Psi.GlobalNo[PsiMaxAdd]) % Psi->MaxPsiGroup; // calculate the rest
1001 Psi->LocalNoAdd = (P->Lat.Psi.GlobalNo[PsiMaxAdd]) / Psi->MaxPsiGroup; // local number of Psis per process
1002 r1 = (P->Lat.Psi.GlobalNo[PsiMaxAdd]) % Psi->MaxPsiGroup; // calculate the rest
1003 if (P->R.DoUnOccupied && (r1 != 0)) Error(SomeError,"AddPsis must be multiple of PEPsi!\n");
1004 if (Psi->PsiGroup < r) Psi->LocalNo++; // distribute the rest into the first processes
1005 if (Psi->PsiGroup < r1) Psi->LocalNoAdd++; // distribute the rest into the first processes
1006 Psi->TypeStartIndex[Occupied] = 0;
1007 Psi->TypeStartIndex[UnOccupied] = Psi->LocalNo - Psi->LocalNoAdd;
1008 if (P->R.DoPerturbation == 1) { // six times NoPsis for Perturbed_RxP and Perturbed_P
1009 for (i=Perturbed_P0; i<= Perturbed_RxP2;i++) {
1010 Psi->TypeStartIndex[i] = Psi->LocalNo;
1011 Psi->LocalNo += (NoPsis) / Psi->MaxPsiGroup; // local number of Psis per process (just one array for all perturbed)
1012 r = (NoPsis) % Psi->MaxPsiGroup; // calculate the rest
1013 if (Psi->PsiGroup < r) Error(SomeError,"Psis must be multiple of PEPsi!\n");
1014 //if (Psi->PsiGroup < r) Psi->LocalNo++; // distribute the rest into the first processes
1015 }
1016 } else {
1017 for (i=Perturbed_P0; i<= Perturbed_RxP2;i++)
1018 Psi->TypeStartIndex[i] = Psi->LocalNo;
1019 }
1020 Psi->TypeStartIndex[Extra] = Psi->LocalNo; // always set to end
1021 Psi->TypeStartIndex[Extra+1] = Psi->LocalNo+1; // always set to end
1022
1023 if (P->Call.out[PsiOut])
1024 for(type=Occupied;type<=Extra+1;type++)
1025 fprintf(stderr,"(%i) TypeStartIndex[%i] = %i\n",P->Par.me, type,Psi->TypeStartIndex[type]);
1026
1027 if (P->Call.out[StepLeaderOut]) fprintf(stderr, "(%i) PsiLocalNo %i \n", P->Par.me, Psi->LocalNo);
1028 // gather local number of Psis from all processes
1029 Psi->RealAllLocalNo = (int *)
1030 Malloc(sizeof(int)*P->Par.Max_me_comm_ST_PsiT,"FirstInitGramSchData: Psi->RealAllLocalNo");
1031 MPI_Allgather ( &Psi->LocalNo, 1, MPI_INT,
1032 Psi->RealAllLocalNo, 1, MPI_INT, P->Par.comm_ST_PsiT );
1033 // determine maximum local number, depending on spin
1034 switch (Psi->PsiST) {
1035 case SpinDouble:
1036 MPI_Allreduce(&Psi->LocalNo, &Psi->AllMaxLocalNo, 1,
1037 MPI_INT, MPI_MAX, P->Par.comm_ST_PsiT );
1038 break;
1039 case SpinUp:
1040 MPI_Allreduce(&Psi->LocalNo, &AllMaxLocalNoUp, 1,
1041 MPI_INT, MPI_MAX, P->Par.comm_ST_PsiT );
1042 MPI_Sendrecv( &AllMaxLocalNoUp, 1, MPI_INT, P->Par.me_comm_ST, AllMaxLocalNoTag1,
1043 &AllMaxLocalNoDown, 1, MPI_INT, P->Par.me_comm_ST, AllMaxLocalNoTag2,
1044 P->Par.comm_STInter, &status );
1045 Psi->AllMaxLocalNo = MAX(AllMaxLocalNoUp, AllMaxLocalNoDown);
1046 break;
1047 case SpinDown:
1048 MPI_Allreduce(&Psi->LocalNo, &AllMaxLocalNoDown, 1,
1049 MPI_INT, MPI_MAX, P->Par.comm_ST_PsiT );
1050 MPI_Sendrecv( &AllMaxLocalNoDown, 1, MPI_INT, P->Par.me_comm_ST, AllMaxLocalNoTag2,
1051 &AllMaxLocalNoUp, 1, MPI_INT, P->Par.me_comm_ST, AllMaxLocalNoTag1,
1052 P->Par.comm_STInter, &status );
1053 Psi->AllMaxLocalNo = MAX(AllMaxLocalNoUp, AllMaxLocalNoDown);
1054 break;
1055 }
1056}
1057
1058/** Intialization of the wave functions.
1059 * Allocates/sets OnePsiElementAddData elements to zero, allocates memory for coefficients and
1060 * pointing to them from Lattice and LatticeLevel.
1061 * \param *P Problem at hand
1062 */
1063static void InitPsis(struct Problem *const P) {
1064 int i,j,l;
1065 struct Lattice *Lat = &P->Lat;
1066 struct RunStruct *R = &P->R;
1067 struct LatticeLevel *Lev = R->InitLevS;
1068 int CreateOld = P->R.UseOldPsi;
1069 int NoPsis;
1070 if (P->Call.out[NormalOut]) fprintf(stderr, "(%i)InitPsis\n", P->Par.me);
1071 /// For Lattice::Psi memory for OnePsiElementAddData is allocated and entries zeroed.
1072 Lat->Psi.AddData = (struct OnePsiElementAddData *)
1073 Malloc((Lat->Psi.LocalNo+1)*sizeof(struct OnePsiElementAddData), "InitPsis: Psi->AddData");
1074 for (i = 0; i <= Lat->Psi.LocalNo; i++) {
1075 Lat->Psi.AddData[i].T = 0.0;
1076 Lat->Psi.AddData[i].Lambda = 0.0;
1077 Lat->Psi.AddData[i].Gamma = 0.0;
1078 Lat->Psi.AddData[i].Step = 0;
1079 Lat->Psi.AddData[i].WannierSpread = 0.;
1080 for (j=0;j<NDIM;j++)
1081 Lat->Psi.AddData[i].WannierCentre[j] = 0. ;
1082 }
1083 // lambda contains H eigenvalues
1084 switch (Lat->Psi.PsiST) {
1085 default:
1086 case SpinDouble:
1087 Lat->Psi.NoOfPsis = Lat->Psi.GlobalNo[PsiMaxNoDouble];
1088 Lat->Psi.NoOfTotalPsis = Lat->Psi.NoOfPsis + Lat->Psi.GlobalNo[PsiMaxAdd];
1089 break;
1090 case SpinUp:
1091 Lat->Psi.NoOfPsis = Lat->Psi.GlobalNo[PsiMaxNoUp];
1092 Lat->Psi.NoOfTotalPsis = Lat->Psi.NoOfPsis + Lat->Psi.GlobalNo[PsiMaxAdd];
1093 break;
1094 case SpinDown:
1095 Lat->Psi.NoOfPsis = Lat->Psi.GlobalNo[PsiMaxNoDown];
1096 Lat->Psi.NoOfTotalPsis = Lat->Psi.NoOfPsis + Lat->Psi.GlobalNo[PsiMaxAdd];
1097 break;
1098 };
1099 if (P->Call.out[StepLeaderOut]) fprintf(stderr, "(%i) NoOfPsis %i \n", P->Par.me, Lat->Psi.NoOfPsis);
1100 Lat->Psi.lambda = (double **) Malloc(sizeof(double *)* Lat->Psi.NoOfTotalPsis, "InitPsis: Psi->Lambda");
1101 Lat->Psi.Overlap = (double **) Malloc(sizeof(double *)* Lat->Psi.NoOfPsis, "InitPsis: Psi->Overlap");
1102 for (i=0;i<Lat->Psi.NoOfTotalPsis;i++)
1103 Lat->Psi.lambda[i] = (double *) Malloc(sizeof(double)* Lat->Psi.NoOfTotalPsis, "InitPsis: Psi->Lambda[i]");
1104 for (i=0;i<Lat->Psi.NoOfPsis;i++)
1105 Lat->Psi.Overlap[i] = (double *) Malloc(sizeof(double)* Lat->Psi.NoOfPsis, "InitPsis: Psi->Overlap[i]");
1106
1107 /// Allocation for initial LevelPsi LatticeLevel::LPsi and LevelPsi::PsiDat
1108 NoPsis = (Lat->Psi.TypeStartIndex[Perturbed_P1] - Lat->Psi.TypeStartIndex[Occupied]); //
1109 if (P->Call.out[ValueOut]) fprintf(stderr,"(%i) InitPsis(): Number of Psi arrays in memory %i\n", P->Par.me, NoPsis);
1110 Lev->LPsi = (struct LevelPsi *)
1111 Malloc(sizeof(struct LevelPsi),"InitPsis: LPsi");
1112 Lev->LPsi->PsiDat = (fftw_complex *)
1113 Malloc((NoPsis+3)*sizeof(fftw_complex)*Lev->MaxG, "InitPsis: LPsi->PsiDat"); // +3 because of TempPsi and TempPsi2 and extra
1114 if (CreateOld)
1115 Lev->LPsi->OldPsiDat = (fftw_complex *)
1116 Malloc((NoPsis+1)*sizeof(fftw_complex)*Lev->MaxG, "InitPsis: LPsi->PsiDat");
1117 else
1118 Lev->LPsi->OldPsiDat = NULL;
1119
1120 /// Allocation for all other levels LatticeLevel::LPsi and LevelPsi::PsiDat, the latter initialised from initial level
1121 /// here Lev[1].LPsi, because it's the biggest level for the Psis and they might get overwritten otherwise during the perturbed
1122 /// load and transform-sequence, see ReadSrcPerturbedPsis()
1123 for (i=1; i < Lat->MaxLevel; i++) { // for all levels
1124 if (i > 1) Lat->Lev[i].LPsi = (struct LevelPsi *)
1125 Malloc(sizeof(struct LevelPsi),"InitPsis: LPsi");
1126 Lat->Lev[i].LPsi->PsiDat = Lev->LPsi->PsiDat;
1127 Lat->Lev[i].LPsi->OldPsiDat = Lev->LPsi->OldPsiDat;
1128 Lat->Lev[i].LPsi->LocalPsi = (fftw_complex **)
1129 Malloc((Lat->Psi.LocalNo+1)*sizeof(fftw_complex *),"InitPsi: LocalPsi");
1130 /// Initialise each LevelPsi::LocalPsi by pointing it to its respective part of LevelPsi::PsiDat
1131 for (j=0; j <= Lat->Psi.LocalNo; j++) { // for each local Psi
1132 if (j < Lat->Psi.TypeStartIndex[Perturbed_P0]) { // if it's not a perturbed wave function
1133 //if (P->Call.out[PsiOut]) fprintf(stderr,"(%i) Setting LocalPsi[%i] to %p\n",P->Par.me, j, &Lat->Lev[i].LPsi->PsiDat[j*Lat->Lev[1].MaxG]);
1134 Lat->Lev[i].LPsi->LocalPsi[j] = &Lat->Lev[i].LPsi->PsiDat[j*Lat->Lev[1].MaxG];
1135 } else if (j >= Lat->Psi.TypeStartIndex[Extra]) { // if it's the extra wave function
1136 //if (P->Call.out[PsiOut]) fprintf(stderr,"(%i) Setting LocalPsi[%i] to %p\n",P->Par.me, j, &Lat->Lev[i].LPsi->PsiDat[(NoPsis)*Lat->Lev[1].MaxG]);
1137 Lat->Lev[i].LPsi->LocalPsi[j] = &Lat->Lev[i].LPsi->PsiDat[(NoPsis)*Lat->Lev[1].MaxG];
1138 } else { // ... a perturbed wave function
1139 l = Lat->Psi.TypeStartIndex[Perturbed_P0]
1140 + ((j - Lat->Psi.TypeStartIndex[Perturbed_P0]) % (Lat->Psi.TypeStartIndex[Perturbed_P1] - Lat->Psi.TypeStartIndex[Perturbed_P0]));
1141 //if (P->Call.out[PsiOut]) fprintf(stderr,"(%i) Setting LocalPsi[%i] to %p\n",P->Par.me, j, &Lat->Lev[i].LPsi->PsiDat[l*Lat->Lev[1].MaxG]);
1142 Lat->Lev[i].LPsi->LocalPsi[j] = &Lat->Lev[i].LPsi->PsiDat[l*Lat->Lev[1].MaxG];
1143 }
1144 }
1145 Lat->Lev[i].LPsi->TempPsi = &Lat->Lev[i].LPsi->PsiDat[(NoPsis+1)*Lat->Lev[1].MaxG];
1146 Lat->Lev[i].LPsi->TempPsi2 = &Lat->Lev[i].LPsi->PsiDat[(NoPsis+2)*Lat->Lev[1].MaxG];
1147
1148 Lat->Lev[i].LPsi->OldLocalPsi = (fftw_complex **)
1149 Malloc(((Lat->Psi.TypeStartIndex[Perturbed_P0] - Lat->Psi.TypeStartIndex[Occupied])+1)*sizeof(fftw_complex *),"InitPsi: OldLocalPsi");
1150 for (j=Lat->Psi.TypeStartIndex[Occupied]; j < Lat->Psi.TypeStartIndex[Perturbed_P0]; j++) { // OldPsis are only needed during the Wannier procedure
1151 if (CreateOld)
1152 Lat->Lev[i].LPsi->OldLocalPsi[j] = &Lat->Lev[i].LPsi->OldPsiDat[j*Lat->Lev[1].MaxG];
1153 else
1154 Lat->Lev[i].LPsi->OldLocalPsi[j] = NULL;
1155 }
1156 }
1157 Lat->Lev[0].LPsi = NULL;
1158}
1159
1160/** Initialization of wave function coefficients.
1161 * The random number generator's seed is set to 1, rand called numerously depending on the rank in the
1162 * communicator, the number of LatticeLevel::AllMaxG in each process. Finally, for each local Psi and each
1163 * reciprocal grid vector the real and imaginary part of the specific coefficient \f$c_{i,G}\f$ are
1164 * initialized by a \f$1-\frac{1}{2} \frac{rand()}{|G|^2}\f$, where rand() yields a number between 0
1165 * and the largest integer value.
1166 * \param *P Problem at hand
1167 * \param start The init starts at local this local wave function array ...
1168 * \param end ... and ends at this local array, e.g. Lattice#Psis#LocalNo
1169 */
1170void InitPsisValue(struct Problem *const P, int start, int end) {
1171 int i,j,k, index;
1172 int myPE;
1173 int NoBefore = 0;
1174 struct Lattice *Lat = &P->Lat;
1175 struct RunStruct *R = &P->R;
1176 struct LatticeLevel *LevS = R->LevS;
1177 MPI_Comm_rank(P->Par.comm_ST_Psi, &myPE); // Determines the rank of the calling process in the communicator
1178 //char name[255];
1179 //sprintf(name, ".Psis-%i.all", myPE);
1180 //FILE *psi;
1181 //OpenFile(P,&psi, name, "w",P->Call.out[ReadOut]);
1182
1183 if (P->Call.out[NormalOut]) fprintf(stderr, "(%i)InitPsisValue\n", P->Par.me);
1184 for (i=0; i < P->Par.my_color_comm_ST_Psi; i++) {
1185 NoBefore += Lat->Psi.RealAllLocalNo[i];
1186 }
1187 srand(R->Seed);
1188 for (i=0; i<NoBefore; i++)
1189 for (k=0; k<P->Par.Max_me_comm_ST_Psi; k++)
1190 for (j=0; j<2*LevS->AllMaxG[k]; j++)
1191 rand();
1192 for (j=0;(j<end) && (j < Lat->Psi.LocalNo);j++) // for all local Psis
1193 for (i=0; i < LevS->TotalAllMaxG; i++) { // for all coefficients
1194 if ((LevS->HashG[i].myPE == myPE) && (j >= start)) {
1195 index = LevS->HashG[i].i;
1196 //if (!j) fprintf(stderr,"(%i) LevS->GArray[%i].GSq = %e\n",P->Par.me, index, LevS->GArray[index].GSq);
1197 LevS->LPsi->LocalPsi[j][index].re = (1.-2.*(rand()/(double)RAND_MAX))*(LevS->GArray[index].GSq == 0.0 ? 1.0 : 1/LevS->GArray[index].GSq);
1198 LevS->LPsi->LocalPsi[j][index].im = (1.-2.*(rand()/(double)RAND_MAX))*(LevS->GArray[index].GSq == 0.0 ? 0.0 : 1/LevS->GArray[index].GSq);
1199 //if (!j) fprintf(stderr,"(%i) LevS->LPsi->LocalPsi[%i][%i/%i] = %e + i%e, GArray[%i].GSq = %e\n",myPE, j, index, i, LevS->LPsi->LocalPsi[j][index].re, LevS->LPsi->LocalPsi[j][index].im, index, LevS->GArray[index].GSq);
1200 //fprintf(psi, "LevS->LPsi->LocalPsi[%i][%i] = %e + i%e\n", j, i, LevS->LPsi->LocalPsi[j][index].re, LevS->LPsi->LocalPsi[j][index].im);
1201 } else {
1202 rand();
1203 rand();
1204 }
1205
1206/* for (j=0;j<Lat->Psi.LocalNo;j++) // for all local Psis
1207 for (i=0; i < LevS->MaxG; i++) { // for all coefficients
1208 if ((R->Seed == 0) && (j >= Lat->Psi.TypeStartIndex[Perturbed_P0])) {
1209 if (i == 0) fprintf(stderr,"(%i) Initializing wave function %i with 1 over %i\n",P->Par.me, j, LevS->TotalAllMaxG);
1210 LevS->LPsi->LocalPsi[j][i].re = 1./LevS->TotalAllMaxG;
1211 LevS->LPsi->LocalPsi[j][i].im = 0.;
1212 } else {
1213 LevS->LPsi->LocalPsi[j][i].re = (1.-2.*(rand()/(double)RAND_MAX))*(LevS->GArray[i].GSq == 0.0 ? 1.0 : 1/LevS->GArray[i].GSq);
1214 LevS->LPsi->LocalPsi[j][i].im = (1.-2.*(rand()/(double)RAND_MAX))*(LevS->GArray[i].GSq == 0.0 ? 0.0 : 1/LevS->GArray[i].GSq);
1215 }*/
1216
1217 /*if ((j==0 && i==0) || (j==1 && i==1) || (j==2 && i==2) || (j==3 && i==3))
1218 LevS->LPsi->LocalPsi[j][i].re = 1.0;*/
1219 /*
1220 if ( j==0 && P->Par.me_comm_ST_PsiT == 0 &&
1221 fabs(LevS->GArray[i].G[0] - 1.0*Lat->ReciBasis[0]) < MYEPSILON &&
1222 fabs(LevS->GArray[i].G[1] - 0.0*Lat->ReciBasis[0]) < MYEPSILON &&
1223 fabs(LevS->GArray[i].G[2] - 0.0*Lat->ReciBasis[0]) < MYEPSILON ) {
1224 LevS->LPsi->LocalPsi[j][i].re = 1.0;
1225 fprintf(stdout, "(%i) %i g = %i\n", P->Par.me, j, i);
1226 }
1227 if ( j==1 && P->Par.me_comm_ST_PsiT == 0 &&
1228 fabs(LevS->GArray[i].G[0] - 0.0*Lat->ReciBasis[0]) < MYEPSILON &&
1229 fabs(LevS->GArray[i].G[1] - 1.0*Lat->ReciBasis[0]) < MYEPSILON &&
1230 fabs(LevS->GArray[i].G[2] - 0.0*Lat->ReciBasis[0]) < MYEPSILON ) {
1231 LevS->LPsi->LocalPsi[j][i].re = 1.0;
1232 fprintf(stdout, "(%i) %i g = %i\n", P->Par.me, j, i);
1233 }
1234 if ( j==2 && P->Par.me_comm_ST_PsiT == 0 &&
1235 fabs(LevS->GArray[i].G[0] - 0.0*Lat->ReciBasis[0]) < MYEPSILON &&
1236 fabs(LevS->GArray[i].G[1] - 0.0*Lat->ReciBasis[0]) < MYEPSILON &&
1237 fabs(LevS->GArray[i].G[2] - 1.0*Lat->ReciBasis[0]) < MYEPSILON ) {
1238 LevS->LPsi->LocalPsi[j][i].re = 1.0;
1239 fprintf(stdout, "(%i) %i g = %i\n", P->Par.me, j, i);
1240 }
1241 if ( j==3 && P->Par.me_comm_ST_PsiT == 0 &&
1242 fabs(LevS->GArray[i].G[0] - 1.0*Lat->ReciBasis[0]) < MYEPSILON &&
1243 fabs(LevS->GArray[i].G[1] - 1.0*Lat->ReciBasis[0]) < MYEPSILON &&
1244 fabs(LevS->GArray[i].G[2] - 0.0*Lat->ReciBasis[0]) < MYEPSILON ) {
1245 LevS->LPsi->LocalPsi[j][i].re = 1.0;
1246 fprintf(stdout, "(%i) %i g = %i\n", P->Par.me, j, i);
1247 }
1248 */
1249 /*
1250 if ( j==0 && P->Par.me_comm_ST_PsiT == 0 &&
1251 fabs(LevS->GArray[i].G[0] - 1.0*Lat->ReciBasis[0]) < MYEPSILON &&
1252 fabs(LevS->GArray[i].G[1] - 0.0*Lat->ReciBasis[0]) < MYEPSILON &&
1253 fabs(LevS->GArray[i].G[2] - 0.0*Lat->ReciBasis[0]) < MYEPSILON ) {
1254 LevS->LPsi->LocalPsi[j][i].re = 1.0;
1255 fprintf(stdout, "(%i) %i g = %i\n", P->Par.me, j, i);
1256 }
1257 if ( j==1 && P->Par.me_comm_ST_PsiT == 0 &&
1258 fabs(LevS->GArray[i].G[0] - 0.0*Lat->ReciBasis[0]) < MYEPSILON &&
1259 fabs(LevS->GArray[i].G[1] - 1.0*Lat->ReciBasis[0]) < MYEPSILON &&
1260 fabs(LevS->GArray[i].G[2] - 0.0*Lat->ReciBasis[0]) < MYEPSILON ) {
1261 LevS->LPsi->LocalPsi[j][i].re = 1.0;
1262 fprintf(stdout, "(%i) %i g = %i\n", P->Par.me, j, i);
1263 }
1264 if ( j==0 && P->Par.me_comm_ST_PsiT == 1 &&
1265 fabs(LevS->GArray[i].G[0] - 0.0*Lat->ReciBasis[0]) < MYEPSILON &&
1266 fabs(LevS->GArray[i].G[1] - 0.0*Lat->ReciBasis[0]) < MYEPSILON &&
1267 fabs(LevS->GArray[i].G[2] - 1.0*Lat->ReciBasis[0]) < MYEPSILON ) {
1268 LevS->LPsi->LocalPsi[j][i].re = 1.0;
1269 fprintf(stdout, "(%i) %i g = %i\n", P->Par.me, j, i);
1270 }
1271 if ( j==1 && P->Par.me_comm_ST_PsiT == 1 &&
1272 fabs(LevS->GArray[i].G[0] - 1.0*Lat->ReciBasis[0]) < MYEPSILON &&
1273 fabs(LevS->GArray[i].G[1] - 1.0*Lat->ReciBasis[0]) < MYEPSILON &&
1274 fabs(LevS->GArray[i].G[2] - 0.0*Lat->ReciBasis[0]) < MYEPSILON ) {
1275 LevS->LPsi->LocalPsi[j][i].re = 1.0;
1276 fprintf(stdout, "(%i) %i g = %i\n", P->Par.me, j, i);
1277 }
1278 */
1279 }
1280 //fclose(psi);
1281}
1282
1283/* Init Lattice End */
1284
1285
1286/** Reads parameter from a parsed file.
1287 * The file is either parsed for a certain keyword or if null is given for
1288 * the value in row yth and column xth. If the keyword was necessity#critical,
1289 * then an error is thrown and the programme aborted.
1290 * \warning value is modified (both in contents and position)!
1291 * \param verbose 1 - print found value to stderr, 0 - don't
1292 * \param file file to be parsed
1293 * \param name Name of value in file (at least 3 chars!)
1294 * \param sequential 1 - do not reset file pointer to begin of file, 0 - set to beginning
1295 * (if file is sequentially parsed this can be way faster! However, beware of multiple values per line, as whole line is read -
1296 * best approach: 0 0 0 1 (not resetted only on last value of line) - and of yth, which is now
1297 * counted from this unresetted position!)
1298 * \param xth Which among a number of parameters it is (in grid case it's row number as grid is read as a whole!)
1299 * \param yth In grid case specifying column number, otherwise the yth \a name matching line
1300 * \param type Type of the Parameter to be read
1301 * \param value address of the value to be read (must have been allocated)
1302 * \param repetition determines, if the keyword appears multiply in the config file, which repetition shall be parsed, i.e. 1 if not multiply
1303 * \param critical necessity of this keyword being specified (optional, critical)
1304 * \return 1 - found, 0 - not found
1305 * \sa ReadMainParameterFile Calling routine
1306 */
1307int ParseForParameter(int verbose, FILE *file, const char *const name, int sequential, int const xth, int const yth, enum value_type type, void *value, int repetition, enum necessity critical) {
1308 int i,j; // loop variables
1309 int me, length, maxlength = -1;
1310 long file_position = ftell(file); // mark current position
1311 char *dummy2, *dummy1, *dummy, *free_dummy; // pointers in the line that is read in per step
1312
1313 if (repetition == 0)
1314 Error(SomeError, "ParseForParameter(): argument repetition must not be 0!");
1315
1316 // allocated memory and rank in multi-process word
1317 dummy1 = free_dummy = (char *) Malloc(256 * sizeof(char),"ParseForParameter: MemAlloc for dummy1 failed");
1318 MPI_Comm_rank(MPI_COMM_WORLD, &me);
1319
1320 //fprintf(stderr,"(%i) Parsing for %s\n",me,name);
1321 int line = 0; // marks line where parameter was found
1322 int found = (type >= grid) ? 0 : (-yth + 1); // marks if yth parameter name was found
1323 while((found != repetition)) {
1324 dummy1 = dummy = free_dummy;
1325 do {
1326 fgets(dummy1, 256, file); // Read the whole line
1327 if (feof(file)) {
1328 if ((critical) && (found == 0)) {
1329 Free(free_dummy, "ParseForParameter: free_dummy");
1330 Error(InitReading, name);
1331 } else {
1332 //if (!sequential)
1333 fseek(file, file_position, SEEK_SET); // rewind to start position
1334 Free(free_dummy, "ParseForParameter: free_dummy");
1335 return 0;
1336 }
1337 }
1338 line++;
1339 } while (((dummy1[0] == '#') || (dummy1[0] == '\n')) && dummy != NULL); // skip commentary and empty lines
1340
1341 // C++ getline removes newline at end, thus re-add
1342 if (strchr(dummy1,'\n') == NULL) {
1343 i = strlen(dummy1);
1344 dummy1[i] = '\n';
1345 dummy1[i+1] = '\0';
1346 }
1347
1348 if (dummy1 == NULL) {
1349 if (verbose) fprintf(stderr,"(%i) Error reading line %i\n",me,line);
1350 } else {
1351 //fprintf(stderr,"(%i) Reading next line %i: %s\n",me, line, dummy1);
1352 }
1353 // Seek for possible end of keyword on line if given ...
1354 if (name != NULL) {
1355 dummy = strchr(dummy1,'\t'); // set dummy on first tab or space which ever nearer
1356 dummy2 = strchr(dummy1, ' '); // if not found seek for space
1357 if ((dummy != NULL) || (dummy2 != NULL)) {
1358 if ((dummy == NULL) || ((dummy2 != NULL) && (dummy2 < dummy)))
1359 dummy = dummy2;
1360 }
1361 if (dummy == NULL) {
1362 dummy = strchr(dummy1, '\n'); // set on line end then (whole line = keyword)
1363 //fprintf(stderr,"(%i)Error: Cannot find tabs or spaces on line %i in search for %s\n", me, line, name);
1364 //Free(free_dummy, "ParseForParameter: free_dummy");
1365 //Error(FileOpenParams, NULL);
1366 } else {
1367 //fprintf(stderr,"(%i) found tab at %li\n",me,(long)((char *)dummy-(char *)dummy1));
1368 }
1369 } else dummy = dummy1;
1370 // ... and check if it is the keyword!
1371 if ((name == NULL) || ((dummy-dummy1 >= 3) && (strncmp(dummy1, name, strlen(name)) == 0) && (dummy-dummy1 == strlen(name)))) {
1372 found++; // found the parameter!
1373 //fprintf(stderr,"(%i) found %s at line %i\n",me, name, line);
1374
1375 if (found == repetition) {
1376 for (i=0;i<xth;i++) { // i = rows
1377 if (type >= grid) {
1378 // grid structure means that grid starts on the next line, not right after keyword
1379 dummy1 = dummy = free_dummy;
1380 do {
1381 fgets(dummy1, 256, file); // Read the whole line, skip commentary and empty ones
1382 if (feof(file)) {
1383 if ((critical) && (found == 0)) {
1384 Free(free_dummy, "ParseForParameter: free_dummy");
1385 Error(InitReading, name);
1386 } else {
1387 //if (!sequential)
1388 fseek(file, file_position, SEEK_SET); // rewind to start position
1389 Free(free_dummy, "ParseForParameter: free_dummy");
1390 return 0;
1391 }
1392 }
1393 line++;
1394 } while ((dummy1[0] == '#') || (dummy1[0] == '\n'));
1395 if (dummy1 == NULL){
1396 if (verbose) fprintf(stderr,"(%i) Error reading line %i\n", me, line);
1397 } else {
1398 //fprintf(stderr,"(%i) Reading next line %i: %s\n", me, line, dummy1);
1399 }
1400 } else { // simple int, strings or doubles start in the same line
1401 while ((*dummy == '\t') || (*dummy == ' ')) // skip interjacent tabs and spaces
1402 dummy++;
1403 }
1404 // C++ getline removes newline at end, thus re-add
1405 if ((dummy1 != NULL) && (strchr(dummy1,'\n') == NULL)) {
1406 j = strlen(dummy1);
1407 dummy1[j] = '\n';
1408 dummy1[j+1] = '\0';
1409 }
1410
1411 int start = (type >= grid) ? 0 : yth-1 ;
1412 for (j=start;j<yth;j++) { // j = columns
1413 // check for lower triangular area and upper triangular area
1414 if ( ((i > j) && (type == upper_trigrid)) || ((j > i) && (type == lower_trigrid))) {
1415 *((double *)value) = 0.0;
1416 //fprintf(stderr,"%f\t",*((double *)value));
1417 value += sizeof(double);
1418 } else {
1419 // otherwise we must skip all interjacent tabs and spaces and find next value
1420 dummy1 = dummy;
1421 dummy = strchr(dummy1, '\t'); // seek for tab or space (space if appears sooner)
1422 dummy2 = strchr(dummy1, ' ');
1423 //fprintf(stderr,"dummy (%p) is %c\t dummy2 (%p) is %c\n", dummy, (dummy == NULL ? '-' : *dummy), dummy2, (dummy2 == NULL ? '-' : *dummy2));
1424 if ((dummy != NULL) || (dummy2 != NULL)) {
1425 if ((dummy == NULL) || ((dummy2 != NULL) && (dummy2 < dummy)))
1426 dummy = dummy2;
1427 //while ((dummy != NULL) && ((*dummy == '\t') || (*dummy == ' '))) // skip some more tabs and spaces if necessary
1428 // dummy++;
1429 }
1430/* while ((dummy != NULL) && ((*dummy == '\t') || (*dummy == ' '))) // skip some more tabs and spaces if necessary
1431 dummy++;*/
1432 //fprintf(stderr,"dummy is %c\n", *dummy);
1433 dummy2 = strchr(dummy1, '#');
1434 if ((dummy == NULL) || ((dummy2 != NULL) && (dummy1 >= dummy2))) { // if still zero returned or in comment area ...
1435 dummy = strchr(dummy1, '\n'); // ... at line end then
1436 if ((i < xth-1) && (type < 4)) { // check if xth value or not yet
1437 if (critical) {
1438 if (verbose) fprintf(stderr,"(%i)Error: EoL or comment at %i and still missing %i value(s) for parameter %s\n", me, line, yth-j, name);
1439 Free(free_dummy, "ParseForParameter: free_dummy");
1440 Error(InitReading, name);
1441 } else {
1442 //if (!sequential)
1443 fseek(file, file_position, SEEK_SET); // rewind to start position
1444 Free(free_dummy, "ParseForParameter: free_dummy");
1445 return 0;
1446 }
1447 //Error(FileOpenParams, NULL);
1448 }
1449 } else {
1450 //fprintf(stderr,"(%i) found tab at %i\n",me,(char *)dummy-(char *)free_dummy);
1451 }
1452 //fprintf(stderr,"(%i) value from %i to %i\n",me,(char *)dummy1-(char *)free_dummy,(char *)dummy-(char *)free_dummy);
1453 switch(type) {
1454 case (row_int):
1455 *((int *)value) = atoi(dummy1);
1456 if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"(%i) %s = ",me, name);
1457 if (verbose) fprintf(stderr,"%i\t",*((int *)value));
1458 value += sizeof(int);
1459 break;
1460 case (row_double):
1461 case(grid):
1462 case(lower_trigrid):
1463 case(upper_trigrid):
1464 *((double *)value) = atof(dummy1);
1465 if ((verbose) && (i==0) && (j==0)) fprintf(stderr,"(%i) %s = ",me, name);
1466 if (verbose) fprintf(stderr,"%lg\t",*((double *)value));
1467 value += sizeof(double);
1468 break;
1469 case(double_type):
1470 *((double *)value) = atof(dummy1);
1471 if ((verbose) && (i == xth-1)) fprintf(stderr,"(%i) %s = %lg\n",me, name, *((double *) value));
1472 //value += sizeof(double);
1473 break;
1474 case(int_type):
1475 *((int *)value) = atoi(dummy1);
1476 if ((verbose) && (i == xth-1)) fprintf(stderr,"(%i) %s = %i\n",me, name, *((int *) value));
1477 //value += sizeof(int);
1478 break;
1479 default:
1480 case(string_type):
1481 if (value != NULL) {
1482 if (maxlength == -1) maxlength = strlen((char *)value); // get maximum size of string array
1483 length = maxlength > (dummy-dummy1) ? (dummy-dummy1) : maxlength; // cap at maximum
1484 strncpy((char *)value, dummy1, length); // copy as much
1485 ((char *)value)[length] = '\0'; // and set end marker
1486 if ((verbose) && (i == xth-1)) fprintf(stderr,"(%i) %s is '%s' (%i chars)\n",me,name,((char *) value), length);
1487 //value += sizeof(char);
1488 } else {
1489 Error(SomeError, "ParseForParameter: given string array points to NULL!");
1490 }
1491 break;
1492 }
1493 }
1494 while (*dummy == '\t')
1495 dummy++;
1496 }
1497 }
1498 }
1499 }
1500 }
1501 if ((type >= row_int) && (verbose)) fprintf(stderr,"\n");
1502 if (!sequential) fseek(file, file_position, SEEK_SET); // rewind to start position
1503 Free(free_dummy, "ParseForParameter: free_dummy");
1504 //fprintf(stderr, "(%i) End of Parsing\n\n",me);
1505
1506 return (found); // true if found, false if not
1507}
1508
1509/** Readin of main parameter file.
1510 * creates RunStruct and FileData, opens \a filename \n
1511 * Only for process 0: and then scans the whole thing.
1512 *
1513 * \param P Problem structure to be filled
1514 * \param filename const char array with parameter file name
1515 * \sa ParseForParameter
1516 */
1517void ReadParameters(struct Problem *const P, const char *const filename) {
1518 /* Oeffne Hauptparameterdatei */
1519 struct RunStruct *R = &P->R;
1520 struct FileData *F = &P->Files;
1521 FILE *file;
1522 int i, di, me;
1523 //double BField[NDIM];
1524
1525 MPI_Comm_rank(MPI_COMM_WORLD, &me);
1526 if (P->Call.out[NormalOut]) fprintf(stderr, "(%i)ReadMainParameterFile\n", me);
1527 file = fopen(filename, "r");
1528 if (file == NULL) {
1529 fprintf(stderr,"(%i)Error: Cannot open main parameter file: %s\n", me, filename);
1530 Error(FileOpenParams, NULL);
1531 } else if(P->Call.out[ReadOut]) fprintf(stderr,"(%i)File is open: %s\n", me, filename);
1532
1533 /* Namen einlesen */
1534
1535 P->Files.filename = MallocString(MAXDUMMYSTRING,"ReadParameters: filename");
1536 ParseForParameter(P->Call.out[ReadOut],file, "mainname", 0, 1, 1, string_type, P->Files.filename, 1, critical);
1537 //debug(P,"mainname");
1538 CreateMainname(P, filename);
1539 P->Files.default_path = MallocString(MAXDUMMYSTRING,"ReadParameters: default_path");
1540 ParseForParameter(P->Call.out[ReadOut],file, "defaultpath", 0, 1, 1, string_type, P->Files.default_path, 1, critical);
1541 P->Files.pseudopot_path = MallocString(MAXDUMMYSTRING,"ReadParameters: pseudopot_path");
1542 ParseForParameter(P->Call.out[ReadOut],file, "pseudopotpath", 0, 1, 1, string_type, P->Files.pseudopot_path, 1, critical);
1543 ParseForParameter(P->Call.out[ReadOut],file,"ProcPEGamma", 0, 1, 1, int_type, &(P->Par.proc[PEGamma]), 1, critical);
1544 ParseForParameter(P->Call.out[ReadOut],file,"ProcPEPsi", 0, 1, 1, int_type, &(P->Par.proc[PEPsi]), 1, critical);
1545 if (P->Call.proc[PEPsi]) { /* Kommandozeilenoption */
1546 P->Par.proc[PEPsi] = P->Call.proc[PEPsi];
1547 P->Par.proc[PEGamma] = P->Call.proc[PEGamma];
1548 }
1549 /*
1550 Run
1551 */
1552 if (!ParseForParameter(P->Call.out[ReadOut],file,"Seed", 0, 1, 1, int_type, &(R->Seed), 1, optional))
1553 R->Seed = 1;
1554 if (!ParseForParameter(P->Call.out[ReadOut],file,"WaveNr", 0, 1, 1, int_type, &(R->WaveNr), 1, optional))
1555 R->WaveNr = 0;
1556 if (!ParseForParameter(P->Call.out[ReadOut],file,"Lambda", 0, 1, 1, double_type, &R->Lambda, 1, optional))
1557 R->Lambda = 1.;
1558
1559 if(!ParseForParameter(P->Call.out[ReadOut],file,"DoOutOrbitals", 0, 1, 1, int_type, &F->DoOutOrbitals, 1, optional)) {
1560 F->DoOutOrbitals = 0;
1561 } else {
1562 if (F->DoOutOrbitals < 0) F->DoOutOrbitals = 0;
1563 if (F->DoOutOrbitals > 1) F->DoOutOrbitals = 1;
1564 }
1565 ParseForParameter(P->Call.out[ReadOut],file,"DoOutVis", 0, 1, 1, int_type, &F->DoOutVis, 1, critical);
1566 if (F->DoOutVis < 0) F->DoOutVis = 0;
1567 if (F->DoOutVis > 2) F->DoOutVis = 1;
1568 if (!ParseForParameter(P->Call.out[ReadOut],file,"VectorPlane", 0, 1, 1, int_type, &R->VectorPlane, 1, optional))
1569 R->VectorPlane = -1;
1570 if (R->VectorPlane < -1 || R->VectorPlane > 2) {
1571 fprintf(stderr,"(%i) ! -1 <= R-VectorPlane <= 2: We simulate three-dimensional worlds! Disabling current vector plot: -1\n", P->Par.me);
1572 R->VectorPlane = -1;
1573 }
1574 if (!ParseForParameter(P->Call.out[ReadOut],file,"VectorCut", 0, 1, 1, double_type, &R->VectorCut, 1, optional))
1575 R->VectorCut = 0.;
1576 ParseForParameter(P->Call.out[ReadOut],file,"DoOutMes", 0, 1, 1, int_type, &F->DoOutMes, 1, critical);
1577 if (F->DoOutMes < 0) F->DoOutMes = 0;
1578 if (F->DoOutMes > 1) F->DoOutMes = 1;
1579 if (!ParseForParameter(P->Call.out[ReadOut],file,"DoOutCurr", 0, 1, 1, int_type, &F->DoOutCurr, 1, optional))
1580 F->DoOutCurr = 0;
1581 if (!ParseForParameter(P->Call.out[ReadOut],file,"DoOutNICS", 0, 1, 1, int_type, &F->DoOutNICS, 1, optional))
1582 F->DoOutNICS = 0;
1583 if (F->DoOutCurr < 0) F->DoOutCurr = 0;
1584 if (F->DoOutCurr > 1) F->DoOutCurr = 1;
1585 ParseForParameter(P->Call.out[ReadOut],file,"AddGramSch", 0, 1, 1, int_type, &R->UseAddGramSch, 1, critical);
1586 if (R->UseAddGramSch < 0) R->UseAddGramSch = 0;
1587 if (R->UseAddGramSch > 2) R->UseAddGramSch = 2;
1588 if(P->Call.out[ReadOut]) fprintf(stderr,"(%i)UseAddGramSch = %i\n",me,R->UseAddGramSch);
1589 if(!ParseForParameter(P->Call.out[ReadOut],file,"CommonWannier", 0, 1, 1, int_type, &R->CommonWannier, 1, optional)) {
1590 R->CommonWannier = 0;
1591 } else {
1592 if (R->CommonWannier < 0) R->CommonWannier = 0;
1593 if (R->CommonWannier > 4) R->CommonWannier = 4;
1594 }
1595 if(!ParseForParameter(P->Call.out[ReadOut],file,"SawtoothStart", 0, 1, 1, double_type, &P->Lat.SawtoothStart, 1, optional)) {
1596 P->Lat.SawtoothStart = 0.01;
1597 } else {
1598 if (P->Lat.SawtoothStart < 0.) P->Lat.SawtoothStart = 0.;
1599 if (P->Lat.SawtoothStart > 1.) P->Lat.SawtoothStart = 1.;
1600 }
1601 if (!ParseForParameter(P->Call.out[ReadOut],file,"DoBrent", 0, 1, 1, int_type, &R->DoBrent, 1, optional)) {
1602 R->DoBrent = 0;
1603 } else {
1604 if (R->DoBrent < 0) R->DoBrent = 0;
1605 if (R->DoBrent > 1) R->DoBrent = 1;
1606 }
1607
1608
1609 if (!ParseForParameter(P->Call.out[ReadOut],file,"MaxOuterStep", 0, 1, 1, int_type, &R->MaxOuterStep, 1, optional))
1610 R->MaxOuterStep = 0;
1611 if (!ParseForParameter(P->Call.out[ReadOut],file,"MaxStructOptStep", 0, 1, 1, int_type, &R->MaxStructOptStep, 1, optional)) {
1612 if (R->MaxOuterStep != 0) { // if StructOptStep not explicitely specified, then use OuterStep
1613 R->MaxStructOptStep = R->MaxOuterStep;
1614 } else {
1615 R->MaxStructOptStep = 100;
1616 }
1617 }
1618 // the following values are MD specific and should be dropped in further revisions
1619 if (!ParseForParameter(P->Call.out[ReadOut],file,"Deltat", 0, 1, 1, double_type, &R->delta_t, 1, optional))
1620 R->delta_t = 1.;
1621 if (!ParseForParameter(P->Call.out[ReadOut],file,"OutVisStep", 0, 1, 1, int_type, &R->OutVisStep, 1, optional))
1622 R->OutVisStep = 10;
1623 if (!ParseForParameter(P->Call.out[ReadOut],file,"OutSrcStep", 0, 1, 1, int_type, &R->OutSrcStep, 1, optional))
1624 R->OutSrcStep = 5;
1625 if (!ParseForParameter(P->Call.out[ReadOut],file,"TargetTemp", 0, 1, 1, double_type, &R->TargetTemp, 1, optional))
1626 R->TargetTemp = 0;
1627
1628 if (!ParseForParameter(P->Call.out[ReadOut],file,"EpsWannier", 0, 1, 1, double_type, &R->EpsWannier, 1, optional))
1629 R->EpsWannier = 1e-8;
1630
1631 // stop conditions
1632 R->t = 0;
1633 //if (R->MaxOuterStep <= 0) R->MaxOuterStep = 1;
1634 if(P->Call.out[NormalOut]) fprintf(stderr,"(%i)MaxOuterStep = %i\n",me,R->MaxOuterStep);
1635 if(P->Call.out[NormalOut]) fprintf(stderr,"(%i)Deltat = %g\n",me,R->delta_t);
1636 ParseForParameter(P->Call.out[ReadOut],file,"MaxPsiStep", 0, 1, 1, int_type, &R->MaxPsiStep, 1, critical);
1637 if (R->MaxPsiStep <= 0) R->MaxPsiStep = 3;
1638 if(P->Call.out[NormalOut]) fprintf(stderr,"(%i)MaxPsiStep = %i\n",me,R->MaxPsiStep);
1639
1640 ParseForParameter(P->Call.out[ReadOut],file,"MaxMinStep", 0, 1, 1, int_type, &R->MaxMinStep, 1, critical);
1641 ParseForParameter(P->Call.out[ReadOut],file,"RelEpsTotalE", 0, 1, 1, double_type, &R->RelEpsTotalEnergy, 1, critical);
1642 ParseForParameter(P->Call.out[ReadOut],file,"RelEpsKineticE", 0, 1, 1, double_type, &R->RelEpsKineticEnergy, 1, critical);
1643 ParseForParameter(P->Call.out[ReadOut],file,"MaxMinStopStep", 0, 1, 1, int_type, &R->MaxMinStopStep, 1, critical);
1644 ParseForParameter(P->Call.out[ReadOut],file,"MaxMinGapStopStep", 0, 1, 1, int_type, &R->MaxMinGapStopStep, 1, critical);
1645 if (R->MaxMinStep <= 0) R->MaxMinStep = R->MaxPsiStep;
1646 if (R->MaxMinStopStep < 1) R->MaxMinStopStep = 1;
1647 if (R->MaxMinGapStopStep < 1) R->MaxMinGapStopStep = 1;
1648 if(P->Call.out[NormalOut]) fprintf(stderr,"(%i)MaxMinStep = %i\tRelEpsTotalEnergy: %e\tRelEpsKineticEnergy %e\tMaxMinStopStep %i\n",me,R->MaxMinStep,R->RelEpsTotalEnergy,R->RelEpsKineticEnergy,R->MaxMinStopStep);
1649
1650 ParseForParameter(P->Call.out[ReadOut],file,"MaxInitMinStep", 0, 1, 1, int_type, &R->MaxInitMinStep, 1, critical);
1651 ParseForParameter(P->Call.out[ReadOut],file,"InitRelEpsTotalE", 0, 1, 1, double_type, &R->InitRelEpsTotalEnergy, 1, critical);
1652 ParseForParameter(P->Call.out[ReadOut],file,"InitRelEpsKineticE", 0, 1, 1, double_type, &R->InitRelEpsKineticEnergy, 1, critical);
1653 ParseForParameter(P->Call.out[ReadOut],file,"InitMaxMinStopStep", 0, 1, 1, int_type, &R->InitMaxMinStopStep, 1, critical);
1654 ParseForParameter(P->Call.out[ReadOut],file,"InitMaxMinGapStopStep", 0, 1, 1, int_type, &R->InitMaxMinGapStopStep, 1, critical);
1655 if (R->MaxInitMinStep <= 0) R->MaxInitMinStep = R->MaxPsiStep;
1656 if (R->InitMaxMinStopStep < 1) R->InitMaxMinStopStep = 1;
1657 if (R->InitMaxMinGapStopStep < 1) R->InitMaxMinGapStopStep = 1;
1658 if(P->Call.out[NormalOut]) fprintf(stderr,"(%i)INIT:MaxMinStep = %i\tRelEpsTotalEnergy: %e\tRelEpsKineticEnergy %e\tMaxMinStopStep %i\tMaxMinGapStopStep %i\n",me,R->MaxInitMinStep,R->InitRelEpsTotalEnergy,R->InitRelEpsKineticEnergy,R->InitMaxMinStopStep,R->InitMaxMinStopStep);
1659
1660 // Unit cell and magnetic field
1661 ParseForParameter(P->Call.out[ReadOut],file, "BoxLength", 0, 3, 3, lower_trigrid, &P->Lat.RealBasis, 1, critical); /* Lattice->RealBasis */
1662 ParseForParameter(P->Call.out[ReadOut],file, "DoPerturbation", 0, 1, 1, int_type, &R->DoPerturbation, 1, optional);
1663 if (!R->DoPerturbation) {
1664 if (!ParseForParameter(P->Call.out[ReadOut],file, "BField", 0, 1, 3, grid, &R->BField, 1, optional)) { // old parameter for perturbation with field direction
1665 if (P->Call.out[ReadOut]) fprintf(stderr,"(%i) No perturbation specified.\n", P->Par.me);
1666 if (F->DoOutCurr || F->DoOutNICS) {
1667 if (P->Call.out[ReadOut]) fprintf(stderr,"(%i) DoOutCurr/DoOutNICS = 1 though no DoPerturbation specified: setting DoOutCurr = 0\n", P->Par.me);
1668 F->DoOutCurr = 0;
1669 F->DoOutNICS = 0;
1670 R->DoPerturbation = 0;
1671 }
1672 } else {
1673 R->DoPerturbation = 1;
1674 }
1675 }
1676 if (!P->Call.WriteSrcFiles && R->DoPerturbation) {
1677 if (P->Call.out[ReadOut]) fprintf(stderr,"(%i)Perturbation: Always writing source files (\"-w\").\n", P->Par.me);
1678 P->Call.WriteSrcFiles = 1;
1679 }
1680 RMatReci3(P->Lat.InvBasis, P->Lat.RealBasis);
1681
1682 if (!ParseForParameter(P->Call.out[ReadOut],file,"DoFullCurrent", 0, 1, 1, int_type, &R->DoFullCurrent, 1, optional))
1683 R->DoFullCurrent = 0;
1684 if (R->DoFullCurrent < 0) R->DoFullCurrent = 0;
1685 if (R->DoFullCurrent > 2) R->DoFullCurrent = 2;
1686 if (R->DoPerturbation == 0) {
1687 if (P->Call.out[ReadOut]) fprintf(stderr,"(%i) No Magnetic field: RunStruct#DoFullCurrent = 0\n", P->Par.me);
1688 R->DoFullCurrent = 0;
1689 }
1690
1691 ParseForParameter(P->Call.out[ReadOut],file,"ECut", 0, 1, 1, double_type, &P->Lat.ECut, 1, critical);
1692 if(P->Call.out[NormalOut]) fprintf(stderr,"(%i) ECut = %e -> %e Rydberg\n", me, P->Lat.ECut, 2.*P->Lat.ECut);
1693 ParseForParameter(P->Call.out[ReadOut],file,"MaxLevel", 0, 1, 1, int_type, &P->Lat.MaxLevel, 1, critical);
1694 ParseForParameter(P->Call.out[ReadOut],file,"Level0Factor", 0, 1, 1, int_type, &P->Lat.Lev0Factor, 1, critical);
1695 if (P->Lat.Lev0Factor < 2) {
1696 if(P->Call.out[ReadOut]) fprintf(stderr,"(%i) Set Lev0Factor to 2!\n",me);
1697 P->Lat.Lev0Factor = 2;
1698 }
1699 ParseForParameter(P->Call.out[ReadOut],file,"RiemannTensor", 0, 1, 1, int_type, &di, 1, critical);
1700 if (di >= 0 && di < 2) {
1701 P->Lat.RT.Use = (enum UseRiemannTensor)di;
1702 } else {
1703 Error(SomeError, "0 <= RiemanTensor < 2: 0 UseNotRT, 1 UseRT");
1704 }
1705 if(P->Call.out[ReadOut]) fprintf(stderr,"(%i)!RiemannTensor = %i\n",me,P->Lat.RT.Use), critical;
1706 switch (P->Lat.RT.Use) {
1707 case UseNotRT:
1708 if (P->Lat.MaxLevel < 2) {
1709 if(P->Call.out[ReadOut]) fprintf(stderr,"(%i) Set MaxLevel to 2!\n",me);
1710 P->Lat.MaxLevel = 2;
1711 }
1712 P->Lat.LevRFactor = 2;
1713 P->Lat.RT.ActualUse = inactive;
1714 break;
1715 case UseRT:
1716 if (P->Lat.MaxLevel < 3) {
1717 if(P->Call.out[ReadOut]) fprintf(stderr,"(%i) Set MaxLevel to 3!\n",me);
1718 P->Lat.MaxLevel = 3;
1719 }
1720 ParseForParameter(P->Call.out[ReadOut],file,"RiemannLevel", 0, 1, 1, int_type, &P->Lat.RT.RiemannLevel, 1, critical);
1721 if(P->Call.out[ReadOut]) fprintf(stderr,"(%i)!RiemannLevel = %i\n",me,P->Lat.RT.RiemannLevel);
1722 if (P->Lat.RT.RiemannLevel < 2) {
1723 if(P->Call.out[ReadOut]) fprintf(stderr,"(%i) Set RiemannLevel to 2!\n",me);
1724 P->Lat.RT.RiemannLevel = 2;
1725 }
1726 if (P->Lat.RT.RiemannLevel > P->Lat.MaxLevel-1) {
1727 if(P->Call.out[ReadOut]) fprintf(stderr,"(%i) Set RiemannLevel to %i (MaxLevel-1)!\n",me,P->Lat.MaxLevel-1);
1728 P->Lat.RT.RiemannLevel = P->Lat.MaxLevel-1;
1729 }
1730 ParseForParameter(P->Call.out[ReadOut],file,"LevRFactor", 0, 1, 1, int_type, &P->Lat.LevRFactor, 1, critical);
1731 if(P->Call.out[ReadOut]) fprintf(stderr,"(%i)!LevRFactor = %i\n",me,P->Lat.LevRFactor);
1732 if (P->Lat.LevRFactor < 2) {
1733 if(P->Call.out[ReadOut]) fprintf(stderr,"(%i) Set LevRFactor to 2!\n",me);
1734 P->Lat.LevRFactor = 2;
1735 }
1736 P->Lat.Lev0Factor = 2;
1737 P->Lat.RT.ActualUse = standby;
1738 break;
1739 }
1740 ParseForParameter(P->Call.out[ReadOut],file,"PsiType", 0, 1, 1, int_type, &di, 1, critical);
1741 if (di >= 0 && di < 2) {
1742 P->Lat.Psi.Use = (enum UseSpinType)di;
1743 } else {
1744 Error(SomeError, "0 <= PsiType < 2: 0 UseSpinDouble, 1 UseSpinUpDown");
1745 }
1746 if(P->Call.out[ReadOut]) fprintf(stderr,"(%i)!PsiType = %i\n",me,P->Lat.Psi.Use);
1747 for (i=0; i<MaxPsiNoType; i++)
1748 P->Lat.Psi.GlobalNo[i] = 0;
1749 switch (P->Lat.Psi.Use) {
1750 case UseSpinDouble:
1751 ParseForParameter(P->Call.out[ReadOut],file,"MaxPsiDouble", 0, 1, 1, int_type, &P->Lat.Psi.GlobalNo[PsiMaxNoDouble], 1, critical);
1752 if (!ParseForParameter(P->Call.out[ReadOut],file,"AddPsis", 0, 1, 1, int_type, &P->Lat.Psi.GlobalNo[PsiMaxAdd], 1, optional))
1753 P->Lat.Psi.GlobalNo[PsiMaxAdd] = 0;
1754 if (P->Lat.Psi.GlobalNo[PsiMaxAdd] != 0)
1755 R->DoUnOccupied = 1;
1756 else
1757 R->DoUnOccupied = 0;
1758 if(P->Call.out[ReadOut]) fprintf(stderr,"(%i)!MaxPsiDouble = %i + %i\n",me,P->Lat.Psi.GlobalNo[PsiMaxNoDouble],P->Lat.Psi.GlobalNo[PsiMaxAdd]);
1759 //P->Lat.Psi.GlobalNo[PsiMaxNoDouble] += P->Lat.Psi.GlobalNo[PsiMaxAdd]; no more adding up on occupied ones
1760 P->Lat.Psi.GlobalNo[PsiMaxNo] = P->Lat.Psi.GlobalNo[PsiMaxNoDouble];
1761 break;
1762 case UseSpinUpDown:
1763 if (P->Par.proc[PEPsi] % 2) Error(SomeError,"UseSpinUpDown & P->Par.proc[PEGamma] % 2");
1764 ParseForParameter(P->Call.out[ReadOut],file,"PsiMaxNoUp", 0, 1, 1, int_type, &P->Lat.Psi.GlobalNo[PsiMaxNoUp], 1, critical);
1765 ParseForParameter(P->Call.out[ReadOut],file,"PsiMaxNoDown", 0, 1, 1, int_type, &P->Lat.Psi.GlobalNo[PsiMaxNoDown], 1, critical);
1766 if (!ParseForParameter(P->Call.out[ReadOut],file,"AddPsis", 0, 1, 1, int_type, &P->Lat.Psi.GlobalNo[PsiMaxAdd], 1, optional))
1767 P->Lat.Psi.GlobalNo[PsiMaxAdd] = 0;
1768 if (P->Lat.Psi.GlobalNo[PsiMaxAdd] != 0)
1769 R->DoUnOccupied = 1;
1770 else
1771 R->DoUnOccupied = 0;
1772 if(P->Call.out[ReadOut]) fprintf(stderr,"(%i)!PsiMaxPsiUp = %i + %i\n",me,P->Lat.Psi.GlobalNo[PsiMaxNoUp],P->Lat.Psi.GlobalNo[PsiMaxAdd]);
1773 if(P->Call.out[ReadOut]) fprintf(stderr,"(%i)!PsiMaxPsiDown = %i + %i\n",me,P->Lat.Psi.GlobalNo[PsiMaxNoDown],P->Lat.Psi.GlobalNo[PsiMaxAdd]);
1774 //P->Lat.Psi.GlobalNo[PsiMaxNoUp] += P->Lat.Psi.GlobalNo[PsiMaxAdd];
1775 //P->Lat.Psi.GlobalNo[PsiMaxNoDown] += P->Lat.Psi.GlobalNo[PsiMaxAdd];
1776 if (abs(P->Lat.Psi.GlobalNo[PsiMaxNoUp]-P->Lat.Psi.GlobalNo[PsiMaxNoDown])>1) Error(SomeError,"|Up - Down| > 1");
1777 P->Lat.Psi.GlobalNo[PsiMaxNo] = P->Lat.Psi.GlobalNo[PsiMaxNoUp] + P->Lat.Psi.GlobalNo[PsiMaxNoDown];
1778 break;
1779 }
1780
1781 IonsInitRead(P, file);
1782 fclose(file);
1783}
1784
1785/** Writes parameters as a parsable config file to \a filename.
1786 * \param *P Problem at hand
1787 * \param filename name of config file to be written
1788 */
1789void WriteParameters(struct Problem *const P, const char *const filename) {
1790 struct Lattice *Lat = &P->Lat;
1791 struct RunStruct *R = &P->R;
1792 struct FileData *F = &P->Files;
1793 struct Ions *I = &P->Ion;
1794 FILE *output;
1795 double BorAng = (I->IsAngstroem) ? 1./ANGSTROEMINBOHRRADIUS : 1.;
1796 int i, it, nr = 0;
1797 if ((P->Par.me == 0) && (output = fopen(filename,"w"))) {
1798 //fprintf(stderr, "(%i) Writing config file %s\n",P->Par.me, filename);
1799
1800 fprintf(output,"# ParallelCarParinello - main configuration file - optimized geometry\n");
1801 fprintf(output,"\n");
1802 fprintf(output,"mainname\t%s\t# programm name (for runtime files)\n", F->mainname);
1803 fprintf(output,"defaultpath\t%s\t# where to put files during runtime\n", F->default_path);
1804 fprintf(output,"pseudopotpath\t%s\t# where to find pseudopotentials\n", F->pseudopot_path);
1805 fprintf(output,"\n");
1806 fprintf(output,"ProcPEGamma\t%i\t# for parallel computing: share constants\n", P->Par.proc[PEGamma]);
1807 fprintf(output,"ProcPEPsi\t%i\t# for parallel computing: share wave functions\n", P->Par.proc[PEPsi]);
1808 fprintf(output,"DoOutVis\t%i\t# Output data for OpenDX\n", F->DoOutVis);
1809 fprintf(output,"DoOutMes\t%i\t# Output data for measurements\n", F->DoOutMes);
1810 fprintf(output,"DoOutCurr\t%i\t# Ouput current density for OpenDx\n", F->DoOutCurr);
1811 fprintf(output,"DoPerturbation\t%i\t# Do perturbation calculate and determine susceptibility and shielding\n", R->DoPerturbation);
1812 fprintf(output,"DoFullCurrent\t%i\t# Do full perturbation\n", R->DoFullCurrent);
1813 fprintf(output,"DoOutOrbitals\t%i\t# Output all orbitals on end\n", F->DoOutOrbitals);
1814 fprintf(output,"CommonWannier\t%i\t# Put virtual centers at indivual orbits, all common, merged by variance, to grid point, to cell center\n", R->CommonWannier);
1815 fprintf(output,"SawtoothStart\t%lg\t# Absolute value for smooth transition at cell border \n", Lat->SawtoothStart);
1816 fprintf(output,"VectorPlane\t%i\t# Cut plane axis (x, y or z: 0,1,2) for two-dim current vector plot\n", R->VectorPlane);
1817 fprintf(output,"VectorCut\t%lg\t# Cut plane axis value\n", R->VectorCut);
1818 fprintf(output,"AddGramSch\t%i\t# Additional GramSchmidtOrtogonalization to be safe (1 - per MinStep, 2 - per PsiStep)\n", R->UseAddGramSch);
1819 fprintf(output,"Seed\t\t%i\t# initial value for random seed for Psi coefficients\n", R->Seed);
1820 fprintf(output,"DoBrent\t%i\t# Brent line search instead of CG with second taylor approximation\n", R->DoBrent);
1821 fprintf(output,"\n");
1822 fprintf(output,"MaxOuterStep\t%i\t# number of MolecularDynamics/Structure optimization steps\n", R->MaxOuterStep);
1823 fprintf(output,"Deltat\t%lg\t# time in atomic time per MD step\n", R->delta_t);
1824 fprintf(output,"OutVisStep\t%i\t# Output visual data every ...th step\n", R->OutVisStep);
1825 fprintf(output,"OutSrcStep\t%i\t# Output \"restart\" data every ..th step\n", R->OutSrcStep);
1826 fprintf(output,"TargetTemp\t%lg\t# Target temperature in Hartree\n", R->TargetTemp);
1827 fprintf(output,"Thermostat\t%s", I->ThermostatNames[I->Thermostat]);
1828 switch(I->Thermostat) {
1829 default:
1830 case 0: // None
1831 break;
1832 case 1: // Woodcock
1833 fprintf(output,"\t%i", R->ScaleTempStep);
1834 break;
1835 case 2: // Gaussian
1836 fprintf(output,"\t%i", R->ScaleTempStep);
1837 break;
1838 case 3: // Langevin
1839 fprintf(output,"\t%lg\t%lg", R->TempFrequency, R->alpha);
1840 break;
1841 case 4: // Berendsen
1842 fprintf(output,"\t%lg", R->TempFrequency);
1843 break;
1844 case 5: // NoseHoover
1845 fprintf(output,"\t%lg", R->HooverMass);
1846 break;
1847 }
1848 fprintf(output,"\t# Thermostat to be used with parameters\n");
1849 fprintf(output,"MaxPsiStep\t%i\t# number of Minimisation steps per state (0 - default)\n", R->MaxPsiStep);
1850 fprintf(output,"EpsWannier\t%lg\t# tolerance value for spread minimisation of orbitals\n", R->EpsWannier);
1851 fprintf(output,"\n");
1852 fprintf(output,"# Values specifying when to stop\n");
1853 fprintf(output,"MaxMinStep\t%i\t# Maximum number of steps\n", R->MaxMinStep);
1854 fprintf(output,"RelEpsTotalE\t%lg\t# relative change in total energy\n", R->RelEpsTotalEnergy);
1855 fprintf(output,"RelEpsKineticE\t%lg\t# relative change in kinetic energy\n", R->RelEpsKineticEnergy);
1856 fprintf(output,"MaxMinStopStep\t%i\t# check every ..th steps\n", R->MaxMinStopStep);
1857 fprintf(output,"MaxMinGapStopStep\t%i\t# check every ..th steps\n", R->MaxMinGapStopStep);
1858 fprintf(output,"\n");
1859 fprintf(output,"# Values specifying when to stop for INIT, otherwise same as above\n");
1860 fprintf(output,"MaxInitMinStep\t%i\t# Maximum number of steps\n", R->MaxInitMinStep);
1861 fprintf(output,"InitRelEpsTotalE\t%lg\t# relative change in total energy\n", R->InitRelEpsTotalEnergy);
1862 fprintf(output,"InitRelEpsKineticE\t%lg\t# relative change in kinetic energy\n", R->InitRelEpsKineticEnergy);
1863 fprintf(output,"InitMaxMinStopStep\t%i\t# check every ..th steps\n", R->InitMaxMinStopStep);
1864 fprintf(output,"InitMaxMinGapStopStep\t%i\t# check every ..th steps\n", R->InitMaxMinGapStopStep);
1865 fprintf(output,"\n");
1866 fprintf(output,"BoxLength\t\t\t# (Length of a unit cell)\n");
1867 fprintf(output,"%lg\t\n", Lat->RealBasis[0]*BorAng);
1868 fprintf(output,"%lg\t%lg\t\n", Lat->RealBasis[3]*BorAng, Lat->RealBasis[4]*BorAng);
1869 fprintf(output,"%lg\t%lg\t%lg\t\n", Lat->RealBasis[6]*BorAng, Lat->RealBasis[7]*BorAng, Lat->RealBasis[8]*BorAng);
1870 // FIXME
1871 fprintf(output,"\n");
1872 fprintf(output,"ECut\t\t%lg\t# energy cutoff for discretization in Hartrees\n", Lat->ECut/(Lat->LevelSizes[0]*Lat->LevelSizes[0]));
1873 fprintf(output,"MaxLevel\t%i\t# number of different levels in the code, >=2\n", P->Lat.MaxLevel);
1874 fprintf(output,"Level0Factor\t%i\t# factor by which node number increases from S to 0 level\n", P->Lat.Lev0Factor);
1875 fprintf(output,"RiemannTensor\t%i\t# (Use metric)\n", P->Lat.RT.Use);
1876 switch (P->Lat.RT.Use) {
1877 case 0: //UseNoRT
1878 break;
1879 case 1: // UseRT
1880 fprintf(output,"RiemannLevel\t%i\t# Number of Riemann Levels\n", P->Lat.RT.RiemannLevel);
1881 fprintf(output,"LevRFactor\t%i\t# factor by which node number increases from 0 to R level from\n", P->Lat.LevRFactor);
1882 break;
1883 }
1884 fprintf(output,"PsiType\t\t%i\t# 0 - doubly occupied, 1 - SpinUp,SpinDown\n", P->Lat.Psi.Use);
1885 // write out both types for easier changing afterwards
1886 // switch (PsiType) {
1887 // case 0:
1888 fprintf(output,"MaxPsiDouble\t%i\t# here: specifying both maximum number of SpinUp- and -Down-states\n", P->Lat.Psi.GlobalNo[PsiMaxNoDouble]);
1889 // break;
1890 // case 1:
1891 fprintf(output,"PsiMaxNoUp\t%i\t# here: specifying maximum number of SpinUp-states\n", P->Lat.Psi.GlobalNo[PsiMaxNoUp]);
1892 fprintf(output,"PsiMaxNoDown\t%i\t# here: specifying maximum number of SpinDown-states\n", P->Lat.Psi.GlobalNo[PsiMaxNoDown]);
1893 // break;
1894 // }
1895 fprintf(output,"AddPsis\t\t%i\t# Additional unoccupied Psis for bandgap determination\n", P->Lat.Psi.GlobalNo[PsiMaxAdd]);
1896 fprintf(output,"\n");
1897 fprintf(output,"RCut\t\t%lg\t# R-cut for the ewald summation\n", I->R_cut);
1898 fprintf(output,"StructOpt\t%i\t# Do structure optimization beforehand\n", I->StructOpt);
1899 fprintf(output,"IsAngstroem\t%i\t# 0 - Bohr, 1 - Angstroem\n", I->IsAngstroem);
1900 fprintf(output,"RelativeCoord\t0\t# whether ion coordinates are relative (1) or absolute (0)\n");
1901 fprintf(output,"MaxTypes\t%i\t# maximum number of different ion types\n", I->Max_Types);
1902 fprintf(output,"\n");
1903 // now elements ...
1904 fprintf(output,"# Ion type data (PP = PseudoPotential, Z = atomic number)\n");
1905 fprintf(output,"#Ion_TypeNr.\tAmount\tZ\tRGauss\tL_Max(PP)L_Loc(PP)IonMass\tName\tSymbol\n");
1906 for (i=0; i < I->Max_Types; i++)
1907 fprintf(output,"Ion_Type%i\t%i\t%i\t%lg\t%i\t%i\t%lg\t%s\t%s\n", i+1, I->I[i].Max_IonsOfType, I->I[i].Z, I->I[i].rgauss, I->I[i].l_max, I->I[i].l_loc, I->I[i].IonMass/Units2Electronmass, &I->I[i].Name[0], &I->I[i].Symbol[0]);
1908 // ... and each ion coordination
1909 fprintf(output,"#Ion_TypeNr._Nr.R[0]\tR[1]\tR[2]\tMoveType (0 MoveIon, 1 FixedIon) U[0]\tU[1]\tU[2] (velocities in %s)\n", (I->IsAngstroem) ? "Angstroem" : "atomic units");
1910 for (i=0; i < I->Max_Types; i++)
1911 for (it=0;it<I->I[i].Max_IonsOfType;it++) {
1912 fprintf(output,"Ion_Type%i_%i\t%2.9f\t%2.9f\t%2.9f\t%i\t%2.9f\t%2.9f\t%2.9f\t# Number in molecule %i\n", i+1, it+1, I->I[i].R[0+NDIM*it]*BorAng, I->I[i].R[1+NDIM*it]*BorAng, I->I[i].R[2+NDIM*it]*BorAng, I->I[i].IMT[it], I->I[i].U[0+NDIM*it]*BorAng, I->I[i].U[1+NDIM*it]*BorAng, I->I[i].U[2+NDIM*it]*BorAng, ++nr);
1913 }
1914 fflush(output);
1915 fclose(output);
1916 }
1917}
1918
1919/** Main Initialization.
1920 * Massive calling of initializing super-functions init...():
1921 * -# InitOutputFiles()\n
1922 * Opening and Initializing of output measurement files.
1923 * -# InitLattice()\n
1924 * Initializing Lattice structure.
1925 * -# InitRunLevel()\n
1926 * Initializing RunLevel structure.
1927 * -# InitLatticeLevel0()\n
1928 * Initializing LatticeLevel structure.
1929 * -# InitOtherLevel()\n
1930 * Initialization of first to Lattice::MaxLevel LatticeLevel's.
1931 * -# InitRun()\n
1932 * Initialization of RunStruct structure.
1933 * -# InitPsis()\n
1934 * Initialization of wave functions as a whole.
1935 * -# InitDensity()\n
1936 * Initializing real and complex Density arrays.
1937 * -# either ReadSrcFiles() or InitPsisValues()\n
1938 * read old calculations from source file if desired or initialise with
1939 * random values InitPsisValue().
1940 * -# InitRiemannTensor()\n
1941 * Initializing RiemannTensor structure.
1942 * -# FirstInitGramSchData()\n
1943 * Sets up OnePsiElement as an MPI structure and subsequently initialises all of them.
1944 *
1945 * Now follow various (timed) tests:
1946 * -# GramSch()\n
1947 * (twice) to orthonormalize the random values
1948 * -# TestGramSch()\n
1949 * Test if orbitals now fulfill kronecker delta relation.
1950 * -# InitGradients()\n
1951 * Initializing Gradient structure, allocating its arrays.
1952 * -# InitDensityCalculation()\n
1953 * Calculate naive, real and complex densities and sum them up.
1954 * -# InitPseudoRead()\n
1955 * Read PseudoPot'entials from file.
1956 * -# InitEnergyArray()\n
1957 * Initialize Energy arrays.
1958 * -# InitPsiEnergyCalculation()\n
1959 * Calculate all psi energies and sum up.
1960 * -# CalculateDensityEnergy()\n
1961 * Calculate Density energy.
1962 * -# CalculateIonsEnergy()\n
1963 * Calculate ionic energy.
1964 * -# CalculateEwald()\n
1965 * Calculate ionic ewald summation.
1966 * -# EnergyAllReduce()\n
1967 * Gather energies from all processes and sum up.
1968 * -# EnergyOutput()\n
1969 * First output to file.
1970 * -# InitOutVisArray()\n
1971 * First output of visual for Opendx.
1972 *
1973 * \param *P Problem at hand
1974 */
1975void Init(struct Problem *const P) {
1976 struct RunStruct *R = &P->R;
1977 InitOutputFiles(P);
1978 InitLattice(P);
1979 InitRunLevel(P);
1980 InitLatticeLevel0(P);
1981 InitOtherLevel(P);
1982 InitPsiGroupNo(P);
1983 InitRun(P);
1984 InitPsis(P);
1985 InitDensity(P);
1986 if (P->Call.ReadSrcFiles) {
1987 if (ReadSrcIons(P)) {
1988 if (P->Call.out[NormalOut]) fprintf(stderr,"(%i) Ionic structure read successfully.\n", P->Par.me);
1989 } else {
1990 if (P->Call.out[NormalOut]) fprintf(stderr,"(%i) No readible Ionic structure found.\n", P->Par.me);
1991 }
1992 } else {
1993 InitPsisValue(P, 0, P->Lat.Psi.TypeStartIndex[Perturbed_P0]);
1994 }
1995 InitRiemannTensor(P);
1996 if (P->Lat.RT.ActualUse == standby && R->LevRSNo == R->LevSNo) P->Lat.RT.ActualUse = active;
1997 CalculateRiemannTensorData(P);
1998 FirstInitGramSchData(P,&P->Lat.Psi);
1999 /* Test */
2000 SpeedMeasure(P, InitSimTime, StartTimeDo);
2001 SpeedMeasure(P, InitGramSchTime, StartTimeDo);
2002 GramSch(P, R->LevS, &P->Lat.Psi, Orthonormalize);
2003 ResetGramSch(P, &P->Lat.Psi);
2004 if (R->DoUnOccupied == 1) {
2005 ResetGramSchTagType(P, &P->Lat.Psi, UnOccupied, NotOrthogonal);
2006 GramSch(P, R->LevS, &P->Lat.Psi, Orthonormalize);
2007 }
2008 SpeedMeasure(P, InitGramSchTime, StopTimeDo);
2009 SpeedMeasure(P, InitSimTime, StopTimeDo);
2010 TestGramSch(P, R->LevS, &P->Lat.Psi, -1);
2011 ResetGramSchTagType(P, &P->Lat.Psi, UnOccupied, NotUsedToOrtho);
2012 InitGradients(P, &P->Grad);
2013 SpeedMeasure(P, InitSimTime, StartTimeDo);
2014 SpeedMeasure(P, InitDensityTime, StartTimeDo);
2015 InitDensityCalculation(P);
2016 SpeedMeasure(P, InitDensityTime, StopTimeDo);
2017 SpeedMeasure(P, InitSimTime, StopTimeDo);
2018 InitPseudoRead(P, P->Files.pseudopot_path);
2019 InitEnergyArray(P);
2020 SpeedMeasure(P, InitSimTime, StartTimeDo);
2021 InitPsiEnergyCalculation(P, Occupied); /* STANDARTLEVEL */
2022 CalculateDensityEnergy(P, 1); /* STANDARTLEVEL */
2023 CalculateIonsEnergy(P);
2024 CalculateEwald(P, 1);
2025 EnergyAllReduce(P);
2026/* SetCurrentMinState(P,UnOccupied);
2027 InitPsiEnergyCalculation(P,UnOccupied);
2028 CalculateGapEnergy(P);
2029 EnergyAllReduce(P);
2030 SetCurrentMinState(P,Occupied);*/
2031 SpeedMeasure(P, InitSimTime, StopTimeDo);
2032 R->LevS->Step++;
2033 EnergyOutput(P,0);
2034 InitOutVisArray(P);
2035 Free(P->Lat.GArrayForSort, "Init: P->Lat.GArrayForSort");
2036 P->Speed.InitSteps++;
2037}
2038
Note: See TracBrowser for help on using the repository browser.