| [a0bcf1] | 1 | /** \file helpers.c | 
|---|
|  | 2 | * Malloc-, Realloc-, Free-wrappers and other small routines. | 
|---|
|  | 3 | * | 
|---|
|  | 4 | * This file contains small helpful routines that do such omnipresent tasks | 
|---|
|  | 5 | * as allocation memory Malloc(), Malloci(), Mallocii(), reallocating Realloc(), | 
|---|
|  | 6 | * Realloci(), Reallocii() or disallocating Free() with checks error messages | 
|---|
|  | 7 | * in the case of failure. Speed Measuring is initiated InitSpeedMeasure() by setting | 
|---|
|  | 8 | * SpeedStruct entries to zero, | 
|---|
|  | 9 | * completed for output to file CompleteSpeedMeasure() and actually performed | 
|---|
|  | 10 | * SpeedMeasure() herein.\n | 
|---|
|  | 11 | * RemoveEverything() frees all memory that was alloceted during the course of the | 
|---|
|  | 12 | * programme.\n | 
|---|
|  | 13 | * StartParallel() initializes process groups and ranks, while WaitForOtherProcs() | 
|---|
|  | 14 | * waits for the other running processes between the end of init phase and the begin | 
|---|
|  | 15 | * of the calculation.\n | 
|---|
|  | 16 | * Finally, GetRGB() does a colour translation of an RGB value from integer but it's | 
|---|
|  | 17 | * not used anymore. | 
|---|
|  | 18 | * | 
|---|
|  | 19 | Project: ParallelCarParrinello | 
|---|
|  | 20 | \author Jan Hamaekers | 
|---|
|  | 21 | \date 2000 | 
|---|
|  | 22 |  | 
|---|
|  | 23 | File: helpers.c | 
|---|
|  | 24 | $Id: helpers.c,v 1.39 2007-02-12 09:44:55 foo Exp $ | 
|---|
|  | 25 | */ | 
|---|
|  | 26 |  | 
|---|
|  | 27 | #include <stdlib.h> | 
|---|
|  | 28 | #include <stdio.h> | 
|---|
|  | 29 | #include <stddef.h> | 
|---|
|  | 30 | #include <math.h> | 
|---|
|  | 31 | #include <string.h> | 
|---|
|  | 32 | #include "data.h" | 
|---|
|  | 33 | #include "errors.h" | 
|---|
|  | 34 | #include "helpers.h" | 
|---|
|  | 35 | #include "grad.h" | 
|---|
|  | 36 | #include "pseudo.h" | 
|---|
|  | 37 | #include "ions.h" | 
|---|
|  | 38 | #include "output.h" | 
|---|
|  | 39 | #include "run.h" | 
|---|
|  | 40 | #include "gramsch.h" | 
|---|
|  | 41 | #include "mymath.h" | 
|---|
|  | 42 | #include "myfft.h" | 
|---|
|  | 43 | #include "perturbed.h" | 
|---|
|  | 44 |  | 
|---|
|  | 45 | /** Output of a debug message to stderr. | 
|---|
|  | 46 | * \param *P Problem at hand, points to ParallelSimulationData#me | 
|---|
|  | 47 | * \param output output string | 
|---|
|  | 48 | */ | 
|---|
| [9275a3] | 49 | #ifdef HAVE_DEBUG | 
|---|
|  | 50 | void debug_in(struct Problem *P, const char *output, const char *file, const int line) { | 
|---|
|  | 51 | if (output) fprintf(stderr,"(%i) DEBUG: in %s at line %i: %s\n",P->Par.me, file, line, output); | 
|---|
| [a0bcf1] | 52 | } | 
|---|
| [9275a3] | 53 | #else | 
|---|
|  | 54 | void debug_in(struct Problem *P, const char *output, const char *file, const int line) {}  // print nothing | 
|---|
|  | 55 | #endif | 
|---|
| [a0bcf1] | 56 |  | 
|---|
|  | 57 | /** Malloc with error check. | 
|---|
|  | 58 | * malloc() wrapper, printing error on null pointer | 
|---|
|  | 59 | * \param size size of memory to be allocated | 
|---|
|  | 60 | * \param output error message to be given on failure | 
|---|
|  | 61 | */ | 
|---|
|  | 62 | void* Malloc(size_t size, const char* output) | 
|---|
|  | 63 | { | 
|---|
|  | 64 | void* dummy = malloc(size); | 
|---|
|  | 65 | if (!dummy) | 
|---|
|  | 66 | Error(MallocError, output); | 
|---|
|  | 67 | return dummy; | 
|---|
|  | 68 | } | 
|---|
|  | 69 |  | 
|---|
|  | 70 | /** Malloc string array and set its length to the allocated length. | 
|---|
|  | 71 | * \param *output message if malloc fails | 
|---|
|  | 72 | * \param size number of chars to alloc for \a *buffer | 
|---|
|  | 73 | * \return pointer to string array | 
|---|
|  | 74 | */ | 
|---|
|  | 75 | char* MallocString(size_t size, const char* output) { | 
|---|
|  | 76 | int i; | 
|---|
|  | 77 | char *buffer; | 
|---|
|  | 78 | buffer = Malloc(sizeof(char) * (size+1), output); // alloc | 
|---|
|  | 79 | for (i=0;i<size;i++)  // reset | 
|---|
|  | 80 | buffer[i] = i % 2 == 0 ? 'p': 'c'; | 
|---|
|  | 81 | buffer[size] = '\0'; // and set length marker on its end | 
|---|
|  | 82 | return(buffer); | 
|---|
|  | 83 | } | 
|---|
|  | 84 |  | 
|---|
|  | 85 |  | 
|---|
|  | 86 | /** Malloc with error check and 1 int. | 
|---|
|  | 87 | * malloc() wrapper, printing error on null pointer | 
|---|
|  | 88 | * \param size size of memory to be allocated | 
|---|
|  | 89 | * \param output error message to be given on failure (containing one %d or similar) | 
|---|
|  | 90 | * \param i integer value to be put into error message (%d in output) | 
|---|
|  | 91 | */ | 
|---|
|  | 92 | void* Malloci(size_t size, const char* output, int i) | 
|---|
|  | 93 | { | 
|---|
| [c510a7] | 94 | char dummyoutput[MAXSTRINGSIZE]; | 
|---|
| [a0bcf1] | 95 | void* dummy = (void *) malloc(size); | 
|---|
|  | 96 | if (!dummy) { | 
|---|
|  | 97 | sprintf(dummyoutput,output,i); | 
|---|
|  | 98 | Error(MallocError, dummyoutput); | 
|---|
|  | 99 | } | 
|---|
|  | 100 | return dummy; | 
|---|
|  | 101 | } | 
|---|
|  | 102 |  | 
|---|
|  | 103 | /** Malloc with error check and 2 ints. | 
|---|
|  | 104 | * malloc() wrapper, printing error on null pointer | 
|---|
|  | 105 | * \param size size of memory to be allocated | 
|---|
|  | 106 | * \param output error message to be given on failure (containing two %d or similar) | 
|---|
|  | 107 | * \param i first integer value to be put into error message (%d in output) | 
|---|
|  | 108 | * \param j second integer value to be put into error message (%d in output) | 
|---|
|  | 109 | */ | 
|---|
|  | 110 | void* Mallocii(size_t size, const char* output, int i, int j) | 
|---|
|  | 111 | { | 
|---|
| [c510a7] | 112 | char dummyoutput[MAXSTRINGSIZE]; | 
|---|
| [a0bcf1] | 113 | void* dummy = (void *) malloc(size); | 
|---|
|  | 114 | if (!dummy) { | 
|---|
|  | 115 | sprintf(dummyoutput,output,i,j); | 
|---|
|  | 116 | Error(MallocError, dummyoutput); | 
|---|
|  | 117 | } | 
|---|
|  | 118 | return dummy; | 
|---|
|  | 119 | } | 
|---|
|  | 120 |  | 
|---|
|  | 121 | /** Change size of allocated memory range. | 
|---|
|  | 122 | * Wrapper for realloc(), giving error message on failure | 
|---|
|  | 123 | * \param pointer points to allocated memory | 
|---|
|  | 124 | * \param size new desired size | 
|---|
|  | 125 | * \param output error message on failure | 
|---|
|  | 126 | */ | 
|---|
|  | 127 | void* Realloc(void* pointer, size_t size, const char* output) | 
|---|
|  | 128 | { | 
|---|
|  | 129 | void *dummy = (void *) realloc(pointer, size); | 
|---|
|  | 130 | if (!dummy) | 
|---|
|  | 131 | Error(MallocError, output); | 
|---|
|  | 132 | return dummy; | 
|---|
|  | 133 | } | 
|---|
|  | 134 |  | 
|---|
|  | 135 | /** Change size of allocated memory range, 1 int in error msg. | 
|---|
|  | 136 | * Wrapper for realloc(), giving error message on failure | 
|---|
|  | 137 | * \param pointer points to allocated memory | 
|---|
|  | 138 | * \param size new desired size | 
|---|
|  | 139 | * \param output error message on failure (containing one %d or similar) | 
|---|
|  | 140 | * \param i integer in error message | 
|---|
|  | 141 | */ | 
|---|
|  | 142 | void* Realloci(void* pointer, size_t size, const char* output, int i) | 
|---|
|  | 143 | { | 
|---|
| [c510a7] | 144 | char dummyoutput[MAXSTRINGSIZE]; | 
|---|
| [a0bcf1] | 145 | void *dummy = (void *) realloc(pointer, size); | 
|---|
|  | 146 | if (!dummy) { | 
|---|
|  | 147 | sprintf(dummyoutput, output, i); | 
|---|
|  | 148 | Error(MallocError, dummyoutput); | 
|---|
|  | 149 | } | 
|---|
|  | 150 | return dummy; | 
|---|
|  | 151 | } | 
|---|
|  | 152 |  | 
|---|
|  | 153 | /** Change size of allocated memory range, 2 int in error msg. | 
|---|
|  | 154 | * Wrapper for realloc(), giving error message on failure | 
|---|
|  | 155 | * \param pointer points to allocated memory | 
|---|
|  | 156 | * \param size new desired size | 
|---|
|  | 157 | * \param output error message on failure (containing two %d or similar) | 
|---|
|  | 158 | * \param i first integer in error message | 
|---|
|  | 159 | * \param j second integer in error message | 
|---|
|  | 160 | */ | 
|---|
|  | 161 | void* Reallocii(void* pointer, size_t size, const char* output, int i, int j) | 
|---|
|  | 162 | { | 
|---|
| [c510a7] | 163 | char dummyoutput[MAXSTRINGSIZE]; | 
|---|
| [a0bcf1] | 164 | void *dummy = (void *) realloc(pointer, size); | 
|---|
|  | 165 | if (!dummy) { | 
|---|
|  | 166 | sprintf(dummyoutput,output,i,j); | 
|---|
|  | 167 | Error(MallocError, dummyoutput); | 
|---|
|  | 168 | } | 
|---|
|  | 169 | return dummy; | 
|---|
|  | 170 | } | 
|---|
|  | 171 |  | 
|---|
|  | 172 | /** Free memory with error check. | 
|---|
|  | 173 | * Wrapper for free(), free is only called on given non-null pointer | 
|---|
|  | 174 | * \param *ptr pointer to allocated memory region | 
|---|
| [9275a3] | 175 | * \param *output message to print on failure | 
|---|
| [a0bcf1] | 176 | */ | 
|---|
| [9275a3] | 177 | void Free (void *ptr, const char* output) { | 
|---|
|  | 178 | if (ptr != NULL) | 
|---|
|  | 179 | free(ptr); | 
|---|
|  | 180 | else | 
|---|
|  | 181 | fprintf(stderr,"Free not necessary: %s\n", output); | 
|---|
| [a0bcf1] | 182 | } | 
|---|
|  | 183 |  | 
|---|
|  | 184 | /** Translates a given integer into color code | 
|---|
|  | 185 | * The value is interpreted by powers of the range into an rgb set of | 
|---|
|  | 186 | * values. | 
|---|
|  | 187 | * \param i specifies value within the range | 
|---|
|  | 188 | * \param max   specifies color range | 
|---|
|  | 189 | * \param rgb pointer to double[3] | 
|---|
|  | 190 | */ | 
|---|
|  | 191 | void GetRGB(int i, unsigned int max, double* rgb) { | 
|---|
|  | 192 | int basis,basis2,basis3; | 
|---|
|  | 193 | int maxRGB,RGBint; | 
|---|
|  | 194 | int rgbint[3]; | 
|---|
|  | 195 | i++; | 
|---|
|  | 196 | if (max <= 1) max = 2; /* keine Division durch 0 */ | 
|---|
|  | 197 | basis = ceil(pow((double)(max+1),1./3.)); | 
|---|
|  | 198 | basis2 = basis*basis; | 
|---|
|  | 199 | basis3 = basis2*basis; | 
|---|
|  | 200 | maxRGB = basis3-1; | 
|---|
|  | 201 | /* Koordinatentrans von 1..max -> 1..maxRGB */ | 
|---|
|  | 202 | RGBint = floor(1. + (double)(maxRGB - 1)/(double)(max-1)*(double)(i-1)); | 
|---|
|  | 203 | /* Transferiere RGBint jetzt in Basisdarstellung */ | 
|---|
|  | 204 | rgbint[2] = RGBint/basis2; | 
|---|
|  | 205 | RGBint %= basis2; | 
|---|
|  | 206 | rgbint[1] = RGBint/basis; | 
|---|
|  | 207 | rgbint[0] = RGBint%basis; | 
|---|
|  | 208 | /* Jetzt Basisdarstellung in rgb darstellung */ | 
|---|
|  | 209 | rgb[2] = rgbint[2]*(1./(basis-1)); | 
|---|
|  | 210 | rgb[1] = rgbint[1]*(1./(basis-1)); | 
|---|
|  | 211 | rgb[0] = rgbint[0]*(1./(basis-1)); | 
|---|
|  | 212 | } | 
|---|
|  | 213 |  | 
|---|
|  | 214 | /** Waits for other processes to finish. | 
|---|
|  | 215 | * Simply waits until all processes reach this routine for the MPI_Gather to work | 
|---|
|  | 216 | * \param *P Problem at hand | 
|---|
|  | 217 | * \param out   1 - output ready note, 0 - no output | 
|---|
|  | 218 | */ | 
|---|
|  | 219 | void WaitForOtherProcs(struct Problem *P, int out) { | 
|---|
|  | 220 | /* Warte, bis alle fertig sind! */ | 
|---|
|  | 221 | int buffint = 0; | 
|---|
|  | 222 | MPI_Gather(&buffint, 0, MPI_INT, &buffint, 0, MPI_INT, 0, P->Par.comm); | 
|---|
|  | 223 | if(out && P->Call.out[MinOut]) fprintf(stderr,"\nAll procs ready: %i\n",P->Par.me); | 
|---|
|  | 224 | } | 
|---|
|  | 225 |  | 
|---|
|  | 226 | /** Initialization for parallel computing. | 
|---|
|  | 227 | * determines process ids and defines mpi groups (aka Communicators), being | 
|---|
|  | 228 | * the ones working on the same Psi (when doing fft) and those working on the | 
|---|
|  | 229 | * same section (transposed GramSchmidt) | 
|---|
|  | 230 | * \param *P Problem at hand | 
|---|
|  | 231 | * \param **argv is actually unnecessary | 
|---|
|  | 232 | */ | 
|---|
|  | 233 | void StartParallel (struct Problem *P, char **argv) { | 
|---|
|  | 234 | int info; | 
|---|
|  | 235 | char processor_name[MPI_MAX_PROCESSOR_NAME]; | 
|---|
| [c510a7] | 236 | char dummy[MAXSTRINGSIZE]; | 
|---|
| [a0bcf1] | 237 | P->Par.procs = P->Par.proc[PEPsi]*P->Par.proc[PEGamma]; | 
|---|
|  | 238 | P->Par.me = -1; /* eigene Position noch unklar */ | 
|---|
|  | 239 | /* MPI Initialisierung */ | 
|---|
|  | 240 | argv = argv; /* wird nicht benoetigt */ | 
|---|
|  | 241 | /* mpi Gruppen definieren */ | 
|---|
|  | 242 | P->Par.world = MPI_COMM_WORLD; | 
|---|
|  | 243 | MPI_Comm_dup(P->Par.world, &P->Par.comm); | 
|---|
|  | 244 | MPI_Comm_size(P->Par.comm, &info); | 
|---|
|  | 245 | if (info != P->Par.procs) { | 
|---|
|  | 246 | sprintf(dummy,"StartParallel. Wrong number of processes started %i != %i",info, P->Par.procs); | 
|---|
|  | 247 | Error(SomeError, dummy); | 
|---|
|  | 248 | } | 
|---|
|  | 249 | MPI_Comm_rank(P->Par.comm, &P->Par.mytid); | 
|---|
|  | 250 | MPI_Get_processor_name(processor_name, &info); | 
|---|
|  | 251 | P->Par.me = P->Par.mytid; | 
|---|
|  | 252 | P->Par.mypos[PEGamma] = P->Par.me % P->Par.proc[PEGamma]; | 
|---|
|  | 253 | P->Par.mypos[PEPsi] = P->Par.me / P->Par.proc[PEGamma]; | 
|---|
|  | 254 | if(P->Call.out[NormalOut]) fprintf(stderr,"Process %d(%i,%i) on %s \n", P->Par.mytid, P->Par.mypos[PEPsi], P->Par.mypos[PEGamma], processor_name); | 
|---|
|  | 255 | if (P->Par.me == 0) { /* Master */ | 
|---|
|  | 256 | if (P->Par.procs > 9999) | 
|---|
|  | 257 | fprintf(stderr, "(%d)Warning: procs>9999 will cause trouble with output files\n", P->Par.mytid); | 
|---|
|  | 258 | } | 
|---|
|  | 259 | if(P->Call.out[MinOut]) fprintf(stderr,"Info: %i processes started\n", P->Par.procs); /* Prozesse gestartet */ | 
|---|
|  | 260 |  | 
|---|
|  | 261 |  | 
|---|
|  | 262 | /* Erstellung der Communicatoren */ | 
|---|
|  | 263 | switch (P->Lat.Psi.Use) { | 
|---|
|  | 264 | case UseSpinDouble: | 
|---|
|  | 265 | P->Par.my_color_comm_ST = (int)SpinDouble; | 
|---|
|  | 266 | P->Par.me_comm_ST = P->Par.me; | 
|---|
|  | 267 | P->Par.Max_my_color_comm_ST = 1; | 
|---|
|  | 268 | P->Par.Max_me_comm_ST = P->Par.procs; | 
|---|
|  | 269 | break; | 
|---|
|  | 270 | case UseSpinUpDown: | 
|---|
|  | 271 | P->Par.my_color_comm_ST = P->Par.me / (P->Par.procs/2); | 
|---|
|  | 272 | P->Par.me_comm_ST = P->Par.me % (P->Par.procs/2); | 
|---|
|  | 273 | P->Par.Max_my_color_comm_ST = 2; | 
|---|
|  | 274 | P->Par.Max_me_comm_ST = P->Par.procs/2; | 
|---|
|  | 275 | break; | 
|---|
|  | 276 | } | 
|---|
|  | 277 | MPI_Comm_split (P->Par.comm, P->Par.my_color_comm_ST, P->Par.me_comm_ST, &P->Par.comm_ST); | 
|---|
|  | 278 | if (P->Lat.Psi.Use == UseSpinUpDown) { | 
|---|
|  | 279 | MPI_Intercomm_create ( P->Par.comm_ST, 0, P->Par.comm, | 
|---|
|  | 280 | (P->Par.my_color_comm_ST ? 0 : P->Par.procs/2) | 
|---|
|  | 281 | , InterTag1, &P->Par.comm_STInter); | 
|---|
|  | 282 | } | 
|---|
|  | 283 |  | 
|---|
|  | 284 | /* Alle Procs mit gleichen Psis (Sind alle an einer fft beteiligt)*/ | 
|---|
|  | 285 | P->Par.my_color_comm_ST_Psi = P->Par.me_comm_ST / P->Par.proc[PEGamma]; | 
|---|
|  | 286 | P->Par.me_comm_ST_Psi = P->Par.me_comm_ST % P->Par.proc[PEGamma]; | 
|---|
|  | 287 | P->Par.Max_my_color_comm_ST_Psi =  P->Par.Max_me_comm_ST/P->Par.proc[PEGamma]; | 
|---|
|  | 288 | P->Par.Max_me_comm_ST_Psi = P->Par.proc[PEGamma]; | 
|---|
|  | 289 | MPI_Comm_split (P->Par.comm_ST, P->Par.my_color_comm_ST_Psi, P->Par.me_comm_ST_Psi, &P->Par.comm_ST_Psi); | 
|---|
|  | 290 |  | 
|---|
|  | 291 | /* Alle Procs mit gleichen PsisAbschnitt (Transposed Psi - GramSch)*/ | 
|---|
|  | 292 | P->Par.my_color_comm_ST_PsiT = P->Par.me_comm_ST % P->Par.proc[PEGamma]; | 
|---|
|  | 293 | P->Par.me_comm_ST_PsiT = P->Par.me_comm_ST / P->Par.proc[PEGamma]; | 
|---|
|  | 294 | P->Par.Max_my_color_comm_ST_PsiT = P->Par.proc[PEGamma]; | 
|---|
|  | 295 | P->Par.Max_me_comm_ST_PsiT = P->Par.Max_me_comm_ST/P->Par.proc[PEGamma]; | 
|---|
|  | 296 | MPI_Comm_split (P->Par.comm_ST, P->Par.my_color_comm_ST_PsiT, P->Par.me_comm_ST_PsiT, &P->Par.comm_ST_PsiT); | 
|---|
|  | 297 | } | 
|---|
|  | 298 |  | 
|---|
|  | 299 |  | 
|---|
|  | 300 | /** Removes everything from memory. | 
|---|
|  | 301 | * Frees memory and exits program | 
|---|
|  | 302 | * \param *P Problem at hand | 
|---|
|  | 303 | */ | 
|---|
|  | 304 | void RemoveEverything(struct Problem *P) | 
|---|
|  | 305 | { | 
|---|
|  | 306 | struct Lattice *Lat = &P->Lat; | 
|---|
|  | 307 | struct Psis *Psi = &Lat->Psi; | 
|---|
|  | 308 | int i,d, type; | 
|---|
|  | 309 | if (P->Call.out[NormalOut]) fprintf(stderr,"(%i)RemoveEverything !\n",P->Par.me); | 
|---|
|  | 310 | RemoveGradients(P, &P->Grad); | 
|---|
|  | 311 | RemovePseudoRead(P); | 
|---|
|  | 312 | RemoveIonsRead(&P->Ion); | 
|---|
|  | 313 | fft_3d_destroy_plan(P,P->Lat.plan); | 
|---|
|  | 314 | if (P->Files.MeOutVis) { | 
|---|
| [9275a3] | 315 | Free(P->Files.PosTemp, "RemoveEverything: P->Files.PosTemp"); | 
|---|
|  | 316 | Free(P->Files.OutputPosType, "RemoveEverything: P->Files.OutputPosType"); | 
|---|
| [90c027] | 317 | Free(P->Files.OutVisStep, "RemoveEverything: P->Files.OutVisStep"); | 
|---|
| [a0bcf1] | 318 | } | 
|---|
| [9275a3] | 319 | Free(P->Files.mainname, "RemoveEverything: P->Files.mainname"); | 
|---|
|  | 320 | Free(P->Files.mainpath, "RemoveEverything: P->Files.mainpath"); | 
|---|
|  | 321 | Free(P->Call.MainParameterFile, "RemoveEverything: P->Call.MainParameterFile"); | 
|---|
|  | 322 | if (P->Call.ForcesFile != NULL) | 
|---|
|  | 323 | Free(P->Call.ForcesFile, "RemoveEverything: P->Call.ForcesFile"); | 
|---|
|  | 324 | Free(Lat->MaxNoOfnFields, "RemoveEverything: Lat->MaxNoOfnFields"); | 
|---|
| [a0bcf1] | 325 | for (i=0; i < P->Lat.MaxLevel; i++) { | 
|---|
| [9275a3] | 326 | Free(Lat->Lev[i].AllMaxG, "RemoveEverything: Lat->Lev[i].AllMaxG"); | 
|---|
|  | 327 | Free(Lat->NFields[i], "RemoveEverything: Lat->NFields"); | 
|---|
|  | 328 | Free(Lat->Lev[i].GArray, "RemoveEverything: Lat->Lev[i].GArray"); | 
|---|
|  | 329 | Free(Lat->Lev[i].HashG, "RemoveEverything: Lat->Lev[i].HashG"); | 
|---|
| [a0bcf1] | 330 | if (Lat->Lev[i].MaxDoubleG) | 
|---|
| [9275a3] | 331 | Free(Lat->Lev[i].DoubleG, "RemoveEverything: Lat->Lev[i].DoubleG"); | 
|---|
| [a0bcf1] | 332 | if (i != 0) { | 
|---|
| [9275a3] | 333 | Free(Lat->Lev[i].PosFactorUp, "RemoveEverything: Lat->Lev[i].PosFactorUp"); | 
|---|
| [a0bcf1] | 334 | } else { | 
|---|
|  | 335 | for (d=0; d < (P->R.DoPerturbation == 1 ? MaxDensityTypes : MaxInitDensityTypes); d++) { | 
|---|
| [9275a3] | 336 | if (Lat->Lev[i].Dens->DensityArray[d] != NULL) Free(Lat->Lev[i].Dens->DensityArray[d], "RemoveEverything: Lat->Lev[i].Dens->DensityArray[d]"); | 
|---|
|  | 337 | if (Lat->Lev[i].Dens->DensityCArray[d] != NULL) Free(Lat->Lev[i].Dens->DensityCArray[d], "RemoveEverything: Lat->Lev[i].Dens->DensityCArray[d]"); | 
|---|
| [a0bcf1] | 338 | } | 
|---|
|  | 339 | } | 
|---|
|  | 340 | /* if (i != Lat->MaxLevel-1) */ | 
|---|
| [9275a3] | 341 | Free(Lat->Lev[i].Dens, "RemoveEverything: Lat->Lev[i].Dens"); | 
|---|
| [a0bcf1] | 342 | } | 
|---|
|  | 343 | for (i=1; i < Lat->MaxLevel; i++) { | 
|---|
| [9275a3] | 344 | Free(Lat->Lev[i].LPsi->LocalPsi, "RemoveEverything: Lat->Lev[i].LPsi->LocalPsi"); | 
|---|
|  | 345 | Free(Lat->Lev[i].LPsi->OldLocalPsi, "RemoveEverything: Lat->Lev[i].LPsi->OldLocalPsi"); | 
|---|
| [a0bcf1] | 346 | if (i == 1) { | 
|---|
| [9275a3] | 347 | Free(Lat->Lev[i].LPsi->PsiDat, "RemoveEverything: Lat->Lev[i].LPsi->PsiDat"); | 
|---|
|  | 348 | Free(Lat->Lev[i].LPsi->OldPsiDat, "RemoveEverything: Lat->Lev[i].LPsi->OldPsiDat"); | 
|---|
| [a0bcf1] | 349 | } | 
|---|
| [9275a3] | 350 | Free(Lat->Lev[i].LPsi, "RemoveEverything: Lat->Lev[i].LPsi"); | 
|---|
| [a0bcf1] | 351 | } | 
|---|
|  | 352 | for (i=0;i<Lat->Psi.NoOfTotalPsis;i++) { | 
|---|
| [9275a3] | 353 | Free(Psi->lambda[i], "RemoveEverything: Psi->lambda[i]"); | 
|---|
| [a0bcf1] | 354 | } | 
|---|
|  | 355 | for (i=0;i<Lat->Psi.NoOfPsis;i++) { | 
|---|
| [9275a3] | 356 | Free(Psi->Overlap[i], "RemoveEverything: Psi->Overlap[i]"); | 
|---|
| [a0bcf1] | 357 | } | 
|---|
| [9275a3] | 358 | Free(Psi->lambda, "RemoveEverything: Psi->lambda"); | 
|---|
|  | 359 | Free(Psi->Overlap, "RemoveEverything: Psi->Overlap"); | 
|---|
|  | 360 | Free(Psi->AllPsiStatus, "RemoveEverything: Psi->AllPsiStatus"); | 
|---|
|  | 361 | Free(Psi->AllPsiStatusForSort, "RemoveEverything: Psi->AllPsiStatusForSort"); | 
|---|
|  | 362 | Free(Psi->LocalPsiStatus, "RemoveEverything: Psi->LocalPsiStatus"); | 
|---|
|  | 363 | Free(Psi->AllLocalNo, "RemoveEverything: Psi->AllLocalNo"); | 
|---|
|  | 364 | Free(Psi->RealAllLocalNo, "RemoveEverything: Psi->RealAllLocalNo"); | 
|---|
|  | 365 | Free(Psi->TempSendA, "RemoveEverything: Psi->TempSendA"); | 
|---|
|  | 366 | Free(Psi->AddData, "RemoveEverything: Psi->AddData"); | 
|---|
|  | 367 | Free(Psi->AllActualLocalPsiNo, "RemoveEverything: Psi->AllActualLocalPsiNo"); | 
|---|
|  | 368 | Free(Psi->AllOldActualLocalPsiNo, "RemoveEverything: Psi->AllOldActualLocalPsiNo"); | 
|---|
|  | 369 | Free(Lat->Lev, "RemoveEverything: Lat->Lev"); | 
|---|
|  | 370 | Free(Lat->LevelSizes, "RemoveEverything: Lat->LevelSizes"); | 
|---|
|  | 371 | Free(Lat->NFields, "RemoveEverything: Lat->NFields"); | 
|---|
| [a0bcf1] | 372 | if (Lat->RT.Use == UseRT) { | 
|---|
| [9275a3] | 373 | Free(Lat->RT.Coeff, "RemoveEverything: Lat->RT.Coeff"); | 
|---|
|  | 374 | Free(Lat->RT.RTLaplaceS, "RemoveEverything: Lat->RT.RTLaplaceS"); | 
|---|
|  | 375 | Free(Lat->RT.RTLaplace0, "RemoveEverything: Lat->RT.RTLaplace0"); | 
|---|
|  | 376 | for (i=0; i< MAXRTPOSFAC; i++) Free(Lat->RT.PosFactor[i], "RemoveEverything: Lat->RT.PosFactor[i]"); | 
|---|
| [a0bcf1] | 377 | for (i=0; i< MAXRTARRAYS; i++) { | 
|---|
| [9275a3] | 378 | Free(Lat->RT.DensityC[i], "RemoveEverything: Lat->RT.DensityC[i]"); | 
|---|
| [a0bcf1] | 379 | } | 
|---|
| [9275a3] | 380 | Free(Lat->RT.TempC, "RemoveEverything: Lat->RT.TempC"); | 
|---|
| [a0bcf1] | 381 | } | 
|---|
|  | 382 | for (type=Occupied;type<Extra;type++) | 
|---|
|  | 383 | for (i=0; i<MAXALLPSIENERGY; i++) { | 
|---|
| [9275a3] | 384 | Free(Lat->Energy[type].PsiEnergy[i], "RemoveEverything: Lat->Energy[type].PsiEnergy[i]"); | 
|---|
| [a0bcf1] | 385 | } | 
|---|
|  | 386 | for (i=Occupied;i<Extra;i++) | 
|---|
| [9275a3] | 387 | Free(P->R.MinimisationName[i], "RemoveEverything: P->R.MinimisationName[i]"); | 
|---|
|  | 388 | Free(P->R.MinimisationName, "RemoveEverything: P->R.MinimisationName"); | 
|---|
| [a0bcf1] | 389 | MPI_Comm_free(&P->Par.comm_ST_PsiT); | 
|---|
|  | 390 | //debug(P,"comm_ST_PsiT"); | 
|---|
|  | 391 | MPI_Comm_free(&P->Par.comm_ST_Psi); | 
|---|
|  | 392 | //debug(P,"comm_ST_Psi"); | 
|---|
|  | 393 | if (Psi->Use == UseSpinUpDown) MPI_Comm_free(&P->Par.comm_STInter); | 
|---|
|  | 394 | MPI_Comm_free(&P->Par.comm_ST); | 
|---|
|  | 395 | //debug(P,"comm_ST"); | 
|---|
|  | 396 | MPI_Comm_free(&P->Par.comm); | 
|---|
|  | 397 | //debug(P,"comm"); | 
|---|
| [9275a3] | 398 | Free(P, "RemoveEverything: P"); | 
|---|
| [a0bcf1] | 399 | FreeMPI_OnePsiElement(); | 
|---|
| [9275a3] | 400 | //debug(P,"OnePsiElement"); | 
|---|
| [a0bcf1] | 401 |  | 
|---|
|  | 402 | // Free string names from Files structure | 
|---|
| [9275a3] | 403 | Free(P->Files.filename, "RemoveEverything: P->Files.filename"); | 
|---|
|  | 404 | Free(P->Files.default_path, "RemoveEverything: P->Files.default_path"); | 
|---|
|  | 405 | Free(P->Files.pseudopot_path, "RemoveEverything: P->Files.pseudopot_path"); | 
|---|
| [a0bcf1] | 406 | } | 
|---|
|  | 407 |  | 
|---|
|  | 408 | static const char suffixspeed[] = ".speed";             //!< suffix of the FileData#SpeedFile where the timings are written to | 
|---|
|  | 409 |  | 
|---|
|  | 410 |  | 
|---|
|  | 411 | /** Initializes the timer array. | 
|---|
|  | 412 | * Sets every time, average, min/max and deviation to zero. | 
|---|
|  | 413 | * SpeedStep is set to 1. | 
|---|
|  | 414 | * Opens Filedata::SpeedFile for appended writing | 
|---|
|  | 415 | * \param *P Problem at hand | 
|---|
|  | 416 | */ | 
|---|
|  | 417 | void InitSpeedMeasure(struct Problem *P) | 
|---|
|  | 418 | { | 
|---|
|  | 419 | struct FileData *F = &P->Files; | 
|---|
|  | 420 | struct SpeedStruct *S = &P->Speed; | 
|---|
|  | 421 | int i; | 
|---|
|  | 422 | F->SpeedFile = NULL; | 
|---|
|  | 423 | if (P->Par.me == 0) | 
|---|
|  | 424 | OpenFile(P, &F->SpeedFile, suffixspeed, "a",P->Call.out[ReadOut]); | 
|---|
|  | 425 | for (i=0; i < MAXTIMETYPES; i++) | 
|---|
|  | 426 | S->SpeedStep[i] = 1; | 
|---|
|  | 427 | SetArrayToDouble0(S->time1,MAXTIMETYPES); | 
|---|
|  | 428 | SetArrayToDouble0(S->time2,MAXTIMETYPES); | 
|---|
|  | 429 | SetArrayToDouble0(S->time,MAXTIMETYPES); | 
|---|
|  | 430 | SetArrayToDouble0(S->average,MAXTIMETYPES); | 
|---|
|  | 431 | SetArrayToDouble0(S->min,MAXTIMETYPES); | 
|---|
|  | 432 | SetArrayToDouble0(S->max,MAXTIMETYPES); | 
|---|
|  | 433 | SetArrayToDouble0(S->stddev,MAXTIMETYPES); | 
|---|
|  | 434 | S->InitSteps = 0; | 
|---|
|  | 435 | S->LevUpSteps = 0; | 
|---|
|  | 436 | S->Steps = 0; | 
|---|
|  | 437 | } | 
|---|
|  | 438 |  | 
|---|
|  | 439 | /** Measure speed of a routine. | 
|---|
|  | 440 | * Points to SpeedStruct of the Problem, gets current time and depending on | 
|---|
|  | 441 | * \a TOT (whether we start or stop the watch) and the timing group \a TT | 
|---|
|  | 442 | * puts time in SpeedStruct::time1 (start) or in SpeedStruct::time2 (stop) | 
|---|
|  | 443 | * and in SpeedStruct::time the difference between the two is added. | 
|---|
|  | 444 | * \param *P Problem at hand containing SpeedStruct | 
|---|
|  | 445 | * \param TT TimeTypes | 
|---|
|  | 446 | * \param TOT TimeDotypes | 
|---|
|  | 447 | */ | 
|---|
|  | 448 | void SpeedMeasure(struct Problem *P, enum TimeTypes TT, enum TimeDoTypes TOT) | 
|---|
|  | 449 | { | 
|---|
|  | 450 | struct SpeedStruct *S = &P->Speed; | 
|---|
|  | 451 | double timeA = GetTime(); | 
|---|
|  | 452 | switch (TOT) { | 
|---|
|  | 453 | case StartTimeDo: | 
|---|
|  | 454 | S->time1[TT] = timeA; | 
|---|
|  | 455 | break; | 
|---|
|  | 456 | case StopTimeDo: | 
|---|
|  | 457 | S->time2[TT] = timeA; | 
|---|
|  | 458 | S->time[TT] += (S->time2[TT]-S->time1[TT]); | 
|---|
|  | 459 | break; | 
|---|
|  | 460 | } | 
|---|
|  | 461 | } | 
|---|
|  | 462 |  | 
|---|
|  | 463 | /** Final Measuring and overall time. | 
|---|
|  | 464 | * Does the last measurement calculation and combines results from all processes | 
|---|
|  | 465 | * to calculate min, max, average and writes it to FileData::SpeedFile | 
|---|
|  | 466 | * \param *P Problem at hand | 
|---|
|  | 467 | */ | 
|---|
|  | 468 | void CompleteSpeedMeasure(struct Problem *P) | 
|---|
|  | 469 | { /* gibt letzte Messung aus und benoetigte Gesamtzeit */ | 
|---|
|  | 470 | struct SpeedStruct *S = &P->Speed; | 
|---|
|  | 471 | struct FileData *F = &P->Files; | 
|---|
|  | 472 | struct Lattice *Lat = &P->Lat; | 
|---|
|  | 473 | struct Psis *Psi = &Lat->Psi; | 
|---|
|  | 474 | struct RunStruct *R = &P->R; | 
|---|
|  | 475 | struct Ions *I = &P->Ion; | 
|---|
|  | 476 | double average[MAXTIMETYPES]; | 
|---|
|  | 477 | double stddev[MAXTIMETYPES]; | 
|---|
|  | 478 | double time[MAXTIMETYPES]; | 
|---|
|  | 479 | int i; | 
|---|
|  | 480 | S->InitSteps += S->LevUpSteps; | 
|---|
|  | 481 | for (i=0; i<MAXTIMETYPES; i++) | 
|---|
|  | 482 | switch ((enum TimeTypes)i) { | 
|---|
|  | 483 | case InitSimTime: | 
|---|
|  | 484 | case InitGramSchTime: | 
|---|
|  | 485 | case InitLocTime: | 
|---|
|  | 486 | case InitNonLocTime: | 
|---|
|  | 487 | case InitDensityTime: | 
|---|
|  | 488 | case LocFTime: | 
|---|
|  | 489 | case NonLocFTime: | 
|---|
|  | 490 | case EwaldTime: | 
|---|
|  | 491 | case GapTime: | 
|---|
|  | 492 | S->SpeedStep[i] = S->InitSteps; | 
|---|
|  | 493 | break; | 
|---|
|  | 494 | case SimTime: | 
|---|
|  | 495 | case GramSchTime: | 
|---|
|  | 496 | case LocTime: | 
|---|
|  | 497 | case NonLocTime: | 
|---|
|  | 498 | case DensityTime: | 
|---|
|  | 499 | case WannierTime: | 
|---|
|  | 500 | case ReadnWriteTime: | 
|---|
|  | 501 | S->SpeedStep[i] = S->Steps*P->Par.proc[0]/(double)P->Lat.Psi.GlobalNo[PsiMaxNo]; | 
|---|
|  | 502 | break; | 
|---|
|  | 503 | default: | 
|---|
|  | 504 | S->SpeedStep[i] = 1; | 
|---|
|  | 505 | } | 
|---|
|  | 506 | S->time[LevSMaxG] = R->LevS->MaxG; | 
|---|
|  | 507 | MPI_Allreduce( S->time, time, MAXTIMETYPES, MPI_DOUBLE, MPI_SUM, P->Par.comm); | 
|---|
|  | 508 | for (i=0; i<MAXTIMETYPES; i++) | 
|---|
|  | 509 | time[i] /= (double)P->Par.procs; | 
|---|
|  | 510 | time[LevSMaxG] = R->LevS->TotalAllMaxG; | 
|---|
|  | 511 | for (i=0; i<MAXTIMETYPES; i++) | 
|---|
|  | 512 | average[i] = S->time[i]/S->SpeedStep[i]; | 
|---|
|  | 513 | MPI_Allreduce( average, S->average, MAXTIMETYPES, MPI_DOUBLE, MPI_SUM, P->Par.comm); | 
|---|
|  | 514 | for (i=0; i<MAXTIMETYPES; i++) | 
|---|
|  | 515 | S->average[i] /= (double)P->Par.procs; | 
|---|
|  | 516 | S->average[LevSMaxG] = R->LevS->TotalAllMaxG/(double)P->Par.proc[1]; | 
|---|
|  | 517 | for (i=0; i<MAXTIMETYPES; i++) | 
|---|
|  | 518 | stddev[i] = (average[i]-S->average[i])*(average[i]-S->average[i]); | 
|---|
|  | 519 | MPI_Allreduce( stddev, S->stddev, MAXTIMETYPES, MPI_DOUBLE, MPI_SUM, P->Par.comm); | 
|---|
|  | 520 | MPI_Allreduce( &stddev[LevSMaxG], &S->stddev[LevSMaxG], 1, MPI_DOUBLE, MPI_SUM, P->Par.comm_ST_Psi); | 
|---|
|  | 521 | for (i=0; i<MAXTIMETYPES-1; i++) | 
|---|
|  | 522 | S->stddev[i] /= (double)P->Par.procs; | 
|---|
|  | 523 | S->stddev[LevSMaxG] /= (double)P->Par.proc[1]; | 
|---|
|  | 524 | for (i=0; i<MAXTIMETYPES; i++) | 
|---|
|  | 525 | S->stddev[i] = sqrt(S->stddev[i]); | 
|---|
|  | 526 |  | 
|---|
|  | 527 | MPI_Allreduce( average, S->max, MAXTIMETYPES, MPI_DOUBLE, MPI_MAX, P->Par.comm); | 
|---|
|  | 528 | MPI_Allreduce( average, S->min, MAXTIMETYPES, MPI_DOUBLE, MPI_MIN, P->Par.comm); | 
|---|
|  | 529 | if (P->Par.me != 0) return; | 
|---|
|  | 530 |  | 
|---|
|  | 531 | fprintf(F->SpeedFile, "LevNo\tMaxG\tRMaxG\tMaxN\tN[0]\tN[1]\tN[2]\tRLevSStep\n"); | 
|---|
|  | 532 | for (i=0; i < Lat->MaxLevel; i++) | 
|---|
|  | 533 | fprintf(F->SpeedFile, "%i\t%i\t%i\t%i\t%i\t%i\t%i\t%i\n", Lat->Lev[i].LevelNo, Lat->Lev[i].TotalAllMaxG, Lat->Lev[i].TotalRealAllMaxG, Lat->Lev[i].MaxN, Lat->Lev[i].N[0], Lat->Lev[i].N[1], Lat->Lev[i].N[2], Lat->Lev[i].Step); | 
|---|
|  | 534 | fprintf(F->SpeedFile, "procs\tproc[0]\tproc[1]\tPsiMax\tPsiDoub\tPsiUp\tPsiDown\tNRStep\tTotalIons\n"); | 
|---|
|  | 535 | fprintf(F->SpeedFile, "%i\t%i\t%i\t%i\t%i+%i\t%i+%i\t%i+%i\t%i\t%i\n", P->Par.procs, P->Par.proc[0], P->Par.proc[1], Psi->GlobalNo[PsiMaxNo], Psi->GlobalNo[PsiMaxNoDouble], Psi->GlobalNo[PsiMaxAdd], Psi->GlobalNo[PsiMaxNoUp], Psi->GlobalNo[PsiMaxAdd], Psi->GlobalNo[PsiMaxNoDown], Psi->GlobalNo[PsiMaxAdd], R->NewRStep, I->Max_TotalIons); | 
|---|
|  | 536 |  | 
|---|
|  | 537 | fprintf(F->SpeedFile, "Type\tSimTime\t\tInitSimTime\tInitTime\tInitGramSchTime\tInitLocTime\tInitNonLocTime\tInitDensTime\tGramSchTime\tLocTime\t\tNonLocTime\tDensTime\tLocFTime\tNonLocFTime\tEwaldTime\tGapTime\tCurrDensTime\tWannierTime\tReadnWriteTime\tLevSMaxG\n"); | 
|---|
|  | 538 | fprintf(F->SpeedFile, "Steps"); | 
|---|
|  | 539 | for(i=0;i<MAXTIMETYPES;i++) | 
|---|
|  | 540 | fprintf(F->SpeedFile, "\t%e", S->SpeedStep[i]); | 
|---|
|  | 541 | fprintf(F->SpeedFile, "\n"); | 
|---|
|  | 542 |  | 
|---|
|  | 543 | fprintf(F->SpeedFile, "total"); | 
|---|
|  | 544 | for(i=0;i<MAXTIMETYPES;i++) | 
|---|
|  | 545 | fprintf(F->SpeedFile, "\t%e", time[i]); | 
|---|
|  | 546 | fprintf(F->SpeedFile, "\n"); | 
|---|
|  | 547 |  | 
|---|
|  | 548 | fprintf(F->SpeedFile, "average"); | 
|---|
|  | 549 | for(i=0;i<MAXTIMETYPES;i++) | 
|---|
|  | 550 | fprintf(F->SpeedFile, "\t%e", S->average[i]); | 
|---|
|  | 551 | fprintf(F->SpeedFile, "\n"); | 
|---|
|  | 552 |  | 
|---|
|  | 553 | fprintf(F->SpeedFile, "stddev"); | 
|---|
|  | 554 | for(i=0;i<MAXTIMETYPES;i++) | 
|---|
|  | 555 | fprintf(F->SpeedFile, "\t%e", S->stddev[i]); | 
|---|
|  | 556 | fprintf(F->SpeedFile, "\n"); | 
|---|
|  | 557 |  | 
|---|
|  | 558 | fprintf(F->SpeedFile, "min"); | 
|---|
|  | 559 | for(i=0;i<MAXTIMETYPES;i++) | 
|---|
|  | 560 | fprintf(F->SpeedFile, "\t%e", S->min[i]); | 
|---|
|  | 561 | fprintf(F->SpeedFile, "\n"); | 
|---|
|  | 562 |  | 
|---|
|  | 563 | fprintf(F->SpeedFile, "max"); | 
|---|
|  | 564 | for(i=0;i<MAXTIMETYPES;i++) | 
|---|
|  | 565 | fprintf(F->SpeedFile, "\t%e", S->max[i]); | 
|---|
|  | 566 | fprintf(F->SpeedFile, "\n"); | 
|---|
|  | 567 |  | 
|---|
|  | 568 | fclose(F->SpeedFile); | 
|---|
|  | 569 | } | 
|---|