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