source: pcp/src/output.c@ 60a9f9

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

CreateDensityOutputGeneral(), CombineOutVisDensity(), OutVisIons(), OutputVisSrcFiles(), OutputVis(), OutputCurrentDensity(), OutputVisAllOrbital(): OutVisSteo goes to *OutVisStep

*OutVisStep now contains the step count on each level

  • Property mode set to 100644
File size: 90.0 KB
Line 
1/** \file output.c
2 * Output of forces and energies, Visuals (density and ions for OpenDX).
3 *
4 * Herein all the functions concerning the output of data are gathered:
5 * Initialization of the FileData structure InitOutVisArray() and the files themselves
6 * InitOutputFiles(),
7 * Saving of a calculated state OutputVisSrcFiles() - 1. Psis OutputSrcPsiDensity(), 2. Ions
8 * OutSrcIons() - or retrieving Psis ReadSrcPsiDensity() and Ions ReadSrcIons(),
9 * Preparation (in case of RiemannTensor use) CalculateOutVisDensityPos(), OutVisPosRTransformPosNFRto0(),
10 * Output of visual data (for OpenDx explorer) OutputVis() - 1. OpenDX files CreateDensityOutputGeneral(),
11 * 2. electronic densitiy data OutVisDensity() (uses MPI sending density coefficients OutputOutVisDensity()
12 * and receiving and writing CombineOutVisDensity()), 3. ion data OutVisIons() -
13 * Closing of files CloseOutputFiles().
14 *
15 * There are some more routines: OutputCurrentDensity() outputs the current density for each magnetic field
16 * direction, OutputVisAllOrbital() outputs all orbitals of a certain minimsation type and
17 * TestReadnWriteSrcDensity() checks whether a certain minimisation group can be written and read again
18 * correctly.
19 *
20 * There are some helpers that open files with certain filenames, making extensive usage of all
21 * the suffixes defined in here: OpenFile(), OpenFileNo(), OpenFileNo2(), OpenFileNoNo() and
22 * OpenFileNoPost().
23 *
24 *
25 Project: ParallelCarParrinello
26 \author Jan Hamaekers, Frederik Heber
27 \date 2000, 2006
28
29 File: output.c
30 $Id: output.c,v 1.51.2.2 2007-04-21 12:55:50 foo Exp $
31*/
32#include<stdlib.h>
33#include<stdio.h>
34#include<string.h>
35#include<math.h>
36//#include<sys/time.h>
37#include <time.h>
38#include<unistd.h>
39#include"data.h"
40#include"density.h"
41#include"errors.h"
42#include"gramsch.h"
43#include"helpers.h"
44#include "init.h"
45#include"myfft.h"
46#include"mymath.h"
47#include"output.h"
48#include"pdbformat.h"
49#include"perturbed.h"
50
51
52/* Konvention: Rueckgabe 0 einer Funktion, bedeutet keinen Fehler (entsprechend exitcode 0) */
53/* Oeffnet Datei P->mainname+"..." mit what*/
54
55/** Opens a file with FileData::mainname+suffix.
56 * Both the path under which the main programme resides and the path to the config file are
57 * tried subsequently.
58 * \param *P Problem at hand
59 * \param **file file pointer array
60 * \param *suffix suffix after mainname
61 * \param *what access parameter for the file: r, w, rw, r+, w+ ...
62 * \param verbose 1 - print status, 0 - don't print anything
63 * \return 0 - could not open file, 1 - file is open
64 */
65int OpenFile(struct Problem *P, FILE** file, const char* suffix, const char* what, int verbose)
66{
67 char* name; /* Zu erzeugender Dateiname */
68 name = (char*)
69 Malloc(strlen(P->Files.default_path) + strlen(P->Files.mainname) + strlen(suffix) + 1,"OpenFile");
70 sprintf(name, "%s%s%s", P->Files.default_path, P->Files.mainname, suffix);
71 *file = fopen(name, what);
72 if (*file == NULL) {
73 fprintf(stderr,"(%i) Normal access failed: name %s, what %s\n", P->Par.me, name, what);
74 /* hier default file ausprobieren, falls nur gelesen werden soll! */
75 if(*what == 'r') {
76 name = (char*)
77 Realloc(name,strlen(P->Files.default_path) + strlen(suffix)+1,"OpenFile");
78 sprintf(name, "%s%s", P->Files.default_path,suffix);
79 *file = fopen(name,what);
80 if (*file != NULL) {
81 if (verbose) fprintf(stderr,"(%i) Default file is open: %s\n",P->Par.me,name);
82 Free(name, "OpenFile: name");
83 return(1);
84 } else {
85 fprintf(stderr,"\n(%i)Error: Cannot open neither normal nor default file for reading: %s\n",P->Par.me,name);
86 Free(name, "OpenFile: name");
87 return(0);
88 }
89 } else {
90 fprintf(stderr,"\n(%i)Error: Cannot open normal file for writing: %s\n",P->Par.me,name);
91 Free(name, "OpenFile: name");
92 return(0);
93 }
94 } else {
95 if(verbose) fprintf(stderr,"(%i) File is open: %s\n",P->Par.me,name);
96 Free(name, "OpenFile: name");
97 return(1);
98 }
99}
100
101/** Opens a file with FileData::mainname+suffix+"."+No (2 digits).
102 * Both the path under which the main programme resides and the path to the config file are
103 * tried subsequently.
104 * \param *P Problem at hand
105 * \param **file file pointer array
106 * \param *suffix suffix after mainname
107 * \param No the number with up to two digits
108 * \param *what access parameter for the file: r, w, rw, r+, w+ ...
109 * \param verbose 1 - print status, 0 - don't print anything
110 * \return 0 - could not open file, 1 - file is open
111 */
112int OpenFileNo2(struct Problem *P, FILE** file, const char* suffix, int No, const char* what, int verbose)
113{
114 char* name; /* Zu erzeugender Dateiname */
115 name = (char*)
116 Malloc(strlen(P->Files.default_path) + strlen(P->Files.mainname) + strlen(suffix) + 4,"OpenFile");
117 sprintf(name, "%s%s%s.%02i", P->Files.default_path, P->Files.mainname, suffix, No);
118 *file = fopen(name, what);
119 if (*file == NULL) {
120 /* falls nur gelesen wird, auch default_path ausprobieren */
121 if (*what == 'r') {
122 name = (char*)
123 Realloc(name,strlen(P->Files.default_path) + strlen(suffix) + 4,"OpenFileNo2");
124 sprintf(name, "%s%s.%02i", P->Files.default_path, suffix, No);
125 *file = fopen(name, what);
126 if (*file != NULL) {
127 if(verbose) fprintf(stderr,"(%i) Default file is open: %s\n", P->Par.me, name);
128 Free(name, "OpenFileNo2: name");
129 return(1);
130 }
131 }
132 fprintf(stderr,"\n(%i)Error: Cannot open file: %s\n", P->Par.me, name);
133 Free(name, "OpenFileNo2: name");
134 return(0);
135 } else {
136 if(verbose) fprintf(stderr,"(%i) File is open: %s\n",P->Par.me, name);
137 Free(name, "OpenFileNo2: name");
138 return(1);
139 }
140}
141
142/* Oeffnet Datei P->Files.mainname+"...".Nr(4stellig) mit what*/
143/** Opens a file with FileData::mainname+suffix+"."+No (4 digits).
144 * Both the path under which the main programme resides and the path to the config file are
145 * tried subsequently.
146 * \param *P Problem at hand
147 * \param **file file pointer array
148 * \param *suffix suffix after mainname
149 * \param No the number with up to four digits
150 * \param *what access parameter for the file: r, w, rw, r+, w+ ...
151 * \param verbose 1 - print status, 0 - don't print anything
152 * \return 0 - could not open file, 1 - file is open
153 */
154int OpenFileNo(struct Problem *P, FILE** file, const char* suffix, int No, const char* what, int verbose)
155{
156 char* name; /* Zu erzeugender Dateiname */
157 name = (char*)
158 Malloc(strlen(P->Files.default_path) + strlen(P->Files.mainname) + strlen(suffix) + 6,"OpenFileNo");
159 sprintf(name, "%s%s%s.%04i", P->Files.default_path, P->Files.mainname, suffix, No);
160 *file = fopen(name, what);
161 if (*file == NULL) {
162 /* falls nur gelesen wird, auch default_path ausprobieren */
163 if (*what == 'r') {
164 name = (char*)
165 Realloc(name,strlen(P->Files.default_path) + strlen(suffix) + 6,"OpenFileNo");
166 sprintf(name, "%s%s.%04i", P->Files.default_path, suffix, No);
167 *file = fopen(name, what);
168 if (*file != NULL) {
169 if(verbose) fprintf(stderr,"(%i) Default file is open: %s\n", P->Par.me, name);
170 Free(name, "OpenFileNo: name");
171 return(1);
172 }
173 }
174 fprintf(stderr,"\n(%i)Error: Cannot open file: %s\n", P->Par.me, name);
175 Free(name, "OpenFileNo: name");
176 return(0);
177 } else {
178 if(verbose) fprintf(stderr,"(%i) File is open: %s\n", P->Par.me, name);
179 Free(name, "OpenFileNo: name");
180 return(1);
181 }
182}
183
184/* die nachfolgende Routine wird von seq und par benutzt!!! */
185/* Oeffnet Datei P->Files.mainname+"...".No.postfix mit what*/
186
187/** Opens a file with FileData::mainname+suffix+"."+No(4 digits)+postfix.
188 * Only the path under which the main programme resides is tried.
189 * \param *P Problem at hand
190 * \param **file file pointer array
191 * \param *suffix suffix after mainname
192 * \param No the number with up to four digits
193 * \param *postfix post-suffix at the end of filename
194 * \param *what access parameter for the file: r, w, rw, r+, w+ ...
195 * \param verbose 1 - print status, 0 - don't print anything
196 * \return 0 - could not open file, 1 - file is open
197 */
198int OpenFileNoPost(struct Problem *P, FILE** file, const char* suffix, int No, const char* postfix, const char* what, int verbose)
199{
200 char* name; /* Zu erzeugender Dateiname */
201 name = (char*)
202 Malloc(strlen(P->Files.default_path) + strlen(P->Files.mainname) + strlen(postfix) + strlen(suffix) + 6,"OpenFileNoPost");
203 sprintf(name, "%s%s%s.%04i%s", P->Files.default_path, P->Files.mainname, suffix, No, postfix);
204 *file = fopen(name, what);
205 if (*file == NULL) {
206 fprintf(stderr,"\n(%i)Error: Cannot open file: %s\n", P->Par.me, name);
207 Free(name, "OpenFileNoPost: name");
208 return(0);
209 } else {
210 if(verbose) fprintf(stderr,"(%i) File is open: %s\n", P->Par.me, name);
211 Free(name, "OpenFileNoPost: name");
212 return(1);
213 }
214}
215
216/** Opens a file with FileData::mainname+suffix+"."+No1(4 digits)+"."+No2(4 digits).
217 * Only the path under which the main programme resides is tried.
218 * \param *P Problem at hand
219 * \param **file file pointer array
220 * \param *suffix suffix after mainname
221 * \param No1 first number with up to four digits
222 * \param No2 second number with up to four digits
223 * \param *what access parameter for the file: r, w, rw, r+, w+ ...
224 * \param verbose 1 - print status, 0 - don't print anything
225 * \return 0 - could not open file, 1 - file is open
226 */
227int OpenFileNoNo(struct Problem *P, FILE** file, const char* suffix, int No1, int No2, const char* what, int verbose)
228{ /* zuerst suffix; No1: lfd, No2: procId */
229 char *name;
230 name = (char*)
231 Malloc(strlen(P->Files.default_path) + strlen(P->Files.mainname) + strlen(suffix) + 5 + 6 + 1,"OpenFileNoNo");
232 sprintf(name,"%s%s%s.%04i.%04i", P->Files.default_path, P->Files.mainname, suffix, No1, No2);
233 *file = fopen(name, what);
234 if(*file == NULL) {
235 fprintf(stderr,"\n(%i)Error: Cannot open file: %s\n", P->Par.me, name);
236 Free(name, "OpenFileNoNo: name");
237 return(0);
238 }
239 if(verbose) fprintf(stderr,"(%i) File is open: %s\n", P->Par.me, name);
240 Free(name, "OpenFileNoNo: name");
241 return(1);
242}
243
244/** Transformation of wave function of Riemann level to zeroth before output as Vis.
245 * \param *RT RiemannTensor structure, contains RiemannTensor::LatticeLevel
246 * \param *source source wave function array
247 * \param *dest destination wave function array
248 * \param NF dimensional factor (NDIM, generally 3)
249 */
250static void OutVisPosRTransformPosNFRto0(const struct RiemannTensor *RT, fftw_real *source, fftw_real *dest, const int NF)
251{
252 struct LatticeLevel *Lev = RT->LevR;
253 int es = Lev->NUp0[2]*NF;
254 unsigned int cpyes = sizeof(fftw_real)*es;
255 int nx=Lev->Plan0.plan->local_nx,ny=Lev->N[1],nz=Lev->N[2],Nx=Lev->NUp0[0],Ny=Lev->NUp0[1];
256 int lx,ly,z,Lx,Ly;
257 for(lx=0; lx < nx; lx++)
258 for(Lx=0; Lx < Nx; Lx++)
259 for(ly=0; ly < ny; ly++)
260 for(Ly=0; Ly < Ny; Ly++)
261 for(z=0; z < nz; z++) {
262 memcpy( &dest[es*(z+nz*(Ly+Ny*(ly+ny*(Lx+Nx*lx))))],
263 &source[es*(Ly+Ny*(Lx+Nx*(z+nz*(ly+ny*lx))))],
264 cpyes);
265 }
266}
267
268
269/** prints Norm of each wave function to screen.
270 * \param *out output destination (eg. stdout)
271 * \param *P Problem at hand
272 */
273void OutputNorm (FILE *out, struct Problem *P) {
274 struct Lattice *Lat = &P->Lat;
275 struct Psis *Psi = &Lat->Psi;
276 struct LatticeLevel *Lev = P->R.LevS;
277 struct OnePsiElement *OnePsi, *LOnePsi;
278 int i;
279
280 for (i=0;i<Psi->MaxPsiOfType+P->Par.Max_me_comm_ST_PsiT;i++) {
281 OnePsi =&Psi->AllPsiStatus[i];
282 if (OnePsi->my_color_comm_ST_Psi == P->Par.my_color_comm_ST_Psi) { // local one
283 LOnePsi = &Psi->LocalPsiStatus[OnePsi->MyLocalNo];
284 fprintf(out,"(%i) Norm of Psi %i: %e\n", P->Par.me, OnePsi->MyGlobalNo, GramSchGetNorm2(P,Lev,Lev->LPsi->LocalPsi[OnePsi->MyLocalNo]));
285 }
286 }
287}
288
289/** Output of current Psis state of source level RunStruct::LevS's LevelPsi::LocalPsi to file \ref suffixsrcpsidat.
290 * In case of process 0, the doc file is written in a parsable way with minimisation type RunStruct#CurrentMin, level number
291 * LatticeLevel#LevelNo, and number of grid nodes LatticeLevel#N.
292 * The two (three) different Psis::SpinType's are discerned and in case of SpinUpDown separate data files opened.
293 *
294 * Then for every global wave function of the desired type each coefficient of the reciprocal grid is copied into
295 * Density::DensityCArray[TempDensity], fouriertransformed, copied into Density::DensityArray[TempDensity].
296 *
297 * As the file output is only handled by process 0, all other coefficient shares are sent within the Psi group to which
298 * the current global wave function belongs to process 0 of the Psi group and from there on to process 0 of all via
299 * MPI.
300 * \param *P Problem at hand
301 * \param type Current minimisation state
302 * \return 0 - file written, 1 - unable to open files for writing
303 * \note This serves as a backup file, when the process is terminated and one would like to restart it at the
304 * current calculation lateron, see ReadSrcPsiDensity(). Note also that it is not necessary to specify the
305 * same number of processes on later restart, any number may be used under the condition that the number of
306 * grid nodes match and that there 2 sharing wave functions in case of SpinUpDown.
307 * \sa ReadSrcPsiDensity() - same for Reading the coefficients, TestReadnWriteSrcDensity() - checks both routines against
308 * each other
309 */
310int OutputSrcPsiDensity(struct Problem *P, enum PsiTypeTag type)
311{
312 int i,j,k, Index, zahl, owner;
313 struct Lattice *Lat = &P->Lat;
314 //struct RunStruct *R = &P->R;
315 struct fft_plan_3d *plan = Lat->plan;
316 struct LatticeLevel *LevS = P->R.LevS;
317 struct Psis *Psi = &Lat->Psi;
318 fftw_complex *work = (fftw_complex *)LevS->Dens->DensityArray[TempDensity];
319 double *destpsiR = (double *)LevS->Dens->DensityArray[TempDensity];
320 fftw_real *srcpsiR = (fftw_real *)LevS->Dens->DensityCArray[TempDensity];
321 fftw_complex *srcpsiC = (fftw_complex *)LevS->Dens->DensityCArray[TempDensity];
322 FILE *SrcPsiData, *SrcPsiDoc;
323 char suffixdat[255], suffixdoc[255];
324 MPI_Status status;
325 struct OnePsiElement *OnePsiA, *LOnePsiA;
326 fftw_complex *LPsiDatA;
327 int Num = 0, colorNo = 0;
328 int Sent = 0, sent = 0;
329
330 SpeedMeasure(P,ReadnWriteTime,StartTimeDo);
331 sprintf(suffixdat, ".%.254s.L%i", P->R.MinimisationName[type], LevS->LevelNo);
332 strncpy (suffixdoc, suffixdat, 255);
333 // for the various spin cases, output the doc-file if it's process 0
334 if (P->Par.me_comm_ST == 0) { // if we are process 0 of SpinDouble or SpinUp&-Down
335 switch (Lat->Psi.PsiST) {
336 case SpinDouble:
337 colorNo = 0;
338 strncat (suffixdat, suffixsrcpsidat, 255-strlen(suffixdat));
339 strncat (suffixdoc, suffixsrcpsidoc, 255-strlen(suffixdoc));
340 Num = Lat->Psi.GlobalNo[PsiMaxNoDouble];
341 break;
342 case SpinUp:
343 colorNo = 0;
344 strncat (suffixdat, suffixsrcpsiupdat, 255-strlen(suffixdat));
345 strncat (suffixdoc, suffixsrcpsiupdoc, 255-strlen(suffixdoc));
346 Num = Lat->Psi.GlobalNo[PsiMaxNoUp];
347 break;
348 case SpinDown:
349 colorNo = 1;
350 strncat (suffixdat, suffixsrcpsidowndat, 255-strlen(suffixdat));
351 strncat (suffixdoc, suffixsrcpsidowndoc, 255-strlen(suffixdoc));
352 Num = Lat->Psi.GlobalNo[PsiMaxNoDown];
353 break;
354 }
355 if (!OpenFileNo(P, &SrcPsiData, suffixdat, colorNo, "wb",P->Call.out[ReadOut])) { // open SourcePsiData as write binary
356 fprintf(stderr,"(%i) Error opening file with suffix %s for writing!\n",P->Par.me, suffixdat);
357 return 1;
358 }
359 if (!OpenFile(P, &SrcPsiDoc, suffixdoc, "w",P->Call.out[ReadOut])) { // open the (text) doc file
360 fprintf(stderr,"(%i) Error opening file with suffix %s for writing!\n",P->Par.me, suffixdoc);
361 return 1;
362 }
363 fprintf(SrcPsiDoc, "Mintype\t%i\n", (int)type);
364 fprintf(SrcPsiDoc, "LevelNo\t%i\n", LevS->LevelNo);
365 fprintf(SrcPsiDoc, "GridNodes\t%i\t%i\t%i\n", LevS->N[0], LevS->N[1], LevS->N[2]);
366 fprintf(SrcPsiDoc, "PsiNo\t%i\t%i\n", Num, P->Lat.Psi.GlobalNo[PsiMaxAdd]);
367 fprintf(SrcPsiDoc, "Epsilon\t%lg\t%lg\n", P->R.RelEpsTotalEnergy, P->R.RelEpsKineticEnergy);
368 for (i = 0; i < P->Par.Max_my_color_comm_ST_Psi; i++) {
369 fprintf(SrcPsiDoc, "\t%i", Lat->Psi.RealAllLocalNo[i]); // print number of local Psis
370 }
371 fprintf(SrcPsiDoc, "\n");
372 fclose(SrcPsiDoc);
373 }
374
375 // send/receive around and write share of coefficient array of each wave function
376 MPI_Allreduce(&sent, &Sent, 1, MPI_INT, MPI_SUM, P->Par.comm_ST); // catch all at the starter line
377 if (P->Call.out[PsiOut]) fprintf(stderr,"(%i) me (%i/%i) \t Psi (%i/%i)\t PsiT (%i/%i)\n", P->Par.me, P->Par.me_comm_ST, P->Par.Max_me_comm_ST, P->Par.me_comm_ST_Psi, P->Par.Max_me_comm_ST_Psi, P->Par.me_comm_ST_PsiT, P->Par.Max_me_comm_ST_PsiT);
378 k = -1; // k is global PsiNo counter for the desired group
379 for (j=0; j < Psi->MaxPsiOfType+P->Par.Max_me_comm_ST_PsiT; j++) { // go through all wave functions (plus the extra one for each process)
380 OnePsiA = &Psi->AllPsiStatus[j]; // grab OnePsiA
381 if (OnePsiA->PsiType == type) { // only take desired minimisation group
382 k++;
383 owner = 0; // notes down in process 0 of each psi group the owner of the next coefficient share
384 //fprintf(stderr,"(%i) ST_Psi: OnePsiA %i\tP->Par.me %i\n", P->Par.me,OnePsiA->my_color_comm_ST_Psi,P->Par.my_color_comm_ST_Psi);
385 if (OnePsiA->my_color_comm_ST_Psi == P->Par.my_color_comm_ST_Psi) { // Belongs to my Psi group?
386 LOnePsiA = &Psi->LocalPsiStatus[OnePsiA->MyLocalNo];
387 LPsiDatA = LevS->LPsi->LocalPsi[OnePsiA->MyLocalNo];
388 SetArrayToDouble0((double *)srcpsiR, LevS->Dens->TotalSize*2); // zero DensityCArray[TempDensity]
389 for (i=0;i<LevS->MaxG;i++) { // for each every unique G grid vector
390 Index = LevS->GArray[i].Index;
391 srcpsiC[Index].re = LPsiDatA[i].re; // copy real value
392 srcpsiC[Index].im = LPsiDatA[i].im; // copy imaginary value
393 }
394 for (i=0; i<LevS->MaxDoubleG; i++) { // also for every doubly appearing G vector (symmetry savings)
395 srcpsiC[LevS->DoubleG[2*i+1]].re = srcpsiC[LevS->DoubleG[2*i]].re;
396 srcpsiC[LevS->DoubleG[2*i+1]].im = -srcpsiC[LevS->DoubleG[2*i]].im;
397 }
398 // do an fft transform from complex to real on these srcPsiR
399 fft_3d_complex_to_real(plan, LevS->LevelNo, FFTNF1, srcpsiC, work);
400
401 for (i=0; i < LevS->Dens->LocalSizeR; i++)
402 destpsiR[i] = (double)srcpsiR[i];
403 } else
404 LOnePsiA = NULL;
405
406 if (P->Par.me_comm_ST == 0) { // if we are process 0 of all, only we may access the file
407 for (i=0; i<P->Par.Max_me_comm_ST_Psi;i++) { // for each share of the coefficient in the PsiGroup
408 if (LOnePsiA == NULL) { // if it's not local, receive coefficients from correct PsiGroup (process 0 within that group)
409 if (MPI_Recv( destpsiR, LevS->Dens->LocalSizeR, MPI_DOUBLE, OnePsiA->my_color_comm_ST_Psi, OutputSrcPsiTag, P->Par.comm_ST_PsiT, &status ) != MPI_SUCCESS)
410 Error(SomeError, "OutputSrcPsiDensity: MPI_Recv of loaded coefficients failed!");
411 MPI_Get_count(&status, MPI_DOUBLE, &zahl);
412 if (zahl != LevS->Dens->LocalSizeR) // check number of elements
413 fprintf(stderr,"(%i)OutputSrcPsiDensity: MPI_Recv of loaded coefficients of GlobalNo %i, owner %i failed: Too few coefficients - %i instead of %i!\n", P->Par.me, k, i, zahl, LevS->Dens->LocalSizeR);
414 //else
415 //fprintf(stderr,"(%i)OutputSrcPsiDensity: MPI_Recv of loaded coefficients of GlobalNo %i, owner %i succeeded!\n", P->Par.me, k, i);
416 } else { // if it's local ...
417 if (i != 0) { // but share of array not for us, receive from owner process within Psi group
418 if (MPI_Recv( destpsiR, LevS->Dens->LocalSizeR, MPI_DOUBLE, i, OutputSrcPsiTag, P->Par.comm_ST_Psi, &status ) != MPI_SUCCESS)
419 Error(SomeError, "OutputSrcPsiDensity: MPI_Recv of loaded coefficients failed!");
420 MPI_Get_count(&status, MPI_DOUBLE, &zahl);
421 if (zahl != LevS->Dens->LocalSizeR) // check number of elements
422 fprintf(stderr,"(%i)OutputSrcPsiDensity: MPI_Recv of loaded coefficients of GlobalNo %i, owner %i failed: Too few coefficients - %i instead of %i!\n", P->Par.me, k, i, zahl, LevS->Dens->LocalSizeR);
423 //else
424 //fprintf(stderr,"(%i)OutputSrcPsiDensity: MPI_Recv of loaded coefficients of GlobalNo %i, owner %i succeeded!\n", P->Par.me, k, i);
425 } // otherwise it was our share already
426 }
427 // store the final share on disc
428 if ((zahl = fwrite(destpsiR, sizeof(double), (size_t)(LevS->Dens->LocalSizeR), SrcPsiData)) != (size_t)(LevS->Dens->LocalSizeR)) {
429 fclose(SrcPsiData);
430 //if (P->Par.me == 0)
431 fprintf(stderr, "(%i)OutputSrcPsiDensity: only %i bytes written instead of expected %i\n", P->Par.me, zahl, LevS->Dens->LocalSizeR);
432 Error(SomeError,"OutputSrcPsiDensity: fwrite Error");
433 }
434 }
435 } else { // if we are not process 0 of all, we are but a deliverer
436 if (LOnePsiA != NULL) { // send if it's local
437 if (P->Par.me_comm_ST_Psi == 0) { // if we are process 0 in the group, send final share to our process 0
438 for (owner = 0; owner < P->Par.Max_me_comm_ST_Psi; owner++) { // for all processes of our Psi group
439 if (owner != 0) { // still not our share of coefficients, receive from owner in our Psi group (increasing owner)
440 if (MPI_Recv( destpsiR, LevS->Dens->LocalSizeR, MPI_DOUBLE, owner, OutputSrcPsiTag, P->Par.comm_ST_Psi, &status ) != MPI_SUCCESS)
441 Error(SomeError, "OutputSrcPsiDensity: MPI_Recv of loaded coefficients failed!");
442 MPI_Get_count(&status, MPI_DOUBLE, &zahl);
443 if (zahl != LevS->Dens->LocalSizeR) // check number of elements
444 fprintf(stderr,"(%i)OutputSrcPsiDensity: MPI_Recv of loaded coefficients of GlobalNo %i, owner %i failed: Too few coefficients - %i instead of %i!\n", P->Par.me, k, owner, zahl, LevS->Dens->LocalSizeR);
445 //else
446 //fprintf(stderr,"(%i)OutputSrcPsiDensity: MPI_Recv of loaded coefficients of GlobalNo %i, owner %i succeeded!\n", P->Par.me, k, owner);
447 } else sent++; // only count sent if it was our share
448
449 if (MPI_Send(destpsiR, LevS->Dens->LocalSizeR, MPI_DOUBLE, 0, OutputSrcPsiTag, P->Par.comm_ST_PsiT) != MPI_SUCCESS)
450 Error(SomeError, "OutputSrcPsiDensity: MPI_Send of loaded coefficients failed!");
451 //else
452 //fprintf(stderr,"(%i)OutputSrcPsiDensity: MPI_Send to process %i in PsiT group of loaded coefficients GlobalNo %i succeeded!\n", P->Par.me, 0, k);
453 }
454 } else {
455 sent++;
456 if (MPI_Send(destpsiR, LevS->Dens->LocalSizeR, MPI_DOUBLE, 0, OutputSrcPsiTag, P->Par.comm_ST_Psi) != MPI_SUCCESS)
457 Error(SomeError, "OutputSrcPsiDensity: MPI_Send of loaded coefficients failed!");
458 //else
459 //fprintf(stderr,"(%i)OutputSrcPsiDensity: MPI_Send to process %i in Psi group of loaded coefficients GlobalNo %i succeeded!\n", P->Par.me, 0, k);
460 }
461 }
462 // otherwise we don't have anything to do with this
463 }
464 }
465 }
466 MPI_Allreduce(&sent, &Sent, 1, MPI_INT, MPI_SUM, P->Par.comm_ST); // catch all again at finish
467 if (P->Call.out[PsiOut]) fprintf(stderr,"(%i) Out of %i shares %i had to be sent in total, %i from this process alone.\n", P->Par.me, P->Par.Max_me_comm_ST_Psi*Psi->NoOfPsis, Sent, sent);
468 if (!(P->Par.me_comm_ST))
469 fclose(SrcPsiData);
470 SpeedMeasure(P,ReadnWriteTime,StopTimeDo);
471
472 return 0;
473}
474
475/** Tests whether writing and successant reading of coefficient array is working correctly.
476 * The local wave function array is written to a disc (\sa OutputSrcPsiDensity()), the by \a wavenr
477 * specified coefficient array copied to OldPsiDat and afterwards read again via ReadSrcPsiDensity().
478 * Comparison per process of each local coefficient shows incorrect read or writes.
479 * \param *P Problem at hand
480 * \param type minimisation type array to test for read and write
481 * \return 1 - successful, 0 - test failed
482 */
483int TestReadnWriteSrcDensity(struct Problem *P, enum PsiTypeTag type)
484{
485 struct RunStruct *R = &P->R;
486 struct LatticeLevel *LevS = R->LevS;
487 struct Lattice *Lat = &P->Lat;
488 struct Psis *Psi = &Lat->Psi;
489 int i,k;
490 fftw_complex *destpsiC, *srcpsiC;
491
492 //fprintf(stderr,"(%i)TestReadnWriteSrcDensity\n",P->Par.me);
493 // write whole array of type to disc
494 OutputSrcPsiDensity(P,type);
495 debug(P,"array written");
496
497 // copy specified array to OldPsiDat
498 for (k=0; k < Lat->Psi.LocalNo; k++) // for every local wave function of type, copy coefficients
499 if (Psi->LocalPsiStatus[k].PsiType == type) { // ... yet only for given type
500 srcpsiC = LevS->LPsi->LocalPsi[k];
501 destpsiC = LevS->LPsi->OldLocalPsi[k - Psi->TypeStartIndex[type]];
502 for (i=0;i<LevS->MaxG;i++) { // for each every unique G grid vector
503 destpsiC[i].re = srcpsiC[i].re; // copy real value
504 destpsiC[i].im = srcpsiC[i].im; // copy imaginary value
505 }
506 }
507 debug(P,"array copied");
508
509 // read whole array again
510 if (!ReadSrcPsiDensity(P,type,0,R->LevSNo))
511 return 0;
512 debug(P,"array read");
513
514 // compare with copied array
515 for (k=0; k < Lat->Psi.LocalNo; k++) // for every local wave function of type, compare coefficients
516 if (Psi->LocalPsiStatus[k].PsiType == type) { // ... yet only for given type
517 srcpsiC = LevS->LPsi->LocalPsi[k];
518 destpsiC = LevS->LPsi->OldLocalPsi[k - Psi->TypeStartIndex[type]];
519 for (i=0;i<LevS->MaxG;i++) // for each every unique G grid vector
520 if ((fabs(destpsiC[i].re - srcpsiC[i].re) >= MYEPSILON) ||(fabs(destpsiC[i].im - srcpsiC[i].im) >= MYEPSILON)) {
521 fprintf(stderr,"(%i)TestReadnWriteSrcDensity: First difference at index %i - %lg+i%lg against loaded %lg+i%lg\n",P->Par.me, i, srcpsiC[i].re, srcpsiC[i].im,destpsiC[i].re,destpsiC[i].im);
522 return 0;
523 }
524 }
525 debug(P,"array compared");
526 fprintf(stderr,"(%i)TestReadnWriteSrcDensity: OK!\n",P->Par.me);
527 return 1;
528}
529
530
531/** Read Psis state from an earlier run.
532 * The doc file is opened, mesh sizes LatticeLevel::N[], global number of Psis read and checked against the known
533 * values in the inital level RunStruct::LevS.
534 * Note, only process 0 handles the files, all read coefficients are transfered to their respective owners via MPI
535 * afterwards. Here, process 0 of a certain Psi group is used as a transferer for the coefficients of the other processes
536 * in this Psi group. He receives them all from process 0 and sends them onward accordingly. The complete set of
537 * coefficients on the real grid for one wave function in the Psi group are transformed into complex wave function
538 * coefficients by the usual fft procedure (see ChangeToLevUp()).
539 *
540 * \param *P Problem at hand
541 * \param type minimisation type to read
542 * \param test whether to just test for presence of files (1) or really read them (0)
543 * \param LevSNo level number to be read
544 * \note This is the counterpart to OutputSrcPsiDensity().
545 * \return 1 - success, 0 - failure
546 * \note It is not necessary to specify the same number of processes on later restart, any number may be used under
547 * the condition that the number of grid nodes match and that there at least 2 processes sharing wave functions
548 * in case of SpinUpDown.
549 * \sa OutputSrcPsiDensity() - same for writing the coefficients, TestReadnWriteSrcDensity() - checks both routines against
550 * each other
551 */
552int ReadSrcPsiDensity(struct Problem *P, enum PsiTypeTag type, int test, int LevSNo)
553{
554 int i, j, k, Index, owner;
555 struct RunStruct *R = &P->R;
556 struct Lattice *Lat = &P->Lat;
557 struct fft_plan_3d *plan = Lat->plan;
558 struct LatticeLevel *LevS = R->LevS; // keep open for LevelNo read from file
559 struct Psis *Psi = &Lat->Psi;
560 //struct Energy *E = Lat->E;
561 fftw_complex *work;
562 double *destpsiR;
563 fftw_real *srcpsiR;
564 fftw_complex *srcpsiC;
565 FILE *SrcPsiData, *SrcPsiDoc;
566 int N[NDIM], GlobalNo[2];
567 int LevelNo, readnr=0;
568 int zahl, signal = test ? 1 : 2; // 0 - ok, 1 - test failed, 2 - throw Error
569 char suffixdat[255], suffixdoc[255];
570 int read_type, Num = 0, colorNo = 0;
571 char spin[20];
572 double Eps[2];
573 MPI_Status status;
574 struct OnePsiElement *OnePsiA, *LOnePsiA;
575 int Recv=0, recv=0;
576
577 SpeedMeasure(P,ReadnWriteTime,StartTimeDo);
578 sprintf(suffixdat, ".%.254s.L%i", P->R.MinimisationName[type], LevSNo);
579 strncpy (suffixdoc, suffixdat, 255);
580 // Depending on Psis::SpinType the source psi doc file is opened and header written
581 switch (Lat->Psi.PsiST) {
582 case SpinDouble:
583 colorNo = 0;
584 strncat (suffixdat, suffixsrcpsidat, 255-strlen(suffixdat));
585 strncat (suffixdoc, suffixsrcpsidoc, 255-strlen(suffixdoc));
586 strncpy (spin, "GlobalNoSpinDouble", 20);
587 Num = Lat->Psi.GlobalNo[PsiMaxNoDouble];
588 break;
589 case SpinUp:
590 colorNo = 0;
591 strncat (suffixdat, suffixsrcpsiupdat, 255-strlen(suffixdat));
592 strncat (suffixdoc, suffixsrcpsiupdoc, 255-strlen(suffixdoc));
593 strncpy (spin, "GlobalNoSpinUp", 20);
594 Num = Lat->Psi.GlobalNo[PsiMaxNoUp];
595 break;
596 case SpinDown:
597 colorNo = 1;
598 strncat (suffixdat, suffixsrcpsidowndat, 255-strlen(suffixdat));
599 strncat (suffixdoc, suffixsrcpsidowndoc, 255-strlen(suffixdoc));
600 strncpy (spin, "GlobalNoSpinDown", 20);
601 Num = Lat->Psi.GlobalNo[PsiMaxNoDown];
602 break;
603 }
604 // open doc file ...
605 if (!(P->Par.me_comm_ST)) {
606 if (!OpenFile(P, &SrcPsiDoc, suffixdoc, "r", test ? 0 : P->Call.out[ReadOut])) { // open doc file
607 debug(P,"ReadSrcPsiDensity: doc file pointer NULL\n");
608 if (test) {
609 if (MPI_Bcast(&signal,1,MPI_INT,0,P->Par.comm_ST) != MPI_SUCCESS)
610 Error(SomeError,"ReadSrcPsiDensity: Bcast of signal failed\n");
611 return 0;
612 }
613 if (MPI_Bcast(&signal,1,MPI_INT,0,P->Par.comm_ST) != MPI_SUCCESS)
614 Error(SomeError,"ReadSrcPsiDensity: Bcast of signal failed\n");
615 Error(SomeError,"ReadSrcPsiDensity: cannot open doc file!");
616 }
617 // ... and parse critical ...
618 readnr += ParseForParameter(0,SrcPsiDoc,"Mintype",0,1,1,int_type,(int *)&read_type, 1, test ? optional : critical);
619 readnr += ParseForParameter(0,SrcPsiDoc,"LevelNo",0,1,1,int_type,&LevelNo,1, test ? optional : critical);
620 readnr += 3*ParseForParameter(0,SrcPsiDoc,"GridNodes",0,3,1,row_int,&N[0], 1, test ? optional : critical);
621 readnr += 2*ParseForParameter(0,SrcPsiDoc,"PsiNo",0,2,1,row_int,&GlobalNo[0], 1, test ? optional : critical);
622 // and optional items ...
623 if (ParseForParameter(0,SrcPsiDoc,"Epsilon",0,2,1,row_double,&Eps[0],1,optional))
624 if ((P->Call.ReadSrcFiles == 1) && ((Eps[1] < R->RelEpsKineticEnergy) || (Eps[0] < R->RelEpsTotalEnergy))) {
625 //fprintf(stderr,"(%i) Eps %lg %lg\tRelEps %lg %lg\n", P->Par.me, Eps[0], Eps[1], R->RelEpsTotalEnergy, R->RelEpsKineticEnergy);
626 fprintf(stderr,"(%i) NOTE: Doing minimization after source file parsing due to smaller specified epsilon stop conditions.\n",P->Par.me);
627 P->Call.ReadSrcFiles = 2; // do minimisation even after loading
628 }
629 if (readnr != 7) { // check number of items read
630 debug(P, "ReadSrcPsiDensity: too few doc items in file\n");
631 fclose(SrcPsiDoc);
632 if (test) {
633 if (MPI_Bcast(&signal,1,MPI_INT,0,P->Par.comm_ST) != MPI_SUCCESS)
634 Error(SomeError,"ReadSrcPsiDensity: Bcast of signal failed\n");
635 return 0;
636 }
637 fprintf(stderr,"ReadSrcPsiDensity: Only %i items read!\n",readnr);
638 if (MPI_Bcast(&signal,1,MPI_INT,0,P->Par.comm_ST) != MPI_SUCCESS)
639 Error(SomeError,"ReadSrcPsiDensity: Bcast of signal failed\n");
640 Error(SomeError, "ReadSrcPsiDensity: read error");
641 }
642 // check if levels match
643 if (LevSNo != LevelNo) {
644 debug(P,"ReadSrcPsiDensity: mismatching levels\n");
645 fclose(SrcPsiDoc);
646 if (test) {
647 if (MPI_Bcast(&signal,1,MPI_INT,0,P->Par.comm_ST) != MPI_SUCCESS)
648 Error(SomeError,"ReadSrcPsiDensity: Bcast of signal failed\n");
649 return 0;
650 }
651 if (MPI_Bcast(&signal,1,MPI_INT,0,P->Par.comm_ST) != MPI_SUCCESS)
652 Error(SomeError,"ReadSrcPsiDensity: Bcast of signal failed\n");
653 Error(SomeError,"ReadSrcPsiDensity: Mismatching levels!");
654 } else {
655 LevS = &P->Lat.Lev[LevelNo];
656 }
657
658 // check if systems in memory and file match
659 if ((read_type != R->CurrentMin) || (N[0] != LevS->N[0]) || (N[1] != LevS->N[1]) || (N[2] != LevS->N[2]) || (GlobalNo[0] != Num) || (GlobalNo[1] != Lat->Psi.GlobalNo[PsiMaxAdd])) { // check read system
660 debug(P,"ReadSrcPsiDensity: srcpsi file does not fit to system\n");
661 fclose(SrcPsiDoc);
662 if (test) {
663 fprintf(stderr,"(%i) Min\t N(x,y,z)\tPsiNo+AddNo\n file: %s\t %i %i %i\t %i + %i\nsystem: %s\t %d %d %d\t %d + %d\n",P->Par.me, R->MinimisationName[read_type], N[0], N[1], N[2], GlobalNo[0], GlobalNo[1], R->MinimisationName[R->CurrentMin], LevS->N[0] , LevS->N[1], LevS->N[2], Lat->Psi.GlobalNo[PsiMaxNoDouble], Lat->Psi.GlobalNo[PsiMaxAdd]);
664 if (MPI_Bcast(&signal,1,MPI_INT,0,P->Par.comm_ST) != MPI_SUCCESS)
665 Error(SomeError,"ReadSrcPsiDensity: Bcast of signal failed\n");
666 return 0;
667 }
668 fprintf(stderr,"ReadSrcPsiDensity: Type %i != CurrentMin %i || N[0] %i != %i || N[1] %i != %i || N[2] %i != %i || %s %i + %i != %i + %i\n", read_type, R->CurrentMin, N[0], LevS->N[0], N[1], LevS->N[1], N[2], LevS->N[2], spin, GlobalNo[0], GlobalNo[1], Num, P->Lat.Psi.GlobalNo[PsiMaxAdd]);
669 if (MPI_Bcast(&signal,1,MPI_INT,0,P->Par.comm_ST) != MPI_SUCCESS)
670 Error(SomeError,"ReadSrcPsiDensity: Bcast of signal failed\n");
671 Error(SomeError,"ReadSrcPsiDensity: srcpsi file does not fit to system");
672 }
673 signal = 0; // everything went alright, signal ok
674 if (MPI_Bcast(&signal,1,MPI_INT,0,P->Par.comm_ST) != MPI_SUCCESS)
675 Error(SomeError,"ReadSrcPsiDensity: Bcast of signal failed\n");
676 } else { // others wait for signal from root process
677 if (MPI_Bcast(&signal,1,MPI_INT,0,P->Par.comm_ST) != MPI_SUCCESS)
678 Error(SomeError,"ReadSrcPsiDensity: Bcast of signal failed\n");
679 if (signal == 1)
680 return 0;
681 else if (signal == 2)
682 Error(SomeError, "ReadSrcPsiDensity: Something went utterly wrong, see root process");
683 else if (P->Call.out[PsiOut])
684 fprintf(stderr,"(%i) ReadSrcPsiDensity: Everything went alright so far\n", P->Par.me);
685 }
686 if (MPI_Bcast(&LevelNo,1,MPI_INT,0,P->Par.comm_ST) != MPI_SUCCESS)
687 Error(SomeError,"ReadSrcPsiDensity: Bcast of LevelNo failed\n");
688 LevS = &P->Lat.Lev[LevelNo];
689 //if (!test) fprintf(stderr,"(%i) LevelSNo %i\n", P->Par.me, LevS->LevelNo);
690
691 if (!test) {
692 // set some pointers for work to follow
693 work = (fftw_complex *)LevS->Dens->DensityArray[TempDensity];
694 destpsiR = (double *)LevS->Dens->DensityArray[TempDensity];
695 srcpsiR = (fftw_real *)LevS->Dens->DensityCArray[TempDensity];
696 srcpsiC = (fftw_complex *)LevS->Dens->DensityCArray[TempDensity];
697
698 // read share of coefficient array for each wave function and send/receive around
699 owner = 0;
700 MPI_Allreduce (&recv, &Recv, 1, MPI_INT, MPI_SUM, P->Par.comm_ST);
701 //fprintf(stderr,"(%i) me (%i/%i) \t Psi (%i/%i)\t PsiT (%i/%i)\n", P->Par.me, P->Par.me_comm_ST, P->Par.Max_me_comm_ST, P->Par.me_comm_ST_Psi, P->Par.Max_me_comm_ST_Psi, P->Par.me_comm_ST_PsiT, P->Par.Max_me_comm_ST_PsiT);
702 k = -1; // k is global PsiNo counter for the desired group
703 for (j=0; j < Psi->MaxPsiOfType+P->Par.Max_me_comm_ST_PsiT; j++) { // go through all wave functions (plus the extra one for each process)
704 OnePsiA = &Psi->AllPsiStatus[j]; // grab OnePsiA
705 if (OnePsiA->PsiType == type) { // only take desired minimisation group
706 k++;
707 //fprintf(stderr,"(%i) ST_Psi: OnePsiA %i\tP->Par.my_color_comm_ST_Psi %i\n", P->Par.me,OnePsiA->my_color_comm_ST_Psi,P->Par.my_color_comm_ST_Psi);
708 if (OnePsiA->my_color_comm_ST_Psi == P->Par.my_color_comm_ST_Psi) // Belongs to my Psi group?
709 LOnePsiA = &Psi->LocalPsiStatus[OnePsiA->MyLocalNo];
710 else
711 LOnePsiA = NULL;
712
713 if (P->Par.me_comm_ST == 0) { // if we are process 0 of all, we may access file
714 if (!OpenFileNo(P, &SrcPsiData, suffixdat, colorNo, "r", test ? 0 : P->Call.out[ReadOut])) {
715 Error(SomeError,"ReadSrcPsiDensity: cannot open data file");
716 }
717 for (i=P->Par.Max_me_comm_ST_Psi-1; i>=0;i--) { // load coefficients
718 fseek( SrcPsiData, (long)((k*N[0]*N[1]*N[2]+i*((long)LevS->Dens->LocalSizeR))*sizeof(double)), SEEK_SET); // seek to beginning of this process' coefficients
719 // readin
720 if ((zahl = fread(destpsiR, sizeof(double), (size_t)(LevS->Dens->LocalSizeR), SrcPsiData)) != (size_t)LevS->Dens->LocalSizeR) {
721 fclose(SrcPsiData);
722 fprintf(stderr, "(%i)ReadSrcPsiDensity: only %i bytes read instead of expected %i\n", P->Par.me, zahl, LevS->Dens->LocalSizeR);
723 Error(SomeError,"ReadSrcPsiDensity: fread Error");
724 }
725 if (LOnePsiA == NULL) { // if it's not local, send away coefficients to correct PsiGroup (process 0 within that group)
726 if (MPI_Send(destpsiR, LevS->Dens->LocalSizeR, MPI_DOUBLE, OnePsiA->my_color_comm_ST_Psi, ReadSrcPsiTag, P->Par.comm_ST_PsiT) != MPI_SUCCESS)
727 Error(SomeError, "ReadSrcPsiDensity: MPI_Send of loaded coefficients failed!");
728 //else
729 //fprintf(stderr,"(%i)ReadSrcPsiDensity: MPI_Send to process %i of loaded coefficients GlobalNo %i, owner %i succeeded!\n", P->Par.me, OnePsiA->my_color_comm_ST_Psi, k, i);
730 } else { // if it's local ...
731 if (i != 0) { // but share of array not for us, send to owner process within Psi group
732 if (MPI_Send(destpsiR, LevS->Dens->LocalSizeR, MPI_DOUBLE, i, ReadSrcPsiTag, P->Par.comm_ST_Psi) != MPI_SUCCESS)
733 Error(SomeError, "ReadSrcPsiDensity: MPI_Send within Psi group of loaded coefficients failed!");
734 //else
735 //fprintf(stderr,"(%i)ReadSrcPsiDensity: MPI_Send to process %i within Psi group of loaded coefficients GlobalNo %i succeeded!\n", P->Par.me, i, k);
736 } // otherwise it was our share already
737 }
738 }
739 } else {
740 if (LOnePsiA != NULL) { // receive
741 if (P->Par.me_comm_ST_Psi == 0) { // if we are process 0 in the group, receive share from process 0 of all
742 for (owner = P->Par.Max_me_comm_ST_Psi -1; owner >=0; owner--) { // for all processes of our Psi group
743 if (MPI_Recv(destpsiR, LevS->Dens->LocalSizeR, MPI_DOUBLE, 0, ReadSrcPsiTag, P->Par.comm_ST_PsiT, &status) != MPI_SUCCESS)
744 Error(SomeError, "ReadSrcPsiDensity: MPI_Recv of loaded coefficients failed!");
745 MPI_Get_count(&status, MPI_DOUBLE, &zahl);
746 if (zahl != LevS->Dens->LocalSizeR) // check number of elements
747 fprintf(stderr,"(%i)ReadSrcPsiDensity: MPI_Recv from process 0 of loaded coefficients of GlobalNo %i, owner %i failed: Too few coefficients - %i instead of %i!\n", P->Par.me, k, owner, zahl, LevS->Dens->LocalSizeR);
748 //else
749 //fprintf(stderr,"(%i)ReadSrcPsiDensity: MPI_Recv from process 0 of loaded coefficients of GlobalNo %i, owner %i succeeded!\n", P->Par.me, k, owner);
750
751 if (owner != 0) { // not our share of coefficients, send to owner in our Psi group
752 if (MPI_Send(destpsiR, LevS->Dens->LocalSizeR, MPI_DOUBLE, owner, ReadSrcPsiTag, P->Par.comm_ST_Psi) != MPI_SUCCESS)
753 Error(SomeError, "ReadSrcPsiDensity: MPI_Send within Psi group of loaded coefficients failed!");
754 //else
755 //fprintf(stderr,"(%i)ReadSrcPsiDensity: MPI_Send to process %i within Psi group of loaded coefficients GlobalNo %i succeeded!\n", P->Par.me, owner, k);
756 } else recv++;
757 }
758 // otherwise it's our share!
759 } else { // our share within Psi Group not belonging to process 0 of all
760 recv++;
761 if (MPI_Recv(destpsiR, LevS->Dens->LocalSizeR, MPI_DOUBLE, 0, ReadSrcPsiTag, P->Par.comm_ST_Psi, &status) != MPI_SUCCESS)
762 Error(SomeError, "ReadSrcPsiDensity: MPI_Recv of loaded coefficients failed!");
763 MPI_Get_count(&status, MPI_DOUBLE, &zahl);
764 if (zahl != LevS->Dens->LocalSizeR) // check number of elements
765 fprintf(stderr,"(%i)ReadSrcPsiDensity: MPI_Recv of loaded coefficients of GlobalNo %i, owner %i failed: Too few coefficients - %i instead of %i!\n", P->Par.me, k, P->Par.me_comm_ST_Psi, zahl, LevS->Dens->LocalSizeR);
766 //else
767 //fprintf(stderr,"(%i)ReadSrcPsiDensity: MPI_Recv of loaded coefficients of GlobalNo %i, owner %i succeeded!\n", P->Par.me, k, P->Par.me_comm_ST_Psi);
768 }
769 }
770 // otherwise we don't have anything to do with this
771 }
772
773 if (LOnePsiA != NULL) {
774 SetArrayToDouble0((double *)srcpsiR, LevS->Dens->TotalSize*2);
775 for (i=0; i < LevS->Dens->LocalSizeR; i++) // copy dest to src
776 srcpsiR[i] = (fftw_real)destpsiR[i];
777
778 fft_3d_real_to_complex(plan, LevS->LevelNo, FFTNF1, srcpsiC, work); // fft transform
779 //if (P->Call.out[PsiOut])
780 //fprintf(stderr,"(%i) LevSNo %i\t LocalPsi %p\n", P->Par.me, LevS->LevelNo, LevS->LPsi->LocalPsi[LOnePsiA->MyLocalNo]);
781 for (i=0;i<LevS->MaxG;i++) { // and copy into wave functions coefficients
782 Index = LevS->GArray[i].Index;
783 LevS->LPsi->LocalPsi[LOnePsiA->MyLocalNo][i].re = srcpsiC[Index].re/LevS->MaxN;
784 LevS->LPsi->LocalPsi[LOnePsiA->MyLocalNo][i].im = srcpsiC[Index].im/LevS->MaxN;
785 }
786 }
787 if ((P->Par.me_comm_ST == 0) && (SrcPsiData != NULL)) fclose(SrcPsiData);
788 }
789 }
790 MPI_Allreduce (&recv, &Recv, 1, MPI_INT, MPI_SUM, P->Par.comm_ST);
791 if (P->Call.out[PsiOut]) fprintf(stderr,"(%i) Out of %i shares %i had to be received in total, %i from this process alone.\n", P->Par.me, P->Par.Max_me_comm_ST_Psi*Psi->NoOfPsis, Recv, recv);
792 SpeedMeasure(P,ReadnWriteTime,StopTimeDo);
793 }
794 return 1; // everything went well till the end
795}
796
797/** Creates the density \ref suffixdensdoc and \ref suffixdensdx files for OpenDx.
798 * Opens \ref suffixdensdoc, fills (pos&data file name, byte order, max mesh points, matrix alignment, steps)
799 * and closes it.
800 * Opens \ref suffixdensdx, then for every FileData::*OutVisStep a describing structure for DX is written and
801 * the file closed again.
802 * \param *P Problem at hand
803 * \param me my process number in communicator Psi (0 - do nothing, else - do)
804 */
805static void CreateDensityOutputGeneral(struct Problem *P, const int me)
806{
807 FILE *DensityDoc, *DensityDx;
808 char *posname, *datname, *suffix;
809 struct LatticeLevel *Lev = &P->Lat.Lev[STANDARTLEVEL];
810 unsigned int i, MaxPoints, N[NDIM];
811 double *RB = P->Lat.RealBasis;
812 if (me) return;
813 N[0] = Lev->N[0]*Lev->NUp[0];
814 N[1] = Lev->N[1]*Lev->NUp[1];
815 N[2] = Lev->N[2]*Lev->NUp[2];
816 MaxPoints = (N[0]+1)*(N[1]+1)*(N[2]+1);
817 posname = (char*)
818 Malloc(strlen(P->Files.mainname) + strlen(suffixdenspos) + 3 + 1,"CreateDensityOutputGeneral: posname");
819 sprintf(posname, "%s.L%i%s", P->Files.mainname, Lev->LevelNo, suffixdenspos);
820 datname = (char*)
821 Malloc(strlen(P->Files.mainname) + strlen(suffixdensdat) + 3 + 1,"CreateDensityOutputGeneral: datname");
822 sprintf(datname, "%s.L%i%s", P->Files.mainname, Lev->LevelNo, suffixdensdat);
823 // write doc file
824 suffix = (char *)
825 Malloc(strlen(suffixdensdoc) + 3 + 1,"CreateDensityOutputGeneral: suffix");
826 sprintf(suffix, ".L%i%s", Lev->LevelNo, suffixdensdoc);
827 OpenFile(P, &DensityDoc, suffix, "w",P->Call.out[ReadOut]);
828 fprintf(DensityDoc,"DensityPositions file = %s.####\n", posname);
829 fprintf(DensityDoc,"DensityData file = %s.####\n", datname);
830 fprintf(DensityDoc,"format = ieee float (Bytes %lu) %s\n",(unsigned long) sizeof(float),msb);
831 fprintf(DensityDoc,"points = %i\n", MaxPoints);
832 fprintf(DensityDoc,"majority = row\n");
833 fprintf(DensityDoc,"TimeSeries = %i\n",P->Files.OutVisStep[Lev->LevelNo]+1);
834 fclose(DensityDoc);
835 Free(suffix, "CreateDensityOutputGeneral: suffix");
836 // write DX file
837 suffix = (char *)
838 Malloc(strlen(suffixdensdx) + 3 + 1,"CreateDensityOutputGeneral: suffix");
839 sprintf(suffix, ".L%i%s", Lev->LevelNo, suffixdensdx);
840 OpenFile(P, &DensityDx, suffix, "w",P->Call.out[ReadOut]);
841 for (i=0; i < (unsigned int)P->Files.OutVisStep[Lev->LevelNo]+1; i++) { // for every OutVis step
842 if (i==0) {
843 fprintf(DensityDx,"object \"gridcon\" class gridconnections counts %i %i %i\n\n",(N[0]+1),(N[1]+1),(N[2]+1));
844 if (P->Files.OutputPosType[i] != active)
845 fprintf(DensityDx, "object \"posdens\" class gridpositions counts %i %i %i\norigin 0.0 0.0 0.0\ndelta %f %f %f\ndelta %f %f %f\ndelta %f %f %f\n\n",
846 (N[0]+1),(N[1]+1),(N[2]+1),
847 (float)(RB[0]/N[0]),(float)(RB[1]/N[0]),(float)RB[2]/N[0],
848 (float)(RB[3]/N[1]),(float)(RB[4]/N[1]),(float)RB[5]/N[1],
849 (float)(RB[6]/N[2]),(float)(RB[7]/N[2]),(float)RB[8]/N[2]);
850 }
851 if (P->Files.OutputPosType[i] == active) {
852 fprintf(DensityDx,
853 "object \"pos.%04u\" class array type float rank 1 shape 3 items %i %s binary\n",i,MaxPoints,msb);
854 fprintf(DensityDx,"data file %s.%04u,0\n",posname,i);
855 }
856 fprintf(DensityDx,"attribute \"dep\" string \"positions\"\n");
857 fprintf(DensityDx,"# %lu - %lu Bytes\n\n",MaxPoints*i*(unsigned long)sizeof(float)*NDIM,MaxPoints*(i+1)*(unsigned long)sizeof(float)*NDIM-1);
858
859 fprintf(DensityDx,"object \"dat.%04u\" class array type float rank 0 items %i %s binary\n",i,MaxPoints,msb);
860 fprintf(DensityDx,"data file %s.%04u,0\n",datname,i);
861 fprintf(DensityDx,"attribute \"dep\" string \"positions\"\n");
862 fprintf(DensityDx,"# %lu - %lu Bytes\n\n",MaxPoints*i*(unsigned long)sizeof(float),MaxPoints*(i+1)*(unsigned long)sizeof(float)-1);
863
864 fprintf(DensityDx,"object \"obj.%04u\" class field\n",i);
865 if (P->Files.OutputPosType[i] == active)
866 fprintf(DensityDx,"component \"positions\" \"pos.%04i\"\n",i);
867 if (P->Files.OutputPosType[i] != active)
868 fprintf(DensityDx,"component \"positions\" \"posdens\"\n");
869 fprintf(DensityDx,"component \"connections\" \"gridcon\"\n");
870 fprintf(DensityDx,"component \"data\" \"dat.%04i\"\n",i);
871 }
872 fprintf(DensityDx,"\nobject \"series\" class series\n");
873 for (i=0; i < (unsigned int)P->Files.OutVisStep[Lev->LevelNo]+1; i++)
874 fprintf(DensityDx,"member %i \"obj.%04u\" position %f\n",i,i,(float)i);
875 fprintf(DensityDx,"end\n");
876 fclose(DensityDx);
877 Free(suffix, "CreateDensityOutputGeneral: suffix");
878
879 Free(posname, "CreateDensityOutputGeneral: posname");
880 Free(datname, "CreateDensityOutputGeneral: datname");
881}
882
883/** Calculates the OutVis density of the RiemannTensor level.
884 * The usual pattern arises when a density is fftransformed:
885 * -# over all grid vectors up to MaxG
886 * -# over all doubly grid vectors up to MaxDoubleG
887 * -# call to fft_3d_complex_to_real()
888 *
889 * In this case here followed by call to OutVisPosRTransformPosNFRto0() and finally FileData::work
890 * is copied to FileData::PosR.
891 * \param *Lat Lattice structure, containing Lattice::plan and LatticeLevel
892 * \param *F FileData structure, containing FileData::PosC, FileData::PosR, FileData::work, FileData::Totalsize, FileData::LocalSizeR
893 */
894static void CalculateOutVisDensityPos(struct Lattice *Lat, struct FileData *F/*, const double FactorC_R, const double FactorR_C*/)
895{
896 struct fft_plan_3d *plan = Lat->plan;
897 struct RiemannTensor *RT = &Lat->RT;
898 struct LatticeLevel *LevR = RT->LevR;
899 fftw_complex *destC = F->PosC;
900 fftw_real *destR = F->PosR;
901 fftw_complex *work = F->work;
902 fftw_real *workR = (fftw_real*)work;
903 fftw_complex *PosFactor = F->PosFactor;
904 fftw_complex *posfac, *destpos, *destRCS, *destRCD;
905 fftw_complex *coeff;
906 fftw_complex source;
907 int i, Index, pos, n;
908 int NF = NDIM, MaxNUp = F->MaxNUp, TotalSize = F->TotalSize, LocalSizeR = F->LocalSizeR;
909 SetArrayToDouble0((double *)destC, TotalSize*2);
910 for (i=0;i < LevR->MaxG;i++) {
911 Index = LevR->GArray[i].Index;
912 posfac = &PosFactor[MaxNUp*i];
913 destpos = &destC[MaxNUp*Index*NF];
914 coeff = &RT->Coeff[i];
915 for (pos=0; pos < MaxNUp; pos++) {
916 for (n=0; n < NF; n++) {
917 source.re = coeff[n].re;
918 source.im = coeff[n].im;
919 destpos[n+NF*pos].re = source.re*posfac[pos].re-source.im*posfac[pos].im;
920 destpos[n+NF*pos].im = source.re*posfac[pos].im+source.im*posfac[pos].re;
921 }
922 }
923 }
924 for (i=0; i < LevR->MaxDoubleG; i++) {
925 destRCS = &destC[LevR->DoubleG[2*i]*MaxNUp*NF];
926 destRCD = &destC[LevR->DoubleG[2*i+1]*MaxNUp*NF];
927 for (pos=0; pos < MaxNUp; pos++) {
928 for (n=0; n < NF; n++) {
929 destRCD[n+NF*pos].re = destRCS[n+NF*pos].re;
930 destRCD[n+NF*pos].im = -destRCS[n+NF*pos].im;
931 }
932 }
933 }
934 fft_3d_complex_to_real(plan, LevR->LevelNo, FFTNFRVecUp0, destC, work);
935 OutVisPosRTransformPosNFRto0(RT, destR, workR, NF);
936 memcpy(destR,workR,sizeof(fftw_real)*LocalSizeR);
937}
938
939/** Prepare Density::DensityArray for output.
940 * Into FileData::work subsequently each node (all z, all y, all x) is written as \f$\log(1+x)\f$,
941 * where x is Density::DensityArray[TotalDensity]. In the end result is send to process 0 (yet not
942 * received here, see CombineOutVisArray()). In case of RiemannTensor use, some more complex calculations
943 * are made: FileData::PosR is used, the coefficient offset'ed to the current node and the log taken there.
944 * \param *P Problem at hand
945 * \param myPE this ranks process in the Psi communcator ParallelSimulationData::me_comm_ST_Psi
946 * \param *srcdens Pointer to DensityArray which is to be displayed
947 */
948static void OutputOutVisDensity(struct Problem *P, const int myPE, fftw_real *srcdens)
949{
950 int N[NDIM], n[NDIM], pos[NDIM];
951 int destpos = 0;
952 double fac[NDIM], posd[NDIM];
953 float posf[NDIM+1];
954 struct Lattice *Lat = &P->Lat;
955 struct LatticeLevel *Lev0 = &Lat->Lev[0];
956 fftw_real *srcpos = P->Files.PosR;
957 //fftw_real *srcdens = Lev0->Dens->DensityArray[ActualDensity]; //[TotalDensity]; trick to display single density
958 float *dest = (float *)P->Files.work;
959 int Nx = Lev0->Plan0.plan->N[0];
960 int i;
961 double min, max;
962
963 N[0] = Lev0->Plan0.plan->local_nx;
964 N[1] = Lev0->Plan0.plan->N[1];
965 N[2] = Lev0->Plan0.plan->N[2];
966
967 max = min = srcdens[0];
968 for (i=1;i<P->R.Lev0->Dens->LocalSizeR;i++) {
969 if (srcdens[i] < min) min = srcdens[i];
970 if (srcdens[i] > max) max = srcdens[i];
971 }
972 if (P->Call.out[PsiOut]) fprintf(stderr,"(%i)OutputOutVisDensity: min %e\tmax %e\n",P->Par.me, min, max);
973
974 // go through all nodes
975 for (n[0]=0; n[0] < N[0]; n[0]++) {
976 pos[0] = (n[0] == N[0] ? 0 : n[0]);
977 for (n[1]=0; n[1] <= N[1]; n[1]++) {
978 pos[1] = (n[1] == N[1] ? 0 : n[1]);
979 for (n[2]=0; n[2] <= N[2]; n[2]++) {
980 pos[2] = (n[2] == N[2] ? 0 : n[2]);
981 // depending on RiemannTensor use, fill FileData::work
982 switch (Lat->RT.ActualUse) {
983 case inactive:
984 case standby:
985 if ((srcdens[pos[2]+N[2]*(pos[1]+N[1]*pos[0])]) > 0.)
986 dest[destpos] = log(1.0+(srcdens[pos[2]+N[2]*(pos[1]+N[1]*pos[0])]));
987 else
988 dest[destpos] = 0.;
989 destpos++;
990 break;
991 case active:
992 posf[0] = srcpos[0+NDIM*(pos[2]+N[2]*(pos[1]+N[1]*pos[0]))];
993 posf[1] = srcpos[1+NDIM*(pos[2]+N[2]*(pos[1]+N[1]*pos[0]))];
994 posf[2] = srcpos[2+NDIM*(pos[2]+N[2]*(pos[1]+N[1]*pos[0]))];
995 fac[0] = ((n[0]+N[0]*myPE)/(double)Nx);
996 fac[1] = (n[1]/(double)N[1]);
997 fac[2] = (n[2]/(double)N[2]);
998 RMat33Vec3(posd, Lat->RealBasis, fac);
999 posf[0] += posd[0];
1000 posf[1] += posd[1];
1001 posf[2] += posd[2];
1002 if ((srcdens[pos[2]+N[2]*(pos[1]+N[1]*pos[0])]) > 0.)
1003 posf[3] = log(1.0+(srcdens[pos[2]+N[2]*(pos[1]+N[1]*pos[0])]));
1004 else
1005 posf[3] = 0.;
1006 dest[destpos+0] = posf[0];
1007 dest[destpos+1] = posf[1];
1008 dest[destpos+2] = posf[2];
1009 dest[destpos+3] = posf[3];
1010 destpos += 4;
1011 break;
1012 }
1013 }
1014 }
1015 }
1016 if (myPE) MPI_Send(dest, destpos, MPI_FLOAT, 0, OutputDensTag, P->Par.comm_ST_Psi);
1017}
1018
1019/** Combines prepared electronic Psis density and output to file.
1020 * If we are process 0, open file suffixdensdat (only when RiemannTensor is used) and suffixdenspos, receive
1021 * FileData::work logarithmic coefficients sent by the other processes in OutputOutVisDensity(), go through all
1022 * nodes and save the coefficient to file - again depending on RiemannTensor use - followed by FileData::PosTemp
1023 * (for y and z nodes), close file(s).
1024 * \param *P Problem at hand
1025 * \param me this ranks process in the Psi communcator ParallelSimulationData::me_comm_ST_Psi
1026 * \param Maxme number of processes in this Psi communcator ParallelSimulationData::Max_me_comm_ST_Psi
1027 */
1028static void CombineOutVisDensity(struct Problem *P, const int me, const int Maxme)
1029{
1030 int i,n[NDIM], N[NDIM];
1031 float posf[NDIM+1];
1032 float *source = (float *)P->Files.work;
1033 double posd[NDIM], fac[NDIM];
1034 float *Temp = (float *)P->Files.PosTemp;
1035 struct Lattice *Lat = &P->Lat;
1036 struct LatticeLevel *Lev0 = &Lat->Lev[0];
1037 float step = P->Files.OutVisStep[P->Lat.Lev[STANDARTLEVEL].LevelNo];
1038 int No=0, destpos;
1039 char suffix[255];
1040 FILE *DensityData, *DensityPos;
1041 int Nx = Lev0->Plan0.plan->N[0]+1;
1042 MPI_Status status;
1043 if (me) return; // if we are process 0!
1044 N[0] = Lev0->Plan0.plan->local_nx;
1045 N[1] = Lev0->Plan0.plan->N[1]+1;
1046 N[2] = Lev0->Plan0.plan->N[2]+1;
1047 // Open respective file depending on RiemannTensor use
1048 switch (Lat->RT.ActualUse) {
1049 case active:
1050 sprintf(suffix, ".L%i%s", P->Lat.Lev[STANDARTLEVEL].LevelNo, suffixdenspos);
1051 OpenFileNo(P, &DensityPos, suffix, (int)step, "wb",P->Call.out[ReadOut]);
1052 case inactive:
1053 case standby:
1054 sprintf(suffix, ".L%i%s", P->Lat.Lev[STANDARTLEVEL].LevelNo, suffixdensdat);
1055 OpenFileNo(P, &DensityData, suffix, (int)step, "wb",P->Call.out[ReadOut]);
1056 break;
1057 }
1058 // for all processes in the communicator
1059 for (i=0; i< Maxme; i++) {
1060 if (i) { // if process != 0, receive from this process
1061 /* MPI_Probe( i, OutputDensTag, P->Par.comm_ST_Psi, &status );*/
1062 switch (Lat->RT.ActualUse) {
1063 case inactive:
1064 case standby:
1065 MPI_Recv( source, N[0]*N[1]*N[2], MPI_FLOAT, i, OutputDensTag, P->Par.comm_ST_Psi, &status );
1066 break;
1067 case active:
1068 MPI_Recv( source, N[0]*N[1]*N[2]*4, MPI_FLOAT, i, OutputDensTag, P->Par.comm_ST_Psi, &status );
1069 break;
1070 }
1071 }
1072 destpos = 0;
1073 // go through all nodes and save the coefficient to file DensityData, depending on RiemannTensor
1074 for (n[0]=0; n[0] < N[0]; n[0]++) {
1075 for (n[1]=0; n[1] < N[1]; n[1]++) {
1076 for (n[2]=0; n[2] < N[2]; n[2]++) {
1077 switch (Lat->RT.ActualUse) {
1078 case inactive:
1079 case standby:
1080 posf[3] = source[destpos];
1081 destpos++;
1082 (void)fwrite(&posf[3], sizeof(float), (size_t)(1), DensityData);
1083 No++;
1084 if (i==0 && n[0] == 0)
1085 Temp[(n[2]+N[2]*(n[1]+N[1]*n[0]))] = posf[3];
1086 break;
1087 case active:
1088 posf[0] = source[destpos+0];
1089 posf[1] = source[destpos+1];
1090 posf[2] = source[destpos+2];
1091 posf[3] = source[destpos+3];
1092 destpos += 4;
1093 (void)fwrite(posf, sizeof(float), (size_t)(NDIM), DensityPos);
1094 (void)fwrite(&posf[3], sizeof(float), (size_t)(1), DensityData);
1095 No++;
1096 if (i==0 && n[0] == 0) {
1097 fac[0] = ((n[0]+N[0]*i)/(double)(Nx-1));
1098 fac[1] = (n[1]/(double)(N[1]-1));
1099 fac[2] = (n[2]/(double)(N[2]-1));
1100 RMat33Vec3(posd, Lat->RealBasis, fac);
1101 posf[0] -= posd[0];
1102 posf[1] -= posd[1];
1103 posf[2] -= posd[2];
1104 fac[0] = ((Nx-1)/(double)(Nx-1));
1105 fac[1] = (n[1]/(double)(N[1]-1));
1106 fac[2] = (n[2]/(double)(N[2]-1));
1107 RMat33Vec3(posd, Lat->RealBasis, fac);
1108 posf[0] += posd[0];
1109 posf[1] += posd[1];
1110 posf[2] += posd[2];
1111 Temp[0+(NDIM+1)*(n[2]+N[2]*(n[1]+N[1]*n[0]))] = posf[0];
1112 Temp[1+(NDIM+1)*(n[2]+N[2]*(n[1]+N[1]*n[0]))] = posf[1];
1113 Temp[2+(NDIM+1)*(n[2]+N[2]*(n[1]+N[1]*n[0]))] = posf[2];
1114 Temp[3+(NDIM+1)*(n[2]+N[2]*(n[1]+N[1]*n[0]))] = posf[3];
1115 }
1116 break;
1117 }
1118 }
1119 }
1120 }
1121 }
1122 n[0] = N[0];
1123 for (n[1]=0; n[1] < N[1]; n[1]++) {
1124 for (n[2]=0; n[2] < N[2]; n[2]++) {
1125 switch (Lat->RT.ActualUse) {
1126 case inactive:
1127 case standby:
1128 (void)fwrite(&Temp[n[2]+N[2]*(n[1])], sizeof(float), (size_t)(1), DensityData);
1129 No++;
1130 break;
1131 case active:
1132 (void)fwrite(&Temp[(NDIM+1)*(n[2]+N[2]*(n[1]))], sizeof(float), (size_t)(NDIM), DensityPos);
1133 (void)fwrite(&Temp[(NDIM+1)*(n[2]+N[2]*(n[1]))+3], sizeof(float), (size_t)(1), DensityData);
1134 No++;
1135 break;
1136 }
1137 }
1138 }
1139 if (No != Nx*N[1]*N[2]) Error(SomeError,"CombineOutVisDensity: No != points");
1140 switch (Lat->RT.ActualUse) {
1141 case active:
1142 fclose(DensityPos);
1143 case inactive:
1144 case standby:
1145 fclose(DensityData);
1146 break;
1147 }
1148}
1149
1150/** Main output electronic Psis density for OpenDX.
1151 * If FileData::MeOutVis is set, calls OutputOutVisDensity() followed by CombineOutVisDensity().
1152 * Beforehand CalculateOutVisDensityPos() is called if RiemannTensor is used.
1153 * \param *P Problem at hand
1154 * \param *src_dens Pointer to DensityArray which is to be displayed
1155 */
1156static void OutVisDensity(struct Problem *P, fftw_real *src_dens)
1157{
1158 if (!P->Files.MeOutVis) return;
1159 if (P->Lat.RT.ActualUse == active) CalculateOutVisDensityPos(&P->Lat, &P->Files/*, P->Lat.FactorDensityR, P->Lat.FactorDensityC*/);
1160 OutputOutVisDensity(P, P->Par.me_comm_ST_Psi, src_dens);
1161 /* Achtung hier: P->Files.work (RT->TempC, Dens->DensityCArray[TempDensity]) fuer myPE == 0 nicht veraendern !!! */
1162 CombineOutVisDensity(P, P->Par.me_comm_ST_Psi, P->Par.Max_me_comm_ST_Psi);
1163}
1164
1165/** Opening and Initializing of output measurement files.
1166 * If this is process 0, opens and writes top line of FileData::ForcesFile, FileData::EnergyFile.
1167 * and sets FileData::MeOutVis and FileData::MeOutMes (if output desired) to 1, otherwise 0.
1168 * \param *P Problem at hand
1169 */
1170void InitOutputFiles(struct Problem *P)
1171{
1172 struct FileData *F = &P->Files;
1173 F->ForcesFile = NULL;
1174 F->EnergyFile = NULL;
1175 F->HamiltonianFile = NULL;
1176 F->MinimisationFile = NULL;
1177 F->SpreadFile = NULL;
1178 F->ReciSpreadFile = NULL;
1179 F->TemperatureFile = NULL;
1180 // process 0 ?
1181 F->MeOutVis = ((P->Par.my_color_comm_ST == 0 && P->Par.my_color_comm_ST_Psi == 0 && F->DoOutVis) ? 1 : 0);
1182 F->MeOutCurr = ((P->Par.my_color_comm_ST == 0 && P->Par.my_color_comm_ST_Psi == 0 && F->DoOutCurr) ? 1 : 0);
1183 F->MeOutMes = ((P->Par.me == 0 && F->DoOutMes) ? 1 : 0);
1184 OpenFile(P, &F->HamiltonianFile, suffixhamiltonianall, "w",P->Call.out[ReadOut]);
1185
1186 if (!F->MeOutMes) return;
1187 OpenFile(P, &F->ForcesFile, suffixforcesall, "w",P->Call.out[ReadOut]);
1188 if (F->ForcesFile == NULL) fprintf(stderr,"Error opening ForcesFile\n");
1189 // write header of forces file
1190 fprintf(F->ForcesFile, "%s\t%s\t%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t%s\t%s\t%s\t%s\t\t%s\t\t%s\n",
1191 "Type", "No",
1192 "Pos0", "Pos1", "Pos2",
1193 "Total0", "Total1", "Total2",
1194 "Local0", "Local1", "Local2",
1195 "NLocal0", "NLocal1", "NLocal2",
1196 "Magnetic0", "Magnetic1", "Magnetic2",
1197 "Ewald0", "Ewald1", "Ewald2");
1198 OpenFile(P, &F->EnergyFile, suffixenergyall, "w",P->Call.out[ReadOut]);
1199 if (F->EnergyFile == NULL) fprintf(stderr,"Error opening EnergyFile\n");
1200 // write header of energy file
1201 if (P->R.DoUnOccupied) {
1202 fprintf(F->EnergyFile, "%s\t\t%s\t\t%s\t%s\t\t%s\t%s\t\t%s\t%s\t%s\t\t%s\t\t%s\t%s\t\t%s\t\t%s\t\t%s\n",
1203 "Time",
1204 "Total",
1205 "Total+Gap",
1206 "Kinetic", "NonLocal",
1207 "GapPsi",
1208 "Correlation", "Exchange",
1209 "Pseudo", "Hartree",
1210 "GapDensity",
1211 "-Gauss",
1212 "Ewald",
1213 "IonKin",
1214 "ETotal");
1215 } else {
1216 fprintf(F->EnergyFile, "%s\t\t%s\t\t%s\t\t%s\t%s\t%s\t%s\t\t%s\t\t%s\t\t%s\t\t%s\t\t%s\n",
1217 "Time",
1218 "Total",
1219 "Kinetic", "NonLocal",
1220 "Correlation", "Exchange",
1221 "Pseudo", "Hartree",
1222 "-Gauss",
1223 "Ewald",
1224 "IonKin",
1225 "ETotal");
1226 }
1227 OpenFile(P, &F->MinimisationFile, suffixminall, "w",P->Call.out[ReadOut]);
1228 if (F->MinimisationFile == NULL) fprintf(stderr,"Error opening MinimsationFile\n");
1229 // write header of minimsation file
1230 fprintf(F->MinimisationFile, "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n","Step", "Psi", "PsiStep", "TE", "ATE", "delta", "dEdt0", "ddEdtt0");
1231
1232 OpenFile(P, &F->TemperatureFile, suffixtempall, "w",P->Call.out[ReadOut]);
1233 if (F->TemperatureFile == NULL) fprintf(stderr,"Error opening TemperatureFile\n");
1234 // write header of minimsation file
1235}
1236
1237/** Closes all output measurement files.
1238 * Closes FileData::ForcesFile and FileData::EnergyFile
1239 * \param *P Problem at hand
1240 */
1241void CloseOutputFiles(struct Problem *P)
1242{
1243 struct FileData *F = &P->Files;
1244 if (!F->MeOutMes) return;
1245 if (F->ForcesFile != NULL) fclose(F->ForcesFile); // only they've been opened (thus not pointing to NULL)
1246 if (F->EnergyFile != NULL) fclose(F->EnergyFile);
1247 if (F->HamiltonianFile != NULL) fclose(F->HamiltonianFile);
1248 if (F->MinimisationFile != NULL) fclose(F->MinimisationFile);
1249 if (F->SpreadFile != NULL) fclose(F->SpreadFile);
1250 if (F->ReciSpreadFile != NULL) fclose(F->ReciSpreadFile);
1251 if (F->TemperatureFile != NULL) fclose(F->TemperatureFile);
1252}
1253
1254/** Initialization of Problem::FileData structure for visual output.
1255 * If this is process 0 (and OutVis desired), allocate memory for FileData::PosTemp, FileData::work,
1256 * set the entries of FileData all to their corresponding values from RiemannTensor,
1257 * FileData::*OutVisStep to zero.
1258 * \param *P Problem at hand
1259 */
1260void InitOutVisArray(struct Problem *P)
1261{
1262 struct FileData *F = &P->Files;
1263 struct Lattice *Lat = &P->Lat;
1264 struct RiemannTensor *RT = &Lat->RT;
1265 struct LatticeLevel *Lev0 = &Lat->Lev[0];
1266 int i;
1267 F->OutputPosType = NULL;
1268 if (!F->MeOutVis) return;
1269
1270 F->OutVisStep = Malloc(sizeof(int)*Lat->MaxLevel,"InitOutVisArray: OutVisStep");
1271 for (i=0;i<Lat->MaxLevel;i++)
1272 F->OutVisStep[i] = 0;
1273 F->PosTemp = (fftw_complex *)
1274 Malloc(sizeof(float)*(Lev0->Plan0.plan->N[1]+1)*(Lev0->Plan0.plan->N[2]+1)*
1275 ((Lat->RT.Use != UseRT ? 0 : NDIM)+1), "InitOutVisArray: TempC");
1276 F->work = (fftw_complex *)Lev0->Dens->DensityCArray[TempDensity];
1277 if (Lat->RT.Use != UseRT) return;
1278 F->TotalSize = RT->TotalSize[RTAIRT]/NDIM;
1279 F->LocalSizeR = RT->LocalSizeR[RTAiGcg];
1280 F->LocalSizeC = RT->LocalSizeC[RTAiGcg];
1281 F->MaxNUp = RT->MaxNUp[RTPFRto0];
1282 F->PosC = RT->DensityC[RTAiGcg];
1283 F->PosR = (fftw_real *)F->PosC;
1284 F->work = RT->TempC;
1285 F->PosFactor = RT->PosFactor[RTPFRto0];
1286}
1287
1288static const char suffixionfor[] = ".ions.force"; //!< Suffix for ion forces file
1289static const char suffixionZ[] = ".ions.datZ"; //!< Suffix for ion datZ file
1290static const char suffixionpos[] = ".ions.pos"; //!< Suffix for ion positions file
1291static const char suffixiondx[] = ".ions.dx"; //!< Suffix for ions dx file
1292static const char suffixiondoc[] = ".ions.doc"; //!< Suffix for ions doc file
1293static const char suffixsrciondoc[] = ".srcion.doc"; //!< Suffix for state ions doc file
1294static const char suffixsrciondat[] = ".srcion.data"; //!< Suffix for state ions data file
1295
1296/** Output current ions state.
1297 * If this is process0, open file suffixsrciondoc for writing, output Ions::Max_Types and
1298 * Ions::Max_IonsOfType of each type - each in a new line - closes it.
1299 * Then opens suffixsrciondat for binary writing, outputs Lattice:RealBasis vectors and
1300 * position IonType::R and speed IonType::U, closes it.
1301 * \param *P Problem at hand
1302 * \note This is the ionic counterpart to the elecontric OutputSrcPsiDensity(), storing a so far made
1303 * calculation to file.
1304 */
1305static void OutSrcIons(struct Problem *P)
1306{
1307 struct Ions *I = &P->Ion;
1308 double *U, *pos;
1309 double data[2*NDIM];
1310 int is,ia,i;
1311 FILE *SrcIonDoc, *SrcIonData;
1312 char suffix[255];
1313
1314 if (!(P->Par.me == 0)) return;
1315
1316 // output of ion types and numbers per type
1317 sprintf(suffix, ".L%i%s", P->Lat.Lev[STANDARTLEVEL].LevelNo, suffixsrciondoc);
1318 OpenFile(P, &SrcIonDoc, suffix, "w",P->Call.out[ReadOut]);
1319 fprintf(SrcIonDoc,"%i\n", I->Max_Types);
1320 for (is=0; is < I->Max_Types; is++)
1321 fprintf(SrcIonDoc,"%i\n", I->I[is].Max_IonsOfType);
1322 fclose(SrcIonDoc);
1323
1324 sprintf(suffix, ".L%i%s", P->Lat.Lev[STANDARTLEVEL].LevelNo, suffixsrciondat);
1325 OpenFile(P, &SrcIonData, suffix, "wb",P->Call.out[ReadOut]);
1326 (void)fwrite(P->Lat.RealBasis, sizeof(double), (size_t)(NDIM_NDIM), SrcIonData);
1327 for (is=0; is < I->Max_Types; is++) {
1328 for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
1329 U = &I->I[is].U[NDIM*ia];
1330 pos = &I->I[is].R[NDIM*ia];
1331 for (i=0;i<NDIM;i++) {
1332 data[i] = pos[i];
1333 data[i+NDIM] = U[i];
1334 }
1335 (void)fwrite(&data, sizeof(double), (size_t)(2*NDIM), SrcIonData);
1336 }
1337 }
1338 fclose(SrcIonData);
1339}
1340
1341/** Read ions state from a file.
1342 * Reads the suffixsrciondoc file and checks it against the current state in Ions regarding
1343 * IonType::MaxTypes and IonType::Max_IonsOfType, closes it.
1344 * Afterwards, opens suffixsrciondat for binary reading, retrieves the basis checking it against
1345 * Problem::Lattice::RealBasis. If ok, reads position IonType::R and speed IonType::U, closes it.
1346 * \param *P Problem at hand
1347 * \return 1 - successful, 0 - failure
1348 * \note This is the ionic counterpart to the electronic ReadSrcPsiDensity(), see also OutSrcIons().
1349 */
1350int ReadSrcIons(struct Problem *P)
1351{
1352 struct Ions *I = &P->Ion;
1353 double *U, *pos;
1354 double data[2*NDIM];
1355 int is,ia,i;
1356 int Max_Types;
1357 int *Max_IonsOfType = NULL;
1358 double RealBasis[NDIM_NDIM];
1359 FILE *SrcIonDoc, *SrcIonData;
1360 char *suffix;
1361 int flag = 0;
1362 // read the doc file and check
1363
1364 if (!P->Par.me) { // process 0 reads and broadcasts ..
1365 suffix = (char *)
1366 Malloc(strlen(suffixsrciondoc) + 3 + 1,"ReadSrcIons: suffix");
1367 sprintf(suffix, ".L%i%s", P->Lat.Lev[STANDARTLEVEL].LevelNo, suffixsrciondoc);
1368 if (OpenFile(P, &SrcIonDoc, suffix, "r",P->Call.out[ReadOut])) {
1369 if (fscanf(SrcIonDoc,"%i", &Max_Types) != 1) {
1370 //Error(SomeError, "ReadSrcIons: read error");
1371 Free(suffix, "ReadSrcIons: suffix");
1372 if (MPI_Bcast(&flag,1,MPI_INT,0,P->Par.comm) != MPI_SUCCESS)
1373 Error(SomeError,"ReadSrcIons: Bcast of signal failed\n");
1374 return flag;
1375 }
1376 if (Max_Types != I->Max_Types) {
1377 //Error(SomeError, "ReadSrcIons: srcion file does not fit to system, MaxTypes");
1378 Free(suffix, "ReadSrcIons: suffix");
1379 if (MPI_Bcast(&flag,1,MPI_INT,0,P->Par.comm) != MPI_SUCCESS)
1380 Error(SomeError,"ReadSrcIons: Bcast of signal failed\n");
1381 return flag;
1382 }
1383 Max_IonsOfType = (int *) Malloc(Max_Types*sizeof(int), "ReadSrcIons: Max_IonsOfType");
1384 for (is=0; is < Max_Types; is++) {
1385 if (fscanf(SrcIonDoc,"%i", &Max_IonsOfType[is]) != 1) {
1386 //Error(SomeError, "ReadSrcIons: read error");
1387 Free(suffix, "ReadSrcIons: suffix");
1388 Free(Max_IonsOfType, "ReadSrcIons: Max_IonsOfType");
1389 if (MPI_Bcast(&flag,1,MPI_INT,0,P->Par.comm) != MPI_SUCCESS)
1390 Error(SomeError,"ReadSrcIons: Bcast of signal failed\n");
1391 return flag;
1392 }
1393 if (Max_IonsOfType[is] != I->I[is].Max_IonsOfType) {
1394 //Error(SomeError, "ReadSrcIons: srcion file does not fit to system, Max_IonsOfType");
1395 Free(suffix, "ReadSrcIons: suffix");
1396 Free(Max_IonsOfType, "ReadSrcIons: Max_IonsOfType");
1397 if (MPI_Bcast(&flag,1,MPI_INT,0,P->Par.comm) != MPI_SUCCESS)
1398 Error(SomeError,"ReadSrcIons: Bcast of signal failed\n");
1399 return flag;
1400 }
1401 }
1402 Free(Max_IonsOfType, "ReadSrcIons: Max_IonsOfType");
1403 fclose(SrcIonDoc);
1404 }
1405 // check basis, then read positions and speeds of ions
1406 suffix = (char *)
1407 Realloc(suffix, strlen(suffixsrciondat) + 3 + 1,"ReadSrcIons: suffix");
1408 sprintf(suffix, ".L%i%s", P->Lat.Lev[STANDARTLEVEL].LevelNo, suffixsrciondat);
1409 if (OpenFile(P, &SrcIonData, suffix, "rb",P->Call.out[ReadOut])) {
1410 if (fread(RealBasis, sizeof(double), (size_t)(NDIM_NDIM), SrcIonData) != NDIM_NDIM) {
1411 //Error(SomeError, "ReadSrcIons: read error");
1412 Free(suffix, "ReadSrcIons: suffix");
1413 if (MPI_Bcast(&flag,1,MPI_INT,0,P->Par.comm) != MPI_SUCCESS)
1414 Error(SomeError,"ReadSrcIons: Bcast of signal failed\n");
1415 return flag;
1416 }
1417 for (i=0; i < NDIM_NDIM; i++)
1418 if (RealBasis[i] != P->Lat.RealBasis[i]) {
1419 //Error(SomeError, "ReadSrcIons: srcion file does not fit to system, RealBasis");
1420 Free(suffix, "ReadSrcIons: suffix");
1421 if (MPI_Bcast(&flag,1,MPI_INT,0,P->Par.comm) != MPI_SUCCESS)
1422 Error(SomeError,"ReadSrcIons: Bcast of signal failed\n");
1423 return flag;
1424 }
1425 for (is=0; is < I->Max_Types; is++) {
1426 for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
1427 if (fread(&data, sizeof(double), (size_t)(2*NDIM), SrcIonData) != 2*NDIM) {
1428 //Error(SomeError, "ReadSrcIons: read error");
1429 Free(suffix, "ReadSrcIons: suffix");
1430 if (MPI_Bcast(&flag,1,MPI_INT,0,P->Par.comm) != MPI_SUCCESS)
1431 Error(SomeError,"ReadSrcIons: Bcast of signal failed\n");
1432 return flag;
1433 }
1434 U = &I->I[is].U[NDIM*ia];
1435 pos = &I->I[is].R[NDIM*ia];
1436 for (i=0;i<NDIM;i++) {
1437 pos[i] = data[i];
1438 U[i] = data[i+NDIM];
1439 }
1440 }
1441 }
1442 fclose(SrcIonData);
1443 flag = 1;
1444 }
1445 Free(suffix, "ReadSrcIons: suffix");
1446 }
1447 if (MPI_Bcast(&flag,1,MPI_INT,0,P->Par.comm) != MPI_SUCCESS)
1448 Error(SomeError,"ReadSrcIons: Bcast of signal failed\n");
1449 //fprintf(stderr, "(%i) Flag is %i\n", P->Par.me, flag);
1450 if (flag) {
1451 for (is=0; is < I->Max_Types; is++) {
1452 if (MPI_Bcast(I->I[is].R, I->I[is].Max_IonsOfType*NDIM, MPI_DOUBLE, 0, P->Par.comm) != MPI_SUCCESS)
1453 Error(SomeError,"ReadSrcIons: Bcast of I->I[is].R failed\n");
1454 if (MPI_Bcast(I->I[is].U, I->I[is].Max_IonsOfType*NDIM, MPI_DOUBLE, 0, P->Par.comm) != MPI_SUCCESS)
1455 Error(SomeError,"ReadSrcIons: Bcast of I->I[is].U failed\n");
1456 }
1457 }
1458 //fprintf(stderr, "(%i) ReadSrcIons done\n", P->Par.me);
1459 return flag;
1460}
1461
1462/** Output of ion doc, dx, forces and positions file for OpenDX.
1463 * If this is process 0,
1464 * open, fill and close IonDoc file suffixiondoc,
1465 * open, fill for each FileData::*OutVisStep and close IonDX file suffixiondx
1466 * for every
1467 * open suffixionfor, suffixionpos (and suffixionZ in case of only FileData::*OutVisStep), fill
1468 * them with the ion forces IonType::FIon and positions IonType::R of each type and each ion per type,
1469 * close them all.
1470 * \param *P Problem at hand
1471 */
1472static void OutVisIons(struct Problem *P)
1473{
1474 struct Ions *I = &P->Ion;
1475 struct FileData *F = &P->Files;
1476 struct LatticeLevel *Lev = &P->Lat.Lev[STANDARTLEVEL];
1477 int i,is,ia;
1478 double *fion, *pos;
1479 float data[6]; // holds temporarily twice NDIM values as write buffer
1480 int Z;
1481 char *datnamef, *datnameZ, *posname, suffix[255];
1482 FILE *IonsDataF, *IonsDataZ, *IonsPos, *IonsDoc, *IonsDx;
1483 if (!P->Files.MeOutVis && P->Par.me == 0) return;
1484 // generate file names
1485 datnamef = (char*)
1486 malloc(strlen(P->Files.mainname)+strlen(suffixionfor) + 1);
1487 sprintf(datnamef, "%s.L%i%s", P->Files.mainname, P->Lat.Lev[STANDARTLEVEL].LevelNo, suffixionfor);
1488 datnameZ = (char*)
1489 malloc(strlen(P->Files.mainname)+strlen(suffixionZ) + 1);
1490 sprintf(datnameZ, "%s.L%i%s", P->Files.mainname, P->Lat.Lev[STANDARTLEVEL].LevelNo, suffixionZ);
1491 posname = (char*)
1492 malloc(strlen(P->Files.mainname)+strlen(suffixionpos) + 1);
1493 sprintf(posname, "%s.L%i%s", P->Files.mainname, P->Lat.Lev[STANDARTLEVEL].LevelNo, suffixionpos);
1494 // open, fill and close doc file
1495 sprintf(suffix, ".L%i%s", P->Lat.Lev[STANDARTLEVEL].LevelNo, suffixiondoc);
1496 if (OpenFile(P, &IonsDoc, suffix, "w",P->Call.out[ReadOut])) {
1497 fprintf(IonsDoc,"IonsPos file = %s.####\n", posname);
1498 fprintf(IonsDoc,"IonsForce file = %s.####\n", datnamef);
1499 fprintf(IonsDoc,"format = ieee float (Bytes %lu) %s = Force(3)\n",(unsigned long) sizeof(float),msb);
1500 fprintf(IonsDoc,"IonsZ file = %s.####\n", datnameZ);
1501 fprintf(IonsDoc,"format = int (Bytes %lu) %s = Z(1)\n",(unsigned long) sizeof(int),msb);
1502 fprintf(IonsDoc,"points = %i\n", I->Max_TotalIons);
1503 fprintf(IonsDoc,"majority = row\n");
1504 fprintf(IonsDoc,"TimeSeries = %i\n",F->OutVisStep[Lev->LevelNo]+1);
1505 fclose(IonsDoc);
1506 }
1507 // open dx file and fill it with each output step, close it
1508 sprintf(suffix, ".L%i%s", P->Lat.Lev[STANDARTLEVEL].LevelNo, suffixiondx);
1509 if (OpenFile(P, &IonsDx, suffix, "w",P->Call.out[ReadOut])) {
1510 for (i=0; i < F->OutVisStep[Lev->LevelNo]+1; i++) {
1511 if (i==0) {
1512 /* fprintf(IonsDx,"object \"ioncon\" class array type int rank 1 shape 2 items 0 data follows\nattribute \"element type\" string \"lines\"\nattribute \"ref\" string \"positions\"\n\n"); */
1513 fprintf(IonsDx,"object \"iondatZ\" class array type int rank 0 items %i %s binary\n",I->Max_TotalIons,msb);
1514 fprintf(IonsDx,"data file %s,0\n",datnameZ);
1515 fprintf(IonsDx,"attribute \"dep\" string \"positions\"\n\n");
1516 }
1517
1518 fprintf(IonsDx,"object \"ionpos.%04i\" class array type float rank 1 shape 3 items %i %s binary\n",i,I->Max_TotalIons,msb);
1519 fprintf(IonsDx,"data file %s.%04i,0\n\n",posname,i);
1520
1521 fprintf(IonsDx,"object \"iondatF.%04i\" class array type float rank 1 shape 3 items %i %s binary\n",i,I->Max_TotalIons,msb);
1522 fprintf(IonsDx,"data file %s.%04i,0\n",datnamef,i);
1523 fprintf(IonsDx,"attribute \"dep\" string \"positions\"\n\n");
1524
1525 fprintf(IonsDx,"object \"ionobjF.%04i\" class field\n",i);
1526 fprintf(IonsDx,"component \"positions\" \"ionpos.%04i\"\n",i);
1527 fprintf(IonsDx,"component \"data\" \"iondatF.%04i\"\n",i);
1528 /*fprintf(IonsDx,"component \"connections\" \"ioncon\"\n\n");*/
1529
1530 fprintf(IonsDx,"object \"ionobjZ.%04i\" class field\n",i);
1531 fprintf(IonsDx,"component \"positions\" \"ionpos.%04i\"\n",i);
1532 fprintf(IonsDx,"component \"data\" \"iondatZ\"\n");
1533 /* fprintf(IonsDx,"component \"connections\" \"ioncon\"\n\n");*/
1534 }
1535 fprintf(IonsDx,"\nobject \"ionseriesF\" class series\n");
1536 for (i=0; i < F->OutVisStep[Lev->LevelNo]+1; i++)
1537 fprintf(IonsDx,"member %i \"ionobjF.%04i\" position %f\n",i,i,(float)i);
1538 fprintf(IonsDx,"\nobject \"ionseriesZ\" class series\n");
1539 for (i=0; i < F->OutVisStep[Lev->LevelNo]+1; i++)
1540 fprintf(IonsDx,"member %i \"ionobjZ.%04i\" position %f\n",i,i,(float)i);
1541 fprintf(IonsDx,"end\n");
1542 fclose(IonsDx);
1543 }
1544 Free(datnamef, "OutVisIons: datnamef");
1545 Free(datnameZ, "OutVisIons: datnameZ");
1546 Free(posname, "OutVisIons: posname");
1547 // open IonForces, IonZ and IonPosition file, write forces respectively positions for each ion of each type, close them
1548 sprintf(suffix, ".L%i%s", P->Lat.Lev[STANDARTLEVEL].LevelNo, suffixionfor);
1549 if (OpenFileNo(P, &IonsDataF, suffix, F->OutVisStep[Lev->LevelNo], "wb",P->Call.out[ReadOut])) {
1550 if (F->OutVisStep[Lev->LevelNo] == 0) {
1551 sprintf(suffix, ".L%i%s", P->Lat.Lev[STANDARTLEVEL].LevelNo, suffixionZ);
1552 OpenFile(P, &IonsDataZ, suffix, "wb",P->Call.out[ReadOut]);
1553 }
1554 sprintf(suffix, ".L%i%s", P->Lat.Lev[STANDARTLEVEL].LevelNo, suffixionpos);
1555 if (OpenFileNo(P, &IonsPos, suffix, F->OutVisStep[Lev->LevelNo], "wb",P->Call.out[ReadOut])) {
1556 for (is=0; is < I->Max_Types; is++) {
1557 for (ia=0; ia < I->I[is].Max_IonsOfType; ia++) {
1558 fion = &I->I[is].FIon[NDIM*ia];
1559 pos = &I->I[is].R[NDIM*ia];
1560 for (i=0;i<3;i++) {
1561 data[i+3] = fion[i];
1562 data[i] = pos[i];
1563 }
1564 Z = I->I[is].Z;
1565 if (fwrite(&data[0],sizeof(float), (size_t)(3),IonsPos) != 3)
1566 Error(FileOpenParams, "Error writing ion positions!");
1567 if (F->OutVisStep[Lev->LevelNo] == 0) (void)fwrite(&Z,sizeof(int), (size_t)(1),IonsDataZ);
1568 if (fwrite(&data[3],sizeof(float), (size_t)(3),IonsDataF) != 3)
1569 Error(FileOpenParams, "Error writing ionic forces!");
1570 }
1571 }
1572 fclose(IonsPos);
1573 }
1574 if (F->OutVisStep[Lev->LevelNo] == 0)
1575 fclose(IonsDataZ);
1576 fclose(IonsDataF);
1577 }
1578}
1579
1580/** Output electronic density and ion state files with so far made calculations.
1581 * If CallOptions::WriteSrcFiles is set, OutputSrcPsiDensity() and OutSrcIons() are called.
1582 * \param *P Problem at hand
1583 * \param type which PsiTypeTag should be put to file
1584 */
1585void OutputVisSrcFiles(struct Problem *P, enum PsiTypeTag type)
1586{
1587 if (P->Call.WriteSrcFiles) {
1588 if(P->Call.out[NormalOut]) fprintf(stderr,"(%i) Writing %s srcpsi to disk\n", P->Par.me, P->R.MinimisationName[type]);
1589 OutputSrcPsiDensity(P, type);
1590 if(P->Call.out[NormalOut]) fprintf(stderr,"(%i) Writing srcion to disk\n", P->Par.me);
1591 OutSrcIons(P);
1592 }
1593 // if (!P->Files.MeOutVis) return;
1594 // P->Files.OutputPosType =
1595 // Realloc(P->Files.OutputPosType,sizeof(enum ModeType)*(P->Files.OutVisStep[P->Lat.Lev[STANDARTLEVEL].LevelNo]+1),"OutputVis");
1596 // P->Files.OutputPosType[P->Files.OutVisStep[P->Lat.Lev[STANDARTLEVEL].LevelNo]] = P->Lat.RT.ActualUse;
1597 // CreateDensityOutputGeneral(P, P->Par.me_comm_ST_Psi);
1598 // OutVisDensity(P);
1599 // OutVisIons(P);
1600 // if(P->Call.out[NormalOut]) fprintf(stderr,"(%i) Written OutVisStep %i to disk\n", P->Par.me, P->Files.OutVisStep[P->Lat.Lev[STANDARTLEVEL].LevelNo]);
1601 // /* P->Files.OutVisStep[P->Lat.Lev[STANDARTLEVEL].LevelNo]++; Genau ebend nicht hochzaehlen - wird immer ueberschrieben */
1602}
1603
1604/** Main output total electronic density and ion data for OpenDX.
1605 * Calls subsequently preparing CreateDensityOutputGeneral(), then output of electronic
1606 * densities OutVisDensity() and ion data OutVisIons(), increasing finally FileData::*OutVisStep.
1607 * \param *P Problem at hand
1608 * \param *srcdens Pointer to DensityArray which is to be displayed
1609 * \note Output is made only RunStruct::OutVisStep steps and if FileData::MeOutVis is set.
1610 */
1611void OutputVis(struct Problem *P, fftw_real *srcdens)
1612{
1613 if (!P->Files.MeOutVis) return;
1614 P->Files.OutputPosType = (enum ModeType *) Realloc(P->Files.OutputPosType,sizeof(enum ModeType)*(P->Files.OutVisStep[P->Lat.Lev[STANDARTLEVEL].LevelNo]+1),"OutputVis");
1615 P->Files.OutputPosType[P->Files.OutVisStep[P->Lat.Lev[STANDARTLEVEL].LevelNo]] = P->Lat.RT.ActualUse;
1616
1617 CreateDensityOutputGeneral(P, P->Par.me_comm_ST_Psi);
1618 OutVisDensity(P, srcdens);
1619 OutVisIons(P);
1620 if(P->Call.out[MinOut]) fprintf(stderr,"(%i) Written OutVisStep %i to disk\n", P->Par.me, P->Files.OutVisStep[P->Lat.Lev[STANDARTLEVEL].LevelNo]);
1621 P->Files.OutVisStep[P->Lat.Lev[STANDARTLEVEL].LevelNo]++;
1622}
1623
1624/** Output of each current density component for OpenDX.
1625 * \param *P Problem at hand
1626 * \note Output is made only RunStruct::OutVisStep steps and if FileData::MeOutVis is set.
1627 */
1628void OutputCurrentDensity(struct Problem *P)
1629{
1630 int index, i, r;
1631 fftw_real *density = P->R.Lev0->Dens->DensityArray[ActualDensity];
1632 fftw_real *CurrentDensity[NDIM*NDIM];
1633 if (!P->Files.MeOutCurr) return;
1634
1635 if(P->Call.out[NormalOut]) fprintf(stderr,"(%i)Output of Current Density (Vis)\n", P->Par.me);
1636
1637 P->Files.OutputPosType = (enum ModeType *) Realloc(P->Files.OutputPosType,sizeof(enum ModeType)*(P->Files.OutVisStep[P->Lat.Lev[STANDARTLEVEL].LevelNo]+(1)*NDIM),"OutputVis");
1638 for (i=0;i<(1)*NDIM;i++)
1639 P->Files.OutputPosType[P->Files.OutVisStep[P->Lat.Lev[STANDARTLEVEL].LevelNo]+i] = P->Lat.RT.ActualUse;
1640 if(P->Call.out[PsiOut]) fprintf(stderr,"(%i) OutVisStep %i, OutputPosType %p\n",P->Par.me, P->Files.OutVisStep[P->Lat.Lev[STANDARTLEVEL].LevelNo], P->Files.OutputPosType);
1641
1642 // due to preprocessor values we can't put the following stuff into a loop
1643 CurrentDensity[0] = (fftw_real *) P->R.Lev0->Dens->DensityArray[CurrentDensity0];
1644 CurrentDensity[1] = (fftw_real *) P->R.Lev0->Dens->DensityArray[CurrentDensity1];
1645 CurrentDensity[2] = (fftw_real *) P->R.Lev0->Dens->DensityArray[CurrentDensity2];
1646 CurrentDensity[3] = (fftw_real *) P->R.Lev0->Dens->DensityArray[CurrentDensity3];
1647 CurrentDensity[4] = (fftw_real *) P->R.Lev0->Dens->DensityArray[CurrentDensity4];
1648 CurrentDensity[5] = (fftw_real *) P->R.Lev0->Dens->DensityArray[CurrentDensity5];
1649 CurrentDensity[6] = (fftw_real *) P->R.Lev0->Dens->DensityArray[CurrentDensity6];
1650 CurrentDensity[7] = (fftw_real *) P->R.Lev0->Dens->DensityArray[CurrentDensity7];
1651 CurrentDensity[8] = (fftw_real *) P->R.Lev0->Dens->DensityArray[CurrentDensity8];
1652
1653 // output current density, not vector component
1654 for (index=0;index<NDIM;index++) {
1655 // evaluate euclidian norm for given B component
1656 SetArrayToDouble0((double *)density,P->R.Lev0->Dens->TotalSize*2); // reset
1657 for (r=0;r<P->R.Lev0->Dens->LocalSizeR;r++) {
1658 for (i=0;i<NDIM;i++)
1659 density[r] += CurrentDensity[i + index*NDIM][r]*CurrentDensity[i + index*NDIM][r];
1660 density[r] = sqrt(density[r]);
1661 }
1662 // output
1663 CreateDensityOutputGeneral(P, P->Par.me_comm_ST_Psi);
1664 OutVisDensity(P, density);
1665 OutVisIons(P);
1666 if(P->Call.out[NormalOut]) fprintf(stderr,"(%i) Written OutVisStep %i to disk\n", P->Par.me, P->Files.OutVisStep[P->Lat.Lev[STANDARTLEVEL].LevelNo]);
1667 P->Files.OutVisStep[P->Lat.Lev[STANDARTLEVEL].LevelNo]++;
1668 }
1669}
1670
1671/** Output each orbital in a certain step order for OpenDX.
1672 * \param *P Problem at hand
1673 * \param offset from which step do we start
1674 * \param increment by which increment do we advance step-wise
1675 * \param type Only PsiTypeTag orbitals are displayed
1676 */
1677void OutputVisAllOrbital(struct Problem *P, int offset, int increment, enum PsiTypeTag type) {
1678 struct Lattice *Lat = &P->Lat;
1679 struct Psis *Psi = &Lat->Psi;
1680 struct RunStruct *R = &P->R;
1681 struct LatticeLevel *LevS = R->LevS;
1682 struct LatticeLevel *Lev = &P->Lat.Lev[STANDARTLEVEL];
1683 struct LatticeLevel *Lev0 = R->Lev0;
1684 struct Density *Dens0 = Lev0->Dens;
1685 struct OnePsiElement *OnePsiA, *LOnePsiA;
1686 MPI_Status status;
1687 int ElementSize = (sizeof(fftw_complex) / sizeof(double));
1688 fftw_complex *LPsiDatA;
1689 int i, p, RecvSource;
1690 int Num = Psi->NoOfPsis;
1691
1692 if (!P->Files.MeOutVis) return;
1693
1694 fprintf(stderr,"(%i) Realloc OutputPosType: %li to %i\n",P->Par.me,sizeof(P->Files.OutputPosType), P->Files.OutVisStep[Lev->LevelNo]+(Num));
1695 P->Files.OutputPosType = (enum ModeType *) Realloc(P->Files.OutputPosType,sizeof(enum ModeType)*(P->Files.OutVisStep[Lev->LevelNo]+(Num)),"OutputVis");
1696
1697 P->Files.OutVisStep[Lev->LevelNo] += offset;
1698 //P->Files.OutputPosType[P->Files.OutVisStep[Lev->LevelNo]] = P->Lat.RT.ActualUse;
1699 for (i=0; i < Psi->MaxPsiOfType+P->Par.Max_me_comm_ST_PsiT; i++) { // go through all wave functions (plus the extra one for each process)
1700 OnePsiA = &Psi->AllPsiStatus[i]; // grab the desired OnePsiA
1701 if (OnePsiA->PsiType == type) { // drop if extra one
1702 if (OnePsiA->my_color_comm_ST_Psi == P->Par.my_color_comm_ST_Psi) // local?
1703 LOnePsiA = &Psi->LocalPsiStatus[OnePsiA->MyLocalNo];
1704 else
1705 LOnePsiA = NULL;
1706 if (LOnePsiA == NULL) { // if it's not local ... receive it from respective process into TempPsi
1707 RecvSource = OnePsiA->my_color_comm_ST_Psi;
1708 MPI_Recv( LevS->LPsi->TempPsi, LevS->MaxG*ElementSize, MPI_DOUBLE, RecvSource, WannierTag1, P->Par.comm_ST_PsiT, &status );
1709 LPsiDatA=LevS->LPsi->TempPsi;
1710 } else { // .. otherwise send it to all other processes (Max_me... - 1)
1711 for (p=0;p<P->Par.Max_me_comm_ST_PsiT;p++)
1712 if (p != OnePsiA->my_color_comm_ST_Psi)
1713 MPI_Send( LevS->LPsi->LocalPsi[OnePsiA->MyLocalNo], LevS->MaxG*ElementSize, MPI_DOUBLE, p, WannierTag1, P->Par.comm_ST_PsiT);
1714 LPsiDatA=LevS->LPsi->LocalPsi[OnePsiA->MyLocalNo];
1715 } // LPsiDatA is now set to the coefficients of OnePsi either stored or MPI_Received
1716
1717 P->Files.OutputPosType[P->Files.OutVisStep[Lev->LevelNo]] = P->Lat.RT.ActualUse;
1718 // recalculate density for the specific wave function ...
1719 CalculateOneDensityR(Lat, LevS, Dens0, LPsiDatA, Dens0->DensityArray[ActualDensity], R->FactorDensityR, 0);
1720 // ... and output (wherein ActualDensity is used instead of TotalDensity)
1721 //OutputVis(P);
1722 CreateDensityOutputGeneral(P, P->Par.me_comm_ST_Psi);
1723 OutVisDensity(P, Dens0->DensityArray[ActualDensity]);
1724 OutVisIons(P);
1725 if(P->Call.out[NormalOut]) fprintf(stderr,"(%i) Written OutVisStep %i to disk\n", P->Par.me, P->Files.OutVisStep[Lev->LevelNo]);
1726 P->Files.OutVisStep[Lev->LevelNo]+=increment;
1727 //P->Files.OutputPosType[P->Files.OutVisStep[Lev->LevelNo]] = P->Lat.RT.ActualUse;
1728 }
1729 }
1730}
1731
1732/** Read source files containing stored calculations.
1733 * Calls ReadSrcPsiDensity() and ReadSrcIons().
1734 * \param *P Problem at hand
1735 */
1736void ReadSrcFiles(struct Problem *P)
1737{
1738 if (P->Call.out[NormalOut]) fprintf(stderr, "(%i)ReadSrcPsiDensity\n", P->Par.me);
1739 ReadSrcPsiDensity(P, Occupied, 0, P->R.LevSNo);
1740 ReadSrcPsiDensity(P, UnOccupied, 0, P->R.LevSNo);
1741 if (P->Call.out[NormalOut]) fprintf(stderr, "(%i)ReadSrcIons\n", P->Par.me);
1742 ReadSrcIons(P);
1743}
1744
1745/** Plots a cut plane of the real density of one wave function.
1746 * \param *P Problem at hand
1747 * \param index index of axis (vector orthogonal to plane)
1748 * \param node node specifying where to cut at the given axis
1749 * \param wavenr global number of wave function
1750 * \param *density density array to plot
1751 * \sa PlotVectorPlane() - very similar
1752 */
1753void PlotSrcPlane(struct Problem *P, int index, double node, int wavenr, fftw_real *density)
1754{
1755 struct RunStruct *R = &P->R;
1756 struct Lattice *Lat = &P->Lat;
1757 struct LatticeLevel *Lev0 = R->Lev0;
1758 const int myPE = P->Par.me_comm_ST_Psi;
1759 char filename[255], spin[12];
1760 char *suchpointer;
1761 FILE *PlotFile = NULL;
1762 time_t seconds;
1763
1764
1765 // open file
1766 time(&seconds); // get current time
1767
1768 switch (Lat->Psi.PsiST) {
1769 case SpinDouble:
1770 sprintf(&filename[0], ".psi%i_cut%i.csv", wavenr, index);
1771 strncat(spin,"SpinDouble",12);
1772 break;
1773 case SpinUp:
1774 sprintf(&filename[0], ".psi%i_cut%i_up.csv", wavenr, index);
1775 strncat(spin,"SpinUp",12);
1776 break;
1777 case SpinDown:
1778 sprintf(&filename[0], ".psi%i_cut%i_down.csv", wavenr, index);
1779 strncat(spin,"SpinDown",12);
1780 break;
1781 }
1782
1783 if (!myPE) { // only process 0 writes to file
1784 OpenFile(P, &PlotFile, filename, "w", P->Call.out[ReadOut]);
1785 strcpy(filename, ctime(&seconds));
1786 suchpointer = strchr(filename, '\n');
1787 if (suchpointer != NULL)
1788 *suchpointer = '\0';
1789 if (PlotFile != NULL) {
1790 fprintf(PlotFile,"# Psi %i, type %s (real density) plot of plane perpendicular to direction e_%i at node %lg, seed %i, config %s, run on %s, #cpus %i", wavenr, spin, index, node, R->Seed, P->Files.default_path, filename, P->Par.Max_me_comm_ST_Psi);
1791 fprintf(PlotFile,"\n");
1792 } else { Error(SomeError, "PlotSrcPlane: Opening Plot File"); }
1793 }
1794
1795 // plot density
1796 PlotRealDensity(P, Lev0, PlotFile, index, node, density, density);
1797
1798 if (PlotFile != NULL) {
1799 // close file
1800 fclose(PlotFile);
1801 }
1802}
1803
1804/** plots a cut plane of a given 3d real density.
1805 * \param *P Problem at hand, contains pointer to Lattice structure
1806 * \param *Lev LatticeLevel of the real density
1807 * \param PlotFile file pointer (already open and valid)
1808 * \param index index of lattice axis
1809 * \param n_orth position on lattice axis where to cut
1810 * \param *density1 first real density array
1811 * \param *density2 second real density array (point to \a *density1 if not needed)
1812 */
1813void PlotRealDensity(struct Problem *P, struct LatticeLevel *Lev, FILE *PlotFile, int index, double n_orth, fftw_real *density1, fftw_real *density2)
1814{
1815 struct Lattice *Lat = &P->Lat;
1816 int n[NDIM], n0;
1817 int N[NDIM];
1818 N[0] = Lev->Plan0.plan->N[0];
1819 N[1] = Lev->Plan0.plan->N[1];
1820 N[2] = Lev->Plan0.plan->N[2];
1821 const int N0 = Lev->Plan0.plan->local_nx;
1822 const int myPE = P->Par.me_comm_ST_Psi;
1823 double fac[NDIM], x[NDIM];
1824 int i0, i = 0;
1825 int PE, zahl;
1826 double *buffer;
1827 MPI_Status status;
1828 int sizes[P->Par.Max_me_comm_ST_Psi], c0, c1;
1829 double nodes[NDIM], node[NDIM];
1830
1831 for(i=0;i<NDIM;i++) {
1832 nodes[i] = (i == index) ? n_orth : 0.;
1833 node[i] = 0.;
1834 }
1835 RMat33Vec3(node, Lat->ReciBasis, nodes); // transform cartesian coordinates into cell coordinates [0,1]^3
1836 for(i=0;i<NDIM;i++) // now N^3 within node range of discrete grid
1837 node[i] = (int)(node[i]*N[i]/(2.*PI));
1838 fprintf(stderr,"(%i) n_orth %lg, index %i converted to plane offset vector (%lg, %lg, %lg).\n", P->Par.me, n_orth, index, node[0], node[1], node[2]);
1839
1840 switch (index) {
1841 case 0:
1842 zahl = 4*N[1]*N[2];
1843 break;
1844 case 1:
1845 zahl = 4*N0*N[2];
1846 break;
1847 case 2:
1848 zahl = 4*N0*N[1];
1849 break;
1850 }
1851 fprintf(stderr,"(%i) buffer size %i\n", P->Par.me, zahl);
1852 buffer = Malloc(sizeof(double)*zahl,"PlotRealDensity: buffer");
1853
1854 c0 = cross(index,0);
1855 c1 = cross(index,1);
1856 // then for every point on the grid in real space ...
1857 i=0;
1858 for (n0=0;n0<N0;n0++) // only local points on x axis
1859 for (n[1]=0;n[1]<N[1];n[1]++)
1860 for (n[2]=0;n[2]<N[2];n[2]++) {
1861 n[0]=n0 + N0*myPE; // global relative coordinate: due to partitoning of x-axis in PEPGamma>1 case
1862 if (n[index] == (int)node[index]) { // only on the correct plane orthogonal to desired axis and at desired node ...
1863 fac[0] = (double)n[0]/(double)N[0];
1864 fac[1] = (double)n[1]/(double)N[1];
1865 fac[2] = (double)n[2]/(double)N[2];
1866 RMat33Vec3(x, Lat->RealBasis, fac); // relative coordinate times basis matrix gives absolute ones
1867 i0 = n[2]+N[2]*(n[1]+N[1]*n0); // index to local density array
1868
1869 buffer[i++] = x[c0]; // fill buffer
1870 buffer[i++] = x[c1];
1871 buffer[i++] = density1[i0];
1872 buffer[i++] = density2[i0];
1873 if (i > zahl) Error(SomeError, "PlotRealDensity: buffer too small!");
1874 }
1875 }
1876 // exchange sizes of each buffer
1877 MPI_Allgather(&i, 1, MPI_INT, sizes, 1, MPI_INT, P->Par.comm_ST_Psi);
1878 if (myPE == 0) {
1879 for (PE=0; PE < P->Par.Max_me_comm_ST_Psi; PE++) {
1880 if (PE != 0) {
1881 // receive them
1882 if (MPI_Recv(buffer, sizes[PE], MPI_DOUBLE, PE, PlotRealDensityTag, P->Par.comm_ST_Psi, &status) != MPI_SUCCESS)
1883 Error(SomeError, "PlotRealDensity: MPI_Recv failure!");
1884 MPI_Get_count(&status, MPI_DOUBLE, &zahl);
1885 if (zahl != sizes[PE])
1886 Error(SomeError, "PlotRealDensity: received unexpected amount of elements!");
1887 }
1888 //write them: local one (still in buffer) and received ones
1889 for (i0 = 0; i0 < sizes[PE];) {
1890 fprintf(PlotFile,"%e", buffer[(i0)++]);
1891 if ((i0 % 4) == 0) {
1892 fprintf(PlotFile,"\n");
1893 } else {
1894 fprintf(PlotFile,"\t");
1895 }
1896 }
1897 }
1898 } else { // send them
1899 if (MPI_Send(buffer, i, MPI_DOUBLE, 0, PlotRealDensityTag, P->Par.comm_ST_Psi) != MPI_SUCCESS)
1900 Error(SomeError, "PlotRealDensity: MPI_Send failure!");
1901 }
1902 Free(buffer, "PlotRealDensity: buffer");
1903}
Note: See TracBrowser for help on using the repository browser.