cloudy trunk
|
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 /*ParseStop parse the stop command */ 00004 #include "cddefines.h" 00005 #include "physconst.h" 00006 #include "optimize.h" 00007 #include "phycon.h" 00008 #include "rfield.h" 00009 #include "radius.h" 00010 #include "geometry.h" 00011 #include "iterations.h" 00012 #include "stopcalc.h" 00013 #include "input.h" 00014 #include "parse.h" 00015 00016 void ParseStop(char *chCard) 00017 { 00018 bool lgEOL; 00019 00020 long int i, 00021 j; 00022 00023 double a, 00024 effcol, 00025 tread; 00026 00027 DEBUG_ENTRY( "ParseStop()" ); 00028 00029 /* first scan off a generic number, all subcommands use at least one */ 00030 i = 5; 00031 a = FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL); 00032 00033 /* >>chng 04 nov 09, introduce off option */ 00034 if( lgEOL && !nMatch(" OFF",chCard) ) 00035 { 00036 NoNumb(chCard); 00037 } 00038 00039 if( nMatch("TEMP",chCard) ) 00040 { 00041 /* >>chng 04 nov 09, introduce off option to disable this stopping criterion */ 00042 if( lgEOL && nMatch(" OFF",chCard) ) 00043 { 00044 /* this is special case for ending temperature - do not use - 00045 * but will still stop if Te falls below TeLowest, the lowest 00046 * possible temperature */ 00047 StopCalc.tend = -1.f; 00048 } 00049 else 00050 { 00051 /* lowest electron temperature allowed before stopping 00052 * assumed to be the log of the temperature if <10 00053 * optional keyword LINEAR forces linear */ 00054 if( a <= 10. && !nMatch("LINE",chCard) ) 00055 { 00056 tread = pow(10.,a); 00057 } 00058 else 00059 { 00060 tread = a; 00061 } 00062 00063 /* tread is linear temperature*/ 00064 if( tread < phycon.TEMP_LIMIT_LOW ) 00065 { 00066 fprintf( ioQQQ, 00067 " Temperatures below %.2e K not allowed. Reset to lowest value." 00068 " I am doing this myself.\n" , 00069 phycon.TEMP_LIMIT_LOW ); 00070 /* set slightly off extreme limit for safety */ 00071 tread = phycon.TEMP_LIMIT_LOW*1.01; 00072 } 00073 else if( tread > phycon.TEMP_LIMIT_HIGH ) 00074 { 00075 fprintf( ioQQQ, 00076 " Temperatures is above %.2e K not allowed. Reset to highest value." 00077 " I am doing this myself.\n" , 00078 phycon.TEMP_LIMIT_HIGH); 00079 /* set slightly off extreme limit for safety */ 00080 tread = phycon.TEMP_LIMIT_HIGH*0.99; 00081 } 00082 00083 if( nMatch("EXCE",chCard) ) 00084 { 00085 /* option for this to be highest allowed temperature, 00086 * stop temperate exceeds */ 00087 StopCalc.T2High = (realnum)tread; 00088 } 00089 else 00090 { 00091 /* this is ending temperature - we stop if kinetic temperature 00092 * falls below this */ 00093 StopCalc.tend = (realnum)tread; 00094 } 00095 } 00096 } 00097 00098 /* stop at 21cm line center optical depth */ 00099 else if( nMatch("OPTI",chCard) && nMatch("21CM",chCard) ) 00100 { 00101 /* default is for number to be log of optical depth */ 00102 bool lgLOG = true; 00103 if( nMatch("LINE",chCard) ) 00104 { 00105 /* force it to be linear not log */ 00106 lgLOG = false; 00107 } 00108 i = 4; 00109 j = (long int)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL); 00110 if( j!=21 ) 00111 { 00112 fprintf( ioQQQ, " First number on STOP 21CM OPTICAL DEPTH command must be 21\n" ); 00113 cdEXIT(EXIT_FAILURE); 00114 } 00115 /* now get the next number, which is the optical depth */ 00116 a = (long int)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL); 00117 00118 /* tau must be a log, and second number is energy where tau specified */ 00119 if( lgLOG ) 00120 { 00121 StopCalc.tauend = (realnum)pow(10.,a); 00122 } 00123 else 00124 { 00125 StopCalc.tauend = (realnum)a; 00126 } 00127 /* this flag says that 21cm line optical depth is the stop quantity */ 00128 StopCalc.lgStop21cm = true; 00129 } 00130 /* stop optical depth at some energy */ 00131 else if( nMatch("OPTI",chCard) ) 00132 { 00133 /* default is for number to be log of optical depth */ 00134 bool lgLOG = true; 00135 if( nMatch("LINE",chCard) ) 00136 { 00137 /* force it to be linear not log */ 00138 lgLOG = false; 00139 } 00140 00141 if( a > 37. ) 00142 { 00143 fprintf( ioQQQ, " optical depth too big\n" ); 00144 cdEXIT(EXIT_FAILURE); 00145 } 00146 00147 /* tau must be a log, and second number is energy where tau specified */ 00148 if( lgLOG ) 00149 { 00150 StopCalc.tauend = (realnum)pow(10.,a); 00151 } 00152 else 00153 { 00154 StopCalc.tauend = (realnum)a; 00155 } 00156 00157 /* energy where tau specified */ 00158 StopCalc.taunu = (realnum)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL); 00159 00160 if( lgEOL ) 00161 { 00162 if( nMatch("LYMA",chCard) ) 00163 { 00164 /* largest Lyman limit optical depth */ 00165 StopCalc.taunu = 1.; 00166 } 00167 else if( nMatch("BALM",chCard) ) 00168 { 00169 /* stop at this Balmer continuum optical depth */ 00170 StopCalc.taunu = 0.25; 00171 } 00172 else 00173 { 00174 fprintf( ioQQQ, " There must be a second number, the energy in Ryd. Sorry.\n" ); 00175 cdEXIT(EXIT_FAILURE); 00176 } 00177 } 00178 00179 else 00180 { 00181 /* if second number is negative then log of energy in rydbergs */ 00182 if( StopCalc.taunu < 0. ) 00183 { 00184 StopCalc.taunu = (realnum)pow((realnum)10.f,StopCalc.taunu); 00185 } 00186 00187 /* check that energy is within bounds of code */ 00188 if( StopCalc.taunu < rfield.emm || StopCalc.taunu > rfield.egamry ) 00189 { 00190 fprintf( ioQQQ, " The energy must be in the range %10.2e to %10.2e. It was %10.2e. Sorry.\n", 00191 rfield.emm, rfield.egamry, StopCalc.taunu ); 00192 cdEXIT(EXIT_FAILURE); 00193 } 00194 } 00195 } 00196 00197 /* stop optical depth at extinction in V filter */ 00198 else if( nMatch(" AV ",chCard) ) 00199 { 00200 /* default is for number to be A_V, log if negative */ 00201 if( a<=0. ) 00202 { 00203 a = pow(10.,a); 00204 } 00205 /* A_V can be for either point or extended source, difference is (1-g) multiplied by scat opacity 00206 * if keyword point occurs then for point source, otherwise for extended source */ 00207 if( nMatch("EXTE" , chCard ) ) 00208 { 00209 StopCalc.AV_extended = (realnum)a; 00210 } 00211 else 00212 { 00213 /* default is point, as measured in ism work */ 00214 StopCalc.AV_point = (realnum)a; 00215 } 00216 } 00217 00218 /* stop when a fraction of molecules frozen out on grain surfaces is reached */ 00219 else if( nMatch("MOLE",chCard) && nMatch("DEPL",chCard) ) 00220 { 00221 if( a <= 0. ) 00222 { 00223 StopCalc.StopDepleteFrac = (realnum)pow(10.,a); 00224 } 00225 else 00226 { 00227 StopCalc.StopDepleteFrac = (realnum)a; 00228 } 00229 } 00230 00231 /* stop when absolute value of flow velocity falls below this value */ 00232 else if( nMatch("VELO",chCard) ) 00233 { 00234 /* entered in km/s but stored as cm/s */ 00235 StopCalc.StopVelocity = (realnum)(a*1e5); 00236 } 00237 00238 /* stop at a given computed mass */ 00239 else if( nMatch("MASS",chCard) ) 00240 { 00241 /* number of log of mass in gm if inner radius is specified, 00242 * mass per unit area, gm cm-2 if not 00243 * leave it as a log since dare not deal with linear mass */ 00244 StopCalc.xMass = (realnum)a; 00245 /* NB 0 is sentinel for not set, if a is zero we must reset it */ 00246 if( StopCalc.xMass == 0 ) 00247 StopCalc.xMass = SMALLFLOAT; 00248 } 00249 00250 /* stop thickness command, also stop depth, this must come after stop 00251 * optical depth, since do not want to trigger on depth in optical depth */ 00252 else if( nMatch("THIC",chCard) || nMatch("DEPT",chCard) ) 00253 { 00254 /* decide whether linear or log, 00255 * this branch if key linear appears */ 00256 if( nMatch("LINE",chCard) ) 00257 { 00258 radius.router[0] = a; 00259 } 00260 else 00261 { 00262 /* this is default branch, no key, so log */ 00263 if( a > 37. ) 00264 { 00265 fprintf( ioQQQ, " thickness too large\n" ); 00266 cdEXIT(EXIT_FAILURE); 00267 } 00268 radius.router[0] = pow(10.,a); 00269 } 00270 00271 /* optional parsec unit */ 00272 if( nMatch("PARS",chCard) ) 00273 { 00274 radius.router[0] *= PARSEC; 00275 } 00276 00277 /* can stop at different thickness on each iteration */ 00278 for( j=1; j < iterations.iter_malloc; j++ ) 00279 { 00280 a = FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL); 00281 if( lgEOL ) 00282 { 00283 radius.router[j] = radius.router[j-1]; 00284 } 00285 else 00286 { 00287 if( nMatch("LINE",chCard) ) 00288 { 00289 radius.router[j] = a; 00290 } 00291 else 00292 { 00293 if( a > 37. ) 00294 { 00295 fprintf( ioQQQ, " thickness too large\n" ); 00296 cdEXIT(EXIT_FAILURE); 00297 } 00298 radius.router[j] = pow(10.,a); 00299 } 00300 if( nMatch("PARS",chCard) ) 00301 { 00302 radius.router[j] *= PARSEC; 00303 } 00304 } 00305 } 00306 00307 /* vary option */ 00308 if( optimize.lgVarOn ) 00309 { 00310 optimize.nvarxt[optimize.nparm] = 1; 00311 strcpy( optimize.chVarFmt[optimize.nparm], "STOP THICKNESS %f" ); 00312 00313 /* pointer to where to write */ 00314 optimize.nvfpnt[optimize.nparm] = input.nRead; 00315 00316 /* log of temp will be pointer */ 00317 optimize.vparm[0][optimize.nparm] = (realnum)log10(radius.router[0]); 00318 optimize.vincr[optimize.nparm] = 0.5; 00319 00320 ++optimize.nparm; 00321 } 00322 } 00323 00324 /* stop at a particular zone, for each iteration */ 00325 else if( nMatch("ZONE",chCard) ) 00326 { 00327 /* stop after computing this zone */ 00328 /* >>chng 03 jun 06, do not let fall below 1, stop zone 0 has same effect 00329 * as stop zone 1, bug caught by Joop Schaye */ 00330 geometry.nend[0] = (long)MAX2(1.,a); 00331 geometry.lgZoneSet = true; 00332 00333 /* this tells code that we intend to stop at this zone, so caution not generated*/ 00334 geometry.lgEndDflt = false; 00335 00336 for( j=1; j < iterations.iter_malloc; j++ ) 00337 { 00338 geometry.nend[j] = (long)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL); 00339 /* if eol on this iteration, set to previous. In most cases 00340 * all will be equal to the first */ 00341 if( lgEOL ) 00342 { 00343 geometry.nend[j] = geometry.nend[j-1]; 00344 } 00345 else 00346 { 00347 /* >>chng 03 jun 06, do not let fall below 1, stop zone 0 has same effect 00348 * as stop zone 1, bug caught by Joop Schaye */ 00349 geometry.nend[j] = MAX2( 1 , geometry.nend[j] ); 00350 } 00351 } 00352 } 00353 00354 /* stop at this electron fraction, relative to hydrogen */ 00355 else if( nMatch("EFRA",chCard) ) 00356 { 00357 if( a <= 0. ) 00358 { 00359 StopCalc.StopElecFrac = (realnum)pow(10.,a); 00360 } 00361 else 00362 { 00363 StopCalc.StopElecFrac = (realnum)a; 00364 } 00365 } 00366 00367 /* stop at a hydrogen molecular fraction, relative to total hydrogen, 00368 * this is 2H_2 / H_total*/ 00369 else if( nMatch("MFRA",chCard) ) 00370 { 00371 if( a <= 0. ) 00372 { 00373 StopCalc.StopH2MoleFrac = (realnum)pow(10.,a); 00374 } 00375 else 00376 { 00377 StopCalc.StopH2MoleFrac = (realnum)a; 00378 } 00379 } 00380 00381 /* stop at a ionized hydrogen fraction, relative to total hydrogen, 00382 * this is H+ / H_total */ 00383 else if( nMatch("PFRA",chCard) ) 00384 { 00385 if( a <= 0. ) 00386 { 00387 StopCalc.StopHPlusFrac = (realnum)pow(10.,a); 00388 } 00389 else 00390 { 00391 StopCalc.StopHPlusFrac = (realnum)a; 00392 } 00393 } 00394 00395 /* stop at a particular column density */ 00396 else if( nMatch("COLU",chCard) ) 00397 { 00398 /* check for linear option, if present take log since a being 00399 * log column density is default */ 00400 if( nMatch( "LINE" , chCard ) ) 00401 a = log10(a); 00402 00403 /* stop at an effective column density */ 00404 if( nMatch("EFFE",chCard) ) 00405 { 00406 /* actually stop at certain optical depth at 1keV */ 00407 effcol = pow(10.,a); 00408 StopCalc.tauend = (realnum)(effcol*2.14e-22); 00409 StopCalc.taunu = 73.5; 00410 /* vary option */ 00411 if( optimize.lgVarOn ) 00412 { 00413 optimize.nvarxt[optimize.nparm] = 1; 00414 strcpy( optimize.chVarFmt[optimize.nparm], "STOP EFFECTIVE COLUMN DENSITY %f" ); 00415 /* pointer to where to write */ 00416 optimize.nvfpnt[optimize.nparm] = input.nRead; 00417 /* log of temp will be pointer */ 00418 optimize.vparm[0][optimize.nparm] = (realnum)log10(effcol); 00419 optimize.vincr[optimize.nparm] = 0.5; 00420 ++optimize.nparm; 00421 } 00422 } 00423 00424 else if( nMatch("IONI",chCard) ) 00425 { 00426 /* this is ionized column */ 00427 if( a > 37. ) 00428 { 00429 fprintf( ioQQQ, " column too big\n" ); 00430 cdEXIT(EXIT_FAILURE); 00431 } 00432 00433 StopCalc.colpls = (realnum)pow(10.,a); 00434 00435 /* vary option */ 00436 if( optimize.lgVarOn ) 00437 { 00438 optimize.nvarxt[optimize.nparm] = 1; 00439 strcpy( optimize.chVarFmt[optimize.nparm], "STOP IONIZED COLUMN DENSITY %f" ); 00440 /* pointer to where to write */ 00441 optimize.nvfpnt[optimize.nparm] = input.nRead; 00442 /* log of temp will be pointer */ 00443 optimize.vparm[0][optimize.nparm] = (realnum)log10(StopCalc.colpls); 00444 optimize.vincr[optimize.nparm] = 0.5; 00445 ++optimize.nparm; 00446 } 00447 } 00448 00449 /* stop at a neutral column */ 00450 else if( nMatch("NEUT",chCard) ) 00451 { 00452 StopCalc.colnut = (realnum)pow(10.,a); 00453 00454 /* vary option */ 00455 if( optimize.lgVarOn ) 00456 { 00457 optimize.nvarxt[optimize.nparm] = 1; 00458 strcpy( optimize.chVarFmt[optimize.nparm], "STOP NEUTRAL COLUMN DENSITY %f"); 00459 /* pointer to where to write */ 00460 optimize.nvfpnt[optimize.nparm] = input.nRead; 00461 /* log of temp will be pointer */ 00462 optimize.vparm[0][optimize.nparm] = (realnum)log10(StopCalc.colnut); 00463 optimize.vincr[optimize.nparm] = 0.5; 00464 ++optimize.nparm; 00465 } 00466 } 00467 00468 /* >>chng 03 apr 15, add this option 00469 * stop at a molecular hydrogen column density, input parameter 00470 * is log of the H2 column density */ 00471 else if( nMatch(" H2 ",chCard) ) 00472 { 00473 /* this command has a 2 in the H2 label - must not parse the two by 00474 * accident. Get the first number off the line image, and confirm that 00475 * it is a 2 */ 00476 i = 5; 00477 j = (long int)FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL); 00478 if( j != 2 ) 00479 { 00480 fprintf( ioQQQ, " Something is wrong with the order of the numbers on this line.\n" ); 00481 fprintf( ioQQQ, " The first number I encounter should be the 2 in H2.\n Sorry.\n" ); 00482 cdEXIT(EXIT_FAILURE); 00483 } 00484 a = FFmtRead(chCard,&i,INPUT_LINE_LENGTH,&lgEOL); 00485 StopCalc.col_h2 = (realnum)pow(10.,a); 00486 00487 /* vary option */ 00488 if( optimize.lgVarOn ) 00489 { 00490 optimize.nvarxt[optimize.nparm] = 1; 00491 strcpy( optimize.chVarFmt[optimize.nparm], "STOP H2 COLUMN DENSITY %f"); 00492 /* pointer to where to write */ 00493 optimize.nvfpnt[optimize.nparm] = input.nRead; 00494 /* log of temp will be pointer */ 00495 optimize.vparm[0][optimize.nparm] = (realnum)log10(StopCalc.col_h2); 00496 optimize.vincr[optimize.nparm] = 0.5; 00497 ++optimize.nparm; 00498 } 00499 } 00500 00501 else if( nMatch("ATOM",chCard) ) 00502 { 00503 StopCalc.col_h2_nut = (realnum)pow(10.,a); 00504 /* vary option */ 00505 if( optimize.lgVarOn ) 00506 { 00507 optimize.nvarxt[optimize.nparm] = 1; 00508 strcpy( optimize.chVarFmt[optimize.nparm], "STOP ATOMIC COLUMN DENSITY %f"); 00509 /* pointer to where to write */ 00510 optimize.nvfpnt[optimize.nparm] = input.nRead; 00511 /* log of temp will be pointer */ 00512 optimize.vparm[0][optimize.nparm] = (realnum)log10(StopCalc.col_h2_nut); 00513 optimize.vincr[optimize.nparm] = 0.5; 00514 ++optimize.nparm; 00515 } 00516 } 00517 00518 else if( nMatch("H/TS",chCard) ) 00519 { 00520 /* >> 05 jan 09, add stop integrated n(H0) / Tspin */ 00521 StopCalc.col_H0_ov_Tspin = (realnum)pow(10.,a); 00522 /* vary option */ 00523 if( optimize.lgVarOn ) 00524 { 00525 optimize.nvarxt[optimize.nparm] = 1; 00526 strcpy( optimize.chVarFmt[optimize.nparm], "STOP H/TSPIN COLUMN DENSITY %f"); 00527 /* pointer to where to write */ 00528 optimize.nvfpnt[optimize.nparm] = input.nRead; 00529 /* log of temp will be pointer */ 00530 optimize.vparm[0][optimize.nparm] = (realnum)log10(StopCalc.col_H0_ov_Tspin); 00531 optimize.vincr[optimize.nparm] = 0.5; 00532 ++optimize.nparm; 00533 } 00534 } 00535 00536 else if( nMatch(" CO ",chCard) ) 00537 { 00538 /* chng << 03 Oct. 27--Nick Abel, add this option */ 00539 /* stop at a carbon monoxide column density */ 00540 StopCalc.col_monoxco = (realnum)pow(10.,a); 00541 /* vary option */ 00542 if( optimize.lgVarOn ) 00543 { 00544 optimize.nvarxt[optimize.nparm] = 1; 00545 strcpy( optimize.chVarFmt[optimize.nparm], "STOP CO COLUMN DENSITY %f"); 00546 /* pointer to where to write */ 00547 optimize.nvfpnt[optimize.nparm] = input.nRead; 00548 /* log of temp will be pointer */ 00549 optimize.vparm[0][optimize.nparm] = (realnum)log10(StopCalc.col_monoxco); 00550 optimize.vincr[optimize.nparm] = 0.5; 00551 ++optimize.nparm; 00552 } 00553 } 00554 00555 /* fall through default is total hydrogen column density */ 00556 else 00557 { 00558 /* both HII and HI */ 00559 if( a > 37. ) 00560 { 00561 fprintf( ioQQQ, " column too big\n" ); 00562 cdEXIT(EXIT_FAILURE); 00563 } 00564 00565 StopCalc.HColStop = (realnum)pow(10.,a); 00566 00567 /* vary option */ 00568 if( optimize.lgVarOn ) 00569 { 00570 optimize.nvarxt[optimize.nparm] = 1; 00571 strcpy( optimize.chVarFmt[optimize.nparm], "STOP COLUMN DENSITY %f" ); 00572 /* pointer to where to write */ 00573 optimize.nvfpnt[optimize.nparm] = input.nRead; 00574 /* log of temp will be pointer */ 00575 optimize.vparm[0][optimize.nparm] = (realnum)log10(StopCalc.HColStop); 00576 optimize.vincr[optimize.nparm] = 0.5; 00577 ++optimize.nparm; 00578 } 00579 } 00580 } 00581 00582 /* stop when electron density falls below this value, linear or log */ 00583 else if( nMatch("EDEN",chCard) ) 00584 { 00585 /* stop if electron density falls below this value 00586 * LINEAR option */ 00587 if( nMatch("LINE",chCard) ) 00588 { 00589 StopCalc.StopElecDensity = (realnum)a; 00590 } 00591 else 00592 { 00593 StopCalc.StopElecDensity = (realnum)pow(10.,a); 00594 } 00595 } 00596 00597 /* stop at a particular line ratio - this must come last since many commands 00598 * have linear option - don't want to trigger on that */ 00599 else if( nMatch("LINE",chCard) ) 00600 { 00601 char chLabel[5]; 00602 /* first line wavelength, then intensity relative to Hbeta for stop 00603 * if third number is entered, it is wl of line in denominator */ 00604 00605 /* get label for the line - must do this first so we clear the label string before 00606 * trying to read the wavelength */ 00607 GetQuote( chLabel , chCard , true ); 00608 00609 /* copy first four char of label into caps, and null terminate*/ 00610 strncpy( StopCalc.chStopLabel1[StopCalc.nstpl], chLabel , 4 ); 00611 StopCalc.chStopLabel1[StopCalc.nstpl][4] = 0; 00612 00613 i = 5; 00614 /* get line wavelength */ 00615 StopCalc.StopLineWl1[StopCalc.nstpl] = 00616 (realnum)FFmtRead(chCard,&i,INPUT_LINE_LENGTH, &lgEOL); 00617 00618 /* line was entered, look for possible micron or cm label */ 00619 if( input.chCARDCAPS[i-1] == 'M' ) 00620 { 00621 /* microns */ 00622 StopCalc.StopLineWl1[StopCalc.nstpl] *= 1e4; 00623 } 00624 else if( input.chCARDCAPS[i-1] == 'C' ) 00625 { 00626 /* microns */ 00627 StopCalc.StopLineWl1[StopCalc.nstpl] *= 1e8; 00628 } 00629 00630 /* get relative intensity */ 00631 StopCalc.stpint[StopCalc.nstpl] = 00632 (realnum)FFmtRead(chCard,&i,INPUT_LINE_LENGTH, &lgEOL); 00633 if( lgEOL ) 00634 { 00635 fprintf( ioQQQ, " There MUST be a relative intensity entered " 00636 "for first line in STOP LINE command. Sorry.\n" ); 00637 cdEXIT(EXIT_FAILURE); 00638 } 00639 00640 /* check for second line - use Hbeta is not specified */ 00641 j = i; 00642 a = FFmtRead(chCard,&j,INPUT_LINE_LENGTH, &lgEOL); 00643 00644 if( lgEOL ) 00645 { 00646 /* hit the eol, normalization line will be H beta */ 00647 strncpy( StopCalc.chStopLabel2[StopCalc.nstpl], "TOTL" , 4 ); 00648 StopCalc.chStopLabel2[StopCalc.nstpl][4] = 0; 00649 StopCalc.StopLineWl2[StopCalc.nstpl] = 4861.f; 00650 } 00651 else 00652 { 00653 /* get label for the line - must do this first so we clear the label string before 00654 * trying to read the wavelength */ 00655 GetQuote( chLabel , chCard , true ); 00656 /* copy first four char of label into caps, and null terminate*/ 00657 strncpy( StopCalc.chStopLabel2[StopCalc.nstpl], chLabel , 4 ); 00658 StopCalc.chStopLabel2[StopCalc.nstpl][4] = 0; 00659 00660 /* wavelength of second line, may be absent and so zero - 00661 * we will use Hbeta if not specified */ 00662 StopCalc.StopLineWl2[StopCalc.nstpl] = 00663 (realnum)FFmtRead(chCard,&i, INPUT_LINE_LENGTH,&lgEOL); 00664 00665 /* line was entered, look for possible micron or cm label */ 00666 if( input.chCARDCAPS[i-1] == 'M' ) 00667 { 00668 /* microns */ 00669 StopCalc.StopLineWl2[StopCalc.nstpl] *= 1e4; 00670 } 00671 else if( input.chCARDCAPS[i-1] == 'C' ) 00672 { 00673 /* microns */ 00674 StopCalc.StopLineWl2[StopCalc.nstpl] *= 1e8; 00675 } 00676 } 00677 /* increment number of stop lines commands entered */ 00678 StopCalc.nstpl = MIN2(StopCalc.nstpl+1,MXSTPL-1); 00679 } 00680 00681 else if( nMatch("NTOT" , chCard ) && nMatch("ALIO" , chCard ) ) 00682 { 00683 /* this counter is incremented at end of conv_base - total number of 00684 * times conv base was called 00685 * this is a debugging aid - code aborts */ 00686 StopCalc.nTotalIonizStop = (long)a; 00687 } 00688 00689 /* oops! no keyword that we could find */ 00690 else 00691 { 00692 fprintf( ioQQQ, " I did not recognize a keyword on this STOP line, line image follows;\n" ); 00693 fprintf( ioQQQ, " \"%s\"\n Sorry.\n" , chCard); 00694 cdEXIT(EXIT_FAILURE); 00695 } 00696 return; 00697 }