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 #ifdef MPI_ENABLED
00014 #include "mpi_utilities.h"
00015 #include "grid.h"
00016 #endif
00017
00018 int cdMain( int argc, const char* argv[] );
00019
00022 int main( int argc, char *argv[] )
00023 {
00024 int exit_status = 0;
00025
00026 DEBUG_ENTRY( "main()" );
00027
00028 # ifdef MPI_ENABLED
00029
00030 MPI::Init( argc, argv );
00031
00032 cpu.set_MPI();
00033 cpu.set_nCPU( MPI::COMM_WORLD.Get_size() );
00034 cpu.set_nRANK( MPI::COMM_WORLD.Get_rank() );
00035
00036 # ifdef MPI_GRID_RUN
00037
00038
00039
00040 exit_status = cdMain( argc, (const char**)argv );
00041
00042
00043 MPI::COMM_WORLD.Barrier();
00044
00045
00046 if( grid.lgGrid )
00047 {
00048
00049 grid.lgGridDone = false;
00050
00051
00052 cpu.set_MPISingleRankMode( true );
00053
00054 MPI::load_balance lb( grid.totNumModels );
00055
00056
00057
00058 while( ( optimize.nOptimiz = lb.next_job() ) >= 0 )
00059 {
00060 const char** mpi_argv = new const char*[argc+2];
00061
00062 string jobName = GridPointPrefix( optimize.nOptimiz );
00063 for( int i=0; i < argc; ++i )
00064 mpi_argv[i] = argv[i];
00065 mpi_argv[argc] = "-g";
00066 mpi_argv[argc+1] = jobName.c_str();
00067
00068 int retval = cdMain( argc+2, mpi_argv );
00069
00070 exit_status = max( retval, exit_status );
00071 delete[] mpi_argv;
00072 }
00073
00074 lb.finalize();
00075
00076
00077 grid.lgGridDone = true;
00078 optimize.nOptimiz = grid.totNumModels;
00079 GridGatherInCloudy();
00080
00081
00082 if( cpu.lgMaster() )
00083 process_output();
00084 }
00085
00086
00087 if( cpu.lgMaster() )
00088 {
00089 for( long n=1; n < cpu.nCPU(); ++n )
00090 {
00091 ostringstream oss;
00092 oss << ".err" << setfill('0') << setw(2) << n;
00093 string slave_output = save.chRedirectPrefix + oss.str();
00094 FILE *io = open_data( slave_output.c_str(), "a", AS_LOCAL_ONLY );
00095 bool lgEmpty = ( ftell(io) == 0 );
00096 fclose( io );
00097 if( lgEmpty )
00098 remove( slave_output.c_str() );
00099 }
00100 }
00101
00102 # endif
00103
00104 MPI::Finalize();
00105
00106 # else
00107
00108
00109 exit_status = cdMain( argc, (const char**)argv );
00110
00111 # endif
00112
00113 return exit_status;
00114 }
00115
00117 int cdMain( int argc, const char* argv[] )
00118 {
00119
00120 long int NumberWarnings,
00121 NumberCautions,
00122 NumberNotes,
00123 NumberSurprises,
00124 NumberTempFailures,
00125 NumberPresFailures,
00126 NumberIonFailures,
00127 NumberNeFailures;
00128
00129 bool lgAbort_exit,
00130 lgFileIO,
00131 lgBadExit;
00132
00133 int nread=0;
00134
00135 int i;
00136 const char *s,
00137 *prefix = "",
00138 *gprefix = "",
00139 *pprefix = "",
00140 *rprefix = "";
00141
00142
00143
00144
00145
00146
00147 char chLine[INPUT_LINE_LENGTH];
00148
00149
00150 lgFileIO = false;
00151
00152 int exit_status = EXIT_FAILURE;
00153
00154 DEBUG_ENTRY( "cdMain()" );
00155
00156 try {
00157
00158
00159
00160
00161
00162 for( i=1; i < argc; i++ )
00163 {
00164 s = argv[i];
00165 if( *s != '-' || s[1] == '\0' )
00166 {
00167 fprintf( ioQQQ, "%s: argument %d `%s' not understood\n", argv[0], i, s );
00168 cdEXIT( EXIT_FAILURE );
00169 }
00170 else
00171 {
00172 while( s != NULL && *(++s) )
00173 {
00174 switch( *s )
00175 {
00176 case 'a':
00177 cpu.setAssertAbort( true );
00178 break;
00179 case 'g':
00180 case 'p':
00181 case 'r':
00182 if( s[1] != '\0' )
00183 {
00184 prefix = s+1;
00185 }
00186 else
00187 {
00188 if( ++i == argc || argv[i][0] == '-' )
00189 {
00190 fprintf( ioQQQ, "%s: no argument given for -%c flag\n",
00191 argv[0], *s );
00192 cdEXIT( EXIT_FAILURE );
00193 }
00194 prefix = argv[i];
00195 }
00196 if( *s == 'g' )
00197 gprefix = prefix;
00198 else if( *s == 'p' )
00199 {
00200 pprefix = prefix;
00201 rprefix = prefix;
00202 }
00203 else if( *s == 'r' )
00204 rprefix = prefix;
00205 else
00206 TotalInsanity();
00207 s = NULL;
00208 lgFileIO = true;
00209 break;
00210 default:
00211 fprintf( ioQQQ, "%s: argument %d, `%s': flag -%c not understood\n",
00212 argv[0], i, argv[i], *s );
00213 cdEXIT( EXIT_FAILURE );
00214 }
00215 }
00216 }
00217 }
00218
00219
00220 cdInit();
00221
00222 save.chGridPrefix = gprefix;
00223 save.chFilenamePrefix = pprefix;
00224 save.chRedirectPrefix = rprefix;
00225
00226 if( cpu.lgMPI() && save.chRedirectPrefix.empty() )
00227 {
00228
00229
00230 if( cpu.lgMPI_talk() )
00231 {
00232 fprintf( ioQQQ, " The -p or -r flag to redirect I/O is mandatory in MPI runs.\n" );
00233 fprintf( ioQQQ, " Usage: mpirun -np <n> /path/to/cloudy.exe [ -p | -r ] <prefix>\n" );
00234 }
00235 cdEXIT(EXIT_FAILURE);
00236 }
00237
00238
00239 if( lgFileIO )
00240 {
00241 string Base = save.chGridPrefix + save.chRedirectPrefix;
00242 string InName = Base + ".in";
00243 string OutName;
00244 if( cpu.lgMPI_talk() )
00245 OutName = Base + ".out";
00246 else
00247 {
00248 ostringstream oss;
00249 oss << ".err" << setfill('0') << setw(2) << cpu.nRANK();
00250 OutName = Base + oss.str();
00251 }
00252 cdInput( InName.c_str(), "r" );
00253 cdOutput( OutName.c_str(), "w" );
00254 }
00255
00256 nread = 1;
00257
00258 while( read_whole_line(chLine, (int)sizeof(chLine), ioStdin)!= NULL )
00259 {
00260 char *chChar;
00261
00262
00263
00264
00265
00266 if( chLine[0] == '\n' || chLine[0] == '\r' ||
00267 ( chLine[0] == ' ' && chLine[23] != '*' ) )
00268 break;
00269
00270
00271 if( !lgInputComment(chLine) )
00272 {
00273
00274 if( (chChar = strchr_s(chLine , '\"' ) ) ==NULL )
00275 {
00276
00277 while( (chChar = strchr_s(chLine , '_' ) ) !=NULL )
00278 {
00279 *chChar = ' ';
00280 input.lgUnderscoreFound = true;
00281 }
00282 }
00283
00284
00285
00286
00287
00288 while( (chChar = strchr_s(chLine , '[' ) ) !=NULL )
00289 {
00290 *chChar = ' ';
00291 input.lgBracketFound = true;
00292 }
00293
00294 while( (chChar = strchr_s(chLine , ']' ) ) !=NULL )
00295 {
00296 *chChar = ' ';
00297 input.lgBracketFound = true;
00298 }
00299 }
00300
00301
00302
00303 if( strncmp(chLine," * ",25) == 0 )
00304 {
00305
00306 nread = cdRead( chLine+25 );
00307 }
00308 else
00309 {
00310
00311 nread = cdRead( chLine );
00312 }
00313 }
00314
00315 if( lgAbort )
00316 {
00317
00318 lgBadExit = true;
00319 return(lgBadExit);
00320 }
00321
00322 if( nread <= 0 )
00323 fprintf(ioQQQ," Warning: limit to number of lines exceeded, %i\n", nread);
00324
00325
00326
00327
00328
00329
00330 if( cdDrive() )
00331 lgBadExit = true;
00332 else
00333 lgBadExit = false;
00334
00335
00336 cdNwcns(
00337
00338 &lgAbort_exit,
00339
00340 &NumberWarnings,
00341 &NumberCautions,
00342 &NumberNotes,
00343 &NumberSurprises,
00344
00345 &NumberTempFailures,
00346
00347 &NumberPresFailures,
00348
00349 &NumberIonFailures,
00350
00351 &NumberNeFailures );
00352
00353 ostringstream finalMsg;
00354
00355 finalMsg << " Cloudy ends: " << nzone << " zone";
00356 if( nzone > 1 )
00357 finalMsg << "s";
00358
00359 finalMsg << ", " << iteration << " iteration";
00360 if( iteration > 1 )
00361 finalMsg << "s";
00362
00363 if( lgAbort_exit )
00364 finalMsg << ", ABORT DISASTER PROBLEM";
00365
00366 if( NumberWarnings > 0 )
00367 {
00368 finalMsg << ", " << NumberWarnings << " warning";
00369 if( NumberWarnings > 1 )
00370 finalMsg << "s";
00371
00372 lgBadExit = 1;
00373 }
00374
00375 if( NumberCautions > 0 )
00376 {
00377 finalMsg << ", " << NumberCautions << " caution";
00378 if( NumberCautions > 1 )
00379 finalMsg << "s";
00380 }
00381
00382
00383 if( !lgMonitorsOK )
00384 {
00385 finalMsg << ", ";
00386
00387 if( lgBigBotch )
00388 finalMsg << "BIG ";
00389 finalMsg << "BOTCHED MONITORS!!!";
00390
00391 lgBadExit = 1;
00392 }
00393
00394 if( NumberTempFailures+NumberPresFailures+NumberIonFailures+NumberNeFailures > 0 )
00395 {
00396 finalMsg << ". Failures: " << NumberTempFailures << " thermal, ";
00397 finalMsg << NumberPresFailures << " pressure, ";
00398 finalMsg << NumberIonFailures << " ionization, ";
00399 finalMsg << NumberNeFailures << " electron density";
00400 }
00401
00402
00403
00404 if( prt.lgPrintTime )
00405 {
00406
00407
00408
00409 finalMsg << ". ExecTime(s) " << fixed << setprecision(2) << cdExecTime();
00410 }
00411
00412 if( called.lgTalk )
00413 fprintf( ioQQQ, "%s\n", finalMsg.str().c_str() );
00414
00415
00416
00417 cdEXIT(lgBadExit);
00418 }
00419 catch( bad_alloc )
00420 {
00421 fprintf( ioQQQ, " DISASTER - A memory allocation has failed. Most likely your computer "
00422 "ran out of memory.\n Try monitoring the memory use of your run. Bailing out...\n" );
00423 cdPrepareExit();
00424 }
00425 catch( out_of_range& e )
00426 {
00427 fprintf( ioQQQ, " DISASTER - An out_of_range exception was caught, what() = %s. Bailing out...\n",
00428 e.what() );
00429 cdPrepareExit();
00430 }
00431 catch( bad_assert& e )
00432 {
00433 MyAssert( e.file(), e.line() , e.comment() );
00434 cdPrepareExit();
00435 }
00436 #ifdef CATCH_SIGNAL
00437 catch( bad_signal& e )
00438 {
00439 if( ioQQQ != NULL )
00440 {
00441 if( e.sig() == SIGINT )
00442 fprintf( ioQQQ, " User interrupt request. Bailing out...\n" );
00443 else if( e.sig() == SIGTERM )
00444 fprintf( ioQQQ, " Termination request. Bailing out...\n" );
00445 else if( e.sig() == SIGILL )
00446 fprintf( ioQQQ, " DISASTER - An illegal instruction was found. Bailing out...\n" );
00447 else if( e.sig() == SIGFPE )
00448 fprintf( ioQQQ, " DISASTER - A floating point exception occurred. Bailing out...\n" );
00449 else if( e.sig() == SIGSEGV )
00450 fprintf( ioQQQ, " DISASTER - A segmentation violation occurred. Bailing out...\n" );
00451 # ifdef SIGBUS
00452 else if( e.sig() == SIGBUS )
00453 fprintf( ioQQQ, " DISASTER - A bus error occurred. Bailing out...\n" );
00454 # endif
00455 else
00456 fprintf( ioQQQ, " DISASTER - A signal %d was caught. Bailing out...\n", e.sig() );
00457
00458 }
00459 cdPrepareExit();
00460 }
00461 #endif
00462 catch( cloudy_exit& e )
00463 {
00464 if( called.lgTalk )
00465 {
00466 ostringstream oss;
00467 oss << " [Stop in " << e.routine();
00468 oss << " at " << e.file() << ":" << e.line();
00469 if( e.exit_status() == 0 )
00470 oss << ", Cloudy exited OK]";
00471 else
00472 oss << ", something went wrong]";
00473 fprintf( ioQQQ, "%s\n", oss.str().c_str() );
00474 }
00475 cdPrepareExit();
00476 exit_status = e.exit_status();
00477 }
00478 catch( std::exception& e )
00479 {
00480 fprintf( ioQQQ, " DISASTER - An unknown exception was caught, what() = %s. Bailing out...\n",
00481 e.what() );
00482 cdPrepareExit();
00483 }
00484
00485 catch( ... )
00486 {
00487 fprintf( ioQQQ, " DISASTER - An unknown exception was caught. Bailing out...\n" );
00488 cdPrepareExit();
00489 }
00490
00491 return exit_status;
00492 }