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 | }
|
---|