00001
00002
00003
00004
00005
00006
00007 #include "cddefines.h"
00008 #include "cddrive.h"
00009 #include "physconst.h"
00010 #include "elementnames.h"
00011 #include "input.h"
00012 #include "geometry.h"
00013 #include "prt.h"
00014 #include "optimize.h"
00015 #include "rfield.h"
00016 #include "hcmap.h"
00017 #include "atomfeii.h"
00018 #include "h2.h"
00019 #include "mole.h"
00020 #include "hmi.h"
00021 #include "version.h"
00022 #include "grainvar.h"
00023 #include "parse.h"
00024 #include "grid.h"
00025 #include "save.h"
00026 #include "mpi_utilities.h"
00027 #include "parser.h"
00028
00029
00030 STATIC void ChkUnits(Parser &p);
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 void ParseSave(Parser& p)
00052 {
00053 char chLabel[INPUT_LINE_LENGTH] ,
00054 chFilename[INPUT_LINE_LENGTH] ,
00055 chSecondFilename[INPUT_LINE_LENGTH];
00056 bool lgSecondFilename;
00057
00058 long int i,
00059 nelem;
00060
00061 char chTemp[MAX_HEADER_SIZE];
00062
00063 DEBUG_ENTRY( "ParseSave()" );
00064
00065
00066 if( save.nsave >= LIMPUN )
00067 {
00068 fprintf( ioQQQ,
00069 "The limit to the number of SAVE options is %ld. Increase "
00070 "LIMPUN in save.h if more are needed.\nSorry.\n",
00071 LIMPUN );
00072 cdEXIT(EXIT_FAILURE);
00073 }
00074
00075
00076 save.lgSaveToSeparateFiles[save.nsave] = p.nMatch("SEPA");
00077
00078
00079 save.lgPunLstIter[save.nsave] = p.nMatch("LAST");
00080
00081
00082
00083
00084
00085
00086
00087
00088 if( p.GetQuote( chLabel , true ) )
00089
00090 TotalInsanity();
00091
00092
00093 if( strcmp(chLabel , "opacity.opc") == 0 )
00094 {
00095 fprintf( ioQQQ, "ParseSave will not allow save file name %s, please choose another.\nSorry.\n",
00096 chLabel);
00097 cdEXIT(EXIT_FAILURE);
00098 }
00099 else if( chLabel[0]=='\0' )
00100 {
00101 fprintf( ioQQQ, "ParseSave found a null file name between double quotes, please check command line.\nSorry.\n");
00102 cdEXIT(EXIT_FAILURE);
00103 }
00104
00105
00106 strcpy( chFilename , save.chGridPrefix.c_str() );
00107
00108 strcat( chFilename , save.chFilenamePrefix.c_str() );
00109 strcat( chFilename , chLabel );
00110
00111
00112
00113
00114 if( p.GetQuote( chSecondFilename , false ) )
00115 lgSecondFilename = false;
00116 else
00117 lgSecondFilename = true;
00118
00119
00120
00121 if( p.nMatch("CLOB") )
00122 {
00123 if( p.nMatch(" NO ") )
00124 {
00125
00126 save.lgNoClobber[save.nsave] = true;
00127 }
00128 else
00129 {
00130
00131 save.lgNoClobber[save.nsave] = false;
00132 }
00133 }
00134
00135
00136
00137
00138
00139
00140 if( !p.nMatch("NO TI") && p.nMatch("TITL"))
00141 {
00142 sprintf( save.chHeader[save.nsave],
00143 "# %s %s\n",
00144 t_version::Inst().chVersion, input.chTitle );
00145 }
00146
00147
00148
00149
00150
00151 if( p.nMatch("NO HA") )
00152 save.lgHashEndIter[save.nsave] = false;
00153
00154
00155 if( p.nMatch("OPAC") )
00156 {
00157
00158
00159 ChkUnits(p);
00160
00161 strcpy( save.chSave[save.nsave], "OPAC" );
00162
00163
00164
00165 if( p.nMatch("EVER" ) )
00166 {
00167
00168 save.lgSaveEveryZone[save.nsave] = true;
00169 save.nSaveEveryZone[save.nsave] = 1;
00170 }
00171 else
00172 {
00173
00174 save.lgSaveEveryZone[save.nsave] = false;
00175 save.nSaveEveryZone[save.nsave] = 1;
00176 }
00177
00178 if( p.nMatch("TOTA") )
00179 {
00180
00181
00182 strcpy( save.chOpcTyp[save.nsave], "TOTL" );
00183 sprintf( save.chHeader[save.nsave],
00184 "#nu/%s\tTot opac\tAbs opac\tScat opac\tAlbedo\telem\n",
00185 save.chConPunEnr[save.nsave]);
00186 }
00187
00188 else if( p.nMatch("FIGU") )
00189 {
00190
00191 strcpy( save.chOpcTyp[save.nsave], "FIGU" );
00192 sprintf( save.chHeader[save.nsave],
00193 "#nu/%s\tH\tHe\ttot opac\n",
00194 save.chConPunEnr[save.nsave] );
00195 }
00196
00197 else if( p.nMatch("FINE") )
00198 {
00199
00200 rfield.lgSaveOpacityFine = true;
00201 strcpy( save.chOpcTyp[save.nsave], "FINE" );
00202
00203
00204 ChkUnits(p);
00205
00206 sprintf( save.chHeader[save.nsave],
00207 "#nu/%s\topac\n",
00208 save.chConPunEnr[save.nsave] );
00209
00210
00211
00212 if( p.nMatch("RANGE") )
00213 {
00214
00215 double Energy1 = p.FFmtRead();
00216 double Energy2 = p.FFmtRead();
00217 if( p.lgEOL() )
00218 {
00219 fprintf(ioQQQ,"There must be two numbers, the lower and upper energy range in Ryd.\nSorry.\n");
00220 cdEXIT(EXIT_FAILURE);
00221 }
00222 if( p.nMatch("UNIT" ) )
00223 {
00224
00225 const char *energyUnits = p.StandardEnergyUnit();
00226 Energy unitChange;
00227 unitChange.set(Energy1, energyUnits );
00228 Energy1 = unitChange.Ryd();
00229 unitChange.set(Energy2, energyUnits );
00230 Energy2 = unitChange.Ryd();
00231 }
00232
00233 save.punarg[save.nsave][0] = (realnum)MIN2( Energy1 , Energy2 );
00234 save.punarg[save.nsave][1] = (realnum)MAX2( Energy1 , Energy2 );
00235
00236
00237
00238 }
00239 else
00240 {
00241
00242 save.punarg[save.nsave][0] = 0.;
00243 save.punarg[save.nsave][1] = 0.;
00244 }
00245
00246 save.punarg[save.nsave][2] = (realnum)p.FFmtRead();
00247
00248
00249 if( p.lgEOL() )
00250 save.punarg[save.nsave][2] = 10;
00251
00252 if( save.punarg[save.nsave][2] < 1 )
00253 {
00254 fprintf(ioQQQ,"The number of fine opacities to skip must be > 0 \nSorry.\n");
00255 cdEXIT(EXIT_FAILURE);
00256 }
00257 }
00258
00259 else if( p.nMatch("GRAI") )
00260 {
00261
00262 strcpy( save.chSave[save.nsave], "DUSO" );
00263
00264 sprintf( save.chHeader[save.nsave],
00265 "#grain\tnu\tabs+scat*(1-g)\tabs\tscat*(1-g)\tscat\tscat*(1-g)/[abs+scat*(1-g)]\n" );
00266 }
00267
00268 else if( p.nMatch("BREM") )
00269 {
00270
00271 strcpy( save.chOpcTyp[save.nsave], "BREM" );
00272 sprintf( save.chHeader[save.nsave],
00273 "#nu\tbrem opac\n" );
00274 }
00275
00276 else if( p.nMatch("SHEL") )
00277 {
00278
00279 strcpy( save.chSave[save.nsave], "OPAC" );
00280
00281
00282 strcpy( save.chOpcTyp[save.nsave], "SHEL" );
00283
00284
00285 save.punarg[save.nsave][0] = (realnum)p.FFmtRead();
00286
00287
00288 save.punarg[save.nsave][1] = (realnum)p.FFmtRead();
00289
00290
00291 save.punarg[save.nsave][2] = (realnum)p.FFmtRead();
00292
00293 if( p.lgEOL() )
00294 {
00295 fprintf( ioQQQ, "There must be atom number, ion, shell\nSorry.\n" );
00296 cdEXIT(EXIT_FAILURE);
00297 }
00298 sprintf( save.chHeader[save.nsave],
00299 "#sub shell cross section\n" );
00300 }
00301
00302 else if( p.nMatch("ELEM") )
00303 {
00304
00305
00306
00307
00308
00309
00310
00311 if( (nelem = p.GetElem() ) < 0 )
00312 {
00313 fprintf( ioQQQ, "I did not find an element name on the opacity element command. Sorry.\n" );
00314 cdEXIT(EXIT_FAILURE);
00315 }
00316
00317
00318 strcpy( save.chOpcTyp[save.nsave], elementnames.chElementNameShort[nelem] );
00319 }
00320 else
00321 {
00322 fprintf( ioQQQ, " I did not recognize a keyword on this save opacity command.\n" );
00323 fprintf( ioQQQ, " Sorry.\n" );
00324 cdEXIT(EXIT_FAILURE);
00325 }
00326 }
00327
00328
00329 else if( p.nMatchErase(" H2 ") )
00330 {
00331
00332 h2.H2_ParseSave( p , save.chHeader[save.nsave] );
00333 }
00334
00335
00336 else if( p.nMatchErase(" HD ") )
00337 {
00338
00339 hd.H2_ParseSave( p , save.chHeader[save.nsave] );
00340 }
00341
00342
00343 else if( p.nMatch("ABUN") && !p.nMatch("GRAI") )
00344 {
00345
00346 strcpy( save.chSave[save.nsave], "ABUN" );
00347 sprintf( save.chHeader[save.nsave],
00348 "#abund H" );
00349 for(nelem=ipHELIUM;nelem<LIMELM; ++nelem )
00350 {
00351 sprintf( chTemp, "\t%s",
00352 elementnames.chElementNameShort[nelem] );
00353 strcat( save.chHeader[save.nsave], chTemp );
00354 }
00355 strcat( save.chHeader[save.nsave], "\n");
00356 }
00357
00358 else if( p.nMatch(" AGE") )
00359 {
00360
00361 strcpy( save.chSave[save.nsave], "AGES" );
00362 sprintf( save.chHeader[save.nsave],
00363 "#ages depth\tt(cool)\tt(H2 dest)\tt(CO dest)\tt(OH dest)\tt(H rec)\n" );
00364 }
00365
00366 else if( p.nMatch(" AGN") )
00367 {
00368
00369 strcpy( save.chSave[save.nsave], " AGN" );
00370
00371
00372
00373 if( p.nMatch("CHAR") )
00374 {
00375 strcpy( save.chSave[save.nsave], "CHAG" );
00376 sprintf( save.chHeader[save.nsave],
00377 "#charge exchange rate coefficnt\n" );
00378 }
00379
00380 else if( p.nMatch("RECO") )
00381 {
00382
00383 strcpy( save.chSave[save.nsave], "RECA" );
00384 sprintf( save.chHeader[save.nsave],
00385 "#Recom rates for AGN3 table\n" );
00386 }
00387
00388 else if( p.nMatch("OPAC") )
00389 {
00390
00391 strcpy( save.chOpcTyp[save.nsave], " AGN" );
00392 strcpy( save.chSave[save.nsave], "OPAC" );
00393 }
00394
00395 else if( p.nMatch("HECS") )
00396 {
00397
00398 strcpy( save.chSaveArgs[save.nsave], "HECS" );
00399 sprintf( save.chHeader[save.nsave],
00400 "#AGN3 he cs \n" );
00401 }
00402
00403 else if( p.nMatch("HEMI") )
00404 {
00405
00406 strcpy( save.chSaveArgs[save.nsave], "HEMI" );
00407
00408
00409
00410 ChkUnits(p);
00411 }
00412 else if( p.nMatch("RECC") )
00413 {
00414
00415 strcpy( save.chSave[save.nsave], "HYDr" );
00416 sprintf( save.chHeader[save.nsave],
00417 "#T\tbAS\tb1\tbB\n" );
00418 }
00419 else
00420 {
00421 fprintf( ioQQQ, " I did not recognize this option on the SAVE HYDROGEN command.\n" );
00422 fprintf( ioQQQ, " Sorry.\n" );
00423 cdEXIT(EXIT_FAILURE);
00424 }
00425 }
00426
00427 else if( p.nMatch("AVER") )
00428 {
00429
00430 strcpy( save.chSave[save.nsave], "AVER" );
00431
00432
00433
00434
00435
00436
00437 parse_save_average( p, save.nsave, save.chHeader[save.nsave] );
00438 }
00439
00440
00441 else if( p.nMatch("CHAR") && p.nMatch("TRAN") )
00442 {
00443
00444
00445
00446 strcpy( save.chSave[save.nsave], "CHAR" );
00447 sprintf( save.chHeader[save.nsave],
00448 "#charge exchange rate coefficient\n" );
00449 }
00450
00451
00452 else if( p.nMatch("CHIA"))
00453 {
00454 strcpy( save.chSave[save.nsave], "CHIA" );
00455
00456 }
00457
00458 else if( p.nMatch("CHEM") )
00459 {
00460
00461 if( p.nMatch( "RATE" ) )
00462 {
00463
00464 if( lgSecondFilename )
00465 {
00466 if( p.nMatch( "DEST" ) )
00467 strcpy( save.chSaveArgs[save.nsave], "DEST" );
00468 else if( p.nMatch( "CREA" ) )
00469 strcpy( save.chSaveArgs[save.nsave], "CREA" );
00470 else if( p.nMatch( "CATA" ) )
00471 strcpy( save.chSaveArgs[save.nsave], "CATA" );
00472 else if( p.nMatch( "ALL" ) )
00473 strcpy( save.chSaveArgs[save.nsave], "ALL " );
00474 else
00475 strcpy( save.chSaveArgs[save.nsave], "DFLT" );
00476
00477 strcpy( save.chSave[save.nsave], "CHRT" );
00478 save.optname[save.nsave] = chSecondFilename;
00479
00480
00481 }
00482
00483 else
00484 {
00485 fprintf(ioQQQ," A species label must appear within a second set of quotes (following the output filename).\n" );
00486 fprintf( ioQQQ, " Sorry.\n" );
00487 cdEXIT(EXIT_FAILURE);
00488 }
00489
00490 }
00491 }
00492
00493 else if( p.nMatch("COMP") )
00494 {
00495
00496 strcpy( save.chSave[save.nsave], "COMP" );
00497 sprintf( save.chHeader[save.nsave],
00498 "#nu, comup, comdn\n" );
00499 }
00500
00501 else if( p.nMatch("COOL") )
00502 {
00503
00504 if( p.nMatch("EACH") )
00505 {
00506 strcpy( save.chSave[save.nsave], "EACH");
00507 sprintf( save.chHeader[save.nsave],
00508 "#depth(cm)\tTemp(K)\tCtot(erg/cm3/s)\t" );
00509 for( int i = 0 ; i < LIMELM ; i++ )
00510 {
00511 strcat(save.chHeader[save.nsave], elementnames.chElementSym[i] );
00512 strcat(save.chHeader[save.nsave], "\t" );
00513 }
00514 strcat(save.chHeader[save.nsave], "molecule\tdust\tH2cX\tCT C\tH-fb\tH2ln\tHDro\tH2+ \tFFcm\thvFB\teeff\tComp\tExtr\tExpn\tCycl\tHvin\tdima\n" );
00515 }
00516 else
00517 {
00518 strcpy( save.chSave[save.nsave], "COOL");
00519
00520 sprintf( save.chHeader[save.nsave],
00521 "#depth cm\tTemp K\tHtot erg/cm3/s\tCtot erg/cm3/s\tcool fracs\n" );
00522 }
00523 }
00524
00525
00526 else if( p.nMatch("DOMI") && p.nMatch("RATE"))
00527 {
00528 if( !lgSecondFilename )
00529 {
00530 fprintf( ioQQQ,"This command requires two items in quotes (a filename and a species label). Only one set of quotes was found.\nSorry.\n");
00531 cdEXIT(EXIT_FAILURE);
00532 }
00533
00534 strncpy( save.chSpeciesDominantRates[save.nsave], chSecondFilename, CHARS_SPECIES );
00535
00536
00537 strcpy( save.chSave[save.nsave], "DOMI" );
00538 sprintf( save.chHeader[save.nsave],
00539 "#depth cm\t%s col cm-2\tsrc s-1\tsnk s-1\n",
00540 save.chSpeciesDominantRates[save.nsave] );
00541 }
00542
00543 else if( p.nMatch("DYNA") )
00544 {
00545
00546
00547
00548
00549 if( p.nMatch( "ADVE" ) )
00550 {
00551
00552 strcpy( save.chSave[save.nsave], "DYNa");
00553 sprintf( save.chHeader[save.nsave],
00554 "#advection depth\tHtot\tadCool\tadHeat\tdCoolHeatdT\t"
00555 "Source[hyd][hyd]\tRate\tEnthalph\tadSpecEnthal\n" );
00556 }
00557 else
00558 {
00559 fprintf( ioQQQ, " I did not recognize a sub keyword on this SAVE DYNAMICS command.\n" );
00560 fprintf( ioQQQ, " Sorry.\n" );
00561 cdEXIT(EXIT_FAILURE);
00562 }
00563 }
00564
00565 else if( p.nMatch("ENTH") )
00566 {
00567
00568 strcpy( save.chSave[save.nsave], "ENTH" );
00569 sprintf( save.chHeader[save.nsave],
00570 "#depth\tTotal\tExcit\tIoniz\tBind\tKE\tther+PdV\tmag \n" );
00571 }
00572
00573 else if( p.nMatch("EXEC") && p.nMatch("TIME") )
00574 {
00575
00576 strcpy( save.chSave[save.nsave], "XTIM" );
00577 sprintf( save.chHeader[save.nsave],
00578 "#zone\tdTime\tElapsed t\n" );
00579 }
00580
00581 else if( p.nMatch("FEII") || p.nMatch("FE II") )
00582 {
00583
00584
00585 if( p.nMatch("COLU") && p.nMatch("DENS") )
00586 {
00587
00588 strcpy( save.chSave[save.nsave], "FENl" );
00589
00590
00591 sprintf( save.chHeader[save.nsave],
00592 "#FeII: energy\tstat wght\tcol den\n" );
00593 }
00594
00595
00596 else if( p.nMatch("CONT") )
00597 {
00598
00599
00600 if( p.nMatch("INWA") )
00601 {
00602
00603 strcpy( save.chSave[save.nsave], "FEcI" );
00604
00605
00606 }
00607 else if( p.nMatch(" OUT") )
00608 {
00609
00610 strcpy( save.chSave[save.nsave], "FEcO" );
00611
00612
00613 }
00614 else
00615 {
00616
00617 strcpy( save.chSave[save.nsave], "FEcT" );
00618
00619
00620 }
00621
00622
00623
00624 ChkUnits(p);
00625
00626
00627
00628 if( p.nMatch(" ROW") )
00629 save.punarg[save.nsave][0] = 1;
00630 else
00631
00632 save.punarg[save.nsave][0] = 2;
00633 }
00634
00635 else if( p.nMatch("DEPA") )
00636 {
00637
00638 sprintf( save.chHeader[save.nsave],
00639 "#FeII departure coefficient \n" );
00640
00641 if( p.nMatch(" ALL") )
00642 {
00643
00644 strcpy( save.chSave[save.nsave], "FE2D" );
00645 }
00646 else
00647 {
00648
00649 strcpy( save.chSave[save.nsave], "FE2d" );
00650 }
00651 }
00652
00653 else if( p.nMatch("LEVE") )
00654 {
00655
00656 sprintf( save.chHeader[save.nsave],
00657 "#FeII energy(wn)\tstat weight\n" );
00658 strcpy( save.chSave[save.nsave], "FE2l" );
00659 }
00660
00661 else if( p.nMatch("LINE") )
00662 {
00663
00664
00665
00666
00667
00668 strcpy( save.chSave[save.nsave], "FEli" );
00669
00670
00671 if( p.nMatch("SHOR") )
00672 {
00673 FeII.lgShortFe2 = true;
00674 }
00675 else
00676 {
00677 FeII.lgShortFe2 = false;
00678 }
00679
00680
00681
00682
00683 FeII.fe2thresh = (realnum)p.FFmtRead();
00684 if( p.lgEOL() )
00685 {
00686 FeII.fe2thresh = 0.;
00687 }
00688
00689
00690 if( FeII.fe2thresh < 0. )
00691 {
00692 FeII.fe2thresh = (realnum)pow((realnum)10.f,FeII.fe2thresh);
00693 }
00694
00695
00696
00697 FeII.fe2ener[0] = (realnum)p.FFmtRead();
00698 if( p.lgEOL() )
00699 {
00700 FeII.fe2ener[0] = 0.;
00701 }
00702
00703 FeII.fe2ener[1] = (realnum)p.FFmtRead();
00704 if( p.lgEOL() )
00705 {
00706 FeII.fe2ener[1] = 1e8;
00707 }
00708
00709 if( FeII.fe2ener[0] < 0. || FeII.fe2ener[1] < 0. )
00710 {
00711 FeII.fe2ener[0] = (realnum)pow((realnum)10.f,FeII.fe2ener[0]);
00712 FeII.fe2ener[1] = (realnum)pow((realnum)10.f,FeII.fe2ener[1]);
00713 }
00714
00715
00716 FeII.fe2ener[0] /= (realnum)WAVNRYD;
00717 FeII.fe2ener[1] /= (realnum)WAVNRYD;
00718
00719
00720
00721 sprintf( save.chHeader[save.nsave],
00722 "#FeII ipHi\tipLo\tWL(A)\tlog I\tI/Inorm\t\tTau\n" );
00723 }
00724
00725 else if( p.nMatch("OPTI") && p.nMatch("DEPT") )
00726 {
00727
00728 sprintf( save.chHeader[save.nsave],
00729 "#FeII hi\tlow\twl(A)\ttau\n" );
00730 strcpy( save.chSave[save.nsave], "FE2o" );
00731 }
00732
00733 else if( p.nMatch("POPU") )
00734 {
00735
00736 sprintf( save.chHeader[save.nsave],
00737 "#FeII level populations [cm^-3]\n" );
00738
00739
00740
00741 if( p.nMatch("RELA") )
00742 {
00743 save.punarg[save.nsave][2] = 0.;
00744 }
00745 else
00746 {
00747
00748 save.punarg[save.nsave][2] = 1.;
00749 }
00750
00751
00752 if( p.nMatch(" ALL") )
00753 {
00754
00755 strcpy( save.chSave[save.nsave], "FE2P" );
00756 save.punarg[save.nsave][0] = 0.;
00757 save.punarg[save.nsave][1] = (realnum)NFE2LEVN;
00758 }
00759
00760
00761 else if( p.nMatch("RANG") )
00762 {
00763
00764 strcpy( save.chSave[save.nsave], "FE2P" );
00765 save.punarg[save.nsave][0] = (realnum)p.FFmtRead();
00766 save.punarg[save.nsave][1] = (realnum)p.FFmtRead();
00767 if( p.lgEOL() || save.punarg[save.nsave][0] <0 ||
00768 save.punarg[save.nsave][0]>= save.punarg[save.nsave][1] )
00769 {
00770 fprintf( ioQQQ, "There must be two numbers on this save "
00771 "FeII populations range command.\n" );
00772 fprintf( ioQQQ, "These give the lower and upper levels "
00773 "for the range of FeII levels.\n" );
00774 fprintf( ioQQQ, "The first, %g, must be less than the second, %g.\n",
00775 save.punarg[save.nsave][0],
00776 save.punarg[save.nsave][1]);
00777 fprintf( ioQQQ, "Sorry.\n" );
00778 cdEXIT(EXIT_FAILURE);
00779 }
00780 }
00781
00782 else
00783 {
00784
00785 strcpy( save.chSave[save.nsave], "FE2p" );
00786 }
00787 }
00788 else
00789 {
00790 fprintf( ioQQQ, "There must be a second keyword on this SAVE FEII command.\n" );
00791 fprintf( ioQQQ, "The ones I know about are COLUmn, CONTinuum, "
00792 "DEPArture, LEVEls, LINE, OPTIcal DEPTh, and POPUlations.\n" );
00793 fprintf( ioQQQ, "Sorry.\n" );
00794 cdEXIT(EXIT_FAILURE);
00795 }
00796 }
00797
00798
00799
00800
00801 else if( p.nMatch("CONT") && !p.nMatch("XSPE") )
00802 {
00803
00804
00805 save.lgPunContinuum = true;
00806
00807
00808
00809 ChkUnits(p);
00810
00811 if( p.nMatch("BINS") )
00812 {
00813
00814 strcpy( save.chSave[save.nsave], "CONB" );
00815
00816 sprintf( save.chHeader[save.nsave],
00817 "#Continuum binning enrOrg/%s\tEnergy\twidth of cells\n",
00818 save.chConPunEnr[save.nsave] );
00819 }
00820
00821 else if( p.nMatch("DIFF") )
00822 {
00823
00824 strcpy( save.chSave[save.nsave], "COND" );
00825
00826
00827
00828
00829 if( p.nMatch("ZONE") )
00830 {
00831 sprintf( save.chHeader[save.nsave],
00832 "#energy/%s then emission per zone\n",
00833 save.chConPunEnr[save.nsave] );
00834 save.punarg[save.nsave][0] = 2.;
00835
00836 }
00837 else
00838 {
00839 sprintf( save.chHeader[save.nsave],
00840 "#energy/%s\tConEmitLocal\tDiffuseLineEmission\tTotal\n",
00841 save.chConPunEnr[save.nsave] );
00842 save.punarg[save.nsave][0] = 1.;
00843 }
00844 }
00845
00846 else if( p.nMatch("EMIS") )
00847 {
00848
00849 strcpy( save.chSave[save.nsave], "CONS" );
00850
00851 double num = p.FFmtRead();
00852 if( p.lgEOL() )
00853 p.NoNumb( "continuum emissivity frequency" );
00854 save.emisfreq.set( num, save.chConPunEnr[save.nsave] );
00855 if( save.emisfreq.Ryd() < rfield.emm || save.emisfreq.Ryd() > rfield.egamry )
00856 {
00857 fprintf( ioQQQ, " The frequency is outside the Cloudy range\n Sorry.\n" );
00858 cdEXIT(EXIT_FAILURE);
00859 }
00860
00861 sprintf( save.chHeader[save.nsave],
00862 "#Radius\tdepth\tnujnu\tkappa_abs\tkappa_sct\n" );
00863 }
00864
00865 else if( p.nMatch("EMIT") )
00866 {
00867
00868 strcpy( save.chSave[save.nsave], "CONE" );
00869
00870 sprintf( save.chHeader[save.nsave],
00871 "#Energy/%s\treflec\toutward\ttotal\tline\tcont\n",
00872 save.chConPunEnr[save.nsave] );
00873 }
00874
00875 else if( p.nMatch("FINE" ) )
00876 {
00877 rfield.lgSaveOpacityFine = true;
00878
00879 strcpy( save.chSave[save.nsave], "CONf" );
00880
00881 sprintf( save.chHeader[save.nsave],
00882 "#Energy/%s\tTransmitted\n",
00883 save.chConPunEnr[save.nsave] );
00884
00885
00886 if( p.nMatch("RANGE") )
00887 {
00888
00889 double Energy1 = p.FFmtRead();
00890 double Energy2 = p.FFmtRead();
00891 if( p.lgEOL() )
00892 {
00893 fprintf(ioQQQ,"There must be two numbers, the lower and upper energies in Ryd.\nSorry.\n");
00894 cdEXIT(EXIT_FAILURE);
00895 }
00896 if( p.nMatch("UNIT" ) )
00897 {
00898
00899 const char *energyUnits = p.StandardEnergyUnit();
00900 Energy unitChange;
00901 unitChange.set(Energy1, energyUnits );
00902 Energy1 = unitChange.Ryd();
00903 unitChange.set(Energy2, energyUnits );
00904 Energy2 = unitChange.Ryd();
00905 }
00906
00907 save.punarg[save.nsave][0] = (realnum)MIN2( Energy1 , Energy2 );
00908 save.punarg[save.nsave][1] = (realnum)MAX2( Energy1 , Energy2 );
00909
00910
00911
00912 }
00913 else
00914 {
00915
00916 save.punarg[save.nsave][0] = 0.;
00917 save.punarg[save.nsave][1] = 0.;
00918 }
00919
00920 save.punarg[save.nsave][2] = (realnum)p.FFmtRead();
00921
00922
00923 if( p.lgEOL() )
00924 save.punarg[save.nsave][2] = 10;
00925
00926 if( save.punarg[save.nsave][2] < 1 )
00927 {
00928 fprintf(ioQQQ,"The number of fine opacities to skip must be > 0 \nSorry.\n");
00929 cdEXIT(EXIT_FAILURE);
00930 }
00931 }
00932
00933 else if( p.nMatch("GRAI") )
00934 {
00935
00936 strcpy( save.chSave[save.nsave], "CONG" );
00937
00938 sprintf( save.chHeader[save.nsave],
00939 "#energy\tgraphite\trest\ttotal\n" );
00940 }
00941
00942 else if( p.nMatch("INCI") )
00943 {
00944
00945 strcpy( save.chSave[save.nsave], "CONC" );
00946
00947 sprintf( save.chHeader[save.nsave],
00948 "#Incident Continuum, Enr\tnFn \n" );
00949 }
00950
00951 else if( p.nMatch("INTE") )
00952 {
00953
00954 strcpy( save.chSave[save.nsave], "CONi" );
00955
00956 sprintf( save.chHeader[save.nsave],
00957 "#Continuum interactions, inc, otslin. otscon, ConInterOut, outlin \n" );
00958
00959 save.punarg[save.nsave][0] = (realnum)p.FFmtRead();
00960 }
00961
00962 else if( p.nMatch("IONI") )
00963 {
00964
00965 strcpy( save.chSave[save.nsave], "CONI" );
00966
00967
00968 save.punarg[save.nsave][0] = (realnum)p.FFmtRead();
00969
00970
00971 save.punarg[save.nsave][1] = (realnum)p.FFmtRead();
00972 if( p.lgEOL() )
00973 save.punarg[save.nsave][1] = 0.01f;
00974
00975
00976
00977 if( p.nMatch("EVER" ) )
00978 {
00979
00980 save.lgSaveEveryZone[save.nsave] = true;
00981 save.nSaveEveryZone[save.nsave] = 1;
00982 }
00983 else
00984 {
00985
00986 save.lgSaveEveryZone[save.nsave] = false;
00987 save.nSaveEveryZone[save.nsave] = 1;
00988 }
00989
00990
00991 sprintf( save.chHeader[save.nsave],
00992 "#cell(on C scale)\tnu\tflux\tflx*cs\tFinc\totsl\totsc\toutlin\toutcon\trate/tot\tintegral\tline\tcont\n" );
00993 }
00994 #ifdef USE_NLTE7
00995 else if( p.nMatch("NLTE") )
00996 {
00997
00998 strcpy( save.chSave[save.nsave], "CONl" );
00999
01000 sprintf( save.chHeader[save.nsave],
01001 " spectrum1 NeXY6 XNUMX\n");
01002 }
01003 #endif
01004
01005 else if( p.nMatch("OUTW") )
01006 {
01007
01008 if( p.nMatch("LOCA") )
01009 {
01010 strcpy( save.chSave[save.nsave], "CONo" );
01011 sprintf( save.chHeader[save.nsave],
01012 "#Local Out ConInterOut+line SvOt*opc pass*opc\n" );
01013 }
01014 else
01015 {
01016 strcpy( save.chSave[save.nsave], "CONO" );
01017 sprintf( save.chHeader[save.nsave],
01018 "#Out Con OutIncid OutConD OutLinD OutConS\n" );
01019 }
01020 }
01021
01022 else if( p.nMatch("TRAN") )
01023 {
01024
01025 strcpy( save.chSave[save.nsave], "CONT" );
01026
01027 sprintf( save.chHeader[save.nsave],
01028 "#ener\tTran Contin\ttrn coef\n" );
01029 }
01030
01031 else if( p.nMatch(" TWO") )
01032 {
01033
01034 strcpy( save.chSave[save.nsave], "CON2" );
01035
01036 sprintf( save.chHeader[save.nsave],
01037 "#energy\t n_nu\tnuF_nu \n" );
01038 }
01039
01040 else if( p.nMatch(" RAW") )
01041 {
01042
01043 strcpy( save.chSave[save.nsave], "CORA" );
01044
01045 sprintf( save.chHeader[save.nsave],
01046 "#Raw Con anu\tflux\totslin\totscon\tConRefIncid\tConEmitReflec\tConInterOut\toutlin\tConEmitOut\tline\tcont\tnLines\n" );
01047 }
01048
01049 else if( p.nMatch("REFL") )
01050 {
01051
01052 strcpy( save.chSave[save.nsave], "CONR" );
01053
01054 sprintf( save.chHeader[save.nsave],
01055 "#Reflected\tcont\tline\ttotal\talbedo\tConID\n" );
01056 }
01057
01058 else
01059 {
01060
01061
01062
01063 int ipType = 0;
01064 if( p.nMatch( "CUMU" ) )
01065 ipType = 1;
01066 save.punarg[save.nsave][0] = (realnum)ipType;
01067 strcpy( save.chSave[save.nsave], "CON " );
01068 char chHold[100];
01069 strcpy( chHold, "#Cont " );
01070 if( ipType > 0 )
01071 strcpy( chHold , "#Cumul " );
01072 sprintf( save.chHeader[save.nsave],
01073 "%s nu\tincident\ttrans\tDiffOut\tnet trans\treflc\ttotal\treflin\toutlin\tlineID\tcont\tnLine\n" ,
01074 chHold );
01075
01076
01077
01078 if( p.nMatch("EVER" ) )
01079 {
01080
01081 save.lgSaveEveryZone[save.nsave] = true;
01082
01083 save.nSaveEveryZone[save.nsave] = (long)p.FFmtRead();
01084 if( p.lgEOL() )
01085 save.nSaveEveryZone[save.nsave] = 1;
01086 }
01087 else
01088 {
01089
01090 save.lgSaveEveryZone[save.nsave] = false;
01091 save.nSaveEveryZone[save.nsave] = 1;
01092 }
01093 }
01094 }
01095
01096
01097
01098
01099 else if( p.nMatch("CONV") )
01100 {
01101 if( p.nMatch("REAS") )
01102 {
01103
01104 save.lgPunConv = true;
01105
01106 strcpy( save.chSave[save.nsave], "" );
01107 save.lgRealSave[save.nsave] = false;
01108 }
01109 else if( p.nMatch("ERRO") )
01110 {
01111
01112
01113 strcpy( save.chSave[save.nsave], "CNVE" );
01114 sprintf( save.chHeader[save.nsave],
01115 "#depth\tnPres2Ioniz\tP(cur)\tP%%error\tNE(cor)\tNE(cur)\tNE%%error\tHeat\tCool\tHC%%error\n" );
01116 }
01117 else if( p.nMatch("BASE") )
01118 {
01119
01120
01121 strcpy( save.chSave[save.nsave], "CNVB" );
01122 strcpy( save.chSave[save.nsave], "" );
01123 save.lgRealSave[save.nsave] = false;
01124 }
01125 else
01126 {
01127 fprintf( ioQQQ, "There must be a second keyword on this command.\n" );
01128 fprintf( ioQQQ, "The ones I know about are REASON, ERROR, and BASE.\n" );
01129 fprintf( ioQQQ, "Sorry.\n" );
01130 cdEXIT(EXIT_FAILURE);
01131 }
01132 }
01133
01134 else if( p.nMatch(" DR ") )
01135 {
01136
01137 save.lgDROn = true;
01138 strcpy( save.chSave[save.nsave], "" );
01139 save.lgRealSave[save.nsave] = false;
01140 }
01141
01142 else if( p.nMatch("ELEM") && !p.nMatch("GAMMA") && !p.nMatch("COOL") )
01143 {
01144
01145
01146 strcpy( save.chSave[save.nsave], "ELEM" );
01147
01148
01149
01150 nelem = p.GetElem();
01151 if( nelem < 0 || nelem >= LIMELM )
01152 {
01153 fprintf( ioQQQ, " I could not recognize a valid element name on this line.\n" );
01154 fprintf( ioQQQ, " Please check your input script. Bailing out...\n" );
01155 cdEXIT(EXIT_FAILURE);
01156 }
01157
01158
01159 save.punarg[save.nsave][0] = (realnum)nelem;
01160
01161
01162 save.punarg[save.nsave][1] = 0;
01163 if( p.nMatch("DENS") )
01164 save.punarg[save.nsave][1] = 1.;
01165
01166
01167 sprintf( save.chHeader[save.nsave], "#depth");
01168
01169
01170 for(i=0; i<=nelem+1;++i )
01171 {
01172 sprintf( chTemp,
01173 "\t%2s%2li", elementnames.chElementSym[nelem],i+1);
01174 strcat( save.chHeader[save.nsave], chTemp );
01175 }
01176
01177
01178
01179
01180 if( nelem==ipHYDROGEN )
01181 {
01182 sprintf( chTemp, "\tH2");
01183 strcat( save.chHeader[save.nsave], chTemp );
01184 }
01185 if( nelem==ipCARBON )
01186 {
01187 sprintf( chTemp, "\tC1\tC1*\tC1**\tC2\tC2*\tCO");
01188 strcat( save.chHeader[save.nsave], chTemp );
01189 }
01190 else if( nelem==ipOXYGEN )
01191 {
01192 sprintf( chTemp, "\tO1\tO1*\tO1**");
01193 strcat( save.chHeader[save.nsave], chTemp );
01194 }
01195
01196
01197 strcat( save.chHeader[save.nsave], "\n");
01198 }
01199
01200 else if( p.nMatch("FITS") )
01201 {
01202
01203 #ifdef FLT_IS_DBL
01204 fprintf( ioQQQ, "Saving FITS files is not currently supported in double precision.\n" );
01205 fprintf( ioQQQ, "Please recompile without the FLT_IS_DBL option.\n" );
01206 fprintf( ioQQQ, "Sorry.\n" );
01207 cdEXIT(EXIT_FAILURE);
01208 #else
01209
01210 save.lgFITS[save.nsave] = true;
01211
01212 save.lgSaveToSeparateFiles[save.nsave] = true;
01213 save.lgPunLstIter[save.nsave] = true;
01214 save.FITStype[save.nsave] = NUM_OUTPUT_TYPES;
01215
01216 strcpy( save.chSave[save.nsave], "FITS" );
01217 #endif
01218
01219 }
01220
01221 else if( p.nMatch("FRED") )
01222 {
01223
01224 sprintf( save.chHeader[save.nsave],
01225 "#Radius\tDepth\tVelocity(km/s)\tdvdr(cm/s)\thden\teden\tTemperature\tRadAccel line\tRadAccel con\t"
01226 "Force multiplier\ta(e thin)\t"
01227 "HI\tHII\tHeI\tHeII\tHeIII\tC2\tC3\tC4\tO1\t"
01228 "O2\tO3\tO4\tO5\tO6\tO7\tO8\t"
01229 "HI\tHII\tHeI\tHeII\tHeIII\tC2\tC3\tC4\tO1\t"
01230 "O2\tO3\tO4\tO5\tO6\tO7\tO8\tMg2\tMg2\tOVI(1034) TauIn\tTauCon\n");
01231
01232 strcpy( save.chSave[save.nsave], "FRED" );
01233 }
01234
01235 else if( p.nMatch("GAMM") )
01236 {
01237
01238 sprintf( save.chHeader[save.nsave],
01239 "#Photoionization rates \n" );
01240 if( p.nMatch("ELEMENT") )
01241 {
01242
01243
01244 strcpy( save.chSave[save.nsave], "GAMe" );
01245
01246
01247 nelem = p.GetElem();
01248
01249 save.punarg[save.nsave][0] = (realnum)nelem;
01250
01251
01252 save.punarg[save.nsave][1] = (realnum)p.FFmtRead() - 1;
01253 if( p.lgEOL() )
01254 p.NoNumb("element ionization stage" );
01255 if( save.punarg[save.nsave][1]<0 || save.punarg[save.nsave][1]> nelem+1 )
01256 {
01257 fprintf(ioQQQ,"Bad ionization stage - please check Hazy.\nSorry.\n");
01258 cdEXIT(EXIT_FAILURE);
01259 }
01260 }
01261 else
01262 {
01263
01264 strcpy( save.chSave[save.nsave], "GAMt" );
01265 }
01266
01267 }
01268 else if( p.nMatch("GRAI") )
01269 {
01270
01271 if( p.nMatch("OPAC") )
01272 {
01273
01274
01275 ChkUnits(p);
01276
01277 strcpy( save.chSave[save.nsave], "DUSO" );
01278
01279 sprintf( save.chHeader[save.nsave],
01280 "#grain\tnu/%s\tabs+scat*(1-g)\tabs\tscat*(1-g)\tscat\tscat*(1-g)/[abs+scat*(1-g)]\n",
01281 save.chConPunEnr[save.nsave] );
01282 }
01283 else if( p.nMatch("ABUN") )
01284 {
01285
01286 strcpy( save.chSave[save.nsave], "DUSA" );
01287 sprintf( save.chHeader[save.nsave],
01288 "#grain\tdepth\tabundance (g/cm^3)\n" );
01289 }
01290 else if( p.nMatch("D/G ") )
01291 {
01292
01293 strcpy( save.chSave[save.nsave], "DUSD" );
01294 sprintf( save.chHeader[save.nsave],
01295 "#grain\tdepth\tdust/gas mass ratio\n" );
01296 }
01297 else if( p.nMatch("PHYS") )
01298 {
01299
01300 strcpy( save.chSave[save.nsave], "DUSP" );
01301 sprintf( save.chHeader[save.nsave],
01302 "#grain\tdepth\tpotential\n" );
01303 }
01304 else if( p.nMatch(" QS ") )
01305 {
01306 strcpy( save.chSave[save.nsave], "DUSQ" );
01307 sprintf( save.chHeader[save.nsave],
01308 "#grain\tnu\tQ_abs\tQ_scat\n" );
01309 }
01310 else if( p.nMatch("TEMP") )
01311 {
01312
01313 strcpy( save.chSave[save.nsave], "DUST" );
01314
01315 sprintf( save.chHeader[save.nsave],
01316 "#grain temperature\n" );
01317 }
01318 else if( p.nMatch("DRIF") )
01319 {
01320
01321 strcpy( save.chSave[save.nsave], "DUSV" );
01322
01323 sprintf( save.chHeader[save.nsave],
01324 "#grain drift velocity\n" );
01325 }
01326 else if( p.nMatch("EXTI") )
01327 {
01328
01329 strcpy( save.chSave[save.nsave], "DUSE" );
01330
01331 sprintf( save.chHeader[save.nsave],
01332 "#depth\tA_V(extended)\tA_V(point)\n" );
01333 }
01334 else if( p.nMatch("CHAR") )
01335 {
01336
01337 strcpy( save.chSave[save.nsave], "DUSC" );
01338
01339 sprintf( save.chHeader[save.nsave],
01340 "#grain charge\n" );
01341 }
01342 else if( p.nMatch("HEAT") )
01343 {
01344
01345 strcpy( save.chSave[save.nsave], "DUSH" );
01346
01347 sprintf( save.chHeader[save.nsave],
01348 "#grain heating\n" );
01349 }
01350 else if( p.nMatch("POTE") )
01351 {
01352
01353 strcpy( save.chSave[save.nsave], "DUSP" );
01354
01355 sprintf( save.chHeader[save.nsave],
01356 "#grain\tdepth\tpotential\n" );
01357 }
01358 else if( p.nMatch("H2RA") )
01359 {
01360
01361 strcpy( save.chSave[save.nsave], "DUSR" );
01362
01363 sprintf( save.chHeader[save.nsave],
01364 "#grain H2 formation rates\n" );
01365 }
01366 else
01367 {
01368 fprintf( ioQQQ, "There must be a second key on this GRAIN command; The options I know about follow (required key in CAPS):\n");
01369 fprintf( ioQQQ, "OPACity, ABUNdance, D/G mass ratio, PHYSical conditions, QS , TEMPerature, DRIFt velocity, EXTInction, CHARge, HEATing, POTEntial, H2RAtes\nSorry.\n" );
01370 cdEXIT(EXIT_FAILURE);
01371 }
01372 }
01373
01374 else if( p.nMatch("GAUN") )
01375 {
01376 strcpy( save.chSave[save.nsave], "GAUN" );
01377 sprintf( save.chHeader[save.nsave],
01378 "#Gaunt factors.\n" );
01379 }
01380 else if( p.nMatch("GRID") )
01381 {
01382 strcpy( save.chSave[save.nsave], "GRID" );
01383
01384 save.lgHashEndIter[save.nsave] = false;
01385 }
01386 else if( p.nMatch( "HIST" ) )
01387 {
01388
01389 if( p.nMatch( "PRES") )
01390 {
01391
01392 strcpy( save.chSave[save.nsave], "HISp" );
01393 sprintf( save.chHeader[save.nsave],
01394 "#iter zon\tdensity\tpres cur\tpres error\n" );
01395 }
01396
01397 else if( p.nMatch( "TEMP" ) )
01398 {
01399
01400 strcpy( save.chSave[save.nsave], "HISt" );
01401 sprintf( save.chHeader[save.nsave],
01402 "#iter zon\ttemperature\theating\tcooling\n" );
01403 }
01404 }
01405
01406 else if( p.nMatch("HTWO") )
01407 {
01408 fprintf(ioQQQ," Sorry, this command has been replaced with the "
01409 "SAVE H2 CREATION and SAVE H2 DESTRUCTION commands.\n");
01410 cdEXIT(EXIT_FAILURE);
01411 }
01412
01413
01414 else if( p.nMatch("QHEA") )
01415 {
01416
01417
01418 ((void)0);
01419 }
01420
01421 else if( p.nMatch("HEAT") )
01422 {
01423
01424 strcpy( save.chSave[save.nsave], "HEAT" );
01425
01426 sprintf( save.chHeader[save.nsave],
01427 "#depth cm\tTemp K\tHtot erg/cm3/s\tCtot erg/cm3/s\theat fracs\n" );
01428 }
01429
01430 else if( p.nMatch("HELI") &&!( p.nMatch("IONI")))
01431 {
01432
01433
01434 if( p.nMatch("LINE") && p.nMatch("WAVE") )
01435 {
01436 strcpy( save.chSave[save.nsave], "HELW" );
01437 sprintf( save.chHeader[save.nsave],
01438 "#wavelengths of lines from He-like ions\n" );
01439 }
01440 else
01441 {
01442 fprintf( ioQQQ, "save helium has options: LINE WAVElength.\nSorry.\n" );
01443 cdEXIT(EXIT_FAILURE);
01444
01445 }
01446 }
01447
01448 else if( p.nMatch("HUMM") )
01449 {
01450 strcpy( save.chSave[save.nsave], "HUMM" );
01451 sprintf( save.chHeader[save.nsave],
01452 "#input to DHs routine.\n" );
01453 }
01454
01455 else if( p.nMatch("HYDR") )
01456 {
01457
01458 if( p.nMatch("COND") )
01459 {
01460 strcpy( save.chSave[save.nsave], "HYDc" );
01461 sprintf( save.chHeader[save.nsave],
01462 "#depth\tTe\tHDEN\tEDEN\tHI/H\tHII/H\tH2/H\tH2+/H\tH3+/H\tH-/H\n" );
01463
01464 }
01465
01466
01467 else if( p.nMatch("21 CM") ||p.nMatch("21CM"))
01468 {
01469
01470 strcpy( save.chSave[save.nsave], "21CM" );
01471 sprintf( save.chHeader[save.nsave],
01472 "#depth\tT(spin)\tT(kin)\tT(Lya/21cm)\tnLo\tnHi\tOccLya\ttau(21cm)"
01473 "\ttau(Lya)\topac(21 cm)\tn/Ts\ttau(21)\tTex(Lya)\tN(H0)/Tspin"
01474 "\tSum_F0\tSum_F1\tSum_T21\n" );
01475 }
01476
01477 else if( p.nMatch("IONI") )
01478 {
01479
01480 strcpy( save.chSave[save.nsave], "HYDi" );
01481 sprintf( save.chHeader[save.nsave],
01482 "#hion\tzn\tgam1\tcoll ion1\tRecTot\tHRecCaB\thii/hi\tSim hii/hi"
01483 "\time_Hrecom_long(esc)\tdec2grd\texc pht\texc col\trec eff\tsec ion\n" );
01484 }
01485 else if( p.nMatch("POPU") )
01486 {
01487
01488 strcpy( save.chSave[save.nsave], "HYDp" );
01489 sprintf( save.chHeader[save.nsave],
01490 "#depth\tn(H0)\tn(H+)\tn(1s)\tn(2s)\tn(2p)\tetc\n" );
01491 }
01492 else if( p.nMatch("LINE") )
01493 {
01494
01495
01496 strcpy( save.chSave[save.nsave], "HYDl" );
01497 sprintf( save.chHeader[save.nsave],
01498 "#nHi\tlHi\tnLo\tlLo\tE(ryd)\ttau\n" );
01499 }
01500 else if( p.nMatch(" LYA") )
01501 {
01502
01503 strcpy( save.chSave[save.nsave], "HYDL" );
01504 sprintf( save.chHeader[save.nsave],
01505 "#depth\tTauIn\tTauTot\tn(2p)/n(1s)\tTexc\tTe\tTex/T\tPesc\tPdes\tpump\topacity\talbedo\n" );
01506 }
01507 else
01508 {
01509 fprintf( ioQQQ, "Save hydrogen has options: CONDitions, 21 CM, LINE, POPUlations, and IONIzation.\nSorry.\n" );
01510 cdEXIT(EXIT_FAILURE);
01511 }
01512 }
01513
01514 else if( p.nMatch("IONI") )
01515 {
01516 if( p.nMatch("RATE") )
01517 {
01518
01519 if( (nelem = p.GetElem() ) < 0 )
01520 {
01521 fprintf( ioQQQ, "There must be an element name on the ionization rates command. Sorry.\n" );
01522 cdEXIT(EXIT_FAILURE);
01523 }
01524 save.punarg[save.nsave][0] = (realnum)nelem;
01525 strcpy( save.chSave[save.nsave], "IONR" );
01526 sprintf( save.chHeader[save.nsave],
01527 "#%s depth\teden\tdynamics.Rate\tabund\tTotIonize\tTotRecom\tSource\t ... \n",
01528 elementnames.chElementSym[nelem]);
01529 }
01530 else
01531 {
01532
01533 strcpy( save.chSave[save.nsave], "IONI" );
01534 sprintf( save.chHeader[save.nsave],
01535 "#Mean ionization distribution\n" );
01536 }
01537 }
01538
01539 else if( p.nMatch(" IP ") )
01540 {
01541 strcpy( save.chSave[save.nsave], " IP " );
01542 sprintf( save.chHeader[save.nsave],
01543 "#ionization potentials, valence shell\n" );
01544 }
01545
01546 else if( p.nMatch("LEID") )
01547 {
01548 if( p.nMatch( "LINE" ) )
01549 {
01550
01551
01552 strcpy( save.chSave[save.nsave], "LEIL" );
01553 sprintf( save.chHeader[save.nsave], "#ion\twl\tInt\trel int\n");
01554 }
01555 else
01556 {
01557
01558
01559 strcpy( save.chSave[save.nsave], "LEIS" );
01560 sprintf( save.chHeader[save.nsave],
01561
01562 "#Leid depth\tA_V(extentd)\tA_V(point)\tTe\tH0\tH2\tCo\tC+\tOo\tCO\tO2\tCH\tOH\te\tHe+\tH+\tH3+\t"
01563
01564 "N(H0)\tN(H2)\tN(Co)\tN(C+)\tN(Oo)\tN(CO)\tN(O2)\tN(CH)\tN(OH)\tN(e)\tN(He+)\tN(H+)\tN(H3+)\t"
01565
01566 "H2(Sol)\tH2(FrmGrn)\tH2(photodiss)\t"
01567
01568 "G0(DB96)\trate(CO)\trate(C)\theat\tcool\tGrnP\tGr-Gas-Cool\tGr-Gas-Heat\tCOds\tH2dH\tH2vH\tChaT\tCR H\tMgI\tSI\t"
01569 "Si\tFe\tNa\tAl\tC\tC610\tC370\tC157\tC63\tC146\n" );
01570 }
01571 }
01572
01573
01574
01575
01576 else if( p.nMatch("NLTE") )
01577 {
01578 # ifdef USE_NLTE7
01579 strcpy( save.chSave[save.nsave], "NLTE" );
01580 # else
01581 fprintf(ioQQQ," PROBLEM You must enable the USE_NLTE7 macro at compile-time to use this command.\n");
01582 fprintf(ioQQQ," To do so, add EXTRA=\"-DUSE_NLTE7\" to the end of the make command.\n");
01583 fprintf(ioQQQ," An example for a quad core machine:\n make -j 4 EXTRA=\"-DUSE_NLTE7\" \n");
01584 fprintf(ioQQQ," in the sys_XXX folder that you want to use.\n\n\n");
01585 cdEXIT(EXIT_FAILURE);
01586 # endif
01587 }
01588
01589
01590 else if (p.nMatch("FE2NRG"))
01591 {
01592 strcpy( save.chSave[save.nsave], "LY1" );
01593 }
01594
01595 else if (p.nMatch("FE2TP"))
01596 {
01597 strcpy( save.chSave[save.nsave], "LY2" );
01598 }
01599
01600 else if (p.nMatch("FE2COLL"))
01601 {
01602 strcpy( save.chSave[save.nsave], "LY3" );
01603 }
01604
01605 else if( (p.nMatch("LINE") && p.nMatch("LIST")) || p.nMatch("LINELIST") )
01606 {
01607
01608 strcpy( save.chSave[save.nsave], "LLST" );
01609
01610
01611
01612
01613
01614 if( !lgSecondFilename )
01615 {
01616 fprintf(ioQQQ , "There must be a second file name between "
01617 "double quotes on the SAVE LINE LIST command. This second"
01618 " file contains the input line list. I did not find it.\nSorry.\n");
01619 cdEXIT(EXIT_FAILURE);
01620 }
01621
01622
01623
01624 if( save.ipPnunit[save.nsave] == NULL )
01625 {
01626
01627 save.SaveLineListFree(save.nsave);
01628
01629 save.nLineList[save.nsave] = cdGetLineList(chSecondFilename,
01630 save.chLineListLabel[save.nsave],
01631 save.wlLineList[save.nsave]);
01632
01633 if( save.nLineList[save.nsave] < 0 )
01634 {
01635 fprintf(ioQQQ,"DISASTER could not open SAVE LINE LIST file %s \n",
01636 chSecondFilename );
01637 cdEXIT(EXIT_FAILURE);
01638 }
01639 }
01640
01641
01642 save.lgEmergent[save.nsave] = false;
01643 if( p.nMatch("EMER") )
01644 save.lgEmergent[save.nsave] = true;
01645
01646
01647 save.lgCumulative[save.nsave] = false;
01648 if( p.nMatch("CUMU") )
01649 save.lgCumulative[save.nsave] = true;
01650
01651
01652
01653 if( p.nMatch("RATI") )
01654 {
01655 save.lgLineListRatio[save.nsave] = true;
01656 if( save.nLineList[save.nsave]%2 )
01657 {
01658
01659 fprintf(ioQQQ , "There must be an even number of lines to"
01660 " take ratios of lines. There were %li, an odd number."
01661 "\nSorry.\n", save.nLineList[save.nsave]);
01662 cdEXIT(EXIT_FAILURE);
01663 }
01664 }
01665 else
01666 {
01667
01668 save.lgLineListRatio[save.nsave] = false;
01669 }
01670
01671
01672
01673 if( p.nMatch("ABSO") )
01674 {
01675 save.punarg[save.nsave][0] = 1;
01676 }
01677 else
01678 {
01679 save.punarg[save.nsave][0] = 0;
01680 }
01681
01682
01683 if( p.nMatch("COLUMN") )
01684 {
01685 save.punarg[save.nsave][1] = 1;
01686 }
01687 else
01688 {
01689 save.punarg[save.nsave][1] = 0;
01690 }
01691
01692
01693 sprintf( save.chHeader[save.nsave], "#lineslist" );
01694
01695 if( !save.punarg[save.nsave][1] )
01696 {
01697 for( long int j=0; j<save.nLineList[save.nsave]; ++j )
01698 {
01699
01700 if( save.lgLineListRatio[save.nsave] && is_odd(j) )
01701 strcat( save.chHeader[save.nsave] , "/" );
01702 else
01703 strcat( save.chHeader[save.nsave] , "\t" );
01704 sprintf( chTemp, "%s ", save.chLineListLabel[save.nsave][j] );
01705 strcat( save.chHeader[save.nsave], chTemp );
01706 sprt_wl( chTemp, save.wlLineList[save.nsave][j] );
01707 strcat( save.chHeader[save.nsave], chTemp );
01708 }
01709 }
01710 strcat( save.chHeader[save.nsave], "\n" );
01711 }
01712
01713 else if( p.nMatch("LINE") && !p.nMatch("XSPE") && !p.nMatch("NEAR"))
01714 {
01715
01716
01717
01718
01719 ChkUnits(p);
01720
01721
01722
01723 if( p.nMatch("STRU") )
01724 {
01725 fprintf(ioQQQ," The SAVE LINES STRUCTURE command is now SAVE LINES "
01726 "EMISSIVITY.\n Sorry.\n\n");
01727 cdEXIT(EXIT_FAILURE);
01728 }
01729
01730 else if( p.nMatch("PRES") )
01731 {
01732
01733 strcpy( save.chSave[save.nsave], "PREL" );
01734 sprintf( save.chHeader[save.nsave],
01735 "#P depth\tPtot\tPline/Ptot\tcontributors to line pressure\n" );
01736 }
01737
01738 else if( p.nMatch("EMIS") )
01739 {
01740
01741
01742
01743
01744 save.lgEmergent[save.nsave] = false;
01745 if( p.nMatch("EMER") )
01746 save.lgEmergent[save.nsave] = true;
01747 strcpy( save.chSave[save.nsave], "LINS" );
01748 sprintf( save.chHeader[save.nsave],
01749 "#");
01750
01751 parse_save_line(p,false, chTemp );
01752 strcat( save.chHeader[save.nsave], chTemp );
01753 }
01754
01755 else if( p.nMatch(" RT " ) )
01756 {
01757
01758 strcpy( save.chSave[save.nsave], "LINR" );
01759
01760
01761 Parse_Save_Line_RT(p);
01762 }
01763
01764 else if( p.nMatch("CUMU") )
01765 {
01766 bool lgEOL;
01767
01768
01769 strcpy( save.chSave[save.nsave], "LINC" );
01770
01771 save.lgEmergent[save.nsave] = false;
01772 if( p.nMatch("EMER") )
01773 save.lgEmergent[save.nsave] = true;
01774
01775 if( p.nMatch("RELA") )
01776 {
01777 lgEOL = true;
01778 sprintf( save.chHeader[save.nsave], "#" );
01779 }
01780 else
01781 {
01782 sprintf( save.chHeader[save.nsave], "#" );
01783 lgEOL = false;
01784 }
01785
01786 parse_save_line(p, lgEOL, chTemp );
01787 strcat( save.chHeader[save.nsave], chTemp );
01788 }
01789
01790 else if( p.nMatch("DATA") )
01791 {
01792
01793
01794
01795
01796 save.chConPunEnr[save.nsave] = "labl";
01797
01798
01799
01800 if( p.nMatch("UNIT") )
01801 ChkUnits(p);
01802 strcpy( save.chSave[save.nsave], "LIND" );
01803 sprintf( save.chHeader[save.nsave],
01804 "#Emission line data.\n" );
01805 }
01806
01807 else if( p.nMatch("ARRA") )
01808 {
01809
01810
01811 strcpy( save.chSave[save.nsave], "LINA" );
01812 sprintf( save.chHeader[save.nsave],
01813 "#enr\tID\tI(intrinsic)\tI(emergent)\ttype\n" );
01814 }
01815
01816 else if( p.nMatch("LABE") )
01817 {
01818
01819 strcpy( save.chSave[save.nsave], "LINL" );
01820 sprintf( save.chHeader[save.nsave],
01821 "#index\tlabel\twavelength\tcomment\n" );
01822
01823
01824
01825 if( p.nMatch("LONG") )
01826 save.punarg[save.nsave][0] = 1;
01827 else
01828 save.punarg[save.nsave][0] = 0;
01829 }
01830
01831 else if( p.nMatch("OPTI") )
01832 {
01833
01834 strcpy( save.chSave[save.nsave], "LINO" );
01835
01836
01837
01838 save.chConPunEnr[save.nsave] = "labl";
01839
01840
01841
01842 if( p.nMatch("UNIT") )
01843 ChkUnits(p);
01844
01845 sprintf( save.chHeader[save.nsave],
01846 "#species\tenergy/%s\topt depth\tdamp\n",
01847 save.chConPunEnr[save.nsave] );
01848
01849
01850 save.punarg[save.nsave][0] = (realnum)pow(10.,p.FFmtRead());
01851
01852 if( p.lgEOL() )
01853 {
01854 save.punarg[save.nsave][0] = 0.1f;
01855 }
01856 }
01857
01858 else if( p.nMatch("POPU") )
01859 {
01860
01861
01862
01863 strcpy( save.chSave[save.nsave], "LINP" );
01864 sprintf( save.chHeader[save.nsave],
01865 "#population information\n" );
01866
01867
01868 save.punarg[save.nsave][0] = (realnum)pow(10.,p.FFmtRead());
01869
01870
01871 if( p.lgEOL() )
01872 save.punarg[save.nsave][0] = 0.f;
01873
01874 if( p.nMatch(" OFF") )
01875 {
01876
01877 save.punarg[save.nsave][0] = -1.f;
01878 }
01879 }
01880
01881 else if( p.nMatch("INTE") )
01882 {
01883
01884 strcpy( save.chSave[save.nsave], "LINI" );
01885 sprintf( save.chHeader[save.nsave],
01886 "#Emission line intrinsic intensities per unit inner area\n" );
01887 if( p.nMatch("COLU") )
01888
01889 strcpy( save.chPunRltType, "column" );
01890 else
01891
01892 strcpy( save.chPunRltType, "array " );
01893
01894 save.punarg[save.nsave][0] = 0.;
01895
01896 if( p.nMatch( " ALL" ) )
01897 save.punarg[save.nsave][0] = -1.;
01898
01899
01900 save.lgEmergent[save.nsave] = false;
01901 if( p.nMatch("EMER") )
01902 save.lgEmergent[save.nsave] = true;
01903
01904 if( p.nMatch("EVER") )
01905 {
01906 save.LinEvery = (long int)p.FFmtRead();
01907 save.lgLinEvery = true;
01908 if( p.lgEOL() )
01909 {
01910 fprintf( ioQQQ,
01911 "There must be a second number, the number of zones to print.\nSorry.\n" );
01912 cdEXIT(EXIT_FAILURE);
01913 }
01914 }
01915 else
01916 {
01917 save.LinEvery = geometry.nend[0];
01918 save.lgLinEvery = false;
01919 }
01920 }
01921 else
01922 {
01923 fprintf( ioQQQ,
01924 "This option for SAVE LINE is something that I do not understand. Sorry.\n" );
01925 cdEXIT(EXIT_FAILURE);
01926 }
01927 }
01928
01929 else if( p.nMatch(" MAP") )
01930 {
01931 strcpy( save.chSave[save.nsave], "MAP " );
01932 sprintf( save.chHeader[save.nsave],
01933 "#te, heating, cooling.\n" );
01934
01935
01936
01937
01938 hcmap.MapZone = (long)p.FFmtRead();
01939 if( p.lgEOL() )
01940 {
01941 hcmap.MapZone = 1;
01942 }
01943
01944 if( p.nMatch("RANG") )
01945 {
01946 bool lgLogOn;
01947 hcmap.RangeMap[0] = (realnum)p.FFmtRead();
01948 if( hcmap.RangeMap[0] <= 10. && !p.nMatch("LINE") )
01949 {
01950 hcmap.RangeMap[0] = (realnum)pow((realnum)10.f,hcmap.RangeMap[0]);
01951 lgLogOn = true;
01952 }
01953 else
01954 {
01955 lgLogOn = false;
01956 }
01957
01958 hcmap.RangeMap[1] = (realnum)p.FFmtRead();
01959 if( lgLogOn )
01960 hcmap.RangeMap[1] = (realnum)pow((realnum)10.f,hcmap.RangeMap[1]);
01961
01962 if( p.lgEOL() )
01963 {
01964 fprintf( ioQQQ, "There must be a zone number, followed by two temperatures, on this line. Sorry.\n" );
01965 cdEXIT(EXIT_FAILURE);
01966 }
01967 }
01968 }
01969
01970 else if( p.nMatch("MOLE") )
01971 {
01972
01973 strcpy( save.chSave[save.nsave], "MOLE" );
01974 }
01975
01976 else if( p.nMatch("MONI") )
01977 {
01978
01979 strcpy( save.chSave[save.nsave], "MONI" );
01980 }
01981
01982 else if( p.nMatch("OPTICAL") && p.nMatch("DEPTH") )
01983 {
01984
01985
01986 ChkUnits(p);
01987
01988
01989
01990 if( p.nMatch("EVER" ) )
01991 {
01992
01993 save.lgSaveEveryZone[save.nsave] = true;
01994 save.nSaveEveryZone[save.nsave] = 1;
01995 }
01996 else
01997 {
01998
01999 save.lgSaveEveryZone[save.nsave] = false;
02000 save.nSaveEveryZone[save.nsave] = 1;
02001 }
02002
02003 if( p.nMatch("FINE") )
02004 {
02005
02006 rfield.lgSaveOpacityFine = true;
02007 strcpy( save.chSave[save.nsave], "OPTf" );
02008 sprintf( save.chHeader[save.nsave], "#energy/%s\tTau tot\topacity\n",
02009 save.chConPunEnr[save.nsave] );
02010
02011 if( p.nMatch("RANGE") )
02012 {
02013
02014 double Energy1 = p.FFmtRead();
02015 double Energy2 = p.FFmtRead();
02016 if( p.lgEOL() )
02017 {
02018 fprintf(ioQQQ,"There must be two numbers, the lower and upper energy range in Ryd.\nSorry.\n");
02019 cdEXIT(EXIT_FAILURE);
02020 }
02021 if( p.nMatch("UNIT" ) )
02022 {
02023
02024 const char *energyUnits = p.StandardEnergyUnit();
02025 Energy unitChange;
02026 unitChange.set(Energy1, energyUnits );
02027 Energy1 = unitChange.Ryd();
02028 unitChange.set(Energy2, energyUnits );
02029 Energy2 = unitChange.Ryd();
02030 }
02031
02032 save.punarg[save.nsave][0] = (realnum)MIN2( Energy1 , Energy2 );
02033 save.punarg[save.nsave][1] = (realnum)MAX2( Energy1 , Energy2 );
02034
02035
02036
02037 }
02038 else
02039 {
02040
02041 save.punarg[save.nsave][0] = 0.;
02042 save.punarg[save.nsave][1] = 0.;
02043 }
02044
02045 save.punarg[save.nsave][2] = (realnum)p.FFmtRead();
02046
02047 if( p.lgEOL() )
02048 save.punarg[save.nsave][2] = 10;
02049 if( save.punarg[save.nsave][2] < 1 )
02050 {
02051 fprintf(ioQQQ,"The number of fine opacities to skip must be > 0 \nSorry.\n");
02052 cdEXIT(EXIT_FAILURE);
02053 }
02054 }
02055 else
02056 {
02057
02058 strcpy( save.chSave[save.nsave], "OPTc" );
02059 sprintf( save.chHeader[save.nsave],
02060 "#energy/%s\ttotal\tabsorp\tscat\n",
02061 save.chConPunEnr[save.nsave] );
02062 }
02063
02064 }
02065 else if( p.nMatch(" OTS") )
02066 {
02067 strcpy( save.chSave[save.nsave], " OTS" );
02068 sprintf( save.chHeader[save.nsave],
02069 "#otscon, lin, conOpac LinOpc\n" );
02070 }
02071
02072 else if( p.nMatch("OVER") && p.nMatch(" OVE") )
02073 {
02074
02075 strcpy( save.chSave[save.nsave], "OVER" );
02076 sprintf( save.chHeader[save.nsave],
02077 "#depth\tTe\tHtot\thden\teden\t2H_2/H\tHI\tHII\tHeI\tHeII\tHeIII\tCO/C\tC1\tC2\tC3\tC4\tO1\tO2\tO3\tO4\tO5\tO6\tH2O/O\tAV(point)\tAV(extend)\n" );
02078 }
02079
02080 else if( p.nMatch(" PDR") )
02081 {
02082 strcpy( save.chSave[save.nsave], " PDR" );
02083 sprintf( save.chHeader[save.nsave],
02084 "#depth\tH colden\tTe\tHI/HDEN\tH2/HDEN\tH2*/HDEN\tCI/C\tCO/C\tH2O/O\tG0\tAV(point)\tAV(extend)\tTauV(point)\n" );
02085 }
02086
02087 else if( p.nMatch("PERF") )
02088 {
02089
02090 strcpy( save.chSave[save.nsave], "PERF" );
02091 sprintf( save.chHeader[save.nsave],
02092 "#zone\tdTime\tElapsed t\tnPres2Ioniz\n" );
02093 }
02094
02095 else if( p.nMatch("PHYS") )
02096 {
02097
02098 strcpy( save.chSave[save.nsave], "PHYS" );
02099 sprintf( save.chHeader[save.nsave],
02100 "#PhyC depth\tTe\tn(H)\tn(e)\tHtot\taccel\tfillfac\n" );
02101 }
02102
02103 else if( p.nMatch("POIN") )
02104 {
02105
02106 save.lgPunPoint = true;
02107
02108 strcpy( save.chSave[save.nsave], "" );
02109 save.lgRealSave[save.nsave] = false;
02110 }
02111
02112 else if( p.nMatch("PRES") )
02113 {
02114
02115 strcpy( save.chSave[save.nsave], "PRES" );
02116 sprintf( save.chHeader[save.nsave],
02117 "#P depth\tPerror%%\tPcurrent\tPIn+Pinteg\tPgas(r0)\tPgas\tPram"
02118 "\tPrad(line)\tPinteg\tV(wind km/s)\tcad(wind km/s)\tP(mag)\tV(turb km/s)"
02119 "\tP(turb)\tPgr_Int\tint thin elec\tconv?\n" );
02120 }
02121
02122 else if( p.nMatch("RADI") )
02123 {
02124
02125 sprintf( save.chHeader[save.nsave], "#NZONE\tradius\tdepth\tdr\n" );
02126
02127 if( p.nMatch( "OUTE" ) )
02128 {
02129
02130 strcpy( save.chSave[save.nsave], "RADO" );
02131 }
02132 else
02133 {
02134
02135 strcpy( save.chSave[save.nsave], "RADI" );
02136 }
02137 }
02138
02139 else if( p.nMatch("RECO") )
02140 {
02141 if( p.nMatch("COEF") )
02142 {
02143
02144
02145
02146 save.lgioRecom = true;
02147
02148 strcpy( save.chSave[save.nsave], "" );
02149 save.lgRealSave[save.nsave] = false;
02150 }
02151
02152 else if( p.nMatch("EFFI") )
02153 {
02154
02155 strcpy( save.chSave[save.nsave], "RECE" );
02156 sprintf( save.chHeader[save.nsave],
02157 "#Recom effic H, Heo, He+\n" );
02158 }
02159
02160 else
02161 {
02162 fprintf( ioQQQ, "No option recognized on this save recombination command\n" );
02163 fprintf( ioQQQ, "Valid options are COEFFICIENTS, AGN, and EFFICIENCY\nSorry.\n" );
02164 cdEXIT(EXIT_FAILURE);
02165 }
02166 }
02167
02168
02169 else if( p.nMatch("RESU") )
02170 {
02171 strcpy( save.chSave[save.nsave], "RESU" );
02172 if( p.nMatch("COLU") )
02173 {
02174
02175 strcpy( save.chPunRltType, "column" );
02176 }
02177 else
02178 {
02179
02180 strcpy( save.chPunRltType, "array " );
02181 }
02182
02183
02184 sprintf( save.chHeader[save.nsave],
02185 "#results of calculation\n" );
02186 }
02187
02188 else if( p.nMatch("SECO") )
02189 {
02190
02191 strcpy( save.chSave[save.nsave], "SECO" );
02192 sprintf( save.chHeader[save.nsave],
02193 "#depth\tIon(H^0)\tDiss(H_2)\tExcit(Lya)\n" );
02194 }
02195
02196 else if( p.nMatch("SOUR") )
02197 {
02198
02199
02200
02201 ChkUnits(p);
02202
02203 if( p.nMatch("DEPT") )
02204 {
02205
02206 strcpy( save.chSave[save.nsave], "SOUD" );
02207 sprintf( save.chHeader[save.nsave],
02208 "#continuum source function vs depth\n" );
02209 }
02210 else if( p.nMatch("SPEC") )
02211 {
02212
02213 strcpy( save.chSave[save.nsave], "SOUS" );
02214 sprintf( save.chHeader[save.nsave],
02215 "#continuum source function nu/%s\tConEmitLocal/widflx"
02216 "\tabs opac\tConSourceFcnLocal\tConSourceFcnLocal/plankf\tConSourceFcnLocal/flux\n",
02217 save.chConPunEnr[save.nsave] );
02218 }
02219 else
02220 {
02221 fprintf( ioQQQ, "A second keyword must appear on this line.\n" );
02222 fprintf( ioQQQ, "They are DEPTH and SPECTRUM.\n" );
02223 fprintf( ioQQQ, "Sorry.\n" );
02224 cdEXIT(EXIT_FAILURE);
02225 }
02226 }
02227
02228
02229
02230
02231 else if( p.nMatch("SPECTRUM") && !p.nMatch("XSPE") )
02232 {
02233
02234
02235 save.lgPunContinuum = true;
02236
02237
02238 strcpy( save.chSave[save.nsave], "CONN" );
02239
02240
02241
02242 ChkUnits(p);
02243
02244 sprintf( save.chHeader[save.nsave],
02245 "#Cont Enr/%s\tincid nFn\ttrans\tdiff\tlines \n",
02246 save.chConPunEnr[save.nsave] );
02247 }
02248
02249 else if( p.nMatch("SPECIAL") )
02250 {
02251
02252 strcpy( save.chSave[save.nsave], "SPEC" );
02253 sprintf( save.chHeader[save.nsave], "#Special.\n" );
02254 }
02255
02256 else if( p.nMatch("SPECIES") )
02257 {
02258 strcpy( save.chSave[save.nsave], "SPCS" );
02259
02260
02261
02262 strcpy( chLabel, chSecondFilename );
02263 if( !lgSecondFilename )
02264 {
02265 strcpy( save.chSaveSpecies[save.nsave], "" );
02266 }
02267 else if( strlen(chLabel) >= CHARS_SPECIES )
02268 {
02269 fprintf( ioQQQ,"Species string is limited to %li characters.\nSorry.\n", (long)CHARS_SPECIES );
02270 cdEXIT(EXIT_FAILURE);
02271 }
02272 else
02273 strncpy( save.chSaveSpecies[save.nsave], chLabel, CHARS_SPECIES );
02274
02275 if (p.nMatch( "COLUMN" ) )
02276 {
02277
02278 strcpy( save.chSaveArgs[save.nsave], "COLU" );
02279 }
02280 else if (p.nMatch( "ENERG" ) )
02281 {
02282
02283 ChkUnits(p);
02284 strcpy( save.chSaveArgs[save.nsave], "ENER" );
02285 }
02286 else if( p.nMatch("LABELS") )
02287 {
02288 strcpy( save.chSaveArgs[save.nsave], "LABE" );
02289 }
02290 else if (p.nMatch( "LEVELS" ) )
02291 {
02292
02293 strcpy( save.chSaveArgs[save.nsave], "LEVL" );
02294 }
02295 else if (p.nMatch( "POPUL" ) )
02296 {
02297
02298 strcpy( save.chSaveArgs[save.nsave], "POPU" );
02299 }
02300 else
02301 {
02302 fprintf( ioQQQ, "ParseSave cannot find a recognized keyword on this SAVE SPECIES command line.\n" );
02303 fprintf( ioQQQ, "I know about the keywords COLUMN DENSITIES, LABELS, LEVELS, and POPULATIONS.\nSorry.\n" );
02304 cdEXIT(EXIT_FAILURE);
02305 }
02306 }
02307
02308 else if( p.nMatch("TEMP") )
02309 {
02310
02311 strcpy( save.chSave[save.nsave], "TEMP" );
02312 sprintf( save.chHeader[save.nsave],
02313 "#depth\tTe\tcC/dT\tdt/dr\td^2T/dr^2\n" );
02314 }
02315
02316 else if( p.nMatch("TIME") && p.nMatch("DEPE") )
02317 {
02318
02319 strcpy( save.chSave[save.nsave], "TIMD" );
02320
02321 save.lg_separate_iterations[save.nsave] = false;
02322
02323 sprintf( save.chHeader[save.nsave] ,
02324 "#elapsed time\ttime step \tscale cont\tn(H)\t<T>\t<H+/H rad>\t<H0/H rad>\t<H2/H rad>\t<He+/He rad>\t<CO/H>\t<redshift>\t<ne/nH>\n" );
02325 }
02326
02327 else if( p.nMatch("TPRE") )
02328 {
02329
02330
02331 strcpy( save.chSave[save.nsave], "TPRE" );
02332 sprintf( save.chHeader[save.nsave],
02333 "#zone old temp, guess Tnew, new temp delta \n" );
02334 }
02335
02336 else if( p.nMatch("WIND") )
02337 {
02338 strcpy( save.chSave[save.nsave], "WIND" );
02339 sprintf( save.chHeader[save.nsave],
02340 "#radius\tdepth\tvel [cm/s]\tTot accel [cm s-2]\tLin accel [cm s-2]"
02341 "\tCon accel [cm s-2]\tforce multiplier\ta_gravity\n" );
02342 if( p.nMatch( "TERM" ) )
02343 {
02344
02345 save.punarg[save.nsave][0] = 0.;
02346 }
02347 else
02348 {
02349
02350 save.punarg[save.nsave][0] = 1.;
02351 }
02352 }
02353
02354 else if( p.nMatch("XSPE") )
02355 {
02356
02357 save.lgFITS[save.nsave] = true;
02358
02359
02360 save.lgPunLstIter[save.nsave] = true;
02361
02362
02363 grid.lgSaveXspec = true;
02364
02365
02366 if( p.nMatch("RANGE") )
02367 {
02368
02369 save.punarg[save.nsave][0] = (realnum)p.FFmtRead();
02370 save.punarg[save.nsave][1] = (realnum)p.FFmtRead();
02371 if( p.lgEOL() )
02372 {
02373 fprintf(ioQQQ,"There must be two numbers, the lower and upper energy range in keV.\nSorry.\n");
02374 cdEXIT(EXIT_FAILURE);
02375 }
02376 if( save.punarg[save.nsave][0] >=save.punarg[save.nsave][1] )
02377 {
02378 fprintf(ioQQQ,"The two energies for the range must be in increasing order.\nSorry.\n");
02379 cdEXIT(EXIT_FAILURE);
02380 }
02381
02382 grid.LoEnergy_keV = save.punarg[save.nsave][0];
02383 grid.HiEnergy_keV = save.punarg[save.nsave][1];
02384 }
02385 else
02386 {
02387
02388 save.punarg[save.nsave][0] = 0;
02389 save.punarg[save.nsave][1] = 0;
02390 }
02391
02392 if( p.nMatch("ATAB") )
02393 {
02394
02395
02396 if( p.nMatch("TOTA") )
02397 {
02398
02399 strcpy( save.chSave[save.nsave], "XTOT" );
02400 grid.lgOutputTypeOn[0] = true;
02401 save.FITStype[save.nsave] = 0;
02402 }
02403 else if( p.nMatch("INCI") )
02404 {
02405 if( p.nMatch("ATTE") )
02406 {
02407
02408 strcpy( save.chSave[save.nsave], "XATT" );
02409 grid.lgOutputTypeOn[2] = true;
02410 save.FITStype[save.nsave] = 2;
02411 }
02412 else if( p.nMatch("REFL") )
02413 {
02414
02415 strcpy( save.chSave[save.nsave], "XRFI" );
02416 grid.lgOutputTypeOn[3] = true;
02417 save.FITStype[save.nsave] = 3;
02418 }
02419 else
02420 {
02421
02422 strcpy( save.chSave[save.nsave], "XINC" );
02423 grid.lgOutputTypeOn[1] = true;
02424 save.FITStype[save.nsave] = 1;
02425 }
02426 }
02427 else if( p.nMatch("DIFF") )
02428 {
02429 if( p.nMatch("REFL") )
02430 {
02431
02432 strcpy( save.chSave[save.nsave], "XDFR" );
02433 grid.lgOutputTypeOn[5] = true;
02434 save.FITStype[save.nsave] = 5;
02435 }
02436 else
02437 {
02438
02439 strcpy( save.chSave[save.nsave], "XDFO" );
02440 grid.lgOutputTypeOn[4] = true;
02441 save.FITStype[save.nsave] = 4;
02442 }
02443 }
02444 else if( p.nMatch("LINE") )
02445 {
02446 if( p.nMatch("REFL") )
02447 {
02448
02449 strcpy( save.chSave[save.nsave], "XLNR" );
02450 grid.lgOutputTypeOn[7] = true;
02451 save.FITStype[save.nsave] = 7;
02452 }
02453 else
02454 {
02455
02456 strcpy( save.chSave[save.nsave], "XLNO" );
02457 grid.lgOutputTypeOn[6] = true;
02458 save.FITStype[save.nsave] = 6;
02459 }
02460 }
02461 else if( p.nMatch("SPEC") )
02462 {
02463 if( p.nMatch("REFL") )
02464 {
02465
02466 strcpy( save.chSave[save.nsave], "XREF" );
02467 grid.lgOutputTypeOn[9] = true;
02468 save.FITStype[save.nsave] = 9;
02469 }
02470 else
02471 {
02472
02473 strcpy( save.chSave[save.nsave], "XTRN" );
02474 grid.lgOutputTypeOn[8] = true;
02475 save.FITStype[save.nsave] = 8;
02476 }
02477 }
02478 else
02479 {
02480
02481 strcpy( save.chSave[save.nsave], "XTRN" );
02482 grid.lgOutputTypeOn[8] = true;
02483 save.FITStype[save.nsave] = 8;
02484 }
02485 }
02486 else if( p.nMatch("MTAB") )
02487 {
02488
02489 strcpy( save.chSave[save.nsave], "XSPM" );
02490 grid.lgOutputTypeOn[10] = true;
02491 save.FITStype[save.nsave] = 10;
02492 }
02493 else
02494 {
02495 fprintf( ioQQQ, "Support only for xspec atable and xspec mtable.\n" );
02496 cdEXIT( EXIT_FAILURE );
02497 }
02498 }
02499
02500
02501
02502
02503 else if( p.nMatch("COLU") && p.nMatch("DENS") )
02504 {
02505 if( p.nMatch("SOME" ))
02506 {
02507
02508 strcpy( save.chSave[save.nsave], "COLS" );
02509 parse_save_colden( p, save.chHeader[save.nsave] );
02510 }
02511 else
02512 {
02513
02514 strcpy( save.chSave[save.nsave], "COLU" );
02515 }
02516 }
02517 else
02518 {
02519 fprintf( ioQQQ,
02520 "ParseSave cannot find a recognized keyword on this SAVE command line.\nSorry.\n" );
02521 cdEXIT(EXIT_FAILURE);
02522 }
02523
02524
02525 if( save.ipPnunit[save.nsave] == NULL )
02526 {
02527 string file_name;
02528 file_name += chFilename;
02529 string mode = "w";
02530 if( save.lgFITS[save.nsave] )
02531 mode += "b";
02532
02533
02534 save.ipPnunit[save.nsave] = open_data( file_name.c_str(), mode.c_str(), AS_LOCAL_ONLY );
02535
02536
02537
02538
02539 if( p.nMatch("NO BUFFER") )
02540 setbuf( save.ipPnunit[save.nsave] , NULL );
02541 }
02542
02543
02544
02545
02546
02547
02548
02549
02550
02551
02552 if( p.nMatch("CONV") && p.nMatch("REAS") )
02553 {
02554
02555
02556 save.ipPunConv = save.ipPnunit[save.nsave];
02557 save.lgPunConv_noclobber = save.lgNoClobber[save.nsave];
02558 save.lgPunConv = true;
02559 fprintf( save.ipPunConv,
02560 "# reason for continued iterations\n" );
02561 strcpy( save.chSave[save.nsave], "" );
02562 save.lgRealSave[save.nsave] = false;
02563 }
02564
02565 else if( p.nMatch("CONV") && p.nMatch("BASE") )
02566 {
02567
02568 save.lgTraceConvergeBase = true;
02569
02570
02571 if( p.nMatch("NO HA") )
02572 save.lgTraceConvergeBaseHash = false;
02573 save.ipTraceConvergeBase = save.ipPnunit[save.nsave];
02574
02575 save.lgTraceConvergeBase_noclobber = save.lgNoClobber[save.nsave];
02576 static bool lgPrtHeader = true;
02577 if( lgPrtHeader )
02578 fprintf( save.ipTraceConvergeBase,
02579 "#zone\theat\tcool\teden\n" );
02580 lgPrtHeader = false;
02581 }
02582
02583 else if( p.nMatch(" DR ") )
02584 {
02585 static bool lgPrtHeader = true;
02586
02587
02588 if( p.nMatch("NO HA") )
02589 save.lgDRHash = false;
02590 save.ipDRout = save.ipPnunit[save.nsave];
02591
02592 save.lgDRPLst = save.lgPunLstIter[save.nsave];
02593 save.lgDROn_noclobber = save.lgNoClobber[save.nsave];
02594 if( lgPrtHeader )
02595 fprintf( save.ipDRout,
02596 "#zone\tdepth\tdr\tdr 2 go\treason \n" );
02597 lgPrtHeader = false;
02598 strcpy( save.chSave[save.nsave], "" );
02599 save.lgRealSave[save.nsave] = false;
02600 }
02601
02602 else if( p.nMatch("QHEA") )
02603 {
02604 gv.QHSaveFile = save.ipPnunit[save.nsave];
02605 gv.lgQHPunLast = save.lgPunLstIter[save.nsave];
02606 save.lgQHSaveFile_noclobber = save.lgNoClobber[save.nsave];
02607 fprintf( gv.QHSaveFile,
02608 "#Probability distributions from quantum heating routine.\n" );
02609 save.lgRealSave[save.nsave] = false;
02610 }
02611
02612 else if( p.nMatch("POIN") )
02613 {
02614
02615 save.ipPoint = save.ipPnunit[save.nsave];
02616 save.lgPunPoint_noclobber = save.lgNoClobber[save.nsave];
02617 save.lgPunPoint = true;
02618 fprintf( save.ipPoint,
02619 "#pointers. \n" );
02620 strcpy( save.chSave[save.nsave], "" );
02621 save.lgRealSave[save.nsave] = false;
02622 }
02623
02624 else if( p.nMatch("RECO") && p.nMatch("COEF") )
02625 {
02626
02627
02628
02629
02630
02631
02632 save.ioRecom = save.ipPnunit[save.nsave];
02633 save.lgioRecom_noclobber = save.lgNoClobber[save.nsave];
02634
02635 save.lgioRecom = true;
02636 fprintf( save.ioRecom,
02637 "#recombination coefficients cm3 s-1 for current density and temperature\n" );
02638 strcpy( save.chSave[save.nsave], "" );
02639 save.lgRealSave[save.nsave] = false;
02640 }
02641
02642 else if( p.nMatch("GRID") )
02643 {
02644
02645 grid.pnunit = save.ipPnunit[save.nsave];
02646 save.lgSaveGrid_noclobber = save.lgNoClobber[save.nsave];
02647 }
02648
02649 else if( p.nMatch(" MAP") )
02650 {
02651
02652 ioMAP = save.ipPnunit[save.nsave];
02653 }
02654
02655
02656
02657
02658 char *chEOL = strchr_s(save.chHeader[save.nsave] , '\0' );
02659
02660
02661
02662
02663 if( (chEOL==NULL) || (chEOL - save.chHeader[save.nsave])>=MAX_HEADER_SIZE-1 )
02664 {
02665 fprintf( ioQQQ, "DISASTER save.chHeader[%li] has been overwritten "
02666 "with a line too long to be read.\n", save.nsave );
02667 cdEXIT(EXIT_FAILURE);
02668 }
02669
02670
02671
02672 if( save.lgPunHeader[save.nsave] && !nMatch(save.chHeader[save.nsave],save.chNONSENSE) )
02673 {
02674 fprintf( save.ipPnunit[save.nsave], "%s", save.chHeader[save.nsave] );
02675 save.lgPunHeader[save.nsave] = false;
02676 }
02677
02678
02679 ++save.nsave;
02680 return;
02681 }
02682
02683
02684
02685
02686 void SaveFilesInit()
02687 {
02688 long int i;
02689 static bool lgFIRST = true;
02690
02691 DEBUG_ENTRY( "SaveFilesInit()" );
02692
02693 ASSERT( lgFIRST );
02694 lgFIRST = false;
02695
02696
02697
02698
02699
02700 bool lgNoClobberDefault = false;
02701 if( grid.lgGrid )
02702 {
02703
02704 lgNoClobberDefault = true;
02705 }
02706
02707 for( i=0; i < LIMPUN; i++ )
02708 {
02709 save.lgNoClobber[i] = lgNoClobberDefault;
02710 }
02711 save.lgPunConv_noclobber = lgNoClobberDefault;
02712 save.lgDROn_noclobber = lgNoClobberDefault;
02713 save.lgTraceConvergeBase_noclobber = lgNoClobberDefault;
02714 save.lgPunPoint_noclobber = lgNoClobberDefault;
02715 save.lgioRecom_noclobber = lgNoClobberDefault;
02716 save.lgQHSaveFile_noclobber = lgNoClobberDefault;
02717 save.lgSaveGrid_noclobber = lgNoClobberDefault;
02718
02719
02720 save.chNONSENSE = "ArNdY38dZ9us4N4e12SEcuQ";
02721
02722 for( i=0; i < LIMPUN; i++ )
02723 {
02724 save.ipPnunit[i] = NULL;
02725
02726
02727
02728 save.lgRealSave[i] = true;
02729
02730
02731 save.lgPunHeader[i] = true;
02732 strcpy( save.chHeader[i], save.chNONSENSE );
02733 }
02734
02735 save.lgTraceConvergeBase = false;
02736
02737 save.ipDRout = NULL;
02738 save.lgDROn = false;
02739
02740 save.ipTraceConvergeBase = NULL;
02741 save.lgTraceConvergeBase = false;
02742
02743 save.ipPunConv = NULL;
02744 save.lgPunConv = false;
02745
02746 save.ipPoint = NULL;
02747 save.lgPunPoint = false;
02748
02749 gv.QHSaveFile = NULL;
02750
02751 save.ioRecom = NULL;
02752 save.lgioRecom = false;
02753
02754 grid.pnunit = NULL;
02755
02756 ioMAP = NULL;
02757
02758 return;
02759 }
02760
02761
02762
02763
02764 void CloseSaveFiles( bool lgFinal )
02765 {
02766 long int i;
02767
02768 DEBUG_ENTRY( "CloseSaveFiles()" );
02769
02770
02771
02772
02773 for( i=0; i < save.nsave; i++ )
02774 {
02775
02776
02777 if( save.ipPnunit[i] != NULL && ( !save.lgNoClobber[i] || lgFinal ) )
02778 {
02779
02780 if( save.lgFITS[i] )
02781 {
02782
02783
02784 fseek(save.ipPnunit[i], 0, SEEK_END);
02785 long file_size = ftell(save.ipPnunit[i]);
02786 if( file_size%2880 )
02787 {
02788 fprintf( ioQQQ, " PROBLEM FITS file is wrong size!\n" );
02789 }
02790 }
02791
02792 fclose( save.ipPnunit[i] );
02793 save.ipPnunit[i] = NULL;
02794 }
02795 }
02796
02797
02798 if( save.ipDRout != NULL && ( !save.lgDROn_noclobber || lgFinal ) )
02799 {
02800 save.ipDRout = NULL;
02801 save.lgDROn = false;
02802 }
02803
02804 if( save.ipTraceConvergeBase != NULL && ( !save.lgTraceConvergeBase_noclobber || lgFinal ) )
02805 {
02806 save.ipTraceConvergeBase = NULL;
02807 save.lgTraceConvergeBase = false;
02808 }
02809
02810 if( save.ipPunConv != NULL && ( !save.lgPunConv_noclobber || lgFinal ) )
02811 {
02812 save.ipPunConv = NULL;
02813 save.lgPunConv = false;
02814 }
02815 if( save.ipPoint != NULL && ( !save.lgPunPoint_noclobber || lgFinal ) )
02816 {
02817 save.ipPoint = NULL;
02818 save.lgPunPoint = false;
02819 }
02820 if( gv.QHSaveFile != NULL && ( !save.lgQHSaveFile_noclobber || lgFinal ) )
02821 {
02822 gv.QHSaveFile = NULL;
02823 }
02824 if( save.ioRecom != NULL && ( !save.lgioRecom_noclobber || lgFinal ) )
02825 {
02826 save.ioRecom = NULL;
02827 save.lgioRecom = false;
02828 }
02829 if( grid.pnunit != NULL && ( !save.lgSaveGrid_noclobber || lgFinal ) )
02830 {
02831 grid.pnunit = NULL;
02832 }
02833 ioMAP = NULL;
02834
02835 return;
02836 }
02837
02838
02839
02840
02841
02842 STATIC void ChkUnits( Parser &p )
02843 {
02844
02845 DEBUG_ENTRY( "ChkUnits()" );
02846
02847
02848 if( p.nMatch("UNITS") )
02849 {
02850
02851 save.chConPunEnr[save.nsave] = p.StandardEnergyUnit();
02852 }
02853 else
02854 {
02855 save.chConPunEnr[save.nsave] = StandardEnergyUnit(" RYD ");
02856 }
02857 return;
02858 }