cloudy  trunk
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
cddrive.cpp
Go to the documentation of this file.
1 /* This file is part of Cloudy and is copyright (C)1978-2017 by Gary J. Ferland and
2  * others. For conditions of distribution and use see copyright notice in license.txt */
3 /*cdDrive main routine to call cloudy under all circumstances) */
4 /*cdReasonGeo write why the model stopped and type of geometry on io file */
5 /*cdWarnings write all warnings entered into comment stack */
6 /*cdEms obtain the local emissivity for a line, for the last computed zone */
7 /*cdColm get the column density for a constituent */
8 /*cdLine get the predicted line intensity, also index for line in stack */
9 /*cdLine_ip get the predicted line intensity, using index for line in stack */
10 /*cdCautions print out all cautions after calculation, on arbitrary io unit */
11 /*cdTemp_last routine to query results and return temperature of last zone */
12 /*cdDepth_depth get depth structure from previous iteration */
13 /*cdTimescales returns thermal, recombination, and H2 formation timescales */
14 /*cdSurprises print out all surprises on arbitrary unit number */
15 /*cdNotes print stack of notes about current calculation */
16 /*cdPressure_last routine to query results and return pressure of last zone */
17 /*cdTalk tells the code whether to print results or be silent */
18 /*cdOutput redirect output to arbitrary file */
19 /*cdInput redirect input from arbitrary file */
20 /*cdRead routine to read in command lines when cloudy used as subroutine */
21 /*cdErrors produce summary of all warnings, cautions, etc, on arbitrary io unit */
22 /*cdIonFrac get ionization fractions for a constituent */
23 /*cdTemp get mean electron temperature for any element */
24 /*cdCooling_last routine to query results and return cooling of last zone */
25 /*cdHeating_last routine to query results and return heating of last zone */
26 /*cdEDEN_last return electron density of last zone */
27 /*cdNoExec call this routine to tell code not to actually execute */
28 /*cdDate - puts date of code into string */
29 /*cdVersion produces string that gives version number of the code */
30 /*cdExecTime any routine can call this, find the time [s] since cdInit was called */
31 /*cdPrintCommands( FILE *) prints all input commands into file */
32 /*cdDrive main routine to call cloudy under all circumstances) */
33 /*cdNwcns get the number of cautions and warnings, to tell if calculation is ok */
34 /*debugLine provides a debugging hook into the main line array */
35 /*cdEms_ip obtain the local emissivity for a line with known index */
36 /*cdnZone gets number of zones */
37 /*cdClosePunchFiles closes all the save files that have been used */
38 /*cdB21cm - returns B as measured by 21 cm */
39 /*cdPrtWL print line wavelengths in Angstroms in the standard format */
40 #include "cddefines.h"
41 #include "cddrive.h"
42 
43 #include "trace.h"
44 #include "conv.h"
45 #include "init.h"
46 #include "lines.h"
47 #include "pressure.h"
48 #include "dense.h"
49 #include "radius.h"
50 #include "struc.h"
51 #include "mole.h"
52 #include "elementnames.h"
53 #include "mean.h"
54 #include "phycon.h"
55 #include "called.h"
56 #include "parse.h"
57 #include "input.h"
58 #include "taulines.h"
59 #include "version.h"
60 #include "thermal.h"
61 #include "grid.h"
62 #include "timesc.h"
63 #include "cloudy.h"
64 #include "warnings.h"
65 #include "broke.h"
66 #include "iso.h"
67 #include "save.h"
68 #include "rfield.h"
69 #include "lines_service.h"
70 #include "service.h"
71 #include "generic_state.h"
72 
73 /*************************************************************************
74  *
75  * cdDrive - main routine to call cloudy - returns 0 if all ok, 1 if problems
76  *
77  ************************************************************************/
78 
79 int cdDrive()
80 {
81  bool lgBAD;
82 
83  DEBUG_ENTRY( "cdDrive()" );
84  /*********************************
85  * main routine to call cloudy *
86  *********************************/
87 
88  /* this is set false when code loaded, set true when cdInit called,
89  * this is check that cdInit was called first */
90  if( !lgcdInitCalled )
91  {
92  printf(" cdInit was not called first - this must be the first call.\n");
94  }
95 
96  if( trace.lgTrace )
97  {
98  fprintf( ioQQQ,
99  "cdDrive: lgOptimr=%1i lgVaryOn=%1i lgNoVary=%1i input.nSave:%li\n",
101  }
102 
103  /* should we call cloudy, or the optimization driver?
104  * possible to have VARY on line without OPTIMIZE being set
105  * lgNoVary set with "no optimize" command */
107  optimize.lgVaryOn = true;
108  else
109  optimize.lgVaryOn = false;
110 
111  /* set up the frequency mesh, the SET CONTINUUM RESOLUTION factor was already parsed in cdRead() */
112  /* the bool 'false' inidicates that the cell for the unit test is the highest entry in the regular mesh */
113  rfield.InitMesh(false);
115  /* there must be a cell above nflux for us to pass unity through the vol integrator */
116  /*>>chng 04 oct 10, from nflux = nupper to nupper-1 since vectors must malloc to nupper, but
117  * will address [nflux] for unit continuum test */
120 
121  /* one time initialization of core load - returns if already called
122  * called here rather than in cdInit since at this point we know if
123  * single sim or grid */
124  InitCoreload();
125 
126  if( optimize.lgVaryOn )
127  {
128  /* this branch called if optimizing or grid calculation */
129  if( trace.lgTrace )
130  fprintf( ioQQQ, "cdDrive: calling grid_do\n");
131  /* option to drive optimizer set if OPTIMIZE was in input stream */
132  lgBAD = grid_do();
133  }
134  else
135  {
136  if( trace.lgTrace )
137  fprintf( ioQQQ, "cdDrive: calling cloudy\n");
138 
139  /* optimize did not occur, only compute one model, call cloudy */
140  lgBAD = cloudy();
141  }
142 
143  /* reset flag saying that cdInit has not been called */
144  lgcdInitCalled = false;
145 
146  if( lgAbort || lgBAD )
147  {
148  if( trace.lgTrace )
149  fprintf( ioQQQ, "cdDrive: returning failure during call. \n");
150  /* lgAbort set true if something wrong, so return lgBAD false. */
151  return 1;
152  }
153  else
154  {
155  /* everything is ok, return 0 */
156  return 0;
157  }
158 }
159 
160 
161 /*************************************************************************
162  *
163  * cdReasonGeo write why the model stopped and type of geometry on io file
164  *
165  ************************************************************************/
166 
167 
168 /*cdReasonGeo write why the model stopped and type of geometry on io file */
169 void cdReasonGeo(FILE * ioOUT)
170 {
171 
172  DEBUG_ENTRY( "cdReasonGeo()" );
173 
174  /*this is the reason the calculation stopped*/
175  fprintf( ioOUT, "%s", warnings.chRgcln[0] );
176  fprintf( ioOUT , "\n" );
177  /* this is the geometry */
178  fprintf( ioOUT, "%s", warnings.chRgcln[1] );
179  fprintf( ioOUT , "\n" );
180  return;
181 }
182 
183 
184 /*************************************************************************
185  *
186  * cdWarnings write all warnings entered into comment stack
187  *
188  ************************************************************************/
189 
190 /*cdWarnings write all warnings entered into comment stack */
191 
192 void cdWarnings(FILE *ioPNT )
193 {
194  long int i;
195 
196  DEBUG_ENTRY( "cdWarnings()" );
197 
198  if( warnings.nwarn > 0 )
199  {
200  for( i=0; i < warnings.nwarn; i++ )
201  {
202  /* these are all warnings that were entered in comment */
203  fprintf( ioPNT, "%s", warnings.chWarnln[i] );
204  fprintf( ioPNT, "\n" );
205  }
206  }
207 
208  return;
209 }
210 
211 
212 /*************************************************************************
213  *
214  * cdCautions print out all cautions after calculation, on arbitrary io unit
215  *
216  ************************************************************************/
217 
218 /*cdCautions print out all cautions after calculation, on arbitrary io unit */
219 
220 void cdCautions(FILE * ioOUT)
221 {
222  long int i;
223 
224  DEBUG_ENTRY( "cdCautions()" );
225 
226  if( warnings.ncaun > 0 )
227  {
228  for( i=0; i < warnings.ncaun; i++ )
229  {
230  fprintf( ioOUT, "%s", warnings.chCaunln[i] );
231  fprintf( ioOUT, "\n" );
232  }
233  }
234  return;
235 }
236 
237 /*************************************************************************
238  *
239  * cdTimescales returns thermal, recombination, and H2 formation timescales
240  *
241  ************************************************************************/
242 
244  /* the thermal cooling timescale */
245  double *TTherm ,
246  /* the hydrogen recombination timescale */
247  double *THRecom ,
248  /* the H2 formation timescale */
249  double *TH2 )
250 {
251 
252  DEBUG_ENTRY( "cdTimescales()" );
253 
254  /* these were all evaluated in AgeCheck, which was called by PrtComment */
255 
256  /* thermal or cooling timescale */
257  *TTherm = timesc.time_therm_long;
258 
259  /* the hydrogen recombination timescale */
260  *THRecom = timesc.time_Hrecom_long;
261 
262  /* longer of the the H2 formation and destruction timescales */
264  return;
265 }
266 
267 
268 /*************************************************************************
269  *
270  * cdSurprises print out all surprises on arbitrary unit number
271  *
272  ************************************************************************/
273 
274 /*cdSurprises print out all surprises on arbitrary unit number */
275 
276 void cdSurprises(FILE * ioOUT)
277 {
278  long int i;
279 
280  DEBUG_ENTRY( "cdSurprises()" );
281 
282  if( warnings.nbang > 0 )
283  {
284  for( i=0; i < warnings.nbang; i++ )
285  {
286  fprintf( ioOUT, "%s\n", warnings.chBangln[i] );
287  }
288  }
289 
290  if ( broke.lgPrintFixits )
291  {
292  fprintf (ioOUT, "\nActive fixits for this run\n");
293  for (vector<string>::iterator it = FixitList::Inst().list.begin();
294  it != FixitList::Inst().list.end(); ++it)
295  {
296  fprintf(ioOUT,"%s\n",it->c_str());
297  }
298  fprintf (ioOUT, "\n");
299  }
300 
301  return;
302 }
303 
304 
305 /*************************************************************************
306  *
307  * cdNotes print stack of notes about current calculation
308  *
309  ************************************************************************/
310 
311 /*cdNotes print stack of notes about current calculation */
312 
313 void cdNotes(FILE * ioOUT)
314 {
315  long int i;
316 
317  DEBUG_ENTRY( "cdNotes()" );
318 
319  if( warnings.nnote > 0 )
320  {
321  for( i=0; i < warnings.nnote; i++ )
322  {
323  fprintf( ioOUT, "%s", warnings.chNoteln[i] );
324  fprintf( ioOUT, "\n" );
325  }
326  }
327  return;
328 }
329 
330 /*************************************************************************
331  *
332  * cdCooling_last routine to query results and return cooling of last zone
333  *
334  ************************************************************************/
335 
336 /*cdCooling_last routine to query results and return cooling of last zone */
337 double cdCooling_last() /* return cooling for last zone */
338 {
339  return thermal.ctot;
340 }
341 
342 /*************************************************************************
343  *
344  * cdVersion - puts version number of code into string
345  * incoming string must have sufficient length and will become null
346  * terminated string
347  *
348  ************************************************************************/
349 
350 void cdVersion(char chString[])
351 {
352  strcpy( chString , t_version::Inst().chVersion );
353  return;
354 }
355 
356 /*************************************************************************
357  *
358  * cdDate - puts date of code into string
359  * incoming string must have at least 8 char and will become null
360  * terminated string
361  *
362  ************************************************************************/
363 
364 /* cdDate - puts date of code into string */
365 void cdDate(char chString[])
366 {
367  strcpy( chString , t_version::Inst().chDate );
368  return;
369 }
370 
371 
372 /*************************************************************************
373  *
374  * cdHeating_last routine to query results and return heating of last zone
375  *
376  ************************************************************************/
377 
378 /*cdHeating_last routine to query results and return heating of last zone */
379 
380 double cdHeating_last() /* return heating for last zone */
381 {
382  return thermal.htot;
383 }
384 
385 
386 /*************************************************************************
387  *
388  * cdEDEN_last return electron density of last zone
389  *
390  ************************************************************************/
391 
392 /*cdEDEN_last return electron density of last zone */
393 
394 double cdEDEN_last() /* return electron density for last zone */
395 {
396  return dense.eden;
397 }
398 
399 /*************************************************************************
400  *
401  * cdNoExec call this routine to tell code not to actually execute
402  *
403  ************************************************************************/
404 
405 /*cdNoExec call this routine to tell code not to actually execute */
406 #include "noexec.h"
407 
408 void cdNoExec()
409 {
410 
411  DEBUG_ENTRY( "cdNoExec()" );
412 
413  /* option to read in all input quantiles and NOT execute the actual model
414  * only check on input parameters - set by calling cdNoExec */
415  noexec.lgNoExec = true;
416 
417  return;
418 }
419 
420 
421 /*************************************************************************
422  *
423  * cdSetExecTime routine to initialize variables keeping track of time at start of calculation
424  *
425  ************************************************************************/
426 
427 /* set to false initially, then to true when cdSetExecTime() is called to
428  * initialize the clock */
429 static bool lgCalled=false;
430 
431 #if defined(_MSC_VER)
432 /* _MSC_VER branches assume getrusage isn't implemented by MS */
433 struct timeval {
434  long tv_sec; /* seconds */
435  long tv_usec; /* microseconds */
436 };
437 #else
438 #include <sys/time.h>
439 #include <sys/resource.h>
440 #endif
441 
442 /* will be used to save initial time */
443 static struct timeval before;
444 
445 /* cdClock stores time since arbitrary datum in clock_dat */
446 STATIC void cdClock(struct timeval *clock_dat)
447 {
448  DEBUG_ENTRY( "cdClock()" );
449 
450 /* >>chng 06 sep 2 rjrw: use long recurrence, fine grain UNIX clock *
451  * -- maintain system dependences in a single routine */
452 #if defined(_MSC_VER)
453  clock_t clock_val;
454  /* >>chng 05 dec 21, from above to below due to negative exec times */
455  /*return (double)(clock() - before) / (double)CLOCKS_PER_SEC;*/
456  clock_val = clock();
457  clock_dat->tv_sec = clock_val/CLOCKS_PER_SEC;
458  clock_dat->tv_usec = 1000000*(clock_val-(clock_dat->tv_sec*CLOCKS_PER_SEC))/CLOCKS_PER_SEC;
459  /*>>chng 06 oct 05, this produced very large number, time typically 50% too long
460  clock_dat->tv_usec = 0;*/
461 #else
462  struct rusage rusage;
463  if(getrusage(RUSAGE_SELF,&rusage) != 0)
464  {
465  fprintf( ioQQQ, "DISASTER cdClock called getrusage with invalid arguments.\n" );
466  fprintf( ioQQQ, "Sorry.\n" );
468  }
469  clock_dat->tv_sec = rusage.ru_utime.tv_sec;
470  clock_dat->tv_usec = rusage.ru_utime.tv_usec;
471 #endif
472 
473 }
474 /* cdSetExecTime is called by cdInit when everything is initialized,
475  * so that every time cdExecTime is called the elapsed time is returned */
477 {
478  cdClock(&before);
479  lgCalled = true;
480 }
481 /* cdExecTime returns the elapsed time cpu time (sec) that has elapsed
482  * since cdInit called cdSetExecTime.*/
483 double cdExecTime()
484 {
485  DEBUG_ENTRY( "cdExecTime()" );
486 
487  struct timeval clock_dat;
488  /* check that we were properly initialized */
489  if( lgCalled)
490  {
491  cdClock(&clock_dat);
492  /*fprintf(ioQQQ,"\n DEBUG sec %.2e usec %.2e\n",
493  (double)(clock_dat.tv_sec-before.tv_sec),
494  1e-6*(double)(clock_dat.tv_usec-before.tv_usec));*/
495  return (double)(clock_dat.tv_sec-before.tv_sec)+1e-6*(double)(clock_dat.tv_usec-before.tv_usec);
496  }
497  else
498  {
499  /* this is a big problem, we were asked for the elapsed time but
500  * the timer was not initialized by calling SetExecTime */
501  fprintf( ioQQQ, "DISASTER cdExecTime was called before SetExecTime, impossible.\n" );
502  fprintf( ioQQQ, "Sorry.\n" );
504  }
505 }
506 
507 // Maximum memory used, in kB
508 long cdMemory()
509 {
510 #if defined(MSC_VER)
511  return 0L;
512 #else
513  struct rusage usage;
514  if(getrusage(RUSAGE_SELF,&usage) != 0)
515  {
516  fprintf( ioQQQ, "DISASTER cdClock called getrusage with invalid arguments.\n" );
517  fprintf( ioQQQ, "Sorry.\n" );
519  }
520  return usage.ru_maxrss;
521 #endif
522 }
523 
524 /*************************************************************************
525  *
526  * cdPrintCommands prints all input commands into file
527  *
528  ************************************************************************/
529 
530 /* cdPrintCommands( FILE *)
531  * prints all input commands into file */
532 void cdPrintCommands( FILE * ioOUT )
533 {
534  long int i;
535  fprintf( ioOUT, " Input commands follow:\n" );
536  fprintf( ioOUT, "c ======================\n" );
537 
538  for( i=0; i <= input.nSave; i++ )
539  {
540  fprintf( ioOUT, "%s\n", input.chCardSav[i] );
541  }
542  fprintf( ioOUT, "c ======================\n" );
543 }
544 
545 
546 /*************************************************************************
547  *
548  * cdEmis obtain the local emissivity for a line, for the last computed zone
549  *
550  ************************************************************************/
551 
555 void cdEmis(
556  const char *chLabel,
558  /* the vol emissivity of this line in last computed zone */
559  double *emiss ,
560  // intrinsic or emergent
561  bool lgEmergent )
562 {
563  DEBUG_ENTRY( "cdEmis()" );
564 
565  long ipobs = LineSave.findline(chLabel, wavelength);
566  if (ipobs)
567  cdEmis(&LineSave.lines[ipobs],emiss,lgEmergent);
568  else
569  *emiss = 0.0;
570  return;
571 }
572 
574  /* index of the line in the stack */
575  long int ipLine,
576  /* the vol emissivity of this line in last computed zone */
577  double *emiss ,
578  // intrinsic or emergent
579  bool lgEmergent )
580 {
581  DEBUG_ENTRY( "cdEmis_ip()" );
582 
583  /* returns the emissivity in a line - implements save lines structure
584  * this version uses previously stored line index to save speed */
585  ASSERT( ipLine >= 0 && ipLine < LineSave.nsum );
586  cdEmis(&LineSave.lines[ipLine],emiss,lgEmergent);
587 }
588 
589 /*************************************************************************
590  *
591  * cdColm get the column density for a constituent - 0 return if ok, 1 if problems
592  *
593  ************************************************************************/
594 
595 int cdColm(
596  /* return value is zero if all ok, 1 if errors happened */
597  /* 4-char + eol string that is first
598  * 4 char of element name as spelled by Cloudy, upper or lower case */
599  const char *chLabel,
600 
601  /* integer stage of ionization, 1 for atom, 2 for A+, etc,
602  * 0 is special flag for CO, H2, OH, or excited state */
603  long int ion,
604 
605  /* the column density derived by the code [cm-2] */
606  double *theocl )
607 {
608  long int nelem;
609  /* use following to store local image of character strings */
610  char chLABEL_CAPS[NCHLAB];
611 
612  DEBUG_ENTRY( "cdColm()" );
613  *theocl = 0.;
614 
615  if( strlen(chLabel) > NCHLAB-1 )
616  {
617  fprintf( ioQQQ, " PROBLEM cdColm called with insane chLabel (between quotes) \"%s\", must be no more than %d characters long.\n",
618  chLabel, NCHLAB-1 );
619  return 1;
620  }
621 
622  strcpy( chLABEL_CAPS, chLabel );
623 
624  /* convert element label to all caps */
625  caps(chLABEL_CAPS);
626  trimTrailingWhiteSpace( chLABEL_CAPS );
627 
628  genericState gs;
629 
630  /* zero ionization stage has special meaning. The quantities recognized are
631  * the molecules, "H2 ", "OH ", "CO ", etc
632  * "CII*" excited state C+ */
633  if( ion < 0 )
634  {
635  fprintf( ioQQQ, " PROBLEM cdColm called with insane ion, =%li\n",
636  ion );
637  return 1;
638  }
639 
640  else if( ion == 0 )
641  {
642  /* this case molecular column density */
643  /* want the *total* molecular hydrogen H2 column density */
644  if( strcmp( chLABEL_CAPS , "H2" )==0 )
645  {
646  *theocl = findspecieslocal("H2")->column + findspecieslocal("H2*")->column;
647  }
648  /* H2g - ground H2 column density */
649  else if( strcmp( chLABEL_CAPS , "H2G" )==0 )
650  {
651  gs.sp = findspecieslocal("H2");
652  *theocl = column(gs);
653  }
654  /* H2* - excited H2 - column density */
655  else if( strcmp( chLABEL_CAPS , "H2*" )==0 )
656  {
657  gs.sp = findspecieslocal("H2*");
658  *theocl = column(gs);
659  }
660  /* special option, "H2vJ" */
661  else if( strncmp(chLABEL_CAPS , "H2" , 2 ) == 0 &&
662  isdigit(chLABEL_CAPS[2]) && isdigit(chLABEL_CAPS[3]) )
663  {
664  long int iVib = chLABEL_CAPS[2] - '0';
665  long int iRot = chLABEL_CAPS[3] - '0';
666  if( iVib<0 || iRot < 0 )
667  {
668  fprintf( ioQQQ, " PROBLEM cdColm called with insane v,J for H2=\"%s\" caps=\"%s\"\n",
669  chLabel , chLABEL_CAPS );
670  return 1;
671  }
672  *theocl = cdH2_colden( iVib , iRot );
673  }
674 
675  /* ===========================================================*/
676  /* end special case molecular column densities, start special cases
677  * excited state column densities */
678  else if( strcmp( chLABEL_CAPS , "HE1*" )==0 )
679  {
680  if (dense.lgElmtOn[ipHELIUM])
681  {
683  }
684  *theocl = column(gs);
685  }
686  /* general case */
687  else
688  {
689  vector<genericState> v = matchGeneric(chLabel,false);
690  *theocl = 0.;
691  for (size_t i=0; i<v.size(); ++i)
692  {
693  *theocl += column(v[i]);
694  }
695  }
696  }
697  else
698  {
699  /* this case, ionization stage of some element */
700  /* find which element this is */
701  nelem = 0;
702  while( nelem < LIMELM &&
703  strncmp(chLABEL_CAPS,elementnames.chElementNameShort[nelem],4) != 0 )
704  {
705  ++nelem;
706  }
707 
708  /* this is true if we have one of the first 30 elements in the label,
709  * nelem is on C scale */
710  if( nelem < LIMELM )
711  {
712 
713  /* sanity check - does this ionization stage exist?
714  * max2 is to pick up H2 as H 3 */
715  if( ion > MAX2(3,nelem + 2) )
716  {
717  fprintf( ioQQQ,
718  " cdColm asked to return ionization stage %ld for element \"%s\" but this is not physical.\n",
719  ion, chLabel );
720  return 1;
721  }
722 
723  /* the column density, ion is on physics scale, but means are on C scale */
724  *theocl = mean.xIonMean[0][nelem][ion-1][0];
725  /*>>chng 06 jan 23, div by factor of two
726  * special case of H2 when being tricked as H 3 - this stores 2H_2 so that
727  * the fraction of H in H0 and H+ is correct - need to remove this extra
728  * factor of two here */
729  if( nelem==ipHYDROGEN && ion==3 )
730  *theocl /= 2.;
731  }
732  else
733  {
734  fprintf( ioQQQ,
735  " cdColm did not understand this combination of label \"%s\" and ion %4ld.\n",
736  chLabel, ion );
737  return 1;
738  }
739  }
740  return 0;
741 }
742 
743 
744 /*************************************************************************
745  *
746  *cdErrors produce summary of all warnings, cautions, etc, on arbitrary io unit
747  *
748  ************************************************************************/
749 
750 void cdErrors(FILE *ioOUT)
751 {
752  long int nc,
753  nn,
754  npe,
755  ns,
756  nte,
757  nw ,
758  nIone,
759  nEdene;
760  bool lgAbort_loc;
761 
762  DEBUG_ENTRY( "cdErrors()" );
763 
764  /* first check for number of warnings, cautions, etc */
765  cdNwcns(&lgAbort_loc,&nw,&nc,&nn,&ns,&nte,&npe, &nIone, &nEdene );
766 
767  /* only say something is one of these problems is nonzero */
768  if( nw || nc || nte || npe || nIone || nEdene || lgAbort_loc )
769  {
770  /* say the title of the model */
771  fprintf( ioOUT, "%75.75s\n", input.chTitle );
772 
773  if( lgAbort_loc )
774  fprintf(ioOUT," Calculation ended with abort!\n");
775 
776  /* print warnings on the io unit */
777  if( nw != 0 )
778  {
779  cdWarnings(ioOUT);
780  }
781 
782  /* print cautions on the io unit */
783  if( nc != 0 )
784  {
785  cdCautions(ioOUT);
786  }
787 
788  if( nte != 0 )
789  {
790  fprintf( ioOUT , "Te failures=%4ld\n", nte );
791  }
792 
793  if( npe != 0 )
794  {
795  fprintf( ioOUT , "Pressure failures=%4ld\n", npe );
796  }
797 
798  if( nIone != 0 )
799  {
800  fprintf( ioOUT , "Ionization failures=%4ld\n", nte );
801  }
802 
803  if( nEdene != 0 )
804  {
805  fprintf( ioOUT , "Electron density failures=%4ld\n", npe );
806  }
807  }
808  return;
809 }
810 
811 /*************************************************************************
812  *
813  *cdDepth_depth get depth structure from previous iteration
814  *
815  ************************************************************************/
816 void cdDepth_depth( double cdDepth[] )
817 {
818  long int nz;
819 
820  DEBUG_ENTRY( "cdDepth_depth()" );
821 
822  for( nz = 0; nz<nzone; ++nz )
823  {
824  cdDepth[nz] = struc.depth[nz];
825  }
826  return;
827 }
828 
829 /*************************************************************************
830  *
831  *cdPressure_depth routine to query results and return pressure of last iteration
832  *
833  ************************************************************************/
834 
835 /*
836  * cdPressure_depth
837  * This returns the pressure and its constituents for the last iteration.
838  * space was allocated in the calling routine for the vectors -
839  * before calling this, cdnZone should have been called to get the number of
840  * zones, then space allocated for the arrays */
842  /* total pressure, all forms*/
843  double TotalPressure[],
844  /* gas pressure */
845  double GasPressure[],
846  /* line radiation pressure */
847  double RadiationPressure[])
848 {
849  long int nz;
850 
851  DEBUG_ENTRY( "cdPressure_depth()" );
852 
853  for( nz = 0; nz<nzone; ++nz )
854  {
855  TotalPressure[nz] = struc.pressure[nz];
856  GasPressure[nz] = struc.GasPressure[nz];
857  RadiationPressure[nz] = struc.pres_radiation_lines_curr[nz];
858  }
859  return;
860 }
861 
862 /*************************************************************************
863  *
864  *cdPressure_last routine to query results and return pressure of last zone
865  *
866  ************************************************************************/
867 
869  double *PresTotal, /* total pressure, all forms, for the last computed zone*/
870  double *PresGas, /* gas pressure */
871  double *PresRad) /* line radiation pressure */
872 {
873 
874  DEBUG_ENTRY( "cdPressure_last()" );
875 
876  *PresGas = pressure.PresGasCurr;
878  *PresTotal = pressure.PresTotlCurr;
879  return;
880 }
881 
882 /*************************************************************************
883  *
884  *cdnZone gets number of zones
885  *
886  ************************************************************************/
887 
888 /* returns number of zones */
889 long int cdnZone()
890 {
891  return nzone;
892 }
893 
894 /*************************************************************************
895  *
896  *cdTemp_last routine to query results and return temperature of last zone
897  *
898  ************************************************************************/
899 
900 
901 double cdTemp_last()
902 {
903  return phycon.te;
904 }
905 
906 /*************************************************************************
907  *
908  *cdIonFrac get ionization fractions for a constituent
909  *
910  ************************************************************************/
911 
913  /* four char string, null terminated, giving the element name */
914  const char *chLabel,
915  /* IonStage is ionization stage, 1 for atom, up to N+1 where N is atomic number,
916  * 0 says special case */
917  long int IonStage,
918  /* will be fractional ionization */
919  double *fracin,
920  /* how to weight the average, must be "VOLUME" or "RADIUS" */
921  const char *chWeight ,
922  /* if true then weighting also has electron density, if false then only volume or radius */
923  bool lgDensity )
924  /* return value is 0 if element was found, non-zero if failed */
925 {
926  long int ip,
927  ion, /* used as index within aaa vector*/
928  nelem;
929  realnum aaa[LIMELM + 1];
930  /* use following to store local image of character strings */
931  char chCARD[INPUT_LINE_LENGTH];
932 
933  DEBUG_ENTRY( "cdIonFrac()" );
934 
935  strcpy( chCARD, chWeight );
936  /* make sure chWeight is all caps */
937  caps(chCARD);/* convert to caps */
938 
939  int dim;
940  if( strcmp(chCARD,"RADIUS") == 0 )
941  dim = 0;
942  else if( strcmp(chCARD,"AREA") == 0 )
943  dim = 1;
944  else if( strcmp(chCARD,"VOLUME") == 0 )
945  dim = 2;
946  else
947  {
948  fprintf( ioQQQ, " cdIonFrac: chWeight=%6.6s makes no sense to me, valid options are RADIUS, AREA, and VOLUME\n",
949  chWeight );
950  *fracin = 0.;
951  return 1;
952  }
953 
954  /* first ensure that chLabel is all caps */
955  strcpy( chCARD, chLabel );
956  /* make sure chLabel is all caps */
957  caps(chCARD);/* convert to caps */
958 
959  if( IonStage==0 )
960  {
961  /* special case */
962  if( strcmp(chCARD,"H2 " ) == 0 )
963  {
964  /* this will be request for H2, treated as third stage of hydrogen */
965  nelem = 0;
966  IonStage = 3;
967  }
968  else
969  {
970  fprintf( ioQQQ, " cdIonFrac: ion stage of zero and element %s makes no sense to me\n",
971  chCARD );
972  *fracin = 0.;
973  return 1;
974  }
975  }
976 
977  else
978  {
979  /* find which element this is */
980  nelem = 0;
981  while( nelem < LIMELM &&
982  strcmp(chCARD,elementnames.chElementNameShort[nelem]) != 0 )
983  {
984  ++nelem;
985  }
986  }
987 
988  /* if element not recognized and above loop falls through, nelem is LIMELM */
989  if( nelem >= LIMELM )
990  {
991  fprintf( ioQQQ, " cdIonFrac called with unknown element chLabel, =%4.4s\n",
992  chLabel );
993  return 1;
994  }
995 
996  /* sanity check - does this ionization stage exist?
997  * IonStage is on spectroscopic scale and nelem is on C scale */
998 
999  /* ion will be used as pointer within the aaa array that contains average values,
1000  * convert to C scale */
1001  ion = IonStage - 1;
1002 
1003  if( (ion > nelem+1 || ion < 0 ) && !(nelem==ipHYDROGEN&&ion==2))
1004  {
1005  fprintf( ioQQQ, " cdIonFrac asked to return ionization stage %ld for element %4.4s but this is not physical.\n",
1006  IonStage, chLabel );
1007  *fracin = -1.;
1008  return 1;
1009  }
1010 
1011  /* get average, aaa is filled in from 0 */
1012  /* aaa is dim'd LIMELM+1 so largest argument is LIMELM
1013  * 'i' means ionization, not temperature */
1014  /* last argument says whether to include electron density */
1015  /* MeanIon uses c scale for nelem */
1016  mean.MeanIon('i',nelem,dim,&ip,aaa,lgDensity);
1017  *fracin = exp10((double)aaa[ion]);
1018 
1019  /* we succeeded - say so */
1020  return 0;
1021 }
1022 
1023 /*************************************************************************
1024  *
1025  * debugLine provides a debugging hook into the main line array
1026  *
1027  ************************************************************************/
1028 
1029  /* debugLine provides a debugging hook into the main line array
1030  * loops over whole array and finds every line that matches length,
1031  * the wavelength, the argument to the function
1032  * put breakpoint inside if test
1033  * return value is number of matches, also prints all matches*/
1035 {
1036  long j, kount;
1037  realnum errorwave;
1038 
1039  kount = 0;
1040 
1041  /* get the error associated with specified significant figures */
1042  errorwave = WavlenErrorGet( wavelength, LineSave.sig_figs );
1043 
1044  for( j=0; j < LineSave.nsum; j++ )
1045  {
1046  /* check wavelength and chLabel for a match */
1047  /* if( fabs(LineSave.lines[j].wavelength- wavelength)/MAX2(DELTA,wavelength) < errorwave ) */
1048  if( fabs(LineSave.lines[j].wavelength()-wavelength) < errorwave )
1049  {
1050  LineSave.lines[j].prt(stdout);
1051  printf("\n");
1052  ++kount;
1053  }
1054  }
1055  printf(" hits = %li\n", kount );
1056  return kount;
1057 }
1058 
1059 /*************************************************************************
1060  *
1061  *cdLine get the predicted line intensity, also index for line in stack
1062  *
1063  ************************************************************************/
1064 
1065 // returns array index for line in array stack if we found the line,
1066 // return negative of total number of lines as debugging aid if line not found
1067 // return <0 if problems
1068 // emergent or intrinsic not specified - use intrinsic
1069 long int cdLine(
1070  const char *chLabel,
1071  /* wavelength of line in angstroms, not format printed by code */
1073  /* linear intensity relative to normalization line*/
1074  double *relint,
1075  /* log of luminosity or intensity of line */
1076  double *absint )
1077 {
1078  DEBUG_ENTRY( "cdLine()" );
1079  long int i = cdLine( chLabel , wavelength , relint , absint, 0 );
1080  return i;
1081 }
1082 long int cdLine(
1083  const char *chLabel,
1084  /* wavelength of line in angstroms, not format printed by code */
1086  /* linear intensity relative to normalization line*/
1087  double *relint,
1088  /* log of luminosity or intensity of line */
1089  double *absint ,
1090  // 0 is intrinsic,
1091  // 1 emergent
1092  // 2 is intrinsic cumulative,
1093  // 3 emergent cumulative
1094  int LineType )
1095 {
1096  DEBUG_ENTRY( "cdLine()" );
1097 
1098  *absint = 0.;
1099  *relint = 0.;
1100 
1101  long ipobs = LineSave.findline(chLabel, wavelength);
1102  if (ipobs > 0)
1103  cdLine_ip(ipobs,relint,absint,LineType);
1104  // printf("%s\t %g\t ip = %ld\t absint = %g\n", chLabel, wavelength, ipobs, *absint);
1105 
1106  return ipobs;
1107 }
1108 
1109 
1110 
1111 /*cdLine_ip get the predicted line intensity, using index for line in stack */
1112 void cdLine_ip(long int ipLine,
1113  /* linear intensity relative to normalization line*/
1114  double *relint,
1115  /* log of luminosity or intensity of line */
1116  double *absint )
1117 {
1118 
1119  DEBUG_ENTRY( "cdLine_ip()" );
1120  cdLine_ip( ipLine , relint , absint , 0 );
1121 }
1122 void cdLine_ip(long int ipLine,
1123  /* linear intensity relative to normalization line*/
1124  double *relint,
1125  /* log of luminosity or intensity of line */
1126  double *absint ,
1127  // 0 is intrinsic,
1128  // 1 emergent
1129  // 2 is intrinsic cumulative,
1130  // 3 emergent cumulative
1131  int LineType )
1132 {
1133 
1134  DEBUG_ENTRY( "cdLine_ip()" );
1135 
1136  *relint = 0.;
1137  *absint = 0.;
1138 
1139  if( LineType<0 || LineType>3 )
1140  {
1141  fprintf( ioQQQ, " PROBLEM cdLine_ip called with insane nLineType - it must be between 0 and 3.\n");
1142  return;
1143  }
1144 
1145  /* this is zero when cdLine called with cdNoExec called too */
1146  if( LineSave.nsum == 0 )
1147  {
1148  return;
1149  }
1150  ASSERT( LineSave.ipNormWavL >= 0);
1151  ASSERT( LineSave.nsum > 0);
1152 
1153  /* does the normalization line have a positive intensity */
1154  if( LineSave.lines[LineSave.ipNormWavL].SumLine(LineType) > 0. )
1155  *relint = LineSave.lines[ipLine].SumLine(LineType)/
1156  LineSave.lines[LineSave.ipNormWavL].SumLine(LineType)*
1158 
1159  /* return log of current line intensity if it is positive */
1160  if( LineSave.lines[ipLine].SumLine(LineType) > 0. )
1161  *absint = LineSave.lines[ipLine].SumLine(LineType) *
1163 
1164  return;
1165 }
1166 
1167 
1168 
1169 /*************************************************************************
1170  *
1171  *cdNwcns get the number of cautions and warnings, to tell if calculation is ok
1172  *
1173  ************************************************************************/
1174 
1175 void cdNwcns(
1176  /* abort status, this better be false */
1177  bool *lgAbort_ret ,
1178  /* the number of warnings, cautions, notes, and surprises */
1179  long int *NumberWarnings,
1180  long int *NumberCautions,
1181  long int *NumberNotes,
1182  long int *NumberSurprises,
1183  /* the number of temperature convergence failures */
1184  long int *NumberTempFailures,
1185  /* the number of pressure convergence failures */
1186  long int *NumberPresFailures,
1187  /* the number of ionization convergence failures */
1188  long int *NumberIonFailures,
1189  /* the number of electron density convergence failures */
1190  long int *NumberNeFailures )
1191 {
1192 
1193  DEBUG_ENTRY( "cdNwcns()" );
1194 
1195  /* this would be set true if code ended with abort - very very bad */
1196  *lgAbort_ret = lgAbort;
1197  /* this sub is called after comment, to find the number of various comments */
1198  *NumberWarnings = warnings.nwarn;
1199  *NumberCautions = warnings.ncaun;
1200  *NumberNotes = warnings.nnote;
1201  *NumberSurprises = warnings.nbang;
1202 
1203  /* these are counters that were incremented during convergence failures */
1204  *NumberTempFailures = conv.nTeFail;
1205  *NumberPresFailures = conv.nPreFail;
1206  *NumberIonFailures = conv.nIonFail;
1207  *NumberNeFailures = conv.nNeFail;
1208  return;
1209 }
1210 
1211 void cdOutput( const char* filename, const char *mode )
1212 {
1213  DEBUG_ENTRY( "cdOutput()" );
1214 
1215  if( ioQQQ != stdout && ioQQQ != NULL )
1216  fclose(ioQQQ);
1217  FILE *fp = stdout;
1218  if( *filename != '\0' )
1219  fp = open_data( filename, mode, AS_LOCAL_ONLY );
1220  save.chOutputFile = filename;
1221  ioQQQ = fp;
1222 }
1223 
1224 void cdInput( const char* filename, const char *mode )
1225 {
1226  DEBUG_ENTRY( "cdInput()" );
1227 
1228  if( ioStdin != stdin && ioStdin != NULL )
1229  fclose(ioStdin);
1230  FILE *fp = stdin;
1231  if( *filename != '\0' )
1232  fp = open_data( filename, mode, AS_LOCAL_ONLY );
1233  ioStdin = fp;
1234 }
1235 
1236 /*************************************************************************
1237  *
1238  * cdTalk tells the code whether to print results or be silent
1239  *
1240  ************************************************************************/
1241 
1242 void cdTalk(bool lgTOn)
1243 {
1244 
1245  DEBUG_ENTRY( "cdTalk()" );
1246 
1247  /* MPI talking rules must be obeyed, otherwise loss of output may result */
1248  called.lgTalk = lgTOn && cpu.i().lgMPI_talk();
1249  /* has talk been forced off? */
1250  called.lgTalkForcedOff = !lgTOn;
1251  return;
1252 }
1253 
1254 /*cdB21cm - returns B as measured by 21 cm */
1255 double cdB21cm()
1256 {
1257  double ret;
1258 
1259  DEBUG_ENTRY( "cdB21cm()" );
1260 
1261  // return average over radius
1262  if( mean.TempB_HarMean[0][1] > SMALLFLOAT )
1263  {
1264  ret = mean.TempB_HarMean[0][0]/mean.TempB_HarMean[0][1];
1265  }
1266  else
1267  {
1268  ret = 0.;
1269  }
1270  return ret;
1271 }
1272 
1273 /*************************************************************************
1274  *
1275  * cdTemp get mean electron temperature for any element
1276  *
1277  ************************************************************************/
1278 
1279 /* This routine finds the mean electron temperature for any ionization stage
1280  * It returns 0 if it could find the species, 1 if it could not find the species.
1281  * The first argument is a null terminated 4 char string that gives the element
1282  * name as spelled by Cloudy.
1283  * The second argument is ion stage, 1 for atom, 2 for first ion, etc
1284  * This third argument will be returned as result,
1285  * Last parameter is either "RADIUS", "AREA", or "VOLUME" to give weighting
1286  *
1287  * if the ion stage is zero then the element label will have a special meaning.
1288  * The string "21CM" will return the 21 cm temperature.
1289  * The string "H2 " will return the temperature weighted wrt the H2 density
1290  * There are several other options as listed below */
1294 /* return value is o if things are ok and element was found,
1295  * non-zero if element not found or there are problems */
1297  /* four char string, null terminated, giving the element name */
1298  const char *chLabel,
1299  /* IonStage is ionization stage, 1 for atom, up to Z+1 where Z is atomic number,
1300  * 0 means that chLabel is a special case */
1301  long int IonStage,
1302  /* will be temperature */
1303  double *TeMean,
1304  /* how to weight the average, must be "RADIUS", "AREA, or "VOLUME" */
1305  const char *chWeight )
1306 {
1307  long int ip,
1308  ion, /* used as pointer within aaa vector*/
1309  nelem;
1310  realnum aaa[LIMELM + 1];
1311  /* use following to store local image of character strings */
1312  char chWGHT[INPUT_LINE_LENGTH] , chELEM[INPUT_LINE_LENGTH];
1313 
1314  DEBUG_ENTRY( "cdTemp()" );
1315 
1316  /* make sure strings are all caps */
1317  strcpy( chWGHT, chWeight );
1318  caps(chWGHT);
1319  strcpy( chELEM, chLabel );
1320  caps(chELEM);
1321 
1322  /* now see which weighting */
1323  int dim;
1324  if( strcmp(chWGHT,"RADIUS") == 0 )
1325  dim = 0;
1326  else if( strcmp(chWGHT,"AREA") == 0 )
1327  dim = 1;
1328  else if( strcmp(chWGHT,"VOLUME") == 0 )
1329  dim = 2;
1330  else
1331  {
1332  fprintf( ioQQQ, " cdTemp: chWeight=%6.6s makes no sense to me, the options are RADIUS, AREA, and VOLUME.\n",
1333  chWeight );
1334  *TeMean = 0.;
1335  return 1;
1336  }
1337 
1338  if( IonStage == 0 )
1339  {
1340  /* return atomic hydrogen weighted harmonic mean of gas kinetic temperature */
1341  if( strcmp(chELEM,"21CM") == 0 )
1342  {
1343  if( mean.TempHarMean[dim][1] > SMALLFLOAT )
1344  *TeMean = mean.TempHarMean[dim][0]/mean.TempHarMean[dim][1];
1345  else
1346  *TeMean = 0.;
1347  }
1348  /* return atomic hydrogen weighted harmonic mean 21 cm spin temperature,
1349  * using actual level populations with 1s of H0 */
1350  else if( strcmp(chELEM,"SPIN") == 0 )
1351  {
1352  if( mean.TempH_21cmSpinMean[dim][1] > SMALLFLOAT )
1353  *TeMean = mean.TempH_21cmSpinMean[dim][0] / mean.TempH_21cmSpinMean[dim][1];
1354  else
1355  *TeMean = 0.;
1356  }
1357  /* return temperature deduced from ratio of 21 cm and Lya optical depths */
1358  else if( strcmp(chELEM,"OPTI") == 0 )
1359  {
1360  if( HFLines[0].Emis().TauCon() > SMALLFLOAT )
1361  *TeMean = 3.84e-7 * iso_sp[ipH_LIKE][ipHYDROGEN].trans(ipH2p,ipH1s).Emis().TauCon() /
1362  HFLines[0].Emis().TauCon();
1363  else
1364  *TeMean = 0.;
1365  }
1366  /* mean temp weighted by H2 density */
1367  else if( strcmp(chELEM,"H2") == 0 )
1368  {
1369  if( mean.TempIonMean[dim][ipHYDROGEN][2][1] > SMALLFLOAT )
1370  *TeMean = mean.TempIonMean[dim][ipHYDROGEN][2][0] /
1371  mean.TempIonMean[dim][ipHYDROGEN][2][1];
1372  else
1373  *TeMean = 0.;
1374  }
1375  /* this is temperature weighted by eden */
1376  else if( strcmp(chELEM,"TENE") == 0 )
1377  {
1378  if( mean.TempEdenMean[dim][1] > SMALLFLOAT )
1379  *TeMean = mean.TempEdenMean[dim][0]/mean.TempEdenMean[dim][1];
1380  else
1381  *TeMean = 0.;
1382  }
1383  /* four spaces mean to return simple mean of Te */
1384  else if( strcmp(chELEM,"") == 0 )
1385  {
1386  if( mean.TempMean[dim][1] > SMALLFLOAT )
1387  *TeMean = mean.TempMean[dim][0]/mean.TempMean[dim][1];
1388  else
1389  *TeMean = 0.;
1390  }
1391  else
1392  {
1393  fprintf( ioQQQ, " cdTemp called with ion=0 and unknown quantity, =%4.4s\n",
1394  chLabel );
1395  return 1;
1396  }
1397 
1398  /* say things are ok */
1399  return 0;
1400  }
1401 
1402  /* find which element this is */
1403  nelem = 0;
1404  while( nelem < LIMELM &&
1405  strcmp(chELEM,elementnames.chElementNameShort[nelem]) != 0 )
1406  {
1407  ++nelem;
1408  }
1409 
1410  /* if element not recognized and above loop falls through, nelem is LIMELM */
1411  if( nelem >= LIMELM )
1412  {
1413  fprintf( ioQQQ, " cdTemp called with unknown element chLabel, =%4.4s\n",
1414  chLabel );
1415  return 1;
1416  }
1417 
1418  /* sanity check - does this ionization stage exist?
1419  * IonStage on spectroscopic scale, nelem on c */
1420 
1421  /* ion will be used as pointer within the aaa array that contains average values,
1422  * done this way to prevent lint from false problem in access to aaa array */
1423  ion = IonStage - 1;
1424 
1425  if( ion > nelem+1 || ion < 0 )
1426  {
1427  fprintf( ioQQQ, " cdTemp asked to return ionization stage %ld for element %4.4s but this is not physical.\n",
1428  IonStage, chLabel );
1429  return 1;
1430  }
1431 
1432  /* get average, aaa is filled in from 0 */
1433  /* aaa is dim'd LIMELM+1 so largest arg is LIMELM */
1434  /* MeanIon uses C scale for nelem */
1435  mean.MeanIon('t', nelem,dim,&ip,aaa,false);
1436  *TeMean = exp10((double)aaa[ion]);
1437  return 0;
1438 }
1439 
1440 /*************************************************************************
1441  *
1442  * cdRead routine to read in command lines
1443  * called by user when cloudy used as subroutine
1444  * called by maincl when used as a routine
1445  *
1446  ************************************************************************/
1447 
1448 /* returns the number of lines available in command stack
1449  * this is limit to how many more commands can be read */
1451  /* the string containing the command */
1452  const char *chInputLine )
1453 {
1454  char *chEOL , /* will be used to search for end of line symbols */
1455  chCARD[INPUT_LINE_LENGTH],
1456  chLocal[INPUT_LINE_LENGTH];
1457  bool lgComment;
1458 
1459  DEBUG_ENTRY( "cdRead()" );
1460 
1461  /* this is set false when code loaded, set true when cdInit called,
1462  * this is check that cdInit was called first */
1463  if( !lgcdInitCalled )
1464  {
1465  printf(" cdInit was not called first - this must be the first call.\n");
1467  }
1468 
1469  /* totally ignore any card starting with a #, *, space, //, or %
1470  * but want to include special "c " type of comment
1471  * >>chng 06 sep 04 use routine to check for comments */
1472  if( ( lgInputComment( chInputLine ) ||
1473  /* these two are end-of-input-stream sentinels */
1474  chInputLine[0] == '\n' || chInputLine[0] == ' ' ) &&
1475  /* option to allow "C" lines through */
1476  ! ( chInputLine[0] == 'C' || chInputLine[0] == 'c' ) )
1477  {
1478  /* return value is number of lines that can still be stuffed in */
1479  return NKRD - input.nSave;
1480  }
1481 
1482  /***************************************************************************
1483  * validate a location to store this line image, then store the version *
1484  * that has been truncated from special end of line characters *
1485  * stored image will have < INPUT_LINE_LENGTH valid characters *
1486  ***************************************************************************/
1487 
1488  /* this will now point to the next free slot in the line image save array
1489  * this is where we will stuff this line image */
1490  ++input.nSave;
1491 
1492  if( input.nSave >= NKRD )
1493  {
1494  /* too many input commands were entered - bail */
1495  fprintf( ioQQQ,
1496  " Too many line images entered to cdRead. The limit is %d\n",
1497  NKRD );
1498  fprintf( ioQQQ,
1499  " The limit to the number of allowed input lines is %d. This limit was exceeded. Sorry.\n",
1500  NKRD );
1501  fprintf( ioQQQ,
1502  " This limit is set by the variable NKRD which appears in input.h \n" );
1503  fprintf( ioQQQ,
1504  " Increase it everywhere it appears.\n" );
1506  }
1507 
1508  strncpy( chLocal, chInputLine, INPUT_LINE_LENGTH );
1509  // strncpy will pad chLocal with null bytes if chInputLine is shorter than
1510  // INPUT_LINE_LENGTH characters, so this indicates an overlong input string
1511  if( chLocal[INPUT_LINE_LENGTH-1] != '\0' )
1512  {
1513  chLocal[INPUT_LINE_LENGTH-1] = '\0';
1514  fprintf(ioQQQ," PROBLEM cdRead, while parsing the following input line:\n %s\n",
1515  chInputLine);
1516  fprintf(ioQQQ," found that the line is longer than %i characters, the longest possible line.\n",
1517  INPUT_LINE_LENGTH-1);
1518  fprintf(ioQQQ," Please make the command line no longer than this limit.\n");
1519  }
1520 
1521  /* now kill any part of line image after special end of line character,
1522  * this stops info user wants ignored from entering after here */
1523  if( (chEOL = strchr_s(chLocal, '\n' ) ) != NULL )
1524  {
1525  *chEOL = '\0';
1526  }
1527  if( (chEOL = strchr_s(chLocal, '%' ) ) != NULL )
1528  {
1529  *chEOL = '\0';
1530  }
1531  /* >>chng 02 apr 10, add this char */
1532  if( (chEOL = strchr_s(chLocal, '#' ) ) != NULL )
1533  {
1534  *chEOL = '\0';
1535  }
1536  if( (chEOL = strchr_s(chLocal, ';' ) ) != NULL )
1537  {
1538  *chEOL = '\0';
1539  }
1540  if( (chEOL = strstr_s(chLocal, "//" ) ) != NULL )
1541  {
1542  *chEOL = '\0';
1543  }
1544 
1545  /* now do it again, since we now want to make sure that there is a trailing space
1546  * if the line is shorter than 80 char, test on null is to keep lint happy */
1547  if( (chEOL = strchr_s( chLocal, '\0' )) == NULL )
1548  TotalInsanity();
1549 
1550  /* pad with two spaces if short enough,
1551  * if not short enough for this to be done, then up to user to create correct input */
1552  if( chEOL-chLocal < INPUT_LINE_LENGTH-2 )
1553  {
1554  strcat( chLocal, " " );
1555  }
1556 
1557  /* save string in master array for later use in readr */
1558  strcpy( input.chCardSav[input.nSave], chLocal );
1559 
1560  /* copy string to chCARD, then convert this to caps to check for keywords*/
1561  strcpy( chCARD, chLocal );
1562  caps(chCARD);/* convert to caps */
1563 
1564  // is this a comment? if so do not check for keywords
1565  lgComment = false;
1566  if( strncmp(chCARD , "C ", 2 )==0 )
1567  lgComment = true;
1568  bool lgTitle = ( strncmp(chCARD, "TITL", 4) == 0 );
1569 
1570  /* check whether this is a trace command, turn on printout if so */
1571  if( strncmp(chCARD,"TRACE",5) == 0 )
1572  trace.lgTrace = true;
1573 
1574  /* print input lines if trace specified */
1575  if( trace.lgTrace )
1576  fprintf( ioQQQ,"cdRead=%s=\n",input.chCardSav[input.nSave] );
1577 
1578  // remove string between double quotes
1579  char chFilename[INPUT_LINE_LENGTH],
1580  chTemp[INPUT_LINE_LENGTH];
1581  // this has to have copy of line for GetQuote to function
1582  strcpy( chTemp , input.chCardSav[input.nSave] );
1583  do {} while( GetQuote( chFilename , chCARD , chTemp , false ) == 0 );
1584 
1585  /* now check whether VARY is specified */
1586  if( !lgComment && !lgTitle && nMatch("VARY",chCARD) )
1587  /* a optimize flag was on the line image */
1588  optimize.lgVaryOn = true;
1589 
1590  /* now check whether line is "no vary" command */
1591  if( strncmp(chCARD,"NO VARY",7) == 0 )
1592  optimize.lgNoVary = true;
1593 
1594  /* now check whether line is "grid" command */
1595  if( strncmp(chCARD,"GRID",4) == 0 )
1596  {
1597  grid.lgGrid = true;
1598  ++grid.nGridCommands;
1599  }
1600 
1601  /* NO BUFFERING turn off buffered io for standard output,
1602  * used to get complete output when code crashes */
1603  if( strncmp(chCARD,"NO BUFF",7) == 0 )
1604  {
1605  /* if output has already been redirected (e.g. using cdOutput()) then
1606  * ignore this command, a warning will be printed in ParseDont() */
1607  /* stdout may be a preprocessor macro, so lets be really careful here */
1608  FILE *test = stdout;
1609  if( ioQQQ == test )
1610  {
1611  fprintf( ioQQQ, " cdRead found NO BUFFERING command, redirecting output to stderr now.\n" );
1612  /* make sure output is not lost */
1613  fflush( ioQQQ );
1614  /* stderr is always unbuffered */
1615  /* don't use setvbuf() here since we cannot guarantee
1616  * that no operations have been performed on stdout */
1617  ioQQQ = stderr;
1618  /* will be used to generate comment at end */
1619  input.lgSetNoBuffering = true;
1620  }
1621  else if( !save.chOutputFile.empty() )
1622  {
1623  fprintf( ioQQQ, " cdRead found NO BUFFERING command, reopening file %s now.\n",
1624  save.chOutputFile.c_str() );
1625  fclose( ioQQQ );
1626  // using AS_SILENT_TRY assures that open_data will not write to ioQQQ
1627  ioQQQ = open_data( save.chOutputFile.c_str(), "a", AS_SILENT_TRY );
1628  if( ioQQQ == NULL )
1629  {
1630  // ioQQQ is no longer valid, so switch to stderr and abort...
1631  ioQQQ = stderr;
1632  fprintf( ioQQQ, " cdRead failed to reopen %s, aborting!\n",
1633  save.chOutputFile.c_str() );
1635  }
1636  if( setvbuf( ioQQQ, NULL, _IONBF, 0 ) != 0 )
1637  fprintf( ioQQQ, " PROBLEM -- cdRead failed to set NO BUFFERING mode.\n" );
1638  else
1639  input.lgSetNoBuffering = true;
1640  }
1641  }
1642 
1643  /* use grid command as substitute for optimize command */
1644  if( strncmp(chCARD,"OPTI",4) == 0 || strncmp(chCARD,"GRID",4) == 0 )
1645  /* optimize command read in */
1646  optimize.lgOptimr = true;
1647 
1648  if( strncmp(chCARD,"SET ",4) == 0 && nMatch("CONT",chCARD) && nMatch("RESO",chCARD) )
1649  {
1650  bool lgEOL;
1651  long i = 1;
1652  double factor = FFmtRead(chCARD,&i,INPUT_LINE_LENGTH,&lgEOL);
1653  /* negative numbers were logs, a missing number will default to 1. this way */
1654  if( factor <= 0. )
1655  factor = exp10(factor);
1657  }
1658 
1659  return NKRD - input.nSave;
1660 }
1661 
1662 /* wrapper to close all save files */
1664 {
1665 
1666  DEBUG_ENTRY( "cdClosePunchFiles()" );
1667 
1668  CloseSaveFiles( true );
1669  return;
1670 }
void cdDate(char chString[])
Definition: cddrive.cpp:365
multi_arr< double, 2 > TempH_21cmSpinMean
Definition: mean.h:34
long int nSave
Definition: input.h:62
long int nTeFail
Definition: conv.h:203
static bool lgCalled
Definition: cddrive.cpp:429
void cdNotes(FILE *ioOUT)
Definition: cddrive.cpp:313
void cdLine_ip(long int ipLine, double *relint, double *absint)
Definition: cddrive.cpp:1112
double htot
Definition: thermal.h:169
FILE * open_data(const char *fname, const char *mode, access_scheme scheme)
Definition: cpu.cpp:751
void cdPrintCommands(FILE *ioOUT)
Definition: cddrive.cpp:532
t_thermal thermal
Definition: thermal.cpp:6
qList st
Definition: iso.h:482
realnum WavlenErrorGet(realnum wavelength, long sig_figs)
double exp10(double x)
Definition: cddefines.h:1383
const int ipHE_LIKE
Definition: iso.h:65
const int NKRD
Definition: input.h:12
NORETURN void TotalInsanity(void)
Definition: service.cpp:1067
t_input input
Definition: input.cpp:12
bool lgGrid
Definition: grid.h:42
t_struc struc
Definition: struc.cpp:6
double cdHeating_last()
Definition: cddrive.cpp:380
bool cloudy()
Definition: cloudy.cpp:37
long findline(const char *chLabel, realnum wavelength)
Definition: lines.cpp:293
const realnum SMALLFLOAT
Definition: cpu.h:246
t_cpu_i & i()
Definition: cpu.h:415
void cdPressure_last(double *PresTotal, double *PresGas, double *PresRad)
Definition: cddrive.cpp:868
int cdDrive()
Definition: cddrive.cpp:79
void cdCautions(FILE *ioOUT)
Definition: cddrive.cpp:220
const int ipHe2s3S
Definition: iso.h:46
t_warnings warnings
Definition: warnings.cpp:11
int cdIonFrac(const char *chLabel, long int IonStage, double *fracin, const char *chWeight, bool lgDensity)
Definition: cddrive.cpp:912
void cdWarnings(FILE *ioPNT)
Definition: cddrive.cpp:192
long nMatch(const char *chKey, const char *chCard)
Definition: service.cpp:537
t_conv conv
Definition: conv.cpp:5
long int nNeFail
Definition: conv.h:212
TransitionList HFLines("HFLines",&AnonStates)
void cdInput(const char *filename, const char *mode)
Definition: cddrive.cpp:1224
char chWarnln[LIMWCN][INPUT_LINE_LENGTH]
Definition: warnings.h:38
t_phycon phycon
Definition: phycon.cpp:6
t_LineSave LineSave
Definition: lines.cpp:9
void CloseSaveFiles(bool lgFinal)
const char * strstr_s(const char *haystack, const char *needle)
Definition: cddefines.h:1315
void cdTimescales(double *TTherm, double *THRecom, double *TH2)
Definition: cddrive.cpp:243
int cdTemp(const char *chLabel, long int IonStage, double *TeMean, const char *chWeight)
Definition: cddrive.cpp:1296
vector< genericState > matchGeneric(const char *chLabel, bool lgValidate)
void cdDepth_depth(double cdDepth[])
Definition: cddrive.cpp:816
realnum column
Definition: mole.h:422
bool lgVaryOn
Definition: optimize.h:173
t_noexec noexec
Definition: noexec.cpp:4
bool lgcdInitCalled
Definition: cdinit.cpp:27
FILE * ioQQQ
Definition: cddefines.cpp:7
long int ncaun
Definition: warnings.h:28
molezone * findspecieslocal(const char buf[])
void InitMesh(bool lgUnitCell)
Definition: mesh.h:63
char chTitle[INPUT_LINE_LENGTH]
Definition: input.h:48
long int nzone
Definition: cddefines.cpp:14
bool lgTalk
Definition: called.h:12
char chRgcln[2][INPUT_LINE_LENGTH]
Definition: warnings.h:34
int cdRead(const char *chInputLine)
Definition: cddrive.cpp:1450
STATIC void cdClock(struct timeval *clock_dat)
Definition: cddrive.cpp:446
double PresTotlCurr
Definition: pressure.h:46
vector< LinSv > lines
Definition: lines.h:132
bool lgNoExec
Definition: noexec.h:14
void setResolutionScaleFactor(double fac)
Definition: mesh.h:96
void trimTrailingWhiteSpace(string &str)
Definition: service.cpp:155
double pres_radiation_lines_curr
Definition: pressure.h:61
t_dense dense
Definition: global.cpp:15
void cdNoExec()
Definition: cddrive.cpp:408
static FixitList & Inst()
Definition: cddefines.h:209
void cdEmis_ip(long int ipLine, double *emiss, bool lgEmergent)
Definition: cddrive.cpp:573
double time_H2_Dest_longest
Definition: timesc.h:48
t_elementnames elementnames
Definition: elementnames.cpp:5
t_iso_sp iso_sp[NISO][LIMELM]
Definition: iso.cpp:11
long int nflux_with_check
Definition: rfield.h:51
bool lgOptimr
Definition: optimize.h:178
t_trace trace
Definition: trace.cpp:5
int GetQuote(char *chLabel, char *chCard, char *chCardRaw, bool lgABORT)
Definition: service.cpp:599
double cdH2_colden(long iVib, long iRot)
Definition: mole_h2.cpp:2312
realnum * depth
Definition: struc.h:25
void cdOutput(const char *filename, const char *mode)
Definition: cddrive.cpp:1211
multi_arr< double, 2 > TempB_HarMean
Definition: mean.h:29
long int nbang
Definition: warnings.h:28
char chNoteln[LIMWCN][INPUT_LINE_LENGTH]
Definition: warnings.h:38
const int ipH1s
Definition: iso.h:29
char chCaunln[LIMWCN][INPUT_LINE_LENGTH]
Definition: warnings.h:38
#define STATIC
Definition: cddefines.h:118
bool lgTrace
Definition: trace.h:12
realnum * GasPressure
Definition: struc.h:25
EmissionList::reference Emis() const
Definition: transition.h:447
multi_arr< double, 2 > TempEdenMean
Definition: mean.h:38
void cdSetExecTime()
Definition: cddrive.cpp:476
long debugLine(realnum wavelength)
Definition: cddrive.cpp:1034
t_pressure pressure
Definition: pressure.cpp:9
t_rfield rfield
Definition: rfield.cpp:9
t_mean mean
Definition: mean.cpp:16
bool lgPrintFixits
Definition: broke.h:34
float realnum
Definition: cddefines.h:124
#define EXIT_FAILURE
Definition: cddefines.h:168
const int INPUT_LINE_LENGTH
Definition: cddefines.h:301
#define cdEXIT(FAIL)
Definition: cddefines.h:484
bool lgMPI_talk() const
Definition: cpu.h:394
t_broke broke
Definition: broke.cpp:10
const char * strchr_s(const char *s, int c)
Definition: cddefines.h:1325
void cdPressure_depth(double TotalPressure[], double GasPressure[], double RadiationPressure[])
Definition: cddrive.cpp:841
double column(const genericState &gs)
double PresGasCurr
Definition: pressure.h:46
long int sig_figs
Definition: lines.h:109
const molezone * sp
Definition: generic_state.h:19
t_optimize optimize
Definition: optimize.cpp:6
char chElementNameShort[LIMELM][CHARS_ELEMENT_NAME_SHORT]
Definition: elementnames.h:21
t_grid grid
Definition: grid.cpp:5
double cdExecTime()
Definition: cddrive.cpp:483
t_radius radius
Definition: radius.cpp:5
t_timesc timesc
Definition: timesc.cpp:7
double cdTemp_last()
Definition: cddrive.cpp:901
bool lgElmtOn[LIMELM]
Definition: dense.h:160
TransitionProxy trans(const long ipHi, const long ipLo)
Definition: iso.h:473
double time_Hrecom_long
Definition: timesc.h:36
double Conv2PrtInten
Definition: radius.h:152
const int ipH2p
Definition: iso.h:31
long int nPreFail
Definition: conv.h:209
bool grid_do(void)
Definition: grid_do.cpp:19
double cdEDEN_last()
Definition: cddrive.cpp:394
#define ASSERT(exp)
Definition: cddefines.h:617
long int nnote
Definition: warnings.h:28
double cdB21cm()
Definition: cddrive.cpp:1255
void MeanIon(char chType, long nelem, long dim, long *n, realnum arlog[], bool lgDensity) const
Definition: mean.cpp:151
long int cdnZone()
Definition: cddrive.cpp:889
realnum & TauCon() const
Definition: emission.h:498
void cdEmis(const char *chLabel, realnum wavelength, double *emiss, bool lgEmergent)
Definition: cddrive.cpp:555
long int cdLine(const char *chLabel, realnum wavelength, double *relint, double *absint)
Definition: cddrive.cpp:1069
long int ipNormWavL
Definition: lines.h:102
const int ipH_LIKE
Definition: iso.h:64
const int LIMELM
Definition: cddefines.h:307
void cdClosePunchFiles()
Definition: cddrive.cpp:1663
int cdColm(const char *chLabel, long int ion, double *theocl)
Definition: cddrive.cpp:595
multi_arr< double, 4 > TempIonMean
Definition: mean.h:24
string chOutputFile
Definition: save.h:421
void cdErrors(FILE *ioOUT)
Definition: cddrive.cpp:750
long cdMemory()
Definition: cddrive.cpp:508
#define DEBUG_ENTRY(funcname)
Definition: cddefines.h:729
void cdVersion(char chString[])
Definition: cddrive.cpp:350
const int ipHELIUM
Definition: cddefines.h:349
double cdCooling_last()
Definition: cddrive.cpp:337
bool lgTalkForcedOff
Definition: called.h:19
static vector< realnum > wavelength
void cdTalk(bool lgTOn)
Definition: cddrive.cpp:1242
multi_arr< double, 2 > TempMean
Definition: mean.h:36
double eden
Definition: dense.h:201
bool lgSetNoBuffering
Definition: input.h:86
void InitCoreload(void)
void cdSurprises(FILE *ioOUT)
Definition: cddrive.cpp:276
void cdNwcns(bool *lgAbort_ret, long int *NumberWarnings, long int *NumberCautions, long int *NumberNotes, long int *NumberSurprises, long int *NumberTempFailures, long int *NumberPresFailures, long int *NumberIonFailures, long int *NumberNeFailures)
Definition: cddrive.cpp:1175
const int NCHLAB
Definition: cddefines.h:303
#define MAX2(a, b)
Definition: cddefines.h:828
int fprintf(const Output &stream, const char *format,...)
Definition: service.cpp:1217
multi_arr< double, 4 > xIonMean
Definition: mean.h:17
void cdReasonGeo(FILE *ioOUT)
Definition: cddrive.cpp:169
bool lgInputComment(const char *chLine)
Definition: input.cpp:31
long int nIonFail
Definition: conv.h:218
vector< string > list
Definition: broke.h:17
long ncells() const
Definition: mesh.h:80
long int nsum
Definition: lines.h:87
long int nwarn
Definition: warnings.h:28
void caps(char *chCard)
Definition: service.cpp:304
char chCardSav[NKRD][INPUT_LINE_LENGTH]
Definition: input.h:48
static t_cpu cpu
Definition: cpu.h:423
t_save save
Definition: save.cpp:5
double te
Definition: phycon.h:21
bool lgNoVary
Definition: optimize.h:175
double time_H2_Form_longest
Definition: timesc.h:48
double time_therm_long
Definition: timesc.h:29
const int ipHYDROGEN
Definition: cddefines.h:348
long int nGridCommands
Definition: grid.h:55
qStateConstProxy q
Definition: generic_state.h:20
char chBangln[LIMWCN][INPUT_LINE_LENGTH]
Definition: warnings.h:38
long int nflux
Definition: rfield.h:48
long int nPositive
Definition: rfield.h:55
static long int * ipLine
Definition: prt_linesum.cpp:14
t_called called
Definition: called.cpp:4
EmissionList & Emis()
Definition: transition.h:363
bool lgAbort
Definition: cddefines.cpp:10
realnum * pressure
Definition: struc.h:25
double ctot
Definition: thermal.h:130
double ScaleNormLine
Definition: lines.h:117
FILE * ioStdin
Definition: cddefines.cpp:8
double FFmtRead(const char *chCard, long int *ipnt, long int last, bool *lgEOL)
Definition: service.cpp:393
multi_arr< double, 2 > TempHarMean
Definition: mean.h:32
realnum * pres_radiation_lines_curr
Definition: struc.h:25
static struct timeval before
Definition: cddrive.cpp:443