/home66/gary/public_html/cloudy/c08_branch/source/maincl.cpp

Go to the documentation of this file.
00001 /* This file is part of Cloudy and is copyright (C)1978-2008 by Gary J. Ferland and
00002  * others.  For conditions of distribution and use see copyright notice in license.txt */
00003 /*main program that reads input and calls cloudy to compute a single model, or
00004  * try to optimize an observed model.  Routine returns 0 if model is ok, 
00005  * and 1 if problems occurred. */
00006 #include "cddefines.h"
00007 #include "cddrive.h"
00008 #include "input.h"
00009 #include "prt.h"
00010 #include "punch.h"
00011 #include "assertresults.h"
00012 #include "grains.h"
00013 
00014 int main( int argc, char *argv[] )
00015 {
00016         /* these will be used to count number of various problems */
00017         long int NumberWarnings, 
00018           NumberCautions, 
00019           NumberNotes, 
00020           NumberSurprises, 
00021           NumberTempFailures, 
00022           NumberPresFailures,
00023           NumberIonFailures, 
00024           NumberNeFailures;
00025 
00026         bool lgAbort_exit,
00027           lgFileIO,
00028           lgBadExit;
00029         /* number of lines we can still read in */
00030         int nread=0;
00031 
00032         int i,
00033           lenp,
00034           leno,
00035           leni,
00036           lena;
00037         char *s, 
00038           *prefix = NULL, 
00039           *filename,
00040           outtag[] = ".out",
00041           intag[] = ".in";
00042 
00043         /* the length of the following vector will be the longest line image
00044          * the code will be able to read here.  Cloudy itself will ignore anything 
00045          * beyond INPUT_LINE_LENGTH, and checks that no information exists beyond it. 
00046          * The code will stop if the input line is longer than INPUT_LINE_LENGTH
00047          * since extra characters would become a new command line due to buffer overrun */
00048         char chLine[INPUT_LINE_LENGTH];
00049 
00050         /* change following to true to write to debugging file */
00051         lgFileIO = false;
00052 
00053         DEBUG_ENTRY( "main()" );
00054 
00055         try {
00056                 /* 
00057                  * Handle argument input -- written generally, but presently handles
00058                  * only `-p prefix' or `-pprefix' to set input file as `prefix.in',
00059                  * output file as `prefix.out' and the punch prefix.
00060                  */
00061                 for(i=1; i<argc; i++) 
00062                 {
00063                         s = argv[i];
00064                         if(*s != '-') 
00065                         {
00066                                 fprintf(stderr,"%s: argument %d `%s' not understood\n",argv[0],i,s);
00067                                 cdEXIT( EXIT_FAILURE );
00068                         }
00069                         else
00070                         {
00071                                 while (s != NULL && *(++s)) {
00072                                         switch (*s) 
00073                                         {
00074                                         case 'a':
00075                                                 cpu.setAssertAbort( true );
00076                                                 break;
00077                                         case 'p':
00078                                                 if(s[1] != '\0')
00079                                                 {
00080                                                         prefix = s+1;
00081                                                 }                                       
00082                                                 else
00083                                                 {
00084                                                         if(++i == argc || argv[i][0] == '-') {
00085                                                                 fprintf(stderr,"%s: no argument given for -p flag\n",
00086                                                                         argv[0]);
00087                                                                 cdEXIT( EXIT_FAILURE );
00088                                                         }
00089                                                         prefix = argv[i];
00090                                                 }
00091                                                 s = NULL;
00092                                                 lgFileIO = true;
00093                                                 break;
00094                                         default:
00095                                                 fprintf(stderr,"%s: argument %d, `%s': flag -%c not understood\n",
00096                                                         argv[0],i,argv[i],*s);
00097                                                 cdEXIT( EXIT_FAILURE );
00098                                         }
00099                                 }
00100                         }
00101                 }
00102 
00103                 /* initialize the code for this run */
00104                 cdInit();
00105 
00106                 /* following should be set true to print to file instead of std output */
00107                 if( lgFileIO )
00108                 {
00109                         FILE *ioOut, *ioInp;
00110                         if(prefix == NULL) 
00111                         {
00112                                 /* this is an option to direct code to a file rather than stdout*/
00113                                 /* following used for passing output to temp file*/
00114                                 if( (ioOut = fopen("c:\\projects\\cloudy\\tests\\CallCloudy.txt", "w" ))==NULL)
00115                                         BadOpen();
00116                                 cdOutp(ioOut);
00117                         }
00118                         else
00119                         {
00120                                 leno = (int)strlen(outtag);
00121                                 leni = (int)strlen(intag);
00122                                 lenp = (int)strlen(prefix);
00123                                 if(leno > leni)
00124                                         lena = lenp+leno+1;
00125                                 else
00126                                         lena = lenp+leni+1;
00127                                 filename = (char *)MALLOC((unsigned)lena*sizeof(char));
00128                                 if(filename == NULL) 
00129                                 {
00130                                         fprintf(stderr,"%s: can't allocate memory\n",argv[0]);
00131                                         cdEXIT( EXIT_FAILURE );
00132                                 }
00133                                 strcpy(filename,prefix);
00134                                 strcpy(filename+lenp,outtag);
00135                                 if( (ioOut = fopen(filename, "w" ))==NULL)
00136                                         BadOpen();
00137                                 cdOutp(ioOut);
00138                                 strcpy(filename+lenp,intag);
00139                                 if( (ioInp = fopen(filename, "r" ))==NULL)
00140                                         BadOpen();
00141                                 cdInp(ioInp);
00142                                 strcpy( punch.chFilenamePrefix , prefix );
00143                                 free(filename);
00144                         }
00145                 }
00146 
00147                 nread = 1;
00148                 /* keep reading input lines until end of file */
00149                 while( read_whole_line(chLine, (int)sizeof(chLine), ioStdin)!= NULL )
00150                 {
00151                         char *chChar;
00152                         /* when running from command prompt, last line can be \n or 
00153                          * \r (this can happen with gcc under cygwin in windows) 
00154                          * or space, so check for each here, and break if present,
00155                          * check on chLine[23] is for case where we are reading cloudy output */
00156                         /*fprintf(ioQQQ,"DEBUG char0 %i\n", (int)chLine[0] );*/
00157                         if( chLine[0] == '\n' || chLine[0] == '\r' || 
00158                             ( chLine[0] == ' ' && chLine[23] != '*' ) )
00159                                 break;
00160                         
00161                         /* read entire line of input - lgAbort set true if lines too long */
00162                         if( !lgInputComment(chLine) )
00163                         {
00164 
00165                                 if( (chChar = strchr(chLine , '\"' ) ) ==NULL )
00166                                 {
00167                                         /* check for underscore, probably meant as a space */
00168                                         while( (chChar = strchr(chLine , '_' ) ) !=NULL )
00169                                         {
00170                                                 *chChar = ' ';
00171                                                 input.lgUnderscoreFound = true;
00172                                         }
00173                                 }
00174 
00175                                 /* change _, [, and ] to space if no filename occurs on line 
00176                                  * >>chng 06 sep 04 use routine to check for comments 
00177                                  * do not remove _, [, and ] in comments */
00178                                 /* check for left or right bracket, probably meant as a space */
00179                                 while( (chChar = strchr(chLine , '[' ) ) !=NULL )
00180                                 {
00181                                         *chChar = ' ';
00182                                         input.lgBracketFound = true;
00183                                 }
00184 
00185                                 while( (chChar = strchr(chLine , ']' ) ) !=NULL )
00186                                 {
00187                                         *chChar = ' ';
00188                                         input.lgBracketFound = true;
00189                                 }
00190                         }
00191 
00192                         /* this is trick so that cloudy input can read cloudy output */
00193                         /* are first 25 char of input string equal to output? */
00194                         if( strncmp(chLine,"                       * ",25) == 0 )
00195                         {
00196                                 /* reading cloudy output, send in shifted input */
00197                                 nread = cdRead( chLine+25 );
00198                         }
00199                         else
00200                         {
00201                                 /* stuff the command line into the internal stack */
00202                                 nread = cdRead( chLine  );
00203                         }
00204                 }
00205 
00206                 if( lgAbort )
00207                 {
00208                         /* input parser hit something REALLY bad */
00209                         lgBadExit = true;
00210                         return(lgBadExit);
00211                 }
00212 
00213                 if( nread <= 0 )
00214                         fprintf(ioQQQ," Warning: limit to number of lines exceeded, %i\n", nread);
00215 
00216                 /* actually call the code.  This routine figures out whether the code will do
00217                  * a single model or be used to optimize on a spectrum, by looking for the
00218                  * keyword VARY on command lines.  It will call routine cloudy if no vary commands
00219                  * occur, and lgOptimize_do if VARY does occur.  
00220                  * cdDrive returns 0 if calculation is ok, 1 if problems happened */
00221                 if( cdDrive() )
00222                         lgBadExit = true;
00223                 else
00224                         lgBadExit = false;
00225 
00226                 /* the last line of output will contain some interesting information about the model*/
00227                 cdNwcns(
00228                         /* abort status, this better be false, 0 */
00229                         &lgAbort_exit,
00230                         /* the number of warnings, cautions, notes, and surprises */
00231                         &NumberWarnings, 
00232                         &NumberCautions, 
00233                         &NumberNotes, 
00234                         &NumberSurprises, 
00235                         /* the number of temperature convergence failures */
00236                         &NumberTempFailures, 
00237                         /* the number of pressure convergence failures */
00238                         &NumberPresFailures,
00239                         /* the number of ionization convergence failures */
00240                         &NumberIonFailures, 
00241                         /* the number of electron density convergence failures */
00242                         &NumberNeFailures );
00243 
00244                 fprintf( ioQQQ, 
00245                          " Cloudy ends:%4ld zone" ,
00246                          nzone);
00247 
00248                 /* put an s in iteration if more than one */
00249                 if( nzone > 1 )
00250                         fprintf( ioQQQ,"s");
00251 
00252                 fprintf( ioQQQ, 
00253                          ", %3ld iteration" ,
00254                          iteration );
00255 
00256                 /* put an s in iteration if more than one */
00257                 if( iteration > 1 )
00258                         fprintf( ioQQQ,"s");
00259 
00260                 if( lgAbort_exit )
00261                 {
00262                         fprintf( ioQQQ, 
00263                                  ", ABORT DISASTER PROBLEM" );
00264                 }
00265 
00266                 if( NumberWarnings > 0 )
00267                 {
00268                         fprintf( ioQQQ, 
00269                                  ",%3ld warning", 
00270                                  NumberWarnings);
00271 
00272                         /* put an s in iteration if more than one */
00273                         if( NumberWarnings > 1 )
00274                         {
00275                                 fprintf( ioQQQ,"s");
00276                         }
00277                         /* this indicates error */
00278                         lgBadExit = 1;
00279                 }
00280 
00281                 if( NumberCautions > 0 )
00282                 {
00283                         fprintf( ioQQQ, 
00284                                  ",%3ld caution", 
00285                                  NumberCautions);
00286 
00287                         /* put an s in iteration if more than one */
00288                         if( NumberCautions > 1 )
00289                                 fprintf( ioQQQ,"s");
00290                 }
00291 
00292                 /* this flag was set in lgCheckAsserts*/
00293                 if( !lgAssertsOK )
00294                 {
00295                         fprintf(ioQQQ,", ");
00296                         /* some botches were three sigma */
00297                         if( lgBigBotch  )
00298                                 fprintf(ioQQQ,"BIG ");
00299                         fprintf(ioQQQ,"BOTCHED ASSERTS!!!");
00300                         /* this indicates error */
00301                         lgBadExit = 1;
00302                 }
00303 
00304                 if( NumberTempFailures+NumberPresFailures +NumberIonFailures+NumberNeFailures >0 )
00305                 {
00306                         fprintf( ioQQQ, 
00307                                  ". Failures:%3ld thermal,%3ld pressure,%3ld ionization,%3ld electron density", 
00308                                  NumberTempFailures, 
00309                                  NumberPresFailures ,
00310                                  NumberIonFailures, 
00311                                  NumberNeFailures);
00312                 }
00313 
00314                 /* NB DO NOT CHANGE ANY ASPECT OF THE FOLLOWING STRINGS - THEY ARE USED TO RECORD
00315                  * EXEC TIME BY A PERL SCRIPT */
00316                 if( prt.lgPrintTime )
00317                 {
00318                         /* print execution time [s] by default,
00319                          * need spaces around number so that logging perl script picks up correct number 
00320                          * ir_extime.pl script will delete through "ExecTime(s)" and remainder of line must be number */
00321                         fprintf( ioQQQ, ".  ExecTime(s) %.2f",  cdExecTime());
00322                 }
00323 
00324                 fprintf( ioQQQ, "\n");
00325 
00326                 /* return memory used by the grains */
00327                 ReturnGrainBins();
00328 
00329                 /* cdDrive returned 1 if something bad happened, and 0 if everything is ok.  We will
00330                  * return 0 if everything is ok, and 1 if something bad happened.*/
00331                 cdEXIT(lgBadExit);
00332         }
00333         catch( bad_alloc )
00334         {
00335                 fprintf( ioQQQ, " DISASTER - A memory allocation has failed. Bailing out...\n" );
00336                 cdExit(EXIT_FAILURE);
00337         }
00338         catch( out_of_range& e )
00339         {
00340                 fprintf( ioQQQ, " DISASTER - An out_of_range exception was caught, what() = %s. Bailing out...\n",
00341                          e.what() );
00342                 cdExit(EXIT_FAILURE);
00343         }
00344         catch( bad_assert& e )
00345         {
00346                 MyAssert( e.file(), e.line() );
00347                 cdExit(EXIT_FAILURE);
00348         }
00349 #ifdef CATCH_SIGNAL
00350         catch( bad_signal& e )
00351         {
00352                 if( ioQQQ != NULL )
00353                 {
00354                         if( e.sig() == SIGINT )
00355                                 fprintf( ioQQQ, " User interrupt request. Bailing out...\n" );
00356                         else if( e.sig() == SIGTERM )
00357                                 fprintf( ioQQQ, " Termination request. Bailing out...\n" );
00358                         else if( e.sig() == SIGILL )
00359                                 fprintf( ioQQQ, " DISASTER - An illegal instruction was found. Bailing out...\n" );
00360                         else if( e.sig() == SIGFPE )
00361                                 fprintf( ioQQQ, " DISASTER - A floating point exception occurred. Bailing out...\n" );
00362                         else if( e.sig() == SIGSEGV )
00363                                 fprintf( ioQQQ, " DISASTER - A segmentation violation occurred. Bailing out...\n" );
00364 #                       ifdef SIGBUS
00365                         else if( e.sig() == SIGBUS )
00366                                 fprintf( ioQQQ, " DISASTER - A bus error occurred. Bailing out...\n" );
00367 #                       endif
00368                         else
00369                                 fprintf( ioQQQ, " DISASTER - A signal %d was caught. Bailing out...\n", e.sig() );
00370 
00371                 }
00372                 cdExit(EXIT_FAILURE);
00373         }
00374 #endif
00375         catch( cloudy_exit& e )
00376         {
00377                 if( ioQQQ != NULL )
00378                 {
00379                         ostringstream oss;
00380                         oss << " [Stop in " << e.routine();
00381                         oss << " at " << e.file() << ":" << e.line();
00382                         if( e.exit_status() == 0 )
00383                                 oss << ", Cloudy exited OK]";
00384                         else
00385                                 oss << ", something went wrong]";
00386                         fprintf( ioQQQ, "%s\n", oss.str().c_str() );
00387                 }
00388                 cdExit(e.exit_status());
00389         }
00390         catch( std::exception& e )
00391         {
00392                 fprintf( ioQQQ, " DISASTER - An unknown exception was caught, what() = %s. Bailing out...\n",
00393                          e.what() );
00394                 cdExit(EXIT_FAILURE);
00395         }
00396         // generic catch-all in case we forget any specific exception above... so this MUST be the last one.
00397         catch( ... )
00398         {
00399                 fprintf( ioQQQ, " DISASTER - An unknown exception was caught. Bailing out...\n" );
00400                 cdExit(EXIT_FAILURE);
00401         }
00402 }

Generated on Mon Feb 16 12:01:18 2009 for cloudy by  doxygen 1.4.7