| 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 |  */
 | 
|---|
| 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);
 | 
|---|
| 52 | }
 | 
|---|
| 53 | #else
 | 
|---|
| 54 | void debug_in(struct Problem *P, const char *output, const char *file, const int line) {}  // print nothing
 | 
|---|
| 55 | #endif
 | 
|---|
| 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 | {
 | 
|---|
| 94 |   char dummyoutput[MAXDUMMYSTRING];
 | 
|---|
| 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 | {
 | 
|---|
| 112 |   char dummyoutput[MAXDUMMYSTRING];
 | 
|---|
| 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 | {
 | 
|---|
| 144 |   char dummyoutput[MAXDUMMYSTRING];
 | 
|---|
| 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 | {
 | 
|---|
| 163 |   char dummyoutput[MAXDUMMYSTRING];
 | 
|---|
| 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
 | 
|---|
| 175 |  * \param *output message to print on failure
 | 
|---|
| 176 |  */
 | 
|---|
| 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);
 | 
|---|
| 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];
 | 
|---|
| 236 |   char dummy[MAXDUMMYSTRING];
 | 
|---|
| 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) {
 | 
|---|
| 315 |     Free(P->Files.PosTemp, "RemoveEverything: P->Files.PosTemp");
 | 
|---|
| 316 |     Free(P->Files.OutputPosType, "RemoveEverything: P->Files.OutputPosType");
 | 
|---|
| 317 |     Free(P->Files.OutVisStep, "RemoveEverything: P->Files.OutVisStep");
 | 
|---|
| 318 |   }
 | 
|---|
| 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");
 | 
|---|
| 325 |   for (i=0; i < P->Lat.MaxLevel; i++) {
 | 
|---|
| 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");
 | 
|---|
| 330 |     if (Lat->Lev[i].MaxDoubleG)
 | 
|---|
| 331 |       Free(Lat->Lev[i].DoubleG, "RemoveEverything: Lat->Lev[i].DoubleG");
 | 
|---|
| 332 |     if (i != 0) {
 | 
|---|
| 333 |       Free(Lat->Lev[i].PosFactorUp, "RemoveEverything: Lat->Lev[i].PosFactorUp");
 | 
|---|
| 334 |     } else {
 | 
|---|
| 335 |       for (d=0; d < (P->R.DoPerturbation == 1 ? MaxDensityTypes : MaxInitDensityTypes); d++) {
 | 
|---|
| 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]");
 | 
|---|
| 338 |       }
 | 
|---|
| 339 |     }
 | 
|---|
| 340 |     /* if (i != Lat->MaxLevel-1) */
 | 
|---|
| 341 |       Free(Lat->Lev[i].Dens, "RemoveEverything: Lat->Lev[i].Dens");
 | 
|---|
| 342 |   }
 | 
|---|
| 343 |   for (i=1; i < Lat->MaxLevel; i++) {
 | 
|---|
| 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");
 | 
|---|
| 346 |     if (i == 1) {
 | 
|---|
| 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");
 | 
|---|
| 349 |     }
 | 
|---|
| 350 |     Free(Lat->Lev[i].LPsi, "RemoveEverything: Lat->Lev[i].LPsi");
 | 
|---|
| 351 |   }
 | 
|---|
| 352 |   for (i=0;i<Lat->Psi.NoOfTotalPsis;i++) {
 | 
|---|
| 353 |     Free(Psi->lambda[i], "RemoveEverything: Psi->lambda[i]");
 | 
|---|
| 354 |   }  
 | 
|---|
| 355 |   for (i=0;i<Lat->Psi.NoOfPsis;i++) {
 | 
|---|
| 356 |     Free(Psi->Overlap[i], "RemoveEverything: Psi->Overlap[i]");
 | 
|---|
| 357 |   }
 | 
|---|
| 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");
 | 
|---|
| 372 |   if (Lat->RT.Use == UseRT) {
 | 
|---|
| 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]");
 | 
|---|
| 377 |     for (i=0; i< MAXRTARRAYS; i++) {
 | 
|---|
| 378 |       Free(Lat->RT.DensityC[i], "RemoveEverything: Lat->RT.DensityC[i]");
 | 
|---|
| 379 |     }
 | 
|---|
| 380 |     Free(Lat->RT.TempC, "RemoveEverything: Lat->RT.TempC");
 | 
|---|
| 381 |   }
 | 
|---|
| 382 |   for (type=Occupied;type<Extra;type++)
 | 
|---|
| 383 |     for (i=0; i<MAXALLPSIENERGY; i++) {
 | 
|---|
| 384 |       Free(Lat->Energy[type].PsiEnergy[i], "RemoveEverything: Lat->Energy[type].PsiEnergy[i]");
 | 
|---|
| 385 |     }
 | 
|---|
| 386 |   for (i=Occupied;i<Extra;i++)
 | 
|---|
| 387 |     Free(P->R.MinimisationName[i], "RemoveEverything: P->R.MinimisationName[i]");
 | 
|---|
| 388 |   Free(P->R.MinimisationName, "RemoveEverything: P->R.MinimisationName");
 | 
|---|
| 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");  
 | 
|---|
| 398 |   Free(P, "RemoveEverything: P");
 | 
|---|
| 399 |   FreeMPI_OnePsiElement();
 | 
|---|
| 400 |   //debug(P,"OnePsiElement");  
 | 
|---|
| 401 |   
 | 
|---|
| 402 |   // Free string names from Files structure
 | 
|---|
| 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");
 | 
|---|
| 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 | }
 | 
|---|