source: pcp/src/output.c@ 08e223

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

CallOptions#ReadSrcFile is now enumerated ParseSrcDensities

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

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