00001
00002
00003
00004
00005
00006 #include "cddefines.h"
00007 #include "cddrive.h"
00008 #include "input.h"
00009 #include "prt.h"
00010 #include "save.h"
00011 #include "called.h"
00012 #include "monitor_results.h"
00013 #include "mpi_utilities.h"
00014 #include "grid.h"
00015
00016 exit_type cdMain( int argc, const char* argv[] );
00017
00018 inline void print_delimiter(long nOptimiz)
00019 {
00020 fprintf( ioQQQ, " ************************************************** GRID_DELIMIT" );
00021 if( nOptimiz >= 0 )
00022 fprintf( ioQQQ, " -- grid%9.9ld", nOptimiz );
00023 fprintf( ioQQQ, "\n" );
00024 }
00025
00028 int main( int argc, char *argv[] )
00029 {
00030 exit_type exit_status = ES_SUCCESS;
00031
00032 DEBUG_ENTRY( "main()" );
00033
00034 if( cpu.i().lgMPI() )
00035 {
00036 MPI::Init( argc, argv );
00037
00038 cpu.i().set_nCPU( MPI::COMM_WORLD.Get_size() );
00039 cpu.i().set_nRANK( MPI::COMM_WORLD.Get_rank() );
00040
00041
00042
00043 cpu.i().set_signal_handlers();
00044 }
00045
00046
00047
00048 exit_status = cdMain( argc, (const char**)argv );
00049
00050
00051 if( cpu.i().lgMPI() )
00052 MPI::COMM_WORLD.Barrier();
00053
00054
00055 if( grid.lgGrid )
00056 {
00057
00058 grid.lgGridDone = false;
00059
00060
00061 cpu.i().set_MPISingleRankMode( true );
00062
00063 load_balance lb( grid.totNumModels );
00064
00065
00066
00067 while( ( optimize.nOptimiz = lb.next_job() ) >= 0 )
00068 {
00069 const char** mpi_argv = new const char*[argc+2];
00070
00071 string jobName = GridPointPrefix( optimize.nOptimiz );
00072 for( int i=0; i < argc; ++i )
00073 mpi_argv[i] = argv[i];
00074 mpi_argv[argc] = "-g";
00075 mpi_argv[argc+1] = jobName.c_str();
00076
00077 exit_type retval = cdMain( argc+2, mpi_argv );
00078
00079 exit_status = max( retval, exit_status );
00080 delete[] mpi_argv;
00081
00082 ++grid.seqNum;
00083 }
00084
00085 lb.finalize();
00086
00087
00088 grid.lgGridDone = true;
00089 optimize.nOptimiz = grid.totNumModels;
00090 GridGatherInCloudy();
00091
00092
00093 if( cpu.i().lgMaster() )
00094 process_output();
00095 }
00096
00097
00098 if( cpu.i().lgMPI() && cpu.i().lgMaster() )
00099 {
00100 for( long n=1; n < cpu.i().nCPU(); ++n )
00101 {
00102 ostringstream oss;
00103 oss << ".err" << setfill('0') << setw(2) << n;
00104 string slave_output = save.chRedirectPrefix + oss.str();
00105 FILE *io = open_data( slave_output.c_str(), "a", AS_LOCAL_ONLY );
00106 bool lgEmpty = ( ftell(io) == 0 );
00107 fclose( io );
00108 if( lgEmpty )
00109 remove( slave_output.c_str() );
00110 }
00111 }
00112
00113 if( cpu.i().lgMPI() )
00114 MPI::Finalize();
00115
00116 return exit_status;
00117 }
00118
00120 exit_type cdMain( int argc, const char* argv[] )
00121 {
00122
00123 long int NumberWarnings,
00124 NumberCautions,
00125 NumberNotes,
00126 NumberSurprises,
00127 NumberTempFailures,
00128 NumberPresFailures,
00129 NumberIonFailures,
00130 NumberNeFailures;
00131
00132 bool lgAbort_exit,
00133 lgEarly_exit=true,
00134 lgFileIO;
00135
00136 int nread=0;
00137
00138 int i;
00139 const char *s,
00140 *prefix = "",
00141 *gprefix = "",
00142 *pprefix = "",
00143 *rprefix = "";
00144 string infile("");
00145
00146
00147
00148
00149
00150
00151 char chLine[INPUT_LINE_LENGTH];
00152
00153
00154 lgFileIO = false;
00155
00156 exit_type exit_status = ES_SUCCESS;
00157
00158 DEBUG_ENTRY( "cdMain()" );
00159
00160 try {
00161
00162
00163
00164
00165
00166 for( i=1; i < argc; i++ )
00167 {
00168 s = argv[i];
00169 if( *s != '-' || s[1] == '\0' )
00170 {
00171 if (infile != "")
00172 {
00173 fprintf( ioQQQ, "%s: only one input file argument allowed\n", argv[0] );
00174 cdEXIT(ES_FAILURE);
00175 }
00176 infile = s;
00177 if( infile.find( cpu.i().chDirSeparator() ) != string::npos )
00178 {
00179 fprintf( ioQQQ, "%s %s: read/write from subdirectories is not supported\n",
00180 argv[0], infile.c_str() );
00181 cdEXIT(ES_FAILURE);
00182 }
00183 FILE *fp = fopen(infile.c_str(),"r");
00184 if (!fp)
00185 {
00186 fprintf( ioQQQ, "%s: input filename `%s' not found\n", argv[0], infile.c_str() );
00187 cdEXIT(ES_FAILURE);
00188 }
00189 fclose(fp);
00190 size_t suffindex = infile.find_last_of(".");
00191 if (suffindex != string::npos)
00192 infile = infile.substr(0,suffindex);
00193 pprefix = rprefix = infile.c_str();
00194 lgFileIO = true;
00195 }
00196 else
00197 {
00198 while( s != NULL && *(++s) )
00199 {
00200 exit_type exit = ES_SUCCESS;
00201 switch( *s )
00202 {
00203 case 'a':
00204 cpu.i().setAssertAbort( true );
00205 break;
00206 case 'g':
00207 case 'p':
00208 case 'r':
00209 if( s[1] != '\0' )
00210 {
00211 prefix = s+1;
00212 }
00213 else
00214 {
00215 if( ++i == argc || argv[i][0] == '-' )
00216 {
00217 fprintf( ioQQQ, "%s: no argument given for -%c flag\n",
00218 argv[0], *s );
00219 cdEXIT(ES_FAILURE);
00220 }
00221 prefix = argv[i];
00222 if( strchr(prefix, cpu.i().chDirSeparator()) != NULL )
00223 {
00224 fprintf( ioQQQ, "%s -%c %s: writing in subdirectories is not supported\n",
00225 argv[0], *s, prefix );
00226 cdEXIT(ES_FAILURE);
00227 }
00228 }
00229 if( *s == 'g' )
00230 gprefix = prefix;
00231 else if( *s == 'p' )
00232 {
00233 pprefix = prefix;
00234 rprefix = prefix;
00235 }
00236 else if( *s == 'r' )
00237 {
00238
00239 pprefix = "";
00240 rprefix = prefix;
00241 }
00242 else
00243 TotalInsanity();
00244 s = NULL;
00245 lgFileIO = true;
00246 break;
00247 default:
00248 fprintf( ioQQQ, "%s: argument %d, `%s': flag -%c not understood\n",
00249 argv[0], i, argv[i], *s );
00250 exit = ES_FAILURE;
00251 case 'h':
00252 fprintf( ioQQQ, "\nSupported flags are:\n\n" );
00253 fprintf( ioQQQ, "-p example\n" );
00254 fprintf( ioQQQ, " Cloudy reads the input from the file example.in\n" );
00255 fprintf( ioQQQ, " and writes the output to the file example.out.\n" );
00256 fprintf( ioQQQ, " Additionally, all file names in SAVE commands are\n" );
00257 fprintf( ioQQQ, " prepended with the string \"example\", e.g. the\n" );
00258 fprintf( ioQQQ, " output of SAVE DR \".dr\" will be in example.dr.\n" );
00259 fprintf( ioQQQ, "-r example\n" );
00260 fprintf( ioQQQ, " This does the same as the -p switch, except that\n" );
00261 fprintf( ioQQQ, " the names used in SAVE commands are not altered.\n" );
00262 fprintf( ioQQQ, "-g example\n" );
00263 fprintf( ioQQQ, " This switch is used internally in MPI grid runs.\n" );
00264 fprintf( ioQQQ, " Normal users should not use this switch.\n" );
00265 fprintf( ioQQQ, "-a\n" );
00266 fprintf( ioQQQ, " This switch is used in debugging. It causes the\n" );
00267 fprintf( ioQQQ, " code to crash rather than exit gracefully after\n" );
00268 fprintf( ioQQQ, " a failed assert. This flag is deprecated.\n" );
00269 fprintf( ioQQQ, "-h\n" );
00270 fprintf( ioQQQ, " Print this message.\n" );
00271 cdEXIT(exit);
00272 }
00273 }
00274 }
00275 }
00276
00277
00278 cdInit();
00279
00280 save.chGridPrefix = gprefix;
00281 save.chFilenamePrefix = pprefix;
00282 save.chRedirectPrefix = rprefix;
00283
00284
00285 if( lgFileIO )
00286 {
00287 string Base = save.chGridPrefix + save.chRedirectPrefix;
00288 string InName = Base + ".in";
00289 string OutName;
00290 if( cpu.i().lgMPI_talk() )
00291 OutName = Base + ".out";
00292 else
00293 {
00294 ostringstream oss;
00295 oss << ".err" << setfill('0') << setw(2) << cpu.i().nRANK();
00296 OutName = Base + oss.str();
00297 }
00298 cdInput( InName.c_str(), "r" );
00299 cdOutput( OutName.c_str(), "w" );
00300 }
00301
00302 if( optimize.nOptimiz == 0 && called.lgTalk && cpu.i().lgMPISingleRankMode() )
00303 print_delimiter(-1);
00304
00305 nread = 1;
00306
00307 while( read_whole_line(chLine, (int)sizeof(chLine), ioStdin)!= NULL )
00308 {
00309 char *chChar;
00310
00311
00312
00313
00314
00315 if( chLine[0] == '\n' || chLine[0] == '\r' ||
00316 ( chLine[0] == ' ' && chLine[23] != '*' ) ||
00317 (strncmp( chLine , "***" , 3 )==0 ) )
00318 break;
00319
00320
00321 if( !lgInputComment(chLine) )
00322 {
00323
00324 if( (chChar = strchr_s(chLine , '\"' ) ) ==NULL )
00325 {
00326
00327 while( (chChar = strchr_s(chLine , '_' ) ) !=NULL )
00328 {
00329 *chChar = ' ';
00330 input.lgUnderscoreFound = true;
00331 }
00332 }
00333
00334
00335
00336
00337
00338 while( (chChar = strchr_s(chLine , '[' ) ) !=NULL )
00339 {
00340 *chChar = ' ';
00341 input.lgBracketFound = true;
00342 }
00343
00344 while( (chChar = strchr_s(chLine , ']' ) ) !=NULL )
00345 {
00346 *chChar = ' ';
00347 input.lgBracketFound = true;
00348 }
00349 }
00350
00351
00352
00353 if( strncmp(chLine," * ",25) == 0 )
00354 {
00355
00356 nread = cdRead( chLine+25 );
00357 }
00358 else
00359 {
00360
00361 nread = cdRead( chLine );
00362 }
00363 }
00364
00365 if( lgAbort )
00366 {
00367
00368 cdEXIT(ES_CLOUDY_ABORT);
00369 }
00370
00371 if( nread <= 0 )
00372 fprintf(ioQQQ," Warning: limit to number of lines exceeded, %i\n", nread);
00373
00374
00375 if( ( cpu.i().lgMPI() || optimize.lgVaryOn ) && save.chRedirectPrefix.empty() )
00376 {
00377 if( cpu.i().lgMaster() )
00378 {
00379 if( cpu.i().lgMPI() )
00380 fprintf( ioQQQ, " Please use the style \"mpirun -n np /path/to/cloudy.exe -r input\" when doing grid\n"
00381 "or optimizer runs. See http://trac.nublado.org/wiki/RunCode for more information.\n" );
00382 else
00383 fprintf( ioQQQ, " Please use the style \"/path/to/cloudy.exe -r input\" when doing grid\n"
00384 "or optimizer runs. See http://trac.nublado.org/wiki/RunCode for more information.\n" );
00385 }
00386
00387 grid.lgGrid = false;
00388 cdEXIT(ES_FAILURE);
00389 }
00390
00391
00392
00393
00394
00395
00396 if( cdDrive() )
00397 exit_status = ES_FAILURE;
00398
00399
00400 cdNwcns(
00401
00402 &lgAbort_exit,
00403
00404 &NumberWarnings,
00405 &NumberCautions,
00406 &NumberNotes,
00407 &NumberSurprises,
00408
00409 &NumberTempFailures,
00410
00411 &NumberPresFailures,
00412
00413 &NumberIonFailures,
00414
00415 &NumberNeFailures );
00416
00417 ostringstream finalMsg;
00418
00419 finalMsg << " Cloudy ends: " << nzone << " zone";
00420 if( nzone > 1 )
00421 finalMsg << "s";
00422
00423 finalMsg << ", " << iteration << " iteration";
00424 if( iteration > 1 )
00425 finalMsg << "s";
00426
00427 if( lgAbort_exit )
00428 finalMsg << ", ABORT DISASTER PROBLEM";
00429
00430 if( NumberWarnings > 0 )
00431 {
00432 finalMsg << ", " << NumberWarnings << " warning";
00433 if( NumberWarnings > 1 )
00434 finalMsg << "s";
00435
00436 exit_status = ES_FAILURE;
00437 }
00438
00439 if( NumberCautions > 0 )
00440 {
00441 finalMsg << ", " << NumberCautions << " caution";
00442 if( NumberCautions > 1 )
00443 finalMsg << "s";
00444 }
00445
00446
00447 if( !lgMonitorsOK )
00448 {
00449 finalMsg << ", ";
00450
00451 if( lgBigBotch )
00452 finalMsg << "BIG ";
00453 finalMsg << "BOTCHED MONITORS!!!";
00454
00455 exit_status = ES_FAILURE;
00456 }
00457
00458 if( NumberTempFailures+NumberPresFailures+NumberIonFailures+NumberNeFailures > 0 )
00459 {
00460 finalMsg << ". Failures: " << NumberTempFailures << " thermal, ";
00461 finalMsg << NumberPresFailures << " pressure, ";
00462 finalMsg << NumberIonFailures << " ionization, ";
00463 finalMsg << NumberNeFailures << " electron density";
00464 }
00465
00466
00467
00468 if( prt.lgPrintTime )
00469 {
00470
00471
00472
00473 finalMsg << ". ExecTime(s) " << fixed << setprecision(2) << cdExecTime();
00474 }
00475
00476 if( called.lgTalk )
00477 fprintf( ioQQQ, "%s\n", finalMsg.str().c_str() );
00478
00479 lgEarly_exit = false;
00480
00481
00482
00483 cdEXIT(exit_status);
00484 }
00485 catch( bad_alloc )
00486 {
00487 fprintf( ioQQQ, " DISASTER - A memory allocation has failed. Most likely your computer "
00488 "ran out of memory.\n Try monitoring the memory use of your run. Bailing out...\n" );
00489 exit_status = ES_BAD_ALLOC;
00490 }
00491 catch( out_of_range& e )
00492 {
00493 fprintf( ioQQQ, " DISASTER - An out_of_range exception was caught, what() = %s. Bailing out...\n",
00494 e.what() );
00495 exit_status = ES_OUT_OF_RANGE;
00496 }
00497 catch( bad_assert& e )
00498 {
00499 MyAssert( e.file(), e.line() , e.comment() );
00500 exit_status = ES_BAD_ASSERT;
00501 }
00502 #ifdef CATCH_SIGNAL
00503 catch( bad_signal& e )
00504 {
00505 if( ioQQQ != NULL )
00506 {
00507 if( e.sig() == SIGINT || e.sig() == SIGQUIT )
00508 {
00509 fprintf( ioQQQ, " User interrupt request. Bailing out...\n" );
00510 exit_status = ES_USER_INTERRUPT;
00511 }
00512 else if( e.sig() == SIGTERM )
00513 {
00514 fprintf( ioQQQ, " Termination request. Bailing out...\n" );
00515 exit_status = ES_TERMINATION_REQUEST;
00516 }
00517 else if( e.sig() == SIGILL )
00518 {
00519 fprintf( ioQQQ, " DISASTER - An illegal instruction was found. Bailing out...\n" );
00520 exit_status = ES_ILLEGAL_INSTRUCTION;
00521 }
00522 else if( e.sig() == SIGFPE )
00523 {
00524 fprintf( ioQQQ, " DISASTER - A floating point exception occurred. Bailing out...\n" );
00525 exit_status = ES_FP_EXCEPTION;
00526 }
00527 else if( e.sig() == SIGSEGV )
00528 {
00529 fprintf( ioQQQ, " DISASTER - A segmentation violation occurred. Bailing out...\n" );
00530 exit_status = ES_SEGFAULT;
00531 }
00532 # ifdef SIGBUS
00533 else if( e.sig() == SIGBUS )
00534 {
00535 fprintf( ioQQQ, " DISASTER - A bus error occurred. Bailing out...\n" );
00536 exit_status = ES_BUS_ERROR;
00537 }
00538 # endif
00539 else
00540 {
00541 fprintf( ioQQQ, " DISASTER - A signal %d was caught. Bailing out...\n", e.sig() );
00542 exit_status = ES_UNKNOWN_SIGNAL;
00543 }
00544
00545 }
00546 }
00547 #endif
00548 catch( cloudy_exit& e )
00549 {
00550 if( called.lgTalk )
00551 {
00552 ostringstream oss;
00553 oss << " [Stop in " << e.routine();
00554 oss << " at " << e.file() << ":" << e.line();
00555 if( e.exit_status() == 0 )
00556 oss << ", Cloudy exited OK]";
00557 else
00558 oss << ", something went wrong]";
00559 fprintf( ioQQQ, "%s\n", oss.str().c_str() );
00560 }
00561 exit_status = e.exit_status();
00562 if( exit_status == ES_FAILURE && !lgEarly_exit )
00563 {
00564
00565
00566
00567 if( NumberWarnings > 0 )
00568 exit_status = ES_WARNINGS;
00569 if( !lgMonitorsOK )
00570 exit_status = ES_BOTCHES;
00571 if( lgAbort_exit )
00572 exit_status = ES_CLOUDY_ABORT;
00573 }
00574 }
00575 catch( std::exception& e )
00576 {
00577 fprintf( ioQQQ, " DISASTER - An unknown exception was caught, what() = %s. Bailing out...\n",
00578 e.what() );
00579 exit_status = ES_UNKNOWN_EXCEPTION;
00580 }
00581
00582 catch( ... )
00583 {
00584 fprintf( ioQQQ, " DISASTER - An unknown exception was caught. Bailing out...\n" );
00585 exit_status = ES_UNKNOWN_EXCEPTION;
00586 }
00587
00588 if( called.lgTalk && cpu.i().lgMPISingleRankMode() )
00589 print_delimiter(optimize.nOptimiz);
00590
00591 cdPrepareExit(exit_status);
00592
00593 return exit_status;
00594 }