source: pcp/src/init.c@ a97897

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

CallOptions#ReadSrcFile is now enumerated ParseSrcDensities

This is done to distinguish between when only Occ are parsed (i.e. when StructOpt has been done before and now we do perturbed run), all or we pare and minimise subsequently.

  • Property mode set to 100644
File size: 97.4 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 double x[NDIM];
136 struct LatticeLevel *Lev0;
137 int RL=-1;
138 // Volume
139 if (P->Call.out[NormalOut]) fprintf(stderr, "(%i)InitLattice\n", P->Par.me);
140 Lat->Volume = RDET3(Lat->RealBasis);
141 if (P->Call.out[ValueOut]) fprintf(stderr,"Volume = %g\n",Lat->Volume);
142 if (Lat->Volume == 0.0) {
143 return(1);
144 }
145 for (i=0; i < NDIM; i++) // create center point
146 x[i] = .5;
147 RMat33Vec3(Lat->RealBasisCenter, Lat->RealBasis, x);
148 if (P->Call.out[ValueOut]) fprintf(stderr,"Unit cell center = (%lg, %lg, %lg)\n", Lat->RealBasisCenter[0], Lat->RealBasisCenter[1], Lat->RealBasisCenter[2]);
149 // square-rooted and normal reciprocal (transposed) Base
150 for (i=0; i < NDIM_NDIM; i++) h[i] = Lat->RealBasis[i];
151 RTranspose3(h);
152 RMatReci3(Lat->ReciBasis, h);
153 for (i=0; i < NDIM_NDIM; i++) Lat->ReciBasis[i] *= factor; // SM(Lat->ReciBasis, factor, NDIM_NDIM);
154 for (i=0; i < NDIM; i++) {
155 Lat->ReciBasisSQ[i] = RNORMSQ3(&(Lat->ReciBasis[i*NDIM]));
156 Lat->RealBasisSQ[i] = RNORMSQ3(&(Lat->RealBasis[i*NDIM]));
157 }
158 // Prepares LatticeLevels
159 Lat->Lev = (struct LatticeLevel *)
160 Malloc(Lat->MaxLevel*sizeof(struct LatticeLevel),"InitLattice: Lat->Lev");
161 for (i=0; i < Lat->MaxLevel; i++)
162 Lat->Lev[i].Step = 0;
163 Lev0 = Lat->Lev; // short for &(Lat->Lev[0])
164 Lat->LevelSizes = (int *)
165 Malloc(sizeof(int)*Lat->MaxLevel,"InitLattice: LevelSizes");
166 Lat->LevelSizes[0] = P->Lat.Lev0Factor;
167 for (i=1; i < Lat->MaxLevel-1; i++) Lat->LevelSizes[i] = 2;
168 if (Lat->RT.Use == UseRT) {
169 RL = Lat->RT.RiemannLevel;
170 Lat->LevelSizes[RL-1] = P->Lat.LevRFactor;
171 }
172 Lat->LevelSizes[Lat->MaxLevel-1] = 1;
173 // NFields are next ... depending on use of RiemannTensor
174 Lat->MaxNoOfnFields = (int *)
175 Malloc(sizeof(int)*Lat->MaxLevel,"InitLattice: MaxNoOfnFields");;
176 Lat->NFields = (int **)
177 Malloc(sizeof(int*)*Lat->MaxLevel,"InitLattice: NFields");
178 switch (Lat->RT.Use) {
179 case UseNotRT:
180 for (i=0; i<Lat->MaxLevel; i++) {
181 if (i==0) {
182 Lat->MaxNoOfnFields[i] = 1;
183 Lat->NFields[i] = (int *)
184 Malloc(sizeof(int)*Lat->MaxNoOfnFields[i],"InitLattice: NFields");
185 Lat->NFields[i][FFTNF1] = 1;
186 } else {
187 Lat->MaxNoOfnFields[i] = 2;
188 Lat->NFields[i] = (int *)
189 Malloc(sizeof(int)*Lat->MaxNoOfnFields[i],"InitLattice: NFields");
190 Lat->NFields[i][FFTNF1] = 1;
191 Lat->NFields[i][FFTNFUp] = Lat->LevelSizes[i-1]*Lat->LevelSizes[i-1]*Lat->LevelSizes[i-1];
192 }
193 }
194 break;
195 case UseRT:
196 for (i=0; i<Lat->MaxLevel; i++) {
197 switch (i) {
198 case 0:
199 Lat->MaxNoOfnFields[i] = 2;
200 Lat->NFields[i] = (int *)
201 Malloc(sizeof(int)*Lat->MaxNoOfnFields[i],"InitLattice: NFields");
202 Lat->NFields[i][FFTNF1] = 1;
203 Lat->NFields[i][FFTNF0Vec] = NDIM;
204 break;
205 case STANDARTLEVEL:
206 Lat->MaxNoOfnFields[i] = 4;
207 Lat->NFields[i] = (int *)
208 Malloc(sizeof(int)*Lat->MaxNoOfnFields[i],"InitLattice: NFields");
209 Lat->NFields[i][FFTNF1] = 1;
210 Lat->NFields[i][FFTNFUp] = Lat->LevelSizes[0]*Lat->LevelSizes[0]*Lat->LevelSizes[0];
211 Lat->NFields[i][FFTNFSVecUp] = Lat->NFields[i][FFTNFUp]*NDIM;
212 Lat->NFields[i][FFTNFSVec] = NDIM;
213 break;
214 default:
215 if (i == RL) {
216 Lat->MaxNoOfnFields[i] = 5;
217 Lat->NFields[i] = (int *)
218 Malloc(sizeof(int)*Lat->MaxNoOfnFields[i],"InitLattice: NFields");
219 Lat->NFields[i][FFTNF1] = 1;
220 Lat->NFields[i][FFTNFUp] = Lat->LevelSizes[i-1]*Lat->LevelSizes[i-1]*Lat->LevelSizes[i-1];
221 UpDummy = 1;
222 for (j=RL-1; j >= STANDARTLEVEL; j--)
223 UpDummy *= Lat->LevelSizes[j]*Lat->LevelSizes[j]*Lat->LevelSizes[j];
224 /* UpDummy RL -> S */
225 Lat->NFields[i][FFTNFRMatVecUpS] = UpDummy*NDIM_NDIM*NDIM;
226
227 UpDummy = 1;
228 for (j=RL-1; j >= 0; j--)
229 UpDummy *= Lat->LevelSizes[j]*Lat->LevelSizes[j]*Lat->LevelSizes[j];
230 /* UpDummy RL -> 0 */
231 Lat->NFields[i][FFTNFRMatUp0] = UpDummy*NDIM_NDIM;
232 Lat->NFields[i][FFTNFRVecUp0] = UpDummy*NDIM;
233 } else {
234 Lat->MaxNoOfnFields[i] = 2;
235 Lat->NFields[i] = (int *)
236 Malloc(sizeof(int)*Lat->MaxNoOfnFields[i],"InitLattice: NFields");
237 Lat->NFields[i][FFTNF1] = 1;
238 Lat->NFields[i][FFTNFUp] = Lat->LevelSizes[i-1]*Lat->LevelSizes[i-1]*Lat->LevelSizes[i-1];
239 }
240 break;
241 }
242 }
243 break;
244 }
245 if (P->Call.out[ValueOut]) {
246 for (i=0; i<Lat->MaxLevel; i++) {
247 fprintf(stderr,"NFields[%i] =",i);
248 for (j=0; j<Lat->MaxNoOfnFields[i]; j++) {
249 fprintf(stderr," %i",Lat->NFields[i][j]);
250 }
251 fprintf(stderr,"\n");
252 }
253 }
254 // calculate mesh points per dimension from ECut constraints for 0th level
255 for (i=0; i< NDIM; i++) { // by vector product creates orthogonal reciprocal base vectors, takes norm, ...
256 VP3(V, &Lat->ReciBasis[NDIM*((i+1)%NDIM)], &Lat->ReciBasis[NDIM*((i+2)%NDIM)]);
257 NormV = sqrt(RNORMSQ3(V));
258 if (fabs(NormV) < MYEPSILON) fprintf(stderr,"InitLattice: NormV = %lg",NormV);
259 for (j=0;j<NDIM;j++) V[j] /= NormV;
260 Lat->ReciBasisO[i] = fabs(RSP3(V,&Lat->ReciBasis[NDIM*i]));
261 Lat->ReciBasisOSQ[i] = Lat->ReciBasisO[i]*Lat->ReciBasisO[i];
262 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]);
263 if (Lat->ReciBasisOSQ[i] < MYEPSILON) fprintf(stderr,"InitLattice: Lat->ReciBasisOSQ[i] = %lg",Lat->ReciBasisOSQ[i]);
264 MaxG[i] = floor(sqrt(2.*Lat->ECut/Lat->ReciBasisOSQ[i]));
265 N[i] = 2*MaxG[i]+2;
266 NFactor = ( i==2 ? 2 : 1)*P->Par.proc[PEGamma]; /* TESTINIT */
267 for (j=1; j < Lat->MaxLevel; j++) NFactor *= Lat->LevelSizes[j];
268 if (AddNFactor == 0) fprintf(stderr,"InitLattice: AddNFactor = %d",AddNFactor);
269 NFactor *= AddNFactor;
270 Lev0->N[i] = NFactor*ceil((double)N[i]/(double)NFactor);
271 Lev1N[i] = Lev0->N[i];
272 Lev0->N[i] *= Lat->LevelSizes[0];
273 }
274 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]);
275 if (P->Files.MeOutMes)
276 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]);
277 Lat->E = &Lat->Energy[Occupied];
278
279 if (P->Call.out[ValueOut]) {
280 fprintf(stderr,"(%i) Lat->Realbasis = \n",P->Par.me);
281 for (i=0; i < NDIM_NDIM; i++) {
282 fprintf(stderr,"%lg ",Lat->RealBasis[i]);
283 if (i%NDIM == NDIM-1) fprintf(stderr,"\n");
284 }
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[MAXSTRINGSIZE];
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(MAXSTRINGSIZE,"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(MAXSTRINGSIZE,"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(MAXSTRINGSIZE,"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 != DoNotParse) {
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.