cloudy trunk
Loading...
Searching...
No Matches
maincl.cpp
Go to the documentation of this file.
1/* This file is part of Cloudy and is copyright (C)1978-2013 by Gary J. Ferland and
2 * others. For conditions of distribution and use see copyright notice in license.txt */
3/*main program that reads input and calls cloudy to compute a single model, or
4 * try to optimize an observed model. Routine returns 0 if model is ok,
5 * and 1 if problems occurred. */
6#include "cddefines.h"
7#include "cddrive.h"
8#include "input.h"
9#include "prt.h"
10#include "save.h"
11#include "called.h"
12#include "monitor_results.h"
13#include "mpi_utilities.h"
14#include "grid.h"
15
16exit_type cdMain( int argc, const char* argv[] );
17
18inline void print_delimiter(long nOptimiz)
19{
20 fprintf( ioQQQ, " ************************************************** GRID_DELIMIT" );
21 if( nOptimiz >= 0 )
22 fprintf( ioQQQ, " -- grid%9.9ld", nOptimiz );
23 fprintf( ioQQQ, "\n" );
24}
25
28int main( int argc, char *argv[] )
29{
30 exit_type exit_status = ES_SUCCESS;
31
32 DEBUG_ENTRY( "main()" );
33
34 if( cpu.i().lgMPI() )
35 {
36 MPI::Init( argc, argv );
37
38 cpu.i().set_nCPU( MPI::COMM_WORLD.Get_size() );
39 cpu.i().set_nRANK( MPI::COMM_WORLD.Get_rank() );
40
41 // MPI::Init() will have overwritten our signal handlers
42 // so we need to set them again....
43 cpu.i().set_signal_handlers();
44 }
45
46 // this will generate input files for each grid point,
47 // or execute the Phymir run, whichever is appropriate
48 exit_status = cdMain( argc, (const char**)argv );
49
50 // wait for writing of input files to finish
51 if( cpu.i().lgMPI() )
52 MPI::COMM_WORLD.Barrier();
53
54 // process the individual grid points
55 if( grid.lgGrid && exit_status == ES_SUCCESS )
56 {
57 // this was set to true after we wrote the last input script
58 grid.lgGridDone = false;
59
60 // from now on each rank will run its own model
61 cpu.i().set_MPISingleRankMode( true );
62
63 load_balance lb( grid.totNumModels );
64
65 // Each MPI rank will get jobs assigned by lb and execute them.
66 // If there are no jobs left, lb.next_job() will return -1.
67 while( ( optimize.nOptimiz = lb.next_job() ) >= 0 )
68 {
69 const char** mpi_argv = new const char*[argc+2];
70
71 string jobName = GridPointPrefix( optimize.nOptimiz );
72 for( int i=0; i < argc; ++i )
73 mpi_argv[i] = argv[i];
74 mpi_argv[argc] = "-g";
75 mpi_argv[argc+1] = jobName.c_str();
76
77 exit_type retval = cdMain( argc+2, mpi_argv );
78
79 exit_status = max( retval, exit_status );
80 delete[] mpi_argv;
81
82 ++grid.seqNum;
83 }
84
85 lb.finalize();
86
87 // gather the spectral information from all ranks for saving FITS files
88 grid.lgGridDone = true;
89 optimize.nOptimiz = grid.totNumModels;
91
92 // and concatenate the output
93 if( cpu.i().lgMaster() )
95 }
96
97 // remove empty output files from slave ranks
98 if( cpu.i().lgMPI() && cpu.i().lgMaster() )
99 {
100 for( long n=1; n < cpu.i().nCPU(); ++n )
101 {
102 ostringstream oss;
103 oss << ".err" << setfill('0') << setw(2) << n;
104 string slave_output = save.chRedirectPrefix + oss.str();
105 FILE *io = open_data( slave_output.c_str(), "a", AS_LOCAL_ONLY );
106 bool lgEmpty = ( ftell(io) == 0 );
107 fclose( io );
108 if( lgEmpty )
109 remove( slave_output.c_str() );
110 }
111 }
112
113 if( cpu.i().lgMPI() )
114 MPI::Finalize();
115
116 return exit_status;
117}
118
120exit_type cdMain( int argc, const char* argv[] )
121{
122 /* these will be used to count number of various problems */
123 long int NumberWarnings,
124 NumberCautions,
125 NumberNotes,
126 NumberSurprises,
127 NumberTempFailures,
128 NumberPresFailures,
129 NumberIonFailures,
130 NumberNeFailures;
131
132 bool lgAbort_exit,
133 lgEarly_exit=true,
134 lgFileIO;
135 /* number of lines we can still read in */
136 int nread=0;
137
138 int i;
139 const char *s,
140 *prefix = "",
141 *gprefix = "", // grid prefix
142 *pprefix = "", // save prefix
143 *rprefix = ""; // redirect prefix
144 string infile("");
145
146 /* the length of the following vector will be the longest line image
147 * the code will be able to read here. Cloudy itself will ignore anything
148 * beyond INPUT_LINE_LENGTH, and checks that no information exists beyond it.
149 * The code will stop if the input line is longer than INPUT_LINE_LENGTH
150 * since extra characters would become a new command line due to buffer overrun */
151 char chLine[INPUT_LINE_LENGTH];
152
153 /* indicates that a command line flag to redirect I/O has been used */
154 lgFileIO = false;
155
156 exit_type exit_status = ES_SUCCESS;
157
158 DEBUG_ENTRY( "cdMain()" );
159
160 try {
161 /*
162 * Handle argument input -- written generally, but presently handles
163 * only `-p prefix' or `-pprefix' to set input file as `prefix.in',
164 * output file as `prefix.out' and the save prefix.
165 */
166 for( i=1; i < argc; i++ )
167 {
168 s = argv[i];
169 if( *s != '-' || s[1] == '\0' )
170 {
171 if (infile != "")
172 {
173 fprintf( ioQQQ, "%s: only one input file argument allowed\n", argv[0] );
175 }
176 infile = s;
177 if( infile.find( cpu.i().chDirSeparator() ) != string::npos )
178 {
179 fprintf( ioQQQ, "%s %s: read/write from subdirectories is not supported\n",
180 argv[0], infile.c_str() );
182 }
183 FILE *fp = fopen(infile.c_str(),"r");
184 if (!fp)
185 {
186 fprintf( ioQQQ, "%s: input filename `%s' not found\n", argv[0], infile.c_str() );
188 }
189 fclose(fp);
190 size_t suffindex = infile.find_last_of(".");
191 if (suffindex != string::npos)
192 infile = infile.substr(0,suffindex);
193 pprefix = rprefix = infile.c_str();
194 lgFileIO = true;
195 }
196 else
197 {
198 while( s != NULL && *(++s) )
199 {
200 exit_type exit = ES_SUCCESS;
201 switch( *s )
202 {
203 case 'a':
204 cpu.i().setAssertAbort( true );
205 break;
206 case 'g':
207 case 'p':
208 case 'r':
209 if( s[1] != '\0' )
210 {
211 prefix = s+1;
212 }
213 else
214 {
215 if( ++i == argc || argv[i][0] == '-' )
216 {
217 fprintf( ioQQQ, "%s: no argument given for -%c flag\n",
218 argv[0], *s );
220 }
221 prefix = argv[i];
222 if( strchr(prefix, cpu.i().chDirSeparator()) != NULL )
223 {
224 fprintf( ioQQQ, "%s -%c %s: writing in subdirectories is not supported\n",
225 argv[0], *s, prefix );
227 }
228 }
229 if( *s == 'g' )
230 gprefix = prefix;
231 else if( *s == 'p' )
232 {
233 pprefix = prefix;
234 rprefix = prefix;
235 }
236 else if( *s == 'r' )
237 {
238 // make sure we erase the effects of a possible earlier -p flag
239 pprefix = "";
240 rprefix = prefix;
241 }
242 else
244 s = NULL;
245 lgFileIO = true;
246 break;
247 default:
248 fprintf( ioQQQ, "%s: argument %d, `%s': flag -%c not understood\n",
249 argv[0], i, argv[i], *s );
250 exit = ES_FAILURE;
251 case 'h':
252 fprintf( ioQQQ, "\nSupported flags are:\n\n" );
253 fprintf( ioQQQ, "-p example\n" );
254 fprintf( ioQQQ, " Cloudy reads the input from the file example.in\n" );
255 fprintf( ioQQQ, " and writes the output to the file example.out.\n" );
256 fprintf( ioQQQ, " Additionally, all file names in SAVE commands are\n" );
257 fprintf( ioQQQ, " prepended with the string \"example\", e.g. the\n" );
258 fprintf( ioQQQ, " output of SAVE DR \".dr\" will be in example.dr.\n" );
259 fprintf( ioQQQ, "-r example\n" );
260 fprintf( ioQQQ, " This does the same as the -p switch, except that\n" );
261 fprintf( ioQQQ, " the names used in SAVE commands are not altered.\n" );
262 fprintf( ioQQQ, "-g example\n" );
263 fprintf( ioQQQ, " This switch is used internally in MPI grid runs.\n" );
264 fprintf( ioQQQ, " Normal users should not use this switch.\n" );
265 fprintf( ioQQQ, "-a\n" );
266 fprintf( ioQQQ, " This switch is used in debugging. It causes the\n" );
267 fprintf( ioQQQ, " code to crash rather than exit gracefully after\n" );
268 fprintf( ioQQQ, " a failed assert. This flag is deprecated.\n" );
269 fprintf( ioQQQ, "-h\n" );
270 fprintf( ioQQQ, " Print this message.\n" );
271 cdEXIT(exit);
272 }
273 }
274 }
275 }
276
277 /* initialize the code for this run */
278 cdInit();
279
280 save.chGridPrefix = gprefix;
281 save.chFilenamePrefix = pprefix;
282 save.chRedirectPrefix = rprefix;
283
284 /* following should be set true to print to file instead of std output */
285 if( lgFileIO )
286 {
287 string Base = save.chGridPrefix + save.chRedirectPrefix;
288 string InName = Base + ".in";
289 string OutName;
290 if( cpu.i().lgMPI_talk() )
291 OutName = Base + ".out";
292 else
293 {
294 ostringstream oss;
295 oss << ".err" << setfill('0') << setw(2) << cpu.i().nRANK();
296 OutName = Base + oss.str();
297 }
298 cdInput( InName.c_str(), "r" );
299 cdOutput( OutName.c_str(), "w" );
300 }
301
302 if( optimize.nOptimiz == 0 && called.lgTalk && cpu.i().lgMPISingleRankMode() )
303 print_delimiter(-1);
304
305 nread = 1;
306 /* keep reading input lines until end of file */
307 while( read_whole_line(chLine, (int)sizeof(chLine), ioStdin)!= NULL )
308 {
309 char *chChar;
310 /* when running from command prompt, last line can be \n or
311 * \r (this can happen with gcc under cygwin in windows)
312 * or space, so check for each here, and break if present,
313 * check on chLine[23] is for case where we are reading cloudy output */
314 /*fprintf(ioQQQ,"DEBUG char0 %i\n", (int)chLine[0] );*/
315 if( chLine[0] == '\n' || chLine[0] == '\r' ||
316 ( chLine[0] == ' ' && chLine[23] != '*' ) ||
317 (strncmp( chLine , "***" , 3 )==0 ) )
318 break;
319
320 /* read entire line of input - lgAbort set true if lines too long */
321 if( !lgInputComment(chLine) )
322 {
323
324 if( (chChar = strchr_s(chLine , '\"' ) ) ==NULL )
325 {
326 /* check for underscore, probably meant as a space */
327 while( (chChar = strchr_s(chLine , '_' ) ) !=NULL )
328 {
329 *chChar = ' ';
330 input.lgUnderscoreFound = true;
331 }
332 }
333
334 /* change _, [, and ] to space if no filename occurs on line
335 * >>chng 06 sep 04 use routine to check for comments
336 * do not remove _, [, and ] in comments */
337 /* check for left or right bracket, probably meant as a space */
338 while( (chChar = strchr_s(chLine , '[' ) ) !=NULL )
339 {
340 *chChar = ' ';
341 input.lgBracketFound = true;
342 }
343
344 while( (chChar = strchr_s(chLine , ']' ) ) !=NULL )
345 {
346 *chChar = ' ';
347 input.lgBracketFound = true;
348 }
349 }
350
351 /* this is trick so that cloudy input can read cloudy output */
352 /* are first 25 char of input string equal to output? */
353 if( strncmp(chLine," * ",25) == 0 )
354 {
355 /* reading cloudy output, send in shifted input */
356 nread = cdRead( chLine+25 );
357 }
358 else
359 {
360 /* stuff the command line into the internal stack */
361 nread = cdRead( chLine );
362 }
363 }
364
365 if( lgAbort )
366 {
367 /* input parser hit something REALLY bad */
369 }
370
371 if( nread <= 0 )
372 fprintf(ioQQQ," Warning: limit to number of lines exceeded, %i\n", nread);
373
374 // optimize.lgVaryOn catches both optimizer and grid runs
375 if( ( cpu.i().lgMPI() || optimize.lgVaryOn ) && save.chRedirectPrefix.empty() )
376 {
377 if( cpu.i().lgMaster() )
378 {
379 if( cpu.i().lgMPI() )
380 fprintf( ioQQQ, " Please use the style \"mpirun -n np /path/to/cloudy.exe -r input\" when doing grid\n"
381 "or optimizer runs. See http://trac.nublado.org/wiki/RunCode for more information.\n" );
382 else
383 fprintf( ioQQQ, " Please use the style \"/path/to/cloudy.exe -r input\" when doing grid\n"
384 "or optimizer runs. See http://trac.nublado.org/wiki/RunCode for more information.\n" );
385 }
386 // stop the grid from being executed any further
387 grid.lgGrid = false;
389 }
390
391 /* actually call the code. This routine figures out whether the code will do
392 * a single model or be used to optimize on a spectrum, by looking for the
393 * keyword VARY on command lines. It will call routine cloudy if no vary commands
394 * occur, and lgOptimize_do if VARY does occur.
395 * cdDrive returns 0 if calculation is ok, 1 if problems happened */
396 if( cdDrive() )
397 exit_status = ES_FAILURE;
398
399 /* the last line of output will contain some interesting information about the model*/
400 cdNwcns(
401 /* abort status, this better be false, 0 */
402 &lgAbort_exit,
403 /* the number of warnings, cautions, notes, and surprises */
404 &NumberWarnings,
405 &NumberCautions,
406 &NumberNotes,
407 &NumberSurprises,
408 /* the number of temperature convergence failures */
409 &NumberTempFailures,
410 /* the number of pressure convergence failures */
411 &NumberPresFailures,
412 /* the number of ionization convergence failures */
413 &NumberIonFailures,
414 /* the number of electron density convergence failures */
415 &NumberNeFailures );
416
417 ostringstream finalMsg;
418
419 finalMsg << " Cloudy ends: " << nzone << " zone";
420 if( nzone > 1 )
421 finalMsg << "s";
422
423 finalMsg << ", " << iteration << " iteration";
424 if( iteration > 1 )
425 finalMsg << "s";
426
427 if( lgAbort_exit )
428 finalMsg << ", ABORT DISASTER PROBLEM";
429
430 if( NumberWarnings > 0 )
431 {
432 finalMsg << ", " << NumberWarnings << " warning";
433 if( NumberWarnings > 1 )
434 finalMsg << "s";
435 /* this indicates error */
436 exit_status = ES_FAILURE;
437 }
438
439 if( NumberCautions > 0 )
440 {
441 finalMsg << ", " << NumberCautions << " caution";
442 if( NumberCautions > 1 )
443 finalMsg << "s";
444 }
445
446 /* this flag was set in lgCheckMonitors*/
447 if( !lgMonitorsOK )
448 {
449 finalMsg << ", ";
450 /* some botches were three sigma */
451 if( lgBigBotch )
452 finalMsg << "BIG ";
453 finalMsg << "BOTCHED MONITORS!!!";
454 /* this indicates error */
455 exit_status = ES_FAILURE;
456 }
457
458 if( NumberTempFailures+NumberPresFailures+NumberIonFailures+NumberNeFailures > 0 )
459 {
460 finalMsg << ". Failures: " << NumberTempFailures << " thermal, ";
461 finalMsg << NumberPresFailures << " pressure, ";
462 finalMsg << NumberIonFailures << " ionization, ";
463 finalMsg << NumberNeFailures << " electron density";
464 }
465
466 /* NB DO NOT CHANGE ANY ASPECT OF THE FOLLOWING STRINGS - THEY ARE USED TO RECORD
467 * EXEC TIME BY A PERL SCRIPT */
468 if( prt.lgPrintTime )
469 {
470 /* print execution time [s] by default,
471 * need spaces around number so that logging perl script picks up correct number
472 * ir_extime.pl script will delete through "ExecTime(s)" and remainder of line must be number */
473 finalMsg << ". ExecTime(s) " << fixed << setprecision(2) << cdExecTime();
474 }
475
476 if( called.lgTalk )
477 fprintf( ioQQQ, "%s\n", finalMsg.str().c_str() );
478
479 lgEarly_exit = false;
480
481 /* cdDrive returned 1 if something bad happened, and 0 if everything is ok. We will
482 * return 0 if everything is ok, and a non-zero error code if something bad happened.*/
483 cdEXIT(exit_status);
484 }
485 catch( bad_alloc )
486 {
487 fprintf( ioQQQ, " DISASTER - A memory allocation has failed. Most likely your computer "
488 "ran out of memory.\n Try monitoring the memory use of your run. Bailing out...\n" );
489 exit_status = ES_BAD_ALLOC;
490 }
491 catch( out_of_range& e )
492 {
493 fprintf( ioQQQ, " DISASTER - An out_of_range exception was caught, what() = %s. Bailing out...\n",
494 e.what() );
495 exit_status = ES_OUT_OF_RANGE;
496 }
497 catch( bad_assert& e )
498 {
499 MyAssert( e.file(), e.line() , e.comment() );
500 exit_status = ES_BAD_ASSERT;
501 }
502#ifdef CATCH_SIGNAL
503 catch( bad_signal& e )
504 {
505 if( ioQQQ != NULL )
506 {
507 if( e.sig() == SIGINT || e.sig() == SIGQUIT )
508 {
509 fprintf( ioQQQ, " User interrupt request. Bailing out...\n" );
510 exit_status = ES_USER_INTERRUPT;
511 }
512 else if( e.sig() == SIGTERM )
513 {
514 fprintf( ioQQQ, " Termination request. Bailing out...\n" );
515 exit_status = ES_TERMINATION_REQUEST;
516 }
517 else if( e.sig() == SIGILL )
518 {
519 fprintf( ioQQQ, " DISASTER - An illegal instruction was found. Bailing out...\n" );
520 exit_status = ES_ILLEGAL_INSTRUCTION;
521 }
522 else if( e.sig() == SIGFPE )
523 {
524 fprintf( ioQQQ, " DISASTER - A floating point exception occurred. Bailing out...\n" );
525 exit_status = ES_FP_EXCEPTION;
526 }
527 else if( e.sig() == SIGSEGV )
528 {
529 fprintf( ioQQQ, " DISASTER - A segmentation violation occurred. Bailing out...\n" );
530 exit_status = ES_SEGFAULT;
531 }
532# ifdef SIGBUS
533 else if( e.sig() == SIGBUS )
534 {
535 fprintf( ioQQQ, " DISASTER - A bus error occurred. Bailing out...\n" );
536 exit_status = ES_BUS_ERROR;
537 }
538# endif
539 else
540 {
541 fprintf( ioQQQ, " DISASTER - A signal %d was caught. Bailing out...\n", e.sig() );
542 exit_status = ES_UNKNOWN_SIGNAL;
543 }
544
545 }
546 }
547#endif
548 catch( cloudy_exit& e )
549 {
550 if( called.lgTalk )
551 {
552 ostringstream oss;
553 oss << " [Stop in " << e.routine();
554 oss << " at " << e.file() << ":" << e.line();
555 if( e.exit_status() == 0 )
556 oss << ", Cloudy exited OK]";
557 else
558 oss << ", something went wrong]";
559 fprintf( ioQQQ, "%s\n", oss.str().c_str() );
560 }
561 exit_status = e.exit_status();
562 if( exit_status == ES_FAILURE && !lgEarly_exit )
563 {
564 // try to make the error code more descriptive
565 // when there is no early exit in the code, then these 3
566 // should be the only reasons for a non-zero exit code
567 if( NumberWarnings > 0 )
568 exit_status = ES_WARNINGS;
569 if( !lgMonitorsOK )
570 exit_status = ES_BOTCHES;
571 if( lgAbort_exit )
572 exit_status = ES_CLOUDY_ABORT;
573 }
574 }
575 catch( std::exception& e )
576 {
577 fprintf( ioQQQ, " DISASTER - An unknown exception was caught, what() = %s. Bailing out...\n",
578 e.what() );
579 exit_status = ES_UNKNOWN_EXCEPTION;
580 }
581 // generic catch-all in case we forget any specific exception above... so this MUST be the last one.
582 catch( ... )
583 {
584 fprintf( ioQQQ, " DISASTER - An unknown exception was caught. Bailing out...\n" );
585 exit_status = ES_UNKNOWN_EXCEPTION;
586 }
587
588 if( called.lgTalk && cpu.i().lgMPISingleRankMode() )
589 print_delimiter(optimize.nOptimiz);
590
591 cdPrepareExit(exit_status);
592
593 return exit_status;
594}
int main()
Definition TestMain.cpp:8
t_called called
Definition called.cpp:5
long int nzone
Definition cddefines.cpp:14
FILE * ioQQQ
Definition cddefines.cpp:7
FILE * ioStdin
Definition cddefines.cpp:8
bool lgAbort
Definition cddefines.cpp:10
long int iteration
Definition cddefines.cpp:16
exit_type
Definition cddefines.h:115
@ ES_FAILURE
Definition cddefines.h:117
@ ES_BOTCHES
Definition cddefines.h:119
@ ES_SEGFAULT
Definition cddefines.h:128
@ ES_USER_INTERRUPT
Definition cddefines.h:124
@ ES_TERMINATION_REQUEST
Definition cddefines.h:125
@ ES_WARNINGS
Definition cddefines.h:118
@ ES_BUS_ERROR
Definition cddefines.h:129
@ ES_BAD_ASSERT
Definition cddefines.h:121
@ ES_UNKNOWN_SIGNAL
Definition cddefines.h:130
@ ES_SUCCESS
Definition cddefines.h:116
@ ES_UNKNOWN_EXCEPTION
Definition cddefines.h:131
@ ES_OUT_OF_RANGE
Definition cddefines.h:123
@ ES_BAD_ALLOC
Definition cddefines.h:122
@ ES_ILLEGAL_INSTRUCTION
Definition cddefines.h:126
@ ES_FP_EXCEPTION
Definition cddefines.h:127
@ ES_CLOUDY_ABORT
Definition cddefines.h:120
const int INPUT_LINE_LENGTH
Definition cddefines.h:254
void MyAssert(const char *file, int line, const char *comment)
Definition service.cpp:153
#define cdEXIT(FAIL)
Definition cddefines.h:434
const char * strchr_s(const char *s, int c)
Definition cddefines.h:1439
long max(int a, long b)
Definition cddefines.h:775
char * read_whole_line(char *chLine, int nChar, FILE *ioIN)
Definition service.cpp:70
NORETURN void TotalInsanity(void)
Definition service.cpp:886
#define DEBUG_ENTRY(funcname)
Definition cddefines.h:684
void cdPrepareExit(exit_type)
Definition cdinit.cpp:202
int cdRead(const char *chInputLine)
Definition cddrive.cpp:1752
void cdInput(const char *filename, const char *mode)
Definition cddrive.cpp:1530
int cdDrive()
Definition cddrive.cpp:77
void cdNwcns(bool *lgAbort_ret, long int *NumberWarnings, long int *NumberCautions, long int *NumberNotes, long int *NumberSurprises, long int *NumberTempFailures, long int *NumberPresFailures, long int *NumberIonFailures, long int *NumberNeFailures)
Definition cddrive.cpp:1481
double cdExecTime()
Definition cddrive.cpp:481
void cdOutput(const char *filename, const char *mode)
Definition cddrive.cpp:1517
void cdInit()
Definition cdinit.cpp:115
FILE * open_data(const char *fname, const char *mode, access_scheme scheme)
Definition cpu.cpp:625
static t_cpu cpu
Definition cpu.h:355
@ AS_LOCAL_ONLY
Definition cpu.h:208
t_grid grid
Definition grid.cpp:5
void GridGatherInCloudy(void)
t_input input
Definition input.cpp:12
bool lgInputComment(const char *chLine)
Definition input.cpp:18
void print_delimiter(long nOptimiz)
Definition maincl.cpp:18
exit_type cdMain(int argc, const char *argv[])
Definition maincl.cpp:120
bool lgBigBotch
bool lgMonitorsOK
void process_output()
string GridPointPrefix(int n)
#define Get_size()
#define Get_rank()
t_MPI COMM_WORLD
t_optimize optimize
Definition optimize.cpp:5
t_prt prt
Definition prt.cpp:10
t_save save
Definition save.cpp:5