source: pcp/src/output.c@ 3021d93

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

Merge branch 'ConcaveHull' of ../espack2 into ConcaveHull

Conflicts:

molecuilder/src/boundary.cpp
molecuilder/src/boundary.hpp
molecuilder/src/builder.cpp
molecuilder/src/linkedcell.cpp
molecuilder/src/linkedcell.hpp
molecuilder/src/vector.cpp
molecuilder/src/vector.hpp
util/src/NanoCreator.c

Basically, this resulted from a lot of conversions two from spaces to one tab, which is my standard indentation. The mess was caused by eclipse auto-indenting. And in espack2:ConcaveHull was the new stuff, so all from ConcaveHull was replaced in case of doubt.
Additionally, vector had ofstream << operator instead ostream << ...

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