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