root/trunk/tsuite/programs/mpi/mpi.cpp

Revision 1891, 23.7 kB (checked in by peter, 3 months ago)

source/service.cpp
source/punch_fits.cpp
source/init_coreload.cpp
source/grains_mie.cpp
source/assert_results.cpp
source/parse_punch.cpp
source/optimize_phymir.cpp
source/version.h
source/parse_commands.cpp
source/prt_final.cpp
source/grid_do.cpp
source/parse_print.cpp
source/cddrive.cpp
source/prt_comment.cpp
tsuite/programs/mpi/mpi.cpp

  • Bug-fix for PR59 - cdVersion, cdDate could cause segfault.
  • Start preparing for the change of the release numbering scheme for the next release.
  • Property svn:eol-style set to native
Line 
1 /* This file is part of Cloudy and is copyright (C)1978-2008 by Gary J. Ferland and
2  * others.  For conditions of distribution and use see copyright notice in license.txt */
3 /*main program to call cloudy to generate a large loc data cube */
4 #include "cddefines.h"
5 #include "cddrive.h"
6 #include "version.h"
7
8 /* This flag indicates where we are multi-processing.\
9  * set with -DMPI on compiler command line
10  * if this is true then all output happens at the end,
11  * if false then each set of results is printed and flushed when it happens.
12  * must be set true on parallel machines, false on pc */
13 #ifdef MPI
14 #       include <mpi.h>
15 #endif
16 /*lint -e506  constant value Boolean */
17
18
19 #ifdef _MSC_VER
20         /* disable conditional expression is constant */
21 #       pragma warning( disable : 4127 )
22 #endif
23
24 /* ========================================================================= */
25 /*
26 Main output, file ending in .lin
27 format, tab separated fields
28 Cloudy exit condition for that model
29 number of warnings,
30 elapsed time,
31 hden
32 flux
33 par1
34 par2
35 */
36
37 #define TITLE "std con Fe2 sol, col 24 "
38
39 /* this is name of resulting output files, FILENAME.lin will be main results */
40 #define FILENAME "STD_con_sol"
41
42 /* path to directory where we will write, must end in / or \ for current system
43  * final location will be PATHNAME + FILENAME */
44 /*#define PATHNAME "c:\\projects\\cloudy\\tests\\"*/
45 #define PATHNAME ""
46
47 /* this is an additive offset for hden and flux, usually 0 */
48 #define OFFSET_HDEN (0.)
49 #define OFFSET_FLUX (0.)
50
51 /* these following pairs make 8x8 square grid */
52 /* lower and upper bounds on hydrogen density - log cm^-3
53  * for BLR work usually 7 and 14 */
54 /*#define HDENINIT (12.5+OFFSET_HDEN)*/
55 /*#define HDENLIMIT (12.5+OFFSET_HDEN)*/
56 #define HDENINIT (7.+OFFSET_HDEN)
57 #define HDENLIMIT (14.+OFFSET_HDEN)
58
59 /* low and up bounds on flux of hydrogen ionizing photons - log cm^-2 s-1
60  * for BLR work usually 17 and 24 */
61 #define FLUXINIT (17.+OFFSET_FLUX)
62 #define FLUXLIMIT (24.+OFFSET_FLUX)
63 /*#define FLUXINIT (20.5+OFFSET_FLUX)
64 #define FLUXLIMIT (20.5+OFFSET_FLUX)*/
65
66 /* the increment on both axis */
67 /*#define INCREMENT 0.5*/
68 #define INCREMENT 1./**/
69 /*#define INCREMENT 2.*/
70 /*#define INCREMENT 0.05*/
71
72 /* this is the number of iterations to do - <0 means to convergence, 1 will do 2 iterations,
73  * 0 will do 1  */
74 #define ITERATIONS  2 
75 /*#define ITERATIONS  -1  */
76
77 /* the column density, set to false if not used */
78 #define COLDEN 24
79
80 /* this says whether or not to include the FeII atom */
81 #define FEII true
82
83 /* quick test - 3 zones, constant temperature, 2 iterations */
84 #define QUICK_MODEL false
85
86 /* if true the only call cdNoExec */
87 #define VERY_QUICK_MODEL false
88
89 /* says whether to make the large cloudy output, if true then output created,
90  * if false then not output, only the emission line intensities. */
91 #define DO_PRINT false
92
93 /* print last iteration */
94 #define PRINT_LAST false
95
96 /* set no buffering on output - if true then print as it happens*/
97 #define NO_BUFFERING false
98
99 /* ============================================================================ */
100
101 /* this structure will hold results for final printout */
102 #define NLINTOT 1500 /* the maximum number of lines */
103
104 typedef struct
105 {
106         /* save these parameters for each grid point,
107          * density, flux, and full spectrum */
108         double hden , flux , pred[NLINTOT] ;
109         /* number of cautions and warnings for this calc, all should be zero */
110         int nWarnings , nCautions , nTFail;
111         /* flag returned by Cloudy, 0 == OK, 1 for failure */
112         int lgBadEnd ;
113         /* the execution time for this model */
114         double etime;
115         /* two extra parameters */
116         double par1 , par2;
117 } GRIDTAG;
118
119 /* this is where we will save results */
120 #ifdef MPI
121 void Build_derived_type(GRIDTAG gridtag, MPI_Datatype* message_type_ptr)
122 {
123   int block_lengths[10];
124   MPI_Aint displacements[10];
125   MPI_Aint addresses[11];
126   MPI_Datatype typelist[10];
127
128   /*First specify the types */
129   typelist[0] = MPI_DOUBLE;    /*hden*/
130   typelist[1] = MPI_DOUBLE;    /*flux*/
131   typelist[2] = MPI_DOUBLE;    /*pred*/
132   typelist[3] = MPI_INT;       /*nWarnings*/
133   typelist[4] = MPI_INT;       /*nCautions*/
134   typelist[5] = MPI_INT;       /*nTFail*/
135   typelist[6] = MPI_INT;       /*lgBadEnd*/
136   typelist[7] = MPI_DOUBLE;    /*etime*/
137   typelist[8] = MPI_DOUBLE;    /*par1*/
138   typelist[9] = MPI_DOUBLE;    /*par2*/
139
140   /* Specify the number of elements of each type */
141   block_lengths[0] = block_lengths[1] = block_lengths[3] = 1;
142   block_lengths[4] = block_lengths[5] = block_lengths[6] = 1;
143   block_lengths[7] = 1;
144   /* this one is special since it is NLINTOT long */
145   block_lengths[2] = NLINTOT;
146   /* two new parameters are each one element long */
147   block_lengths[8] = block_lengths[9] = 1;
148
149   /* Calculate the displacement of the members relative to indata */
150   MPI_Address( &gridtag,            &addresses[0]);
151   MPI_Address(&(gridtag.hden),      &addresses[1]);
152   MPI_Address(&(gridtag.flux),      &addresses[2]);
153   MPI_Address(&(gridtag.pred),      &addresses[3]);
154   MPI_Address(&(gridtag.nWarnings), &addresses[4]);
155   MPI_Address(&(gridtag.nCautions), &addresses[5]);
156   MPI_Address(&(gridtag.nTFail),    &addresses[6]);
157   MPI_Address(&(gridtag.lgBadEnd),  &addresses[7]);
158   MPI_Address(&(gridtag.etime),     &addresses[8]);
159   MPI_Address(&(gridtag.par1),      &addresses[9]);
160   MPI_Address(&(gridtag.par2),      &addresses[10]);
161  
162   /* now far each is from the beginning of the structure */
163   displacements[0] = addresses[1] - addresses[0];
164   displacements[1] = addresses[2] - addresses[0];
165   displacements[2] = addresses[3] - addresses[0];
166   displacements[3] = addresses[4] - addresses[0];
167   displacements[4] = addresses[5] - addresses[0];
168   displacements[5] = addresses[6] - addresses[0];
169   displacements[6] = addresses[7] - addresses[0];
170   displacements[7] = addresses[8] - addresses[0];
171   displacements[8] = addresses[9] - addresses[0];
172   displacements[9] = addresses[10]- addresses[0];
173
174   /*Create the derived type */
175   MPI_Type_struct(10, block_lengths, displacements, typelist,message_type_ptr);
176  
177   /*Commit it so that it can be used */
178   MPI_Type_commit(message_type_ptr);
179
180 } /*Build_derived_type */
181
182 # endif
183
184 int main( int argc, char *argv[] )
185 {
186         DEBUG_ENTRY( "main()" );
187
188         try {
189                 bool lgAbort;
190                 int IntegerMod;
191                 int  myrank ;
192                 double hden , absolute , relative , flux;
193                 char chVer[10] , chPath[1000] , chFilename[1000] , chFile[2000] ;
194
195                 double *xpar , *ypar, *par1, *par2;
196
197                 /* following will become array of line wavelengths and the number of lines
198                  * in this array */
199                 long int mod, nLines, LimModels, nModels;
200
201                 /* these will be passed to cdGetLineList and will become arrays of
202                  * labels and wavelengths */
203                 char **chLabel ;
204                 realnum *wl;
205
206                 long int
207                         NumberWarnings1, NumberCautions1, NumberNotes1, NumberSurprises1, NumberTempFailures1,
208                         NumberPresFailures1, NumberIonFailures1, NumberNeFailures1 ;
209                 /* number of time Cloudy returned with error condition */
210                 int nErrorExits;
211
212                 FILE *ioOUT , *ioDATA ;
213                 char chLine[100];
214
215                 long int n;
216                 /* number of processors, =1 for single non-MPI */
217                 int numprocs = 1;
218
219                 /* this will hold a single grid point */
220                 GRIDTAG grid;
221
222                 /* start MPI if -DMPI on command line */
223 #               ifdef MPI
224                 GRIDTAG gridtag;
225                 GRIDTAG *grids;
226                
227                 MPI_Datatype message_type; /* Arguments to */
228
229                 MPI_Init(&argc, &argv);
230                 MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
231                 MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
232
233                 Build_derived_type(gridtag, &message_type);
234 #               else
235                 myrank = 0;
236 #               endif
237
238                 /* the following is the path for the directory where the output should appear,
239                  * it needs to end with the OS standard directory delimiter, a "/" on unix */
240                 strcpy( chPath , PATHNAME );
241
242                 /* this is the first part of the name of the resulting data file.  The final
243                  * file will have this name with a ".lin" after it. */
244                 strcpy( chFilename , FILENAME );
245
246                 /* ====================================================================== */
247                 /*
248                  * make arrays of parameters for this grid */
249
250                 /* total number of models */
251                 LimModels = (long)((FLUXLIMIT - FLUXINIT)/INCREMENT + 1.1);
252                 LimModels *= (long)((HDENLIMIT - HDENINIT)/INCREMENT+1.1);
253                 /* add number of processors since this is most we would possibly have to
254                  * add on to make integer number of mpi calls */
255                 LimModels += numprocs;
256
257                 xpar = (double*)malloc(LimModels*sizeof(double) );
258                 ypar = (double*)malloc(LimModels*sizeof(double) );
259                 par1 = (double*)malloc(LimModels*sizeof(double) );
260                 par2 = (double*)malloc(LimModels*sizeof(double) );
261
262                 if( xpar==NULL || ypar==NULL || par1==NULL || par2==NULL )
263                 {
264                         fprintf(stderr,"malloc failed\n");
265 #                       ifdef MPI
266                         MPI_Finalize();
267 #                       endif
268                         cdEXIT(EXIT_FAILURE);
269                 }
270                 /* now define set of parameters */
271                 hden = HDENINIT;
272                 flux = FLUXINIT;
273                 nModels = 0;
274                 nErrorExits = 0;
275 #               ifdef MPI
276                 /* loop along constant U diagonals, starting from
277                  * bottom right of loc plane, increasing density,
278                  * and ending on the major diagonal.
279                  * this is for load leveling on parallel machines */
280                 for( hden = HDENLIMIT; hden>= HDENINIT; hden-=INCREMENT )
281                 {
282                         for( flux=FLUXINIT; flux<=FLUXLIMIT;  flux+= INCREMENT )
283                         {
284                                 if( hden + (flux-FLUXINIT) > HDENLIMIT ) break;
285                                 assert( nModels < LimModels );
286                                 xpar[nModels] = hden + (flux-FLUXINIT);
287                                 ypar[nModels] = flux;
288                                 par1[nModels] = COLDEN;
289                                 par2[nModels] = 0.;
290                                 ++nModels;
291                         }
292                 }
293                 /* loop increasing flux, starting at lower left plus increment */
294                 for( flux=FLUXINIT+INCREMENT; flux<=FLUXLIMIT;  flux+= INCREMENT )
295                 {
296                         for( hden = HDENINIT; hden<= HDENLIMIT;  hden+=INCREMENT )
297                         {
298                                 if( flux + (hden-HDENINIT) > FLUXLIMIT ) break;
299                                 assert( nModels < LimModels );
300                                 xpar[nModels] = hden ;
301                                 ypar[nModels] = flux + (hden-HDENINIT);
302                                 par1[nModels] = COLDEN;
303                                 par2[nModels] = 0.;
304                                 ++nModels;
305                         }
306                 }
307 #               else
308                 /* on scalar machines do models in xy order */
309                 while( hden < 1.00001 * HDENLIMIT )
310                 {
311                         while( flux < 1.00001*FLUXLIMIT )
312                         {
313                                 xpar[nModels] = hden;
314                                 ypar[nModels] = flux;
315                                 par1[nModels] = COLDEN;
316                                 par2[nModels] = 0.;
317                                 ++nModels;
318                                 flux += INCREMENT;
319                         }
320                         flux = FLUXINIT;
321                         hden += INCREMENT;
322                 }
323 #               endif
324                 /* increase total number to an integer multiple of number of processors */
325                 if( nModels%numprocs)
326                 {
327                         /* add extra bit */
328                         IntegerMod = nModels + (numprocs - nModels%numprocs);
329                 }
330                 else
331                 {
332                         IntegerMod = nModels;
333                 }
334
335                 /* make up data for the "extra" models */
336                 for( mod=nModels; mod<IntegerMod; ++mod)
337                 {
338                         xpar[mod] = xpar[0];
339                         ypar[mod] = ypar[0];
340                         par1[mod] = par1[0];
341                         par2[mod] = par2[0];
342                 }
343
344                 /* ====================================================================== */
345
346 #               ifdef MPI
347                 /* allocate memory for grids */
348                 if( (grids = ((GRIDTAG *)malloc( (size_t)(numprocs)*sizeof(GRIDTAG )))) == NULL )
349                 {
350                         fprintf(stderr," main could not malloc grid\n");
351 #                       ifdef MPI
352                         MPI_Finalize();
353 #                       endif
354                         cdEXIT(EXIT_FAILURE);
355                 }
356 #               endif
357
358                 /* initialize the code so that cdGetLineList can be called */
359                 cdInit();
360                 /* get list of lines from standard data file.  With no arguments this reads
361                  * the file BLRLineList, part of the standard data distribution.  There could
362                  * have been another file name within the quotes - that file would have been
363                  * used instead */
364                 nLines = cdGetLineList("" , &chLabel , &wl);
365                 /*nLines = cdGetLineList("NLRLineList.dat" , &chLabel , &wl);*/
366
367                 /* now copy version into string to print */
368                 cdVersion(chVer);
369
370                 /* open file for large output if this is desired */
371                 if( DO_PRINT )
372                 {
373                         /* now create final filename */
374                         strcpy( chFile , chPath );
375                         strcat( chFile , chFilename );
376                         strcat( chFile , ".out" );
377                         ioOUT = fopen(chFile,"w");
378                         if( ioOUT == NULL )
379                         {
380                                 printf(" main could not open %s for writing.\n", chFile);
381 #                               ifdef MPI
382                                 MPI_Finalize();
383 #                               endif
384                                 cdEXIT(EXIT_FAILURE);
385                         }
386                 }
387                 else
388                 {
389                         /* there should be nothing coming here, but something might */
390                         ioOUT = stderr;
391                 }
392
393                 /* calculation's results, all the lines in file ending .lin */
394                 strcpy( chFile , chPath );
395                 strcat( chFile , chFilename );
396                 strcat( chFile , ".lin" );
397                 ioDATA = fopen(chFile,"w");
398                 if( ioDATA == NULL )
399                 {
400                         printf(" could not open %s for writing.\n" , chFile );
401 #                       ifdef MPI
402                         MPI_Finalize();
403 #                       endif
404                         cdEXIT(EXIT_FAILURE);
405                 }
406
407                 /* print the header information before we begin the calculation */
408                 /* print version number on both headers */
409                 fprintf(ioDATA,"Cloudy version %s, %s\n",chVer,TITLE);
410
411                 for( mod=myrank; mod<IntegerMod; mod+=numprocs )
412                 {
413                         hden = xpar[mod];
414                         flux = ypar[mod];
415                         /* zero out grid, which will hold all info for a single grid point */
416                         memset(&grid, 0, sizeof(GRIDTAG));
417
418                         /* initialize the code for this run */
419                         cdInit();
420
421                         /* direct the standard output to this file */
422                         cdOutp(ioOUT);
423
424                         /* send flag saying whether to create large output */
425                         cdTalk( DO_PRINT );
426
427                         /* title for grid */
428                         sprintf(chLine,"title %s", TITLE);
429                         n = cdRead( chLine  );
430
431                         /* print only last iteration? */
432 #                       if PRINT_LAST
433                         n = cdRead("print last iteration ");
434 #                       endif
435
436                         /* option for fast model, or only header */
437 #                       if QUICK_MODEL
438                         n = cdRead( "stop zone 3 "  );/**/
439                         n = cdRead( "constant temper 4 "  );/**/
440 #                       endif
441 #                       if VERY_QUICK_MODEL
442                         cdNoExec();
443 #                       endif
444
445                         /* iterate if not fast model */
446 #                       if ( (!QUICK_MODEL) && (!VERY_QUICK_MODEL) &&(ITERATIONS!=0) )
447 #                       if ITERATIONS < 0
448                         n = cdRead( "iterate convergence "  );/**/
449 #                       else
450                         sprintf(chLine,"iterate %i", ITERATIONS);
451                         n = cdRead( chLine  );
452 #                       endif
453 #                       endif
454
455 #                       ifdef MPI
456                         /* set flag so that exit handler will call MPI_Finalize */
457                         cdMPI();
458 #                       endif
459
460                         /* option to turn off file buffering if code might crash */
461 #                       ifdef NO_BUFFERING
462                         n = cdRead("no buffering ");
463 #                       endif
464
465                         /* if we have run off end of array of models say not to execute,
466                          * still must do something on this processor so that the gather can occur
467                          * at the bottom of the loop */
468                         if( mod >= nModels )
469                                 cdNoExec();
470
471                         /* flux and density */
472                         sprintf(chLine,"phi(h) %f", flux);
473                         n = cdRead( chLine  );
474
475                         sprintf(chLine,"hden %f", hden);
476                         n = cdRead( chLine  );
477
478                         /* turn on large FeII atom, VERY slow */
479 #                       if FEII
480                         n = cdRead( "atom feii  "  );
481 #                       endif
482
483                         /* this is the continuum we used in the large apjs paper */
484                         n = cdRead( "agn 6.00 -1.40 -0.50 -1.0  "  );/**/
485
486                         /* a bare powerlaw with a break at 1 microns */
487                         /*n = cdRead( "table powerlaw -1.0 1 micron break "  );*/
488
489                         /* the much maligned Mathews&Ferland continuum */
490                         /*n = cdRead( "table agn  "  );*/
491
492                         /*n = cdRead( "blackbody 142,000  "  );*/
493
494                         /* broken power law used in Fred's paper */
495                         /*n = cdRead( "interpolate (0.00000001, -14.899), (0.0091126732, 0.000)  "  );
496                           n = cdRead( "continue (1.00, -1.2242), (73.54, -4.2106)  "  );
497                           n = cdRead( "continue (3675, -5.7395), (7354000, -11.2526)  "  );*/
498
499                         /* broken power law used in Mark's paper */
500                         /*n = cdRead( "interpolate (10.517, -30.850) (13.383, -23.684)   "  );
501                           n = cdRead( "continue (16.684, -26.986) (17.383, -27.9996)    "  );
502                           n = cdRead( "continue (18.383, -28.8899) (19.124, -29.268)    "  );
503                           n = cdRead( "continue (22.383, -35.788)  "  );*/
504
505                         /* add cosmic IR background as well */
506                         n = cdRead( "background z=0  "  );
507
508                         sprintf(chLine,"stop column density %f ", par1[mod]);
509                         n = cdRead( chLine  );/**/
510
511                         n = cdRead( "failures 3 "  );
512
513                         /* options to change abundances */
514 #                       if 0
515                         n = cdRead( "metals 10 "  );/**/
516                         n = cdRead( "element nitrogen scale 10 "  );/**/
517                         n = cdRead( "element helium scale 1.66 "  );/**/
518                         n = cdRead( "metals 20 "  );/**/
519                         n = cdRead(