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