cloudy  trunk
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
prt_final.cpp
Go to the documentation of this file.
1 /* This file is part of Cloudy and is copyright (C)1978-2013 by Gary J. Ferland and
2  * others. For conditions of distribution and use see copyright notice in license.txt */
3 /*PrtFinal create PrtFinal pages of printout, emission line intensities, etc */
4 /*StuffComment routine to stuff comments into the stack of comments, def in lines.h */
5 /*gett2o3 analyze computed [OIII] spectrum to get t^2 */
6 /*gett2 analyze computed structure to get structural t^2 */
7 #include "cddefines.h"
8 #include "iso.h"
9 #include "cddrive.h"
10 #include "dynamics.h"
11 #include "physconst.h"
12 #include "lines.h"
13 #include "taulines.h"
14 #include "warnings.h"
15 #include "phycon.h"
16 #include "dense.h"
17 #include "grainvar.h"
18 #include "h2.h"
19 #include "hmi.h"
20 #include "thermal.h"
21 #include "hydrogenic.h"
22 #include "rt.h"
23 #include "atmdat.h"
24 #include "timesc.h"
25 #include "opacity.h"
26 #include "struc.h"
27 #include "pressure.h"
28 #include "conv.h"
29 #include "geometry.h"
30 #include "called.h"
31 #include "iterations.h"
32 #include "version.h"
33 #include "colden.h"
34 #include "input.h"
35 #include "rfield.h"
36 #include "radius.h"
37 #include "peimbt.h"
38 #include "oxy.h"
39 #include "ipoint.h"
40 #include "lines_service.h"
41 #include "mean.h"
42 #include "wind.h"
43 #include "prt.h"
44 
45 // helper routine to center a line in the output
46 void PrintCenterLine(FILE* io, // file pointer
47  const char chLine[], // string to print, should not end with '\n'
48  size_t ArrLen, // length of chLine
49  size_t LineLen) // width of the line
50 {
51  unsigned long StrLen = min(strlen(chLine),ArrLen);
52  ASSERT( StrLen < LineLen );
53  unsigned long pad = (LineLen-StrLen)/2;
54  for( unsigned long i=0; i < pad; ++i )
55  fprintf( io, " " );
56  fprintf( io, "%s\n", chLine );
57 }
58 
59 /*gett2o3 analyze computed [OIII] spectrum to get t^2 */
60 STATIC void gett2o3(realnum *tsqr);
61 
62 /*gett2 analyze computed structure to get structural t^2 */
63 STATIC void gett2(realnum *tsqr);
64 
65 /* helper routine for printing averaged quantities */
66 inline void PrintRatio(double q1, double q2)
67 {
68  double ratio = ( q2 > SMALLFLOAT ) ? q1/q2 : 0.;
69  fprintf( ioQQQ, " " );
70  fprintf( ioQQQ, PrintEfmt("%9.2e", ratio) );
71  return;
72 }
73 
74 /* return is true if calculation ok, false otherwise */
75 void PrtFinal(void)
76 {
77  short int *lgPrt;
79  realnum *sclsav , *scaled;
80  long int *ipSortLines;
81  double *xLog_line_lumin;
82  char **chSLab;
83  char *chSTyp;
84  char chCKey[5],
85  chGeo[7],
86  chPlaw[21];
87  const char* chUnit;
88 
89  long int
90  i,
91  ipEmType ,
92  ipNegIntensity[33],
93  ip2500,
94  ip2kev,
95  iprnt,
96  j,
97  nline,
98  nNegIntenLines;
99  double o4363,
100  bacobs,
101  absint,
102  bacthn,
103  hbcab,
104  hbeta,
105  o5007;
106 
107  double a,
108  ajmass,
109  ajmin,
110  alfox,
111  bot,
112  bottom,
113  bremtk,
114  coleff,
115  /* N.B. 8 is used for following preset in loop */
116  d[8],
117  dmean,
118  ferode,
119  he4686,
120  he5876,
121  heabun,
122  hescal,
123  pion,
124  plow,
125  powerl,
126  qion,
127  qlow,
128  rate,
129  ratio,
130  reclin,
131  rjeans,
132  snorm,
133  tmean,
134  top,
135  THI,/* HI 21 cm spin temperature */
136  uhel,
137  uhl,
138  usp,
139  wmean,
140  znit;
141 
142  double bac,
143  tel,
144  x;
145 
146  DEBUG_ENTRY( "PrtFinal()" );
147 
148  /* return if not talking */
149  /* >>chng 05 nov 11, also if nzone is zero, sign of abort before model got started */
150  if( !called.lgTalk || (lgAbort && nzone< 1) )
151  {
152  return;
153  }
154 
155  /* print out header, or parts that were saved */
156 
157  /* this would be a major logical error */
158  ASSERT( LineSave.nsum > 1 );
159 
160  /* print name and version number */
161  fprintf( ioQQQ, "\f\n");
162  fprintf( ioQQQ, "%23c", ' ' );
163  int len = (int)strlen(t_version::Inst().chVersion);
164  int repeat = (72-len)/2;
165  for( i=0; i < repeat; ++i )
166  fprintf( ioQQQ, "*" );
167  fprintf( ioQQQ, "> Cloudy %s <", t_version::Inst().chVersion );
168  for( i=0; i < 72-repeat-len; ++i )
169  fprintf( ioQQQ, "*" );
170  fprintf( ioQQQ, "\n" );
171 
172  for( i=0; i <= input.nSave; i++ )
173  {
174  char chCard[INPUT_LINE_LENGTH];
175  /* print command line, unless it is a continue line */
176 
177  /* copy start of command to key, making it into capitals */
178  cap4(chCKey,input.chCardSav[i]);
179 
180  /* copy input to CAPS to make sure hide not on it */
181  strcpy( chCard , input.chCardSav[i] );
182  caps( chCard );
183 
184  /* print if not continue or hide */
185  /* >>chng 04 jan 21, add hide option */
186  if( (strcmp(chCKey,"CONT")!= 0) && !nMatch( "HIDE" , chCard) )
187  fprintf( ioQQQ, "%23c* %-80s*\n", ' ', input.chCardSav[i] );
188  }
189 
190  /* print log of ionization parameter if greater than zero - U==0 for PDR calcs */
191  if( rfield.uh > 0. )
192  {
193  a = log10(rfield.uh);
194  }
195  else
196  {
197  a = -37.;
198  }
199 
200  fprintf( ioQQQ,
201  " *********************************> Log(U):%6.2f <*********************************\n",
202  a );
203 
204  if( t_version::Inst().nBetaVer > 0 )
205  {
206  fprintf( ioQQQ,
207  "\n This is a beta test version of the code, and is intended for testing only.\n\n" );
208  }
209 
210  if( warnings.lgWarngs )
211  {
212  fprintf( ioQQQ, " \n" );
213  fprintf( ioQQQ, " >>>>>>>>>> Warning!\n" );
214  fprintf( ioQQQ, " >>>>>>>>>> Warning!\n" );
215  fprintf( ioQQQ, " >>>>>>>>>> Warning! Warnings exist, this calculation has serious problems.\n" );
216  fprintf( ioQQQ, " >>>>>>>>>> Warning!\n" );
217  fprintf( ioQQQ, " >>>>>>>>>> Warning!\n" );
218  fprintf( ioQQQ, " \n" );
219  }
220  else if( warnings.lgCautns )
221  {
222  fprintf( ioQQQ,
223  " >>>>>>>>>> Cautions are present.\n" );
224  }
225 
226  if( conv.lgBadStop )
227  {
228  fprintf( ioQQQ,
229  " >>>>>>>>>> The calculation stopped for unintended reasons.\n" );
230  }
231 
232  if( iterations.lgIterAgain )
233  {
234  fprintf( ioQQQ,
235  " >>>>>>>>>> Another iteration is needed.\n" );
236  }
237 
238  /* open or closed geometry?? */
239  if( geometry.lgSphere )
240  {
241  strcpy( chGeo, "Closed" );
242  }
243  else
244  {
245  strcpy( chGeo, " Open" );
246  }
247 
248  /* now give description of pressure law */
249  if( strcmp(dense.chDenseLaw,"CPRE") == 0 )
250  {
251  strcpy( chPlaw, " Constant Pressure " );
252  }
253 
254  else if( strcmp(dense.chDenseLaw,"CDEN") == 0 )
255  {
256  strcpy( chPlaw, " Constant Density " );
257  }
258 
259  else if( (strcmp(dense.chDenseLaw,"POWD") == 0 || strcmp(dense.chDenseLaw
260  ,"POWR") == 0) || strcmp(dense.chDenseLaw,"POWC") == 0 )
261  {
262  strcpy( chPlaw, " Power Law Density " );
263  }
264 
265  else if( strcmp(dense.chDenseLaw,"SINE") == 0 )
266  {
267  strcpy( chPlaw, " Rapid Fluctuations " );
268  }
269 
270  else if( strncmp(dense.chDenseLaw , "DLW" , 3) == 0 )
271  {
272  strcpy( chPlaw, " Special Density Lw " );
273  }
274 
275  else if( strcmp(dense.chDenseLaw,"HYDR") == 0 )
276  {
277  strcpy( chPlaw, " Hydrostatic Equlib " );
278  }
279 
280  else if( strcmp(dense.chDenseLaw,"WIND") == 0 )
281  {
282  strcpy( chPlaw, " Radia Driven Wind " );
283  }
284 
285  else if( strcmp(dense.chDenseLaw,"DYNA") == 0 )
286  {
287  strcpy( chPlaw, " Dynamical Flow " );
288  }
289 
290  else if( strcmp(dense.chDenseLaw,"GLOB") == 0 )
291  {
292  strcpy( chPlaw, " Globule " );
293  }
294 
295  else
296  {
297  strcpy( chPlaw, " UNRECOGNIZED CPRES " );
298  }
299 
300  fprintf( ioQQQ,
301  "\n Emission Line Spectrum. %20.20sModel. %6.6s geometry. Iteration %ld of %ld.\n",
302  chPlaw, chGeo, iteration, iterations.itermx + 1 );
303 
304  /* emission lines as logs of total luminosity */
306  {
307  char chLine[INPUT_LINE_LENGTH];
308  if( geometry.iEmissPower == 1 && !geometry.lgSizeSet )
309  chUnit = "/arcsec";
310  else if( geometry.iEmissPower == 0 && !geometry.lgSizeSet )
311  chUnit = "/arcsec^2";
312  else
313  chUnit = "";
314 
315  sprintf( chLine, "Flux observed at the Earth (erg/s/cm^2%s).", chUnit );
316  PrintCenterLine( ioQQQ, chLine, sizeof(chLine), 130 );
317  }
318  else if( prt.lgSurfaceBrightness )
319  {
320  char chLine[INPUT_LINE_LENGTH];
322  chUnit = "sr";
323  else
324  chUnit = "arcsec^2";
325 
326  sprintf( chLine, "Surface brightness (erg/s/cm^2/%s).", chUnit );
327  PrintCenterLine( ioQQQ, chLine, sizeof(chLine), 130 );
328  }
329  else if( radius.lgPredLumin )
330  {
331  char chLine[INPUT_LINE_LENGTH];
332  if( geometry.iEmissPower == 2 )
333  chUnit = "erg/s";
334  else if( geometry.iEmissPower == 1 )
335  chUnit = "erg/s/cm";
336  else if( geometry.iEmissPower == 0 )
337  chUnit = "erg/s/cm^2";
338  else
339  TotalInsanity();
340 
341  char chCoverage[INPUT_LINE_LENGTH];
342  if( fp_equal( geometry.covgeo, realnum(1.) ) )
343  sprintf( chCoverage, "with full coverage" );
344  else
345  sprintf( chCoverage, "with a covering factor of %.1f%%", geometry.covgeo*100. );
346 
347  if( radius.lgCylnOn )
348  sprintf( chLine, "Luminosity (%s) emitted by a partial cylinder %s.", chUnit, chCoverage );
349  else
350  sprintf( chLine, "Luminosity (%s) emitted by a shell %s.", chUnit, chCoverage );
351  PrintCenterLine( ioQQQ, chLine, sizeof(chLine), 130 );
352 
353  if( geometry.iEmissPower != 2 )
354  {
355  const char* chAper;
356  if( geometry.iEmissPower == 1 )
357  chAper = "long slit";
358  else if( geometry.iEmissPower == 0 )
359  chAper = "pencil beam";
360  else
361  TotalInsanity();
362 
363  sprintf( chLine, "Observed through a %s with aperture covering factor %.1f%%.",
364  chAper, geometry.covaper*100. );
365  PrintCenterLine( ioQQQ, chLine, sizeof(chLine), 130 );
366  }
367  }
368  else
369  {
370  char chLine[INPUT_LINE_LENGTH];
371  sprintf( chLine, "Intensity (erg/s/cm^2)." );
372  PrintCenterLine( ioQQQ, chLine, sizeof(chLine), 130 );
373  }
374 
375  fprintf( ioQQQ, "\n" );
376 
377  /******************************************************************
378  * kill Hummer & Storey case b predictions if outside their table *
379  ******************************************************************/
380 
381  /* >>chng 02 aug 29, from lgHCaseBOK to following - caught by Ryan Porter */
382  if( !atmdat.lgHCaseBOK[1][ipHYDROGEN] )
383  {
384  static const int NWLH = 21;
385  /* list of all H case b lines */
386  realnum wlh[NWLH] = {6563.e0f, 4861.e0f, 4340.e0f, 4102.e0f, 1.875e4f, 1.282e4f,
387  1.094e4f, 1.005e4f, 2.625e4f, 2.166e4f, 1.945e4f, 7.458e4f,
388  4.653e4f, 3.740e4f, 4.051e4f, 7.458e4f, 3.296e4f, 1216.e0f,
389  1026.e0f, 972.5e0f, 949.7e0f };
390 
391  /* table exceeded - kill all H case b predictions*/
392  for( i=0; i < LineSave.nsum; i++ )
393  {
394  /* >>chng 04 jun 21, kill both case a and b at same time,
395  * actually lgHCaseBOK has separate A and B flags, but
396  * this is simpler */
397  if( (strcmp( LineSv[i].chALab,"Ca B" )==0) ||
398  (strcmp( LineSv[i].chALab,"Ca A" )==0) )
399  {
400  realnum errorwave;
401  /* this logic must be kept parallel with which H lines are
402  * added as case B in lines_hydro - any automatic hosing of
403  * case b would kill both H I and He II */
404  errorwave = WavlenErrorGet( LineSv[i].wavelength );
405  for( j=0; j<NWLH; ++j )
406  {
407  if( fabs(LineSv[i].wavelength-wlh[j] ) <= errorwave )
408  {
409  LineSv[i].SumLine[0] = 0.;
410  LineSv[i].SumLine[1] = 0.;
411  break;
412  }
413  }
414  }
415  }
416  }
417 
418  if( !atmdat.lgHCaseBOK[1][ipHELIUM] )
419  {
420  /* table exceeded - kill all He case b predictions*/
421  static const int NWLHE = 20;
422  realnum wlhe[NWLHE] = {1640.e0f, 1215.e0f, 1085.e0f, 1025.e0f, 4686.e0f, 3203.e0f,
423  2733.e0f, 2511.e0f, 1.012e4f, 6560.e0f, 5412.e0f, 4860.e0f,
424  1.864e4f, 1.163e4f, 9345.e0f, 8237.e0f, 303.8e0f, 256.3e0f,
425  243.0e0f, 237.3e0f};
426  for( i=0; i < LineSave.nsum; i++ )
427  {
428  if( (strcmp( LineSv[i].chALab,"Ca B" )==0) ||
429  (strcmp( LineSv[i].chALab,"Ca A" )==0) )
430  {
431  realnum errorwave;
432  /* this logic must be kept parallel with which H lines are
433  * added as case B in lines_hydro - any automatic hosing of
434  * case b would kill both H I and He II */
435  errorwave = WavlenErrorGet( LineSv[i].wavelength );
436  for( j=0; j<NWLHE; ++j )
437  {
438  if( fabs(LineSv[i].wavelength-wlhe[j] ) <= errorwave )
439  {
440  LineSv[i].SumLine[0] = 0.;
441  LineSv[i].SumLine[1] = 0.;
442  break;
443  }
444  }
445  }
446  }
447  }
448 
449  /**********************************************************
450  *analyse line arrays for abundances, temp, etc *
451  **********************************************************/
452 
453  /* find apparent helium abundance, will not find these if helium is turned off */
454 
455  if( cdLine("TOTL",4861.36f,&hbeta,&absint)<=0 )
456  {
457  if( dense.lgElmtOn[ipHYDROGEN] )
458  {
459  /* this is a major logical error if hydrogen is turned on */
460  fprintf( ioQQQ, " PrtFinal could not find TOTL 4861 with cdLine.\n" );
462  }
463  }
464 
465  if( dense.lgElmtOn[ipHELIUM] )
466  {
467  /* get HeI 5876 */
468  /* >>chng 06 may 15, changed this so that it works for up to six sig figs. */
469  if( cdLine("He 1",5875.61f,&he5876,&absint)<=0 )
470  {
471  /* 06 aug 28, from numLevels_max to _local. */
472  if( iso_sp[ipHE_LIKE][ipHELIUM].numLevels_local >= 14 )
473  {
474  /* this is a major logical error if helium is turned on */
475  fprintf( ioQQQ, " PrtFinal could not find He 1 5876 with cdLine.\n" );
477  }
478  }
479 
480  /* get HeII 4686 */
481  /* >>chng 06 may 15, changed this so that it works for up to six sig figs. */
482  if( cdLine("He 2",4686.01f,&he4686,&absint)<=0 )
483  {
484  /* 06 aug 28, from numLevels_max to _local. */
485  if( iso_sp[ipH_LIKE][ipHELIUM].numLevels_local > 5 )
486  {
487  /* this is a major logical error if helium is turned on
488  * and the model atom has enough levels */
489  fprintf( ioQQQ, " PrtFinal could not find He 2 4686 with cdLine.\n" );
491  }
492  }
493  }
494  else
495  {
496  he5876 = 0.;
497  absint = 0.;
498  he4686 = 0.;
499  }
500 
501  if( hbeta > 0. )
502  {
503  heabun = (he4686*0.078 + he5876*0.739)/hbeta;
504  }
505  else
506  {
507  heabun = 0.;
508  }
509 
510  if( dense.lgElmtOn[ipHELIUM] )
511  {
512  hescal = heabun/(dense.gas_phase[ipHELIUM]/dense.gas_phase[ipHYDROGEN]);
513  }
514  else
515  {
516  hescal = 0.;
517  }
518 
519  /* get temperature from [OIII] spectrum, o may be turned off,
520  * but lines still dumped into stack */
521  if( cdLine("O 3",5007.,&o5007,&absint)<=0 )
522  {
523  if( dense.lgElmtOn[ipOXYGEN] )
524  {
525  /* this is a major logical error if hydrogen is turned on */
526  fprintf( ioQQQ, " PrtFinal could not find O 3 5007 with cdLine.\n" );
528  }
529  }
530 
531  if( cdLine("TOTL",4363.,&o4363,&absint)<=0 )
532  {
533  if( dense.lgElmtOn[ipOXYGEN] )
534  {
535  /* this is a major logical error if hydrogen is turned on */
536  fprintf( ioQQQ, " PrtFinal could not find TOTL 4363 with cdLine.\n" );
538  }
539  }
540 
541  /* first find low density limit OIII zone temp */
542  if( (o4363 != 0.) && (o5007 != 0.) )
543  {
544  /* following will assume coll excitation only, so correct
545  * for 4363's that cascade as 5007 */
546  bot = o5007 - o4363/oxy.o3enro;
547 
548  if( bot > 0. )
549  {
550  ratio = o4363/bot;
551  }
552  else
553  {
554  ratio = 0.178;
555  }
556 
557  if( ratio > 0.177 )
558  {
559  /* ratio was above infinite temperature limit */
560  peimbt.toiiir = 1e10;
561  }
562  else
563  {
564  /* data for following set in OIII cooling routine
565  * ratio of collision strengths, factor of 4/3 makes 5007+4959
566  * >>chng 96 sep 07, reset cs to values at 10^4K,
567  * had been last temp in model */
568  /*>>chng 06 jul 25, update to recent data */
569  oxy.o3cs12 = 2.2347f;
570  oxy.o3cs13 = 0.29811f;
571  ratio = ratio/1.3333/(oxy.o3cs13/oxy.o3cs12);
572  /* ratio of energies and branching ratio for 4363 */
573  ratio = ratio/oxy.o3enro/oxy.o3br32;
574  peimbt.toiiir = (realnum)(-oxy.o3ex23/log(ratio));
575  }
576  }
577 
578  else
579  {
580  peimbt.toiiir = 0.;
581  }
582 
583  if( geometry.iEmissPower == 2 )
584  {
585  /* find temperature from Balmer continuum */
586  if( cdLine("Bac ",3646.,&bacobs,&absint)<=0 )
587  {
588  fprintf( ioQQQ, " PrtFinal could not find Bac 3546 with cdLine.\n" );
590  }
591 
592  /* we pulled hbeta out of stack with cdLine above */
593  if( hbeta > 0. )
594  {
595  bac = bacobs/hbeta;
596  }
597  else
598  {
599  bac = 0.;
600  }
601  }
602  else
603  {
604  bac = 0.;
605  }
606 
607  if( bac > 0. )
608  {
609  /*----------------------------------------------------------*
610  ***** TableCurve c:\tcwin2\balcon.for Sep 6, 1994 11:13:38 AM
611  ***** log bal/Hbet
612  ***** X= log temp
613  ***** Y=
614  ***** Eqn# 6503 y=a+b/x+c/x^2+d/x^3+e/x^4+f/x^5
615  ***** r2=0.9999987190883581
616  ***** r2adj=0.9999910336185065
617  ***** StdErr=0.001705886369042427
618  ***** Fval=312277.1895753243
619  ***** a= -4.82796940090671
620  ***** b= 33.08493347410885
621  ***** c= -56.08886262205931
622  ***** d= 52.44759454803217
623  ***** e= -25.07958990094209
624  ***** f= 4.815046760060006
625  *----------------------------------------------------------*
626  * bac is double precision!!!! */
627  x = 1.e0/log10(bac);
628  tel = -4.827969400906710 + x*(33.08493347410885 + x*(-56.08886262205931 +
629  x*(52.44759454803217 + x*(-25.07958990094209 + x*(4.815046760060006)))));
630 
631  if( tel > 1. && tel < 5. )
632  {
633  peimbt.tbac = (realnum)pow(10.,tel);
634  }
635  else
636  {
637  peimbt.tbac = 0.;
638  }
639  }
640  else
641  {
642  peimbt.tbac = 0.;
643  }
644 
645  if( geometry.iEmissPower == 2 )
646  {
647  /* find temperature from optically thin Balmer continuum and case B H-beta */
648  if( cdLine("thin",3646.,&bacthn,&absint)<=0 )
649  {
650  fprintf( ioQQQ, " PrtFinal could not find thin 3646 with cdLine.\n" );
652  }
653 
654  /* >>chng 06 may 15, changed this so that it works for up to six sig figs. */
655  if( cdLine("Ca B",4861.36f,&hbcab,&absint)<=0 )
656  {
657  fprintf( ioQQQ, " PrtFinal could not find Ca B 4861 with cdLine.\n" );
659  }
660 
661  if( hbcab > 0. )
662  {
663  bacthn /= hbcab;
664  }
665  else
666  {
667  bacthn = 0.;
668  }
669  }
670  else
671  {
672  bacthn = 0.;
673  }
674 
675  if( bacthn > 0. )
676  {
677  /*----------------------------------------------------------*
678  ***** TableCurve c:\tcwin2\balcon.for Sep 6, 1994 11:13:38 AM
679  ***** log bal/Hbet
680  ***** X= log temp
681  ***** Y=
682  ***** Eqn# 6503 y=a+b/x+c/x^2+d/x^3+e/x^4+f/x^5
683  ***** r2=0.9999987190883581
684  ***** r2adj=0.9999910336185065
685  ***** StdErr=0.001705886369042427
686  ***** Fval=312277.1895753243
687  ***** a= -4.82796940090671
688  ***** b= 33.08493347410885
689  ***** c= -56.08886262205931
690  ***** d= 52.44759454803217
691  ***** e= -25.07958990094209
692  ***** f= 4.815046760060006
693  *----------------------------------------------------------*
694  * bac is double precision!!!! */
695  x = 1.e0/log10(bacthn);
696  tel = -4.827969400906710 + x*(33.08493347410885 + x*(-56.08886262205931 +
697  x*(52.44759454803217 + x*(-25.07958990094209 + x*(4.815046760060006)))));
698 
699  if( tel > 1. && tel < 5. )
700  {
701  peimbt.tbcthn = (realnum)pow(10.,tel);
702  }
703  else
704  {
705  peimbt.tbcthn = 0.;
706  }
707  }
708  else
709  {
710  peimbt.tbcthn = 0.;
711  }
712 
713  /* we now have temps from OIII ratio and BAC ratio, now
714  * do Peimbert analysis, getting To and t^2 */
715 
716  peimbt.tohyox = (realnum)((8.5*peimbt.toiiir - 7.5*peimbt.tbcthn - 228200. +
717  sqrt(POW2(8.5*peimbt.toiiir-7.5*peimbt.tbcthn-228200.)+9.128e5*
718  peimbt.tbcthn))/2.);
719 
720  if( peimbt.tohyox > 0. )
721  {
723  }
724  else
725  {
726  peimbt.t2hyox = 0.;
727  }
728 
729  /*----------------------------------------------------------
730  *
731  * first set scaled lines */
732 
733  /* get space for scaled */
734  scaled = (realnum *)MALLOC( sizeof(realnum)*(unsigned long)LineSave.nsum);
735 
736  /* get space for xLog_line_lumin */
737  xLog_line_lumin = (double *)MALLOC( sizeof(double)*(unsigned long)LineSave.nsum);
738 
739  /* this is option to not print certain contributions */
740  /* gjf 98 jun 10, get space for array lgPrt */
741  lgPrt = (short int *)MALLOC( sizeof(short int)*(unsigned long)LineSave.nsum);
742 
743  /* get space for wavelength */
744  wavelength = (realnum *)MALLOC( sizeof(realnum)*(unsigned long)LineSave.nsum);
745 
746  /* get space for sclsav */
747  sclsav = (realnum *)MALLOC( sizeof(realnum)*(unsigned long)LineSave.nsum );
748 
749  /* get space for chSTyp */
750  chSTyp = (char *)MALLOC( sizeof(char)*(unsigned long)LineSave.nsum );
751 
752  /* get space for chSLab,
753  * first define array of pointers*/
754  /* char chSLab[NLINES][5];*/
755  chSLab = ((char**)MALLOC((unsigned long)LineSave.nsum*sizeof(char*)));
756 
757  /* now allocate all the labels for each of the above lines */
758  for( i=0; i<LineSave.nsum; ++i)
759  {
760  chSLab[i] = (char*)MALLOC(5*sizeof(char));
761  }
762 
763  /* get space for array of indices for lines, for possible sorting */
764  ipSortLines = (long *)MALLOC( sizeof(long)*(unsigned long)LineSave.nsum );
765 
766  ASSERT( LineSave.ipNormWavL >= 0 );
767 
768  /* option to also print usual first two sets of line arrays
769  * but for two sets of cumulative arrays for time-dependent sims too */
770  int nEmType = 2;
772  nEmType = 4;
773 
774  for( ipEmType=0; ipEmType<nEmType; ++ipEmType )
775  {
776  /* this is the intensity of the line spectrum will be normalized to */
777  snorm = LineSv[LineSave.ipNormWavL].SumLine[ipEmType];
778 
779  /* check that this line has positive intensity */
780  if( ((snorm <= SMALLDOUBLE ) || (LineSave.ipNormWavL < 0)) || (LineSave.ipNormWavL > LineSave.nsum) )
781  {
782  fprintf( ioQQQ, "\n\n >>PROBLEM Normalization line has small or zero intensity, its value was %.2e and its intensity was set to 1."
783  "\n >>Please consider using another normalization line (this is set with the NORMALIZE command).\n" , snorm);
784  fprintf( ioQQQ, " >>The relative intensities will be meaningless, and many lines may appear too faint.\n" );
785  snorm = 1.;
786  }
787  for( i=0; i < LineSave.nsum; i++ )
788  {
789 
790  /* when normalization line is off-scale small (generally a model
791  * with mis-set parameters) the scaled intensity can be larger than
792  * a realnum - this is not actually a problem since the number will
793  * overflow the format and hence be unreadable */
794  double scale = LineSv[i].SumLine[ipEmType]/snorm*LineSave.ScaleNormLine;
795  /* this will become a realnum, so limit dynamic range */
796  scale = MIN2(BIGFLOAT , scale );
797  scale = MAX2( -BIGFLOAT , scale );
798 
799  /* find logs of ALL line intensities/luminosities */
800  scaled[i] = (realnum)scale;
801 
802  if( LineSv[i].SumLine[ipEmType] > 0. )
803  {
804  xLog_line_lumin[i] = log10(LineSv[i].SumLine[ipEmType]) + radius.Conv2PrtInten;
805  }
806  else
807  {
808  xLog_line_lumin[i] = -38.;
809  }
810  }
811 
812  /* now find which lines to print, which to ignore because they are the wrong type */
813  for( i=0; i < LineSave.nsum; i++ )
814  {
815  /* never print unit normalization check, at least in main list */
816  if( (strcmp(LineSv[i].chALab,"Unit") == 0) || (strcmp(LineSv[i].chALab,"UntD") == 0) )
817  lgPrt[i] = false;
818  else if( strcmp(LineSv[i].chALab,"Coll") == 0 && !prt.lgPrnColl )
819  lgPrt[i] = false;
820  else if( strcmp(LineSv[i].chALab,"Pump") == 0 && !prt.lgPrnPump )
821  lgPrt[i] = false;
822  else if( strncmp(LineSv[i].chALab,"Inw",3) == 0 && !prt.lgPrnInwd )
823  lgPrt[i] = false;
824  else if( strcmp(LineSv[i].chALab,"Heat") == 0 && !prt.lgPrnHeat )
825  lgPrt[i] = false;
826  else
827  lgPrt[i] = true;
828  }
829 
830  /* do not print relatively faint lines unless requested */
831  nNegIntenLines = 0;
832 
833  /* set ipNegIntensity to bomb to make sure set in following */
834  for(i=0; i< 32; i++ )
835  {
836  ipNegIntensity[i] = LONG_MAX;
837  }
838 
839  for(i=0;i<8;++i)
840  {
841  d[i] = -DBL_MAX;
842  }
843 
844  /* create header for blocks of emission line intensities */
845  const char chIntensityType[4][100]=
846  {" Intrinsic" , " Emergent" , "Cumulative intrinsic" , "Cumulative emergent" };
847  ASSERT( ipEmType==0 || ipEmType==1 || ipEmType==2 || ipEmType==3 );
848  /* if true then printing in 4 columns of lines, this is offset to
849  * center the title */
850  fprintf( ioQQQ, "\n" );
851  if( prt.lgPrtLineArray )
852  fprintf( ioQQQ, " " );
853  fprintf( ioQQQ, "%s" , chIntensityType[ipEmType] );
854  fprintf( ioQQQ, " line intensities\n" );
855  // caution about emergent intensities when outward optical
856  // depths are not yet known
857  if( ipEmType==1 && iteration==1 )
858  fprintf(ioQQQ," Caution: emergent intensities are not reliable on the "
859  "first iteration.\n");
860 
861  /* option to only print brighter lines */
862  if( prt.lgFaintOn )
863  {
864  iprnt = 0;
865  for( i=0; i < LineSave.nsum; i++ )
866  {
867  /* this insanity can happen when arrays overrun */
868  ASSERT( iprnt <= i);
869  if( scaled[i] >= prt.TooFaint && lgPrt[i] )
870  {
871  if( prt.lgPrtLineLog )
872  {
873  xLog_line_lumin[iprnt] = log10(LineSv[i].SumLine[ipEmType]) + radius.Conv2PrtInten;
874  }
875  else
876  {
877  xLog_line_lumin[iprnt] = LineSv[i].SumLine[ipEmType] * pow(10.,radius.Conv2PrtInten);
878  }
879  sclsav[iprnt] = scaled[i];
880  chSTyp[iprnt] = LineSv[i].chSumTyp;
881  /* check that null is correct, string overruns have
882  * been a problem in the past */
883  ASSERT( strlen( LineSv[i].chALab )<5 );
884  strcpy( chSLab[iprnt], LineSv[i].chALab );
885  wavelength[iprnt] = LineSv[i].wavelength;
886  ++iprnt;
887  }
888  else if( -scaled[i] > prt.TooFaint && lgPrt[i] )
889  {
890  /* negative intensities occur if line absorbs continuum */
891  ipNegIntensity[nNegIntenLines] = i;
892  nNegIntenLines = MIN2(32,nNegIntenLines+1);
893  }
894  /* special labels to give id for blocks of lines
895  * do not add these labels when sorting by wavelength since invalid */
896  else if( strcmp( LineSv[i].chALab, "####" ) == 0 &&!prt.lgSortLines )
897  {
898  strcpy( chSLab[iprnt], LineSv[i].chALab );
899  xLog_line_lumin[iprnt] = 0.;
900  sclsav[iprnt] = 0.;
901  chSTyp[iprnt] = LineSv[i].chSumTyp;
902  wavelength[iprnt] = LineSv[i].wavelength;
903  ++iprnt;
904  }
905  }
906  }
907 
908  else
909  {
910  /* print everything */
911  iprnt = LineSave.nsum;
912  for( i=0; i < LineSave.nsum; i++ )
913  {
914  if( strcmp( LineSv[i].chALab, "####" ) == 0 )
915  {
916  strcpy( chSLab[i], LineSv[i].chALab );
917  xLog_line_lumin[i] = 0.;
918  sclsav[i] = 0.;
919  chSTyp[i] = LineSv[i].chSumTyp;
920  wavelength[i] = LineSv[i].wavelength;
921  }
922  else
923  {
924  sclsav[i] = scaled[i];
925  chSTyp[i] = LineSv[i].chSumTyp;
926  strcpy( chSLab[i], LineSv[i].chALab );
927  wavelength[i] = LineSv[i].wavelength;
928  }
929  if( scaled[i] < 0. )
930  {
931  ipNegIntensity[nNegIntenLines] = i;
932  nNegIntenLines = MIN2(32,nNegIntenLines+1);
933  }
934  }
935  }
936 
937  /* the number of lines to print better be positive */
938  ASSERT( iprnt > 0. );
939 
940  /* reorder lines according to wavelength for comparison with spectrum
941  * including writing out the results */
942  if( prt.lgSortLines )
943  {
944  int lgFlag;
946  {
947  /* first check if wavelength range specified */
948  if( prt.wlSort1 >-0.1 )
949  {
950  j = 0;
951  /* skip over those lines not desired */
952  for( i=0; i<iprnt; ++i )
953  {
954  if( wavelength[i]>= prt.wlSort1 && wavelength[i]<= prt.wlSort2 )
955  {
956  if( j!=i )
957  {
958  sclsav[j] = sclsav[i];
959  chSTyp[j] = chSTyp[i];
960  strcpy( chSLab[j], chSLab[i] );
961  wavelength[j] = wavelength[i];
962  /* >>chng 05 feb 03, add this, had been left out,
963  * thanks to Marcus Copetti for discovering the bug */
964  xLog_line_lumin[j] = xLog_line_lumin[i];
965  }
966  ++j;
967  }
968  }
969  iprnt = j;
970  }
971  /*spsort netlib routine to sort array returning sorted indices */
972  spsort(wavelength,
973  iprnt,
974  ipSortLines,
975  /* flag saying what to do - 1 sorts into increasing order, not changing
976  * the original routine */
977  1,
978  &lgFlag);
979  if( lgFlag )
980  TotalInsanity();
981  }
982  else if( prt.lgSortLineIntensity )
983  {
984  /*spsort netlib routine to sort array returning sorted indices */
985  spsort(sclsav,
986  iprnt,
987  ipSortLines,
988  /* flag saying what to do - -1 sorts into decreasing order, not changing
989  * the original routine */
990  -1,
991  &lgFlag);
992  if( lgFlag )
993  TotalInsanity();
994  }
995  else
996  {
997  /* only to keep lint happen, or in case vars clobbered */
998  TotalInsanity();
999  }
1000  }
1001  else
1002  {
1003  /* do not sort lines (usual case) simply print in incoming order */
1004  for( i=0; i<iprnt; ++i )
1005  {
1006  ipSortLines[i] = i;
1007  }
1008  }
1009 
1010  /* print out all lines which made it through the faint filter,
1011  * there are iprnt lines to print
1012  * can print in either 4 column (the default ) or one long
1013  * column of lines */
1014  if( prt.lgPrtLineArray )
1015  {
1016  /* four or three columns ? - depends on how many sig figs */
1017  if( LineSave.sig_figs >= 5 )
1018  {
1019  nline = (iprnt + 2)/3;
1020  }
1021  else
1022  {
1023  /* nline will be the number of horizontal lines -
1024  * the 4 represents the 4 columns */
1025  nline = (iprnt + 3)/4;
1026  }
1027  }
1028  else
1029  {
1030  /* this option print a single column of emission lines */
1031  nline = iprnt;
1032  }
1033 
1034  /* now loop over the spectrum, printing lines */
1035  for( i=0; i < nline; i++ )
1036  {
1037  fprintf( ioQQQ, " " );
1038 
1039  /* this skips over nline per step, to go to the next column in
1040  * the output */
1041  for( j=i; j<iprnt; j = j + nline)
1042  {
1043  /* index with possibly reordered set of lines */
1044  long ipLin = ipSortLines[j];
1045  /* this is the actual print statement for the emission line
1046  * spectrum*/
1047  if( strcmp( chSLab[ipLin], "####" ) == 0 )
1048  {
1049  /* special labels */
1050  /*fprintf( ioQQQ, "1111222223333333444444444 " ); */
1051  /* this string was set in */
1052  fprintf( ioQQQ, "%s",LineSave.chHoldComments[(int)wavelength[ipLin]] );
1053  }
1054  else
1055  {
1056  /* the label for the line */
1057  fprintf( ioQQQ, "%4.4s ",chSLab[ipLin] );
1058 
1059  /* print the wavelength for the line */
1060  prt_wl( ioQQQ , wavelength[ipLin]);
1061 
1062  /* print the log of the intensity/luminosity of the
1063  * lines, the usual case */
1064  if( prt.lgPrtLineLog )
1065  {
1066  fprintf( ioQQQ, " %7.3f", xLog_line_lumin[ipLin] );
1067  }
1068  else
1069  {
1070  /* print linear quantity instead */
1071  fprintf( ioQQQ, " %.2e ", xLog_line_lumin[ipLin] );
1072  }
1073 
1074  /* print scaled intensity with various formats,
1075  * depending on order of magnitude. value is
1076  * always the same but the format changes. */
1077  if( sclsav[ipLin] < 9999.5 )
1078  {
1079  fprintf( ioQQQ, "%9.4f",sclsav[ipLin] );
1080  }
1081  else if( sclsav[ipLin] < 99999.5 )
1082  {
1083  fprintf( ioQQQ, "%9.3f",sclsav[ipLin] );
1084  }
1085  else if( sclsav[ipLin] < 999999.5 )
1086  {
1087  fprintf( ioQQQ, "%9.2f",sclsav[ipLin] );
1088  }
1089  else if( sclsav[ipLin] < 9999999.5 )
1090  {
1091  fprintf( ioQQQ, "%9.1f",sclsav[ipLin] );
1092  }
1093  else
1094  {
1095  fprintf( ioQQQ, "*********" );
1096  }
1097 
1098  /* now end the block with some spaces to set next one off */
1099  fprintf( ioQQQ, " " );
1100  }
1101  }
1102  /* now end the lines */
1103  fprintf( ioQQQ, " \n" );
1104  }
1105 
1106  if( nNegIntenLines > 0 )
1107  {
1108  fprintf( ioQQQ, " Lines with negative intensities - Linear intensities relative to normalize line.\n" );
1109  fprintf( ioQQQ, " " );
1110 
1111  for( i=0; i < nNegIntenLines; ++i )
1112  {
1113  fprintf( ioQQQ, "%ld %s %.0f %.1e, ",
1114  ipNegIntensity[i],
1115  LineSv[ipNegIntensity[i]].chALab,
1116  LineSv[ipNegIntensity[i]].wavelength,
1117  scaled[ipNegIntensity[i]] );
1118  }
1119  fprintf( ioQQQ, "\n" );
1120  }
1121  }
1122 
1123  /* now find which were the very strongest, more that 5% of cooling */
1124  j = 0;
1125  for( i=0; i < LineSave.nsum; i++ )
1126  {
1127  a = (double)LineSv[i].SumLine[0]/(double)thermal.totcol;
1128  if( (a >= 0.05) && LineSv[i].chSumTyp == 'c' )
1129  {
1130  ipNegIntensity[j] = i;
1131  d[j] = a;
1132  j = MIN2(j+1,7);
1133  }
1134  }
1135 
1136  fprintf( ioQQQ, "\n\n\n %s\n", input.chTitle );
1137  if( j != 0 )
1138  {
1139  fprintf( ioQQQ, " Cooling: " );
1140  for( i=0; i < j; i++ )
1141  {
1142  fprintf( ioQQQ, " %4.4s ",
1143  LineSv[ipNegIntensity[i]].chALab);
1144 
1145  prt_wl( ioQQQ, LineSv[ipNegIntensity[i]].wavelength );
1146 
1147  fprintf( ioQQQ, ":%5.3f",
1148  d[i] );
1149  }
1150  fprintf( ioQQQ, " \n" );
1151  }
1152 
1153  /* now find strongest heating, more that 5% of total */
1154  j = 0;
1155  for( i=0; i < LineSave.nsum; i++ )
1156  {
1157  a = (double)LineSv[i].SumLine[0]/(double)thermal.power;
1158  if( (a >= 0.05) && LineSv[i].chSumTyp == 'h' )
1159  {
1160  ipNegIntensity[j] = i;
1161  d[j] = a;
1162  j = MIN2(j+1,7);
1163  }
1164  }
1165 
1166  if( j != 0 )
1167  {
1168  fprintf( ioQQQ, " Heating: " );
1169  for( i=0; i < j; i++ )
1170  {
1171  fprintf( ioQQQ, " %4.4s ",
1172  LineSv[ipNegIntensity[i]].chALab);
1173 
1174  prt_wl(ioQQQ, LineSv[ipNegIntensity[i]].wavelength);
1175 
1176  fprintf( ioQQQ, ":%5.3f",
1177  d[i] );
1178  }
1179  fprintf( ioQQQ, " \n" );
1180  }
1181 
1182  // don't print this text twice...
1183  if( !prt.lgPrtCitations )
1184  {
1185  fprintf( ioQQQ, "\n" );
1187  }
1188 
1189  /* print out ionization parameters and radiation making it through */
1190  qlow = 0.;
1191  plow = 0.;
1192  for( i=0; i < (iso_sp[ipH_LIKE][ipHYDROGEN].fb[ipH1s].ipIsoLevNIonCon - 1); i++ )
1193  {
1194  /* N.B. in following en1ryd prevents overflow */
1195  plow += (rfield.flux[0][i] + rfield.ConInterOut[i]+ rfield.outlin[0][i] + rfield.outlin_noplot[i])*
1196  EN1RYD*rfield.anu[i];
1197  qlow += rfield.flux[0][i] + rfield.ConInterOut[i]+ rfield.outlin[0][i] + rfield.outlin_noplot[i];
1198  }
1199 
1200  qlow *= radius.r1r0sq;
1201  plow *= radius.r1r0sq;
1202  if( plow > 0. )
1203  {
1204  qlow = log10(qlow) + radius.Conv2PrtInten;
1205  plow = log10(plow) + radius.Conv2PrtInten;
1206  }
1207  else
1208  {
1209  qlow = 0.;
1210  plow = 0.;
1211  }
1212 
1213  qion = 0.;
1214  pion = 0.;
1215  for( i=iso_sp[ipH_LIKE][ipHYDROGEN].fb[ipH1s].ipIsoLevNIonCon-1; i < rfield.nflux; i++ )
1216  {
1217  /* N.B. in following en1ryd prevents overflow */
1218  pion += (rfield.flux[0][i] + rfield.ConInterOut[i]+ rfield.outlin[0][i] + rfield.outlin_noplot[i])*
1219  EN1RYD*rfield.anu[i];
1220  qion += rfield.flux[0][i] + rfield.ConInterOut[i]+ rfield.outlin[0][i] + rfield.outlin_noplot[i];
1221  }
1222 
1223  qion *= radius.r1r0sq;
1224  pion *= radius.r1r0sq;
1225 
1226  if( pion > 0. )
1227  {
1228  qion = log10(qion) + radius.Conv2PrtInten;
1229  pion = log10(pion) + radius.Conv2PrtInten;
1230  }
1231  else
1232  {
1233  qion = 0.;
1234  pion = 0.;
1235  }
1236 
1237  /* derive ionization parameter for spherical geometry */
1238  if( rfield.qhtot > 0. )
1239  {
1240  if( rfield.lgUSphON )
1241  {
1242  /* RSTROM is stromgren radius */
1244  2.998e10/dense.gas_phase[ipHYDROGEN];
1245  usp = log10(usp);
1246  }
1247  else
1248  {
1249  /* no stromgren radius found, use outer radius */
1251  usp = log10(usp);
1252  }
1253  }
1254 
1255  else
1256  {
1257  usp = -37.;
1258  }
1259 
1260  if( rfield.uh > 0. )
1261  {
1262  uhl = log10(rfield.uh);
1263  }
1264  else
1265  {
1266  uhl = -37.;
1267  }
1268 
1269  if( rfield.uheii > 0. )
1270  {
1271  uhel = log10(rfield.uheii);
1272  }
1273  else
1274  {
1275  uhel = -37.;
1276  }
1277 
1278  fprintf( ioQQQ,
1279  "\n IONIZE PARMET: U(1-)%8.4f U(4-):%8.4f U(sp):%6.2f "
1280  "Q(ion): %7.3f L(ion)%7.3f Q(low):%7.3f L(low)%7.3f\n",
1281  uhl, uhel, usp, qion, pion, qlow, plow );
1282 
1283  a = fabs((thermal.power-thermal.totcol)*100.)/thermal.power;
1284  /* output power and total cooling; can be neg for shocks, collisional ioniz */
1285  if( thermal.power > 0. )
1286  {
1287  powerl = log10(thermal.power) + radius.Conv2PrtInten;
1288  }
1289  else
1290  {
1291  powerl = 0.;
1292  }
1293 
1294  if( thermal.totcol > 0. )
1295  {
1297  }
1298  else
1299  {
1300  thermal.totcol = 0.;
1301  }
1302 
1303  if( thermal.FreeFreeTotHeat > 0. )
1304  {
1306  }
1307  else
1308  {
1309  thermal.FreeFreeTotHeat = 0.;
1310  }
1311 
1312  /* following is recombination line intensity */
1313  reclin = totlin('r');
1314  if( reclin > 0. )
1315  {
1316  reclin = log10(reclin) + radius.Conv2PrtInten;
1317  }
1318  else
1319  {
1320  reclin = 0.;
1321  }
1322 
1323  fprintf( ioQQQ,
1324  " ENERGY BUDGET: Heat:%8.3f Coolg:%8.3f Error:%5.1f%% Rec Lin:%8.3f F-F H%7.3f P(rad/tot)max ",
1325  powerl,
1326  thermal.totcol,
1327  a,
1328  reclin,
1331  fprintf( ioQQQ, "\n");
1332 
1333  /* effective x-ray column density, from 0.5keV attenuation, no scat
1334  * IPXRY is pointer to 73.5 Ryd */
1335  coleff = opac.TauAbsGeo[0][rt.ipxry-1] - rt.tauxry;
1336  coleff /= 2.14e-22;
1337 
1338  /* find t^2 from H II structure */
1339  gett2(&peimbt.t2hstr);
1340 
1341  /* find t^2 from OIII structure */
1343 
1344  fprintf( ioQQQ, "\n Col(Heff): ");
1345  PrintE93(ioQQQ, coleff);
1346  fprintf( ioQQQ, " snd travl time ");
1348  fprintf( ioQQQ, " sec Te-low: ");
1350  fprintf( ioQQQ, " Te-hi: ");
1352 
1353  /* this is the intensity of the UV continuum at the illuminated face, relative to the Habing value, as
1354  * defined by Tielens & Hollenbach 1985 */
1355  fprintf( ioQQQ, " G0TH85: ");
1357  /* this is the intensity of the UV continuum at the illuminated face, relative to the Habing value, as
1358  * defined by Draine & Bertoldi 1985 */
1359  fprintf( ioQQQ, " G0DB96:");
1361 
1362  fprintf( ioQQQ, "\n");
1363 
1364  fprintf( ioQQQ, " Emiss Measure n(e)n(p) dl ");
1366  fprintf( ioQQQ, " n(e)n(He+)dl ");
1368  fprintf( ioQQQ, " En(e)n(He++) dl ");
1370  fprintf( ioQQQ, " ne nC+:");
1372  fprintf( ioQQQ, "\n");
1373 
1374  /* following is wl where gas goes thick to bremsstrahlung, in cm */
1375  if( rfield.EnergyBremsThin > 0. )
1376  {
1377  bremtk = RYDLAM*1e-8/rfield.EnergyBremsThin;
1378  }
1379  else
1380  {
1381  bremtk = 1e30;
1382  }
1383 
1384  /* apparent helium abundance */
1385  fprintf( ioQQQ, " He/Ha:");
1386  PrintE82( ioQQQ, heabun);
1387 
1388  /* he/h relative to correct helium abundance */
1389  fprintf(ioQQQ, " =%7.2f*true Lthin:",hescal);
1390 
1391  /* wavelength were structure is optically thick to bremsstrahlung absorption */
1392  PrintE82( ioQQQ, bremtk);
1393 
1394  /* this is ratio of conv.nTotalIoniz, the number of times ConvBase
1395  * was called during the model, over the number of zones.
1396  * This is a measure of the convergence of the model -
1397  * includes initial search so worse for short calculations.
1398  * It is a measure of how hard the model was to converge */
1399  if( nzone > 0 )
1400  {
1401  /* >>chng 07 feb 23, subtract n calls to do initial solution
1402  * so this is the number of calls needed to converge the zones.
1403  * different is to discount careful approach to molecular solutions
1404  * in one zone models */
1405  znit = (double)(conv.nTotalIoniz-conv.nTotalIoniz_start)/(double)(nzone);
1406  }
1407  else
1408  {
1409  znit = 0.;
1410  }
1411  /* >>chng 02 jan 09, format from 5.3f to 5.2f */
1412  fprintf(ioQQQ, " itr/zn:%5.2f",znit);
1413 
1414  /* sort-of same thing for large H2 molecule - number is number of level pop solutions per zone */
1415  fprintf(ioQQQ, " H2 itr/zn:%6.2f",h2.H2_itrzn());
1416 
1417  /* say whether we used stored opacities (T) or derived them from scratch (F) */
1418  fprintf(ioQQQ, " File Opacity: F" );
1419 
1420  /* log of total mass in grams if spherical, or gm/cm2 if plane parallel */
1421  /* this is mass per unit inner area */
1422  double xmass;
1423  // if spherical change to total mass, if pp leave gm/cm2
1424  if( radius.pirsq > 0. )
1425  {
1426  chUnit = "(gm)";
1427  xmass = dense.xMassTotal * pow(10., (double)radius.pirsq ) ;
1428  }
1429  else
1430  {
1431  chUnit = "(gm/cm^2)";
1432  xmass = dense.xMassTotal;
1433  }
1434  fprintf(ioQQQ," MassTot %.2e %s", xmass, chUnit );
1435  fprintf(ioQQQ,"\n");
1436 
1437  /* this block is a series of prints dealing with 21 cm quantities
1438  * first this is the temperature derived from Lya - 21 cm optical depths
1439  * get harmonic mean HI temperature, as needed for 21 cm spin temperature */
1440  if( cdTemp( "opti",0,&THI,"volume" ) )
1441  {
1442  fprintf(ioQQQ,"\n>>>>>>>>>>>>>>>>> PrtFinal, impossible problem getting 21cm opt.\n");
1443  TotalInsanity();
1444  }
1445  fprintf( ioQQQ, " Temps(21 cm) T(21cm/Ly a) ");
1446  PrintE82(ioQQQ, THI );
1447 
1448  /* get harmonic mean HI gas kin temperature, as needed for 21 cm spin temperature
1449  * >>chng 06 jul 21, this was over volume but hazy said radius - change to radius,
1450  * bug discovered by Eric Pellegrini & Jack Baldwin */
1451  /*if( cdTemp( "21cm",0,&THI,"volume" ) )*/
1452  if( cdTemp( "21cm",0,&THI,"radius" ) )
1453  {
1454  fprintf(ioQQQ,"\n>>>>>>>>>>>>>>>>> PrtFinal, impossible problem getting 21cm temp.\n");
1455  TotalInsanity();
1456  }
1457  fprintf(ioQQQ, " T(<nH/Tkin>) ");
1458  PrintE82(ioQQQ, THI);
1459 
1460  /* get harmonic mean HI 21 21 spin temperature, as needed for 21 cm spin temperature
1461  * for this, always weighted by radius, volume would be ignored were it present */
1462  if( cdTemp( "spin",0,&THI,"radius" ) )
1463  {
1464  fprintf(ioQQQ,"\n>>>>>>>>>>>>>>>>> PrtFinal, impossible problem getting 21cm spin.\n");
1465  TotalInsanity();
1466  }
1467  fprintf(ioQQQ, " T(<nH/Tspin>) ");
1468  PrintE82(ioQQQ, THI);
1469 
1470  /* now convert this HI spin temperature into a brightness temperature */
1471  THI *= (1. - sexp( HFLines[0].Emis().TauIn() ) );
1472  fprintf( ioQQQ, " TB21cm:");
1473  PrintE82(ioQQQ, THI);
1474  fprintf( ioQQQ, "\n");
1475 
1476  fprintf( ioQQQ, " N(H0/Tspin) ");
1478  fprintf( ioQQQ, " N(OH/Tkin) ");
1480 
1481  /* mean B weighted wrt 21 cm absorption */
1482  bot = cdB21cm();
1483  fprintf( ioQQQ, " B(21cm) ");
1484  PrintE82(ioQQQ, bot );
1485 
1486  /* end prints for 21 cm */
1487  fprintf(ioQQQ, "\n");
1488 
1489  /* timescale (sec here) for photoerosion of Fe-Ni */
1490  rate = timesc.TimeErode*2e-26;
1491  if( rate > SMALLFLOAT )
1492  {
1493  ferode = 1./rate;
1494  }
1495  else
1496  {
1497  ferode = 0.;
1498  }
1499 
1500  /* mean acceleration */
1501  if( wind.acldr > 0. )
1502  {
1503  wind.AccelAver /= wind.acldr;
1504  }
1505  else
1506  {
1507  wind.AccelAver = 0.;
1508  }
1509 
1510  /* DMEAN is mean density (gm per cc); mean temp is weighted by mass density */
1511  wmean = colden.wmas/SDIV(colden.TotMassColl);
1512  /* >>chng 02 aug 21, from radius.depth_x_fillfac to integral of radius times fillfac */
1514  tmean = colden.tmas/SDIV(colden.TotMassColl);
1515  /* mean mass per particle */
1516  wmean = colden.wmas/SDIV(colden.TotMassColl);
1517 
1518  fprintf( ioQQQ, " <a>:");
1520  fprintf( ioQQQ, " erdeFe");
1521  PrintE71(ioQQQ , ferode);
1522  fprintf( ioQQQ, " Tcompt");
1524  fprintf( ioQQQ, " Tthr");
1526  fprintf( ioQQQ, " <Tden>: ");
1527  PrintE82(ioQQQ , tmean);
1528  fprintf( ioQQQ, " <dens>:");
1529  PrintE82(ioQQQ , dmean);
1530  fprintf( ioQQQ, " <MolWgt>");
1531  PrintE82(ioQQQ , wmean);
1532  fprintf(ioQQQ,"\n");
1533 
1534  /* log of Jeans length and mass - this is mean over model */
1535  if( tmean > 0. )
1536  {
1537  rjeans = 7.79637 + (log10(tmean) - log10(dense.wmole) - log10(dense.xMassDensity*
1538  geometry.FillFac))/2.;
1539  }
1540  else
1541  {
1542  /* tmean undefined, set rjeans to large value so 0 printed below */
1543  rjeans = 40.f;
1544  }
1545 
1546  if( rjeans < 36. )
1547  {
1548  rjeans = (double)pow(10.,rjeans);
1549  /* AJMASS is Jeans mass in solar units */
1550  ajmass = 3.*log10(rjeans/2.) + log10(4.*PI/3.*dense.xMassDensity*
1551  geometry.FillFac) - log10(SOLAR_MASS);
1552  if( ajmass < 37 )
1553  {
1554  ajmass = pow(10.,ajmass);
1555  }
1556  else
1557  {
1558  ajmass = 0.;
1559  }
1560  }
1561  else
1562  {
1563  rjeans = 0.;
1564  ajmass = 0.;
1565  }
1566 
1567  /* Jeans length and mass - this is smallest over model */
1568  ajmin = colden.ajmmin - log10(SOLAR_MASS);
1569  if( ajmin < 37 )
1570  {
1571  ajmin = pow(10.,ajmin);
1572  }
1573  else
1574  {
1575  ajmin = 0.;
1576  }
1577 
1578  /* estimate alpha (o-x) */
1579  if( rfield.anu[rfield.nflux-1] > 150. )
1580  {
1581  /* generate pointers to energies where alpha ox will be evaluated */
1582  ip2kev = ipoint(147.);
1583  ip2500 = ipoint(0.3648);
1584 
1585  /* now get fluxes there */
1586  bottom = rfield.flux[0][ip2500-1]*
1587  rfield.anu[ip2500-1]/rfield.widflx[ip2500-1];
1588 
1589  top = rfield.flux[0][ip2kev-1]*
1590  rfield.anu[ip2kev-1]/rfield.widflx[ip2kev-1];
1591 
1592  /* generate alpha ox if denominator is non-zero */
1593  if( bottom > 1e-30 && top > 1e-30 )
1594  {
1595  ratio = log10(top) - log10(bottom);
1596  if( ratio < 36. && ratio > -36. )
1597  {
1598  ratio = pow(10.,ratio);
1599  }
1600  else
1601  {
1602  ratio = 0.;
1603  }
1604  }
1605 
1606  else
1607  {
1608  ratio = 0.;
1609  }
1610 
1611  if( ratio > 0. )
1612  {
1613  // the separate variable freq_ratio is needed to work around a bug in icc 10.0
1614  double freq_ratio = rfield.anu[ip2kev-1]/rfield.anu[ip2500-1];
1615  alfox = log(ratio)/log(freq_ratio);
1616  }
1617  else
1618  {
1619  alfox = 0.;
1620  }
1621  }
1622  else
1623  {
1624  alfox = 0.;
1625  }
1626 
1627  if( colden.rjnmin < 37 )
1628  {
1629  colden.rjnmin = (realnum)pow((realnum)10.f,colden.rjnmin);
1630  }
1631  else
1632  {
1633  colden.rjnmin = FLT_MAX;
1634  }
1635 
1636  fprintf( ioQQQ, " Mean Jeans l(cm)");
1637  PrintE82(ioQQQ, rjeans);
1638  fprintf( ioQQQ, " M(sun)");
1639  PrintE82(ioQQQ, ajmass);
1640  fprintf( ioQQQ, " smallest: len(cm):");
1642  fprintf( ioQQQ, " M(sun):");
1643  PrintE82(ioQQQ, ajmin);
1644  fprintf( ioQQQ, " a_ox tran:%6.2f\n" , alfox);
1645 
1646  fprintf( ioQQQ, " Rion:");
1647  double R_ion;
1648  if( rfield.lgUSphON )
1649  R_ion = rfield.rstrom;
1650  else
1651  R_ion = radius.Radius;
1652  PrintE93(ioQQQ, R_ion);
1653  fprintf( ioQQQ, " Dist:");
1655  fprintf( ioQQQ, " Diam:");
1656  if( radius.distance > 0. )
1657  PrintE93(ioQQQ, 2.*R_ion*AS1RAD/radius.distance);
1658  else
1659  PrintE93(ioQQQ, 0.);
1660  fprintf( ioQQQ, "\n");
1661 
1662  if( prt.lgPrintTime )
1663  {
1664  /* print execution time by default */
1665  alfox = cdExecTime();
1666  }
1667  else
1668  {
1669  /* flag set false with no time command, so that different runs can
1670  * compare exactly */
1671  alfox = 0.;
1672  }
1673 
1674  /* some details about the hydrogen and helium ions */
1675  fprintf( ioQQQ,
1676  " Hatom level%3ld HatomType:%4.4s HInducImp %2c"
1677  " He tot level:%3ld He2 level: %3ld ExecTime%8.1f\n",
1678  /* 06 aug 28, from numLevels_max to _local. */
1679  iso_sp[ipH_LIKE][ipHYDROGEN].numLevels_local,
1680  hydro.chHTopType,
1682  /* 06 aug 28, from numLevels_max to _local. */
1684  /* 06 aug 28, from numLevels_max to _local. */
1685  iso_sp[ipH_LIKE][ipHELIUM].numLevels_local ,
1686  alfox );
1687 
1688  /* now give an indication of the convergence error budget */
1689  fprintf( ioQQQ,
1690  " ConvrgError(%%) <eden>%7.3f MaxEden%7.3f <H-C>%7.2f Max(H-C)%8.2f <Press>%8.3f MaxPrs er%7.3f\n",
1691  conv.AverEdenError/nzone*100. ,
1692  conv.BigEdenError*100. ,
1693  conv.AverHeatCoolError/nzone*100. ,
1694  conv.BigHeatCoolError*100. ,
1695  conv.AverPressError/nzone*100. ,
1696  conv.BigPressError*100. );
1697 
1698  fprintf(ioQQQ,
1699  " Continuity(%%) chng Te%6.1f elec den%6.1f n(H2)%7.1f n(CO) %7.1f\n",
1700  phycon.BigJumpTe*100. ,
1701  phycon.BigJumpne*100. ,
1702  phycon.BigJumpH2*100. ,
1703  phycon.BigJumpCO*100. );
1704 
1705  /* print out some average quantities */
1706  fprintf( ioQQQ, "\n Averaged Quantities\n" );
1707  fprintf( ioQQQ, " Te Te(Ne) Te(NeNp) Te(NeHe+)Te(NeHe2+) Te(NeO+) Te(NeO2+)"
1708  " Te(H2) N(H) Ne(O2+) Ne(Np)\n" );
1709  static const char* weight[3] = { "Radius", "Area", "Volume" };
1710  int dmax = geometry.lgGeoPP ? 1 : 3;
1711  for( int dim=0; dim < dmax; ++dim )
1712  {
1713  fprintf( ioQQQ, " %6s:", weight[dim] );
1714  // <Te>/<1>
1715  PrintRatio( mean.TempMean[dim][0], mean.TempMean[dim][1] );
1716  // <Te*ne>/<ne>
1717  PrintRatio( mean.TempEdenMean[dim][0], mean.TempEdenMean[dim][1] );
1718  // <Te*ne*nion>/<ne*nion>
1719  PrintRatio( mean.TempIonEdenMean[dim][ipHYDROGEN][1][0], mean.TempIonEdenMean[dim][ipHYDROGEN][1][1] );
1720  PrintRatio( mean.TempIonEdenMean[dim][ipHELIUM][1][0], mean.TempIonEdenMean[dim][ipHELIUM][1][1] );
1721  PrintRatio( mean.TempIonEdenMean[dim][ipHELIUM][2][0], mean.TempIonEdenMean[dim][ipHELIUM][2][1] );
1722  PrintRatio( mean.TempIonEdenMean[dim][ipOXYGEN][1][0], mean.TempIonEdenMean[dim][ipOXYGEN][1][1] );
1723  PrintRatio( mean.TempIonEdenMean[dim][ipOXYGEN][2][0], mean.TempIonEdenMean[dim][ipOXYGEN][2][1] );
1724  // <Te*nH2>/<nH2>
1725  PrintRatio( mean.TempIonMean[dim][ipHYDROGEN][2][0], mean.TempIonMean[dim][ipHYDROGEN][2][1] );
1726  // <nH>/<1>
1727  PrintRatio( mean.xIonMean[dim][ipHYDROGEN][0][1], mean.TempMean[dim][1] );
1728  // <ne*nion>/<nion>
1729  PrintRatio( mean.TempIonEdenMean[dim][ipOXYGEN][2][1], mean.TempIonMean[dim][ipOXYGEN][2][1] );
1730  PrintRatio( mean.TempIonEdenMean[dim][ipHYDROGEN][1][1], mean.TempIonMean[dim][ipHYDROGEN][1][1] );
1731  fprintf( ioQQQ, "\n" );
1732  }
1733 
1734  /* print out Peimbert analysis, tsqden default 1e7, changed
1735  * with set tsqden command */
1737  {
1738  fprintf( ioQQQ, " \n" );
1739 
1740  /* temperature from the [OIII] 5007/4363 ratio */
1741  fprintf( ioQQQ, " Peimbert T(OIIIr)");
1743 
1744  /* temperature from predicted Balmer jump relative to Hbeta */
1745  fprintf( ioQQQ, " T(Bac)");
1746  PrintE82( ioQQQ , peimbt.tbac);
1747 
1748  /* temperature predicted from optically thin Balmer jump rel to Hbeta */
1749  fprintf( ioQQQ, " T(Hth)");
1751 
1752  /* t^2 predicted from the structure, weighted by H */
1753  fprintf( ioQQQ, " t2(Hstrc)");
1754  fprintf( ioQQQ,PrintEfmt("%9.2e", peimbt.t2hstr));
1755 
1756  /* temperature from both [OIII] and the Balmer jump rel to Hbeta */
1757  fprintf( ioQQQ, " T(O3-BAC)");
1759 
1760  /* t2 from both [OIII] and the Balmer jump rel to Hbeta */
1761  fprintf( ioQQQ, " t2(O3-BC)");
1762  fprintf( ioQQQ,PrintEfmt("%9.2e", peimbt.t2hyox));
1763 
1764  /* structural t2 from the O+2 predicted radial dependence */
1765  fprintf( ioQQQ, " t2(O3str)");
1766  fprintf( ioQQQ,PrintEfmt("%9.2e", peimbt.t2o3str));
1767 
1768  fprintf( ioQQQ, "\n");
1769 
1770  if( gv.lgDustOn() )
1771  {
1772  fprintf( ioQQQ, " Be careful: grains exist. This spectrum was not corrected for reddening before analysis.\n" );
1773  }
1774  }
1775 
1776  /* print average (over radius) grain dust parameters if lgDustOn() is true,
1777  * average quantities are incremented in radius_increment, zeroed in IterStart */
1778  if( gv.lgDustOn() && gv.lgGrainPhysicsOn )
1779  {
1780  char chQHeat;
1781  double AV , AB;
1782  double total_dust2gas = 0.;
1783 
1784  fprintf( ioQQQ, "\n Average Grain Properties (over radius):\n" );
1785 
1786  for( size_t i0=0; i0 < gv.bin.size(); i0 += 10 )
1787  {
1788  if( i0 > 0 )
1789  fprintf( ioQQQ, "\n" );
1790 
1791  /* this is upper limit to how many grain species we will print across line */
1792  size_t i1 = min(i0+10,gv.bin.size());
1793 
1794  fprintf( ioQQQ, " " );
1795  for( size_t nd=i0; nd < i1; nd++ )
1796  {
1797  chQHeat = (char)(gv.bin[nd]->lgEverQHeat ? '*' : ' ');
1798  fprintf( ioQQQ, "%-12.12s%c", gv.bin[nd]->chDstLab, chQHeat );
1799  }
1800  fprintf( ioQQQ, "\n" );
1801 
1802  fprintf( ioQQQ, " nd:" );
1803  for( size_t nd=i0; nd < i1; nd++ )
1804  {
1805  if( nd != i0 ) fprintf( ioQQQ," " );
1806  fprintf( ioQQQ, "%7ld ", (unsigned long)nd );
1807  }
1808  fprintf( ioQQQ, "\n" );
1809 
1810  fprintf( ioQQQ, " <Tgr>:" );
1811  for( size_t nd=i0; nd < i1; nd++ )
1812  {
1813  if( nd != i0 ) fprintf( ioQQQ," " );
1814  fprintf( ioQQQ,PrintEfmt("%10.3e", gv.bin[nd]->avdust/radius.depth_x_fillfac));
1815  }
1816  fprintf( ioQQQ, "\n" );
1817 
1818  fprintf( ioQQQ, " <Vel>:" );
1819  for( size_t nd=i0; nd < i1; nd++ )
1820  {
1821  if( nd != i0 ) fprintf( ioQQQ," " );
1822  fprintf( ioQQQ,PrintEfmt("%10.3e", gv.bin[nd]->avdft/radius.depth_x_fillfac));
1823  }
1824  fprintf( ioQQQ, "\n" );
1825 
1826  fprintf( ioQQQ, " <Pot>:" );
1827  for( size_t nd=i0; nd < i1; nd++ )
1828  {
1829  if( nd != i0 ) fprintf( ioQQQ," " );
1830  fprintf( ioQQQ,PrintEfmt("%10.3e", gv.bin[nd]->avdpot/radius.depth_x_fillfac));
1831  }
1832  fprintf( ioQQQ, "\n" );
1833 
1834  fprintf( ioQQQ, " <D/G>:" );
1835  for( size_t nd=i0; nd < i1; nd++ )
1836  {
1837  if( nd != i0 ) fprintf( ioQQQ," " );
1838  fprintf( ioQQQ,PrintEfmt("%10.3e", gv.bin[nd]->avDGRatio/radius.depth_x_fillfac));
1839  /* add up total dust to gas mass ratio */
1840  total_dust2gas += gv.bin[nd]->avDGRatio/radius.depth_x_fillfac;
1841  }
1842  fprintf( ioQQQ, "\n" );
1843  }
1844 
1845  fprintf(ioQQQ," Dust to gas ratio (by mass):");
1846  fprintf(ioQQQ,PrintEfmt("%10.3e", total_dust2gas));
1847 
1848  /* total extinction (conv to mags) at V and B per hydrogen, this includes
1849  * forward scattering as an extinction process, so is what would be measured
1850  * for a star, but not for an extended source where forward scattering
1851  * should be discounted */
1854  /* print A_V/N(Htot) for point and extended sources */
1855  fprintf(ioQQQ,", A(V)/N(H)(pnt):%.3e, (ext):%.3e",
1856  AV,
1858 
1859  /* ratio of total to selective extinction */
1860  fprintf(ioQQQ,", R:");
1861 
1862  /* gray grains have AB - AV == 0 */
1863  if( fabs(AB-AV)>SMALLFLOAT )
1864  {
1865  fprintf(ioQQQ,"%.3e", AV/(AB-AV) );
1866  }
1867  else
1868  {
1869  fprintf(ioQQQ,"%.3e", 0. );
1870  }
1871  fprintf(ioQQQ," AV(ext):%.3e (pnt):%.3e\n",
1874  }
1875 
1876  /* now release saved arrays */
1877  free( wavelength );
1878  free( ipSortLines );
1879  free( sclsav );
1880  free( lgPrt );
1881  free( chSTyp );
1882 
1883  /* now return the space claimed for the chSLab array */
1884  for( i=0; i < LineSave.nsum; ++i )
1885  {
1886  free( chSLab[i] );
1887  }
1888  free( chSLab );
1889 
1890  free( scaled );
1891  free( xLog_line_lumin );
1892 
1893  /* option to make short printout */
1894  if( !prt.lgPrtShort && called.lgTalk )
1895  {
1896  /* print log of optical depths,
1897  * calls prtmet if print line optical depths command entered */
1898  PrtAllTau();
1899 
1900  /* only print mean ionization and emergent continuum on last iteration */
1901  if( iterations.lgLastIt )
1902  {
1903  /* option to print column densities, set with print column density command */
1904  if( prt.lgPrintColumns )
1905  PrtColumns(ioQQQ,"PRETTY" , -1);
1906  /* print mean ionization fractions for all elements */
1907  PrtMeanIon('i', false, ioQQQ);
1908  /* print mean ionization fractions for all elements with density weighting*/
1909  PrtMeanIon('i', true , ioQQQ);
1910  /* print mean temperature fractions for all elements */
1911  PrtMeanIon('t', false , ioQQQ);
1912  /* print mean temperature fractions for all elements with density weighting */
1913  PrtMeanIon('t', true , ioQQQ);
1914  }
1915  }
1916 
1917  /* print input title for model */
1918  fprintf( ioQQQ, "%s\n\n", input.chTitle );
1919  fflush(ioQQQ);
1920  return;
1921 }
1922 
1923 /* routine to stuff comments into the stack of comments,
1924  * return is index to this comment */
1925 long int StuffComment( const char * chComment )
1926 {
1927  long int n , i;
1928 
1929  DEBUG_ENTRY( "StuffComment()" );
1930 
1931  /* only do this one time per core load */
1932  if( LineSave.ipass == 0 )
1933  {
1935  {
1936  fprintf( ioQQQ, " Too many comments have been entered into line array; increase the value of NHOLDCOMMENTS.\n" );
1938  }
1939 
1940  /* want this to finally be 33 char long to match format */
1941  static const int NWIDTH = 33;
1942  strcpy( LineSave.chHoldComments[LineSave.nComment], chComment );
1943 
1944  /* current length of this string */
1945  n = (long)strlen( LineSave.chHoldComments[LineSave.nComment] );
1946  for( i=0; i<NWIDTH-n-1-6; ++i )
1947  {
1948  strcat( LineSave.chHoldComments[LineSave.nComment], ".");
1949  }
1950 
1951  strcat( LineSave.chHoldComments[LineSave.nComment], "..");
1952 
1953  for( i=0; i<6; ++i )
1954  {
1955  strcat( LineSave.chHoldComments[LineSave.nComment], " ");
1956  }
1957  }
1958 
1959  ++LineSave.nComment;
1960  return( LineSave.nComment-1 );
1961 }
1962 
1963 /*gett2 analyze computed structure to get structural t^2 */
1964 STATIC void gett2(realnum *tsqr)
1965 {
1966  long int i;
1967 
1968  double tmean;
1969  double a,
1970  as,
1971  b;
1972 
1973  DEBUG_ENTRY( "gett2()" );
1974 
1975  /* get T, t^2 */
1976  a = 0.;
1977  b = 0.;
1978 
1979  ASSERT( nzone < struc.nzlim);
1980  // struc.volstr[] is radius.dVeffAper saved as a function of nzone
1981  // we need this version of radius.dVeff since we want to compare to
1982  // emission lines that react to the APERTURE command
1983  for( i=0; i < nzone; i++ )
1984  {
1985  as = (double)(struc.volstr[i])*(double)(struc.hiistr[i])*
1986  (double)(struc.ednstr[i]);
1987  a += (double)(struc.testr[i])*as;
1988  /* B is used twice below */
1989  b += as;
1990  }
1991 
1992  if( b <= 0. )
1993  {
1994  *tsqr = 0.;
1995  }
1996  else
1997  {
1998  /* following is H+ weighted mean temp over vol */
1999  tmean = a/b;
2000  a = 0.;
2001 
2002  ASSERT( nzone < struc.nzlim );
2003  for( i=0; i < nzone; i++ )
2004  {
2005  as = (double)(struc.volstr[i])*(double)(struc.hiistr[i])*
2006  struc.ednstr[i];
2007  a += (POW2((double)(struc.testr[i]-tmean)))*as;
2008  }
2009  *tsqr = (realnum)(a/(b*(POW2(tmean))));
2010  }
2011 
2012  return;
2013 }
2014 
2015 /*gett2o3 analyze computed [OIII] spectrum to get t^2 */
2017 {
2018  long int i;
2019  double tmean;
2020  double a,
2021  as,
2022  b;
2023 
2024  DEBUG_ENTRY( "gett2o3()" );
2025 
2026  /* get T, t^2 */ a = 0.;
2027  b = 0.;
2029  // struc.volstr[] is radius.dVeffAper saved as a function of nzone
2030  // we need this version of radius.dVeff since we want to compare to
2031  // emission lines that react to the APERTURE command
2032  for( i=0; i < nzone; i++ )
2033  {
2034  as = (double)(struc.volstr[i])*(double)(struc.o3str[i])*
2035  (double)(struc.ednstr[i]);
2036  a += (double)(struc.testr[i])*as;
2037 
2038  /* B is used twice below */
2039  b += as;
2040  }
2041 
2042  if( b <= 0. )
2043  {
2044  *tsqr = 0.;
2045  }
2046 
2047  else
2048  {
2049  /* following is H+ weighted mean temp over vol */
2050  tmean = a/b;
2051  a = 0.;
2052  ASSERT( nzone < struc.nzlim );
2053  for( i=0; i < nzone; i++ )
2054  {
2055  as = (double)(struc.volstr[i])*(double)(struc.o3str[i])*
2056  struc.ednstr[i];
2057  a += (POW2((double)(struc.testr[i]-tmean)))*as;
2058  }
2059  *tsqr = (realnum)(a/(b*(POW2(tmean))));
2060  }
2061  return;
2062 }
long int nSave
Definition: input.h:46
#define MIN2
Definition: cddefines.h:765
realnum toiiir
Definition: peimbt.h:9
bool lgIterAgain
Definition: iterations.h:39
realnum tbac
Definition: peimbt.h:9
realnum wlSort2
Definition: prt.h:109
double totcol
Definition: thermal.h:110
void PrtFinal(void)
Definition: prt_final.cpp:75
realnum BigJumpTe
Definition: phycon.h:106
realnum t2hyox
Definition: peimbt.h:9
double Radius
Definition: radius.h:22
void prt_wl(FILE *ioOUT, realnum wl)
Definition: prt.cpp:13
realnum t2hstr
Definition: peimbt.h:9
realnum * widflx
Definition: rfield.h:65
realnum thist
Definition: thermal.h:56
t_atmdat atmdat
Definition: atmdat.cpp:6
t_thermal thermal
Definition: thermal.cpp:5
void PrintE93(FILE *, double)
Definition: service.cpp:838
t_colden colden
Definition: colden.cpp:5
realnum TimeErode
Definition: timesc.h:48
const int ipHE_LIKE
Definition: iso.h:63
NORETURN void TotalInsanity(void)
Definition: service.cpp:886
t_input input
Definition: input.cpp:12
t_opac opac
Definition: opacity.cpp:5
realnum ** flux
Definition: rfield.h:86
t_struc struc
Definition: struc.cpp:6
bool lgCautns
Definition: warnings.h:56
realnum UV_Cont_rel2_Draine_DB96_face
Definition: hmi.h:73
bool lgWarngs
Definition: warnings.h:56
bool lgPrnHeat
Definition: prt.h:147
const realnum SMALLFLOAT
Definition: cpu.h:178
bool lgPrintLineCumulative
Definition: prt.h:225
realnum EnergyBremsThin
Definition: rfield.h:246
const double AS1RAD
Definition: physconst.h:129
realnum o3cs12
Definition: oxy.h:33
bool lgCylnOn
Definition: radius.h:121
realnum o3br32
Definition: oxy.h:33
realnum * outlin_noplot
Definition: rfield.h:199
realnum wmole
Definition: dense.h:101
static realnum * wavelength
char TorF(bool l)
Definition: cddefines.h:714
const int ipOXYGEN
Definition: cddefines.h:316
#define MAX2
Definition: cddefines.h:786
#define PrintEfmt(F, V)
Definition: cddefines.h:1476
double tcmptn
Definition: timesc.h:16
long int iEmissPower
Definition: geometry.h:61
const double SMALLDOUBLE
Definition: cpu.h:182
realnum BigJumpH2
Definition: phycon.h:106
t_warnings warnings
Definition: warnings.cpp:11
long nMatch(const char *chKey, const char *chCard)
Definition: service.cpp:451
realnum BigHeatCoolError
Definition: conv.h:181
t_conv conv
Definition: conv.cpp:5
realnum * ednstr
Definition: struc.h:25
realnum tmas
Definition: colden.h:90
STATIC void gett2(realnum *tsqr)
Definition: prt_final.cpp:1964
long int nTotalIoniz_start
Definition: conv.h:171
double distance
Definition: radius.h:65
TransitionList HFLines("HFLines",&AnonStates)
t_phycon phycon
Definition: phycon.cpp:6
t_LineSave LineSave
Definition: lines.cpp:5
#define NHOLDCOMMENTS
Definition: lines.h:53
t_dense dense
Definition: dense.cpp:24
realnum AccelAver
Definition: wind.h:46
int cdTemp(const char *chLabel, long int IonStage, double *TeMean, const char *chWeight)
Definition: cddrive.cpp:1602
realnum wavelength
Definition: lines.h:131
sys_float sexp(sys_float x)
Definition: service.cpp:914
realnum AverPressError
Definition: conv.h:186
char chVersion[INPUT_LINE_LENGTH]
Definition: version.h:19
realnum * volstr
Definition: struc.h:25
realnum BigPressError
Definition: conv.h:185
realnum ajmmin
Definition: colden.h:88
const double RYDLAM
Definition: physconst.h:176
bool lgHInducImp
Definition: hydrogenic.h:95
realnum covgeo
Definition: geometry.h:35
bool lgHCaseBOK[2][HS_NZ]
Definition: atmdat.h:193
void PrintCenterLine(FILE *io, const char chLine[], size_t ArrLen, size_t LineLen)
Definition: prt_final.cpp:46
realnum ** outlin
Definition: rfield.h:199
FILE * ioQQQ
Definition: cddefines.cpp:7
realnum AverHeatCoolError
Definition: conv.h:182
void PrtMeanIon(char chType, bool lgDensity, FILE *)
Definition: prt_meanion.cpp:11
realnum FillFac
Definition: geometry.h:19
char chTitle[INPUT_LINE_LENGTH]
Definition: input.h:32
realnum tlowst
Definition: thermal.h:56
long int nzone
Definition: cddefines.cpp:14
bool lgTalk
Definition: called.h:12
realnum rjnmin
Definition: colden.h:88
bool lgPrtCitations
Definition: prt.h:242
t_dynamics dynamics
Definition: dynamics.cpp:44
realnum wlSort1
Definition: prt.h:109
realnum t2o3str
Definition: peimbt.h:9
realnum BigJumpne
Definition: phycon.h:106
vector< freeBound > fb
Definition: iso.h:452
void cap4(char *chCAP, const char *chLab)
Definition: service.cpp:240
void PrtAllTau(void)
Definition: prt_alltau.cpp:15
bool lgSortLineIntensity
Definition: prt.h:105
realnum tohyox
Definition: peimbt.h:9
double SumLine[4]
Definition: lines.h:125
static t_version & Inst()
Definition: cddefines.h:179
bool lgBadStop
Definition: conv.h:253
t_iso_sp iso_sp[NISO][LIMELM]
Definition: iso.cpp:8
double depth_x_fillfac
Definition: radius.h:74
realnum tauxry
Definition: rt.h:253
Wind wind
Definition: wind.cpp:5
bool lgSphere
Definition: geometry.h:24
long int iteration
Definition: cddefines.cpp:16
bool fp_equal(sys_float x, sys_float y, int n=3)
Definition: cddefines.h:816
#define MALLOC(exp)
Definition: cddefines.h:505
char chSumTyp
Definition: lines.h:114
realnum wmas
Definition: colden.h:90
double power
Definition: thermal.h:149
double rinner
Definition: radius.h:22
t_geometry geometry
Definition: geometry.cpp:5
void PrintE71(FILE *, double)
Definition: service.cpp:788
long ipoint(double energy_ryd)
Definition: cont_ipoint.cpp:16
realnum TooFaint
Definition: prt.h:201
#define ipCOL_HTOT
Definition: colden.h:12
#define POW2
Definition: cddefines.h:933
double dlnenCp
Definition: colden.h:55
realnum o3cs13
Definition: oxy.h:33
const int ipH1s
Definition: iso.h:27
LinSv * LineSv
Definition: cdinit.cpp:70
#define STATIC
Definition: cddefines.h:101
multi_arr< double, 2 > TempEdenMean
Definition: mean.h:35
bool lgSurfaceBrightness
Definition: prt.h:138
realnum qhtot
Definition: rfield.h:356
realnum BigJumpCO
Definition: phycon.h:106
t_pressure pressure
Definition: pressure.cpp:5
t_rfield rfield
Definition: rfield.cpp:8
double dlnenHep
Definition: colden.h:49
t_mean mean
Definition: mean.cpp:17
realnum * ConInterOut
Definition: rfield.h:164
STATIC void gett2o3(realnum *tsqr)
Definition: prt_final.cpp:2016
float realnum
Definition: cddefines.h:107
realnum uh
Definition: rfield.h:364
#define EXIT_FAILURE
Definition: cddefines.h:144
double H0_ov_Tspin
Definition: colden.h:58
const realnum BIGFLOAT
Definition: cpu.h:176
double OH_ov_Tspin
Definition: colden.h:61
const int INPUT_LINE_LENGTH
Definition: cddefines.h:258
multi_arr< double, 4 > TempIonEdenMean
Definition: mean.h:23
realnum uheii
Definition: rfield.h:367
bool lgFaintOn
Definition: prt.h:202
bool lgSurfaceBrightness_SR
Definition: prt.h:138
bool lgElmtOn[LIMELM]
Definition: dense.h:146
t_hydro hydro
Definition: hydrogenic.cpp:5
#define cdEXIT(FAIL)
Definition: cddefines.h:438
realnum RadBetaMax
Definition: pressure.h:136
bool lgRadiusKnown
Definition: radius.h:116
long min(int a, long b)
Definition: cddefines.h:727
const double SOLAR_MASS
Definition: physconst.h:71
bool lgGrainPhysicsOn
Definition: grainvar.h:475
diatomics h2("h2", 4100.,&hmi.H2_total, Yan_H2_CS)
bool lgGeoPP
Definition: geometry.h:11
bool lgPrintTime
Definition: prt.h:120
t_iterations iterations
Definition: iterations.cpp:5
realnum rstrom
Definition: rfield.h:372
long int sig_figs
Definition: lines.h:91
const double EN1RYD
Definition: physconst.h:179
bool lgPrtShort
Definition: prt.h:178
realnum UV_Cont_rel2_Habing_TH85_face
Definition: hmi.h:63
double cdExecTime()
Definition: cddrive.cpp:481
t_radius radius
Definition: radius.cpp:5
t_timesc timesc
Definition: timesc.cpp:5
realnum tsqden
Definition: peimbt.h:9
t_prt prt
Definition: prt.cpp:10
realnum pirsq
Definition: radius.h:143
long int nTotalIoniz
Definition: conv.h:166
bool lgPrtLineLog
Definition: prt.h:221
realnum TotMassColl
Definition: colden.h:90
double extin_mag_V_point
Definition: rfield.h:277
bool lgPredLumin
Definition: radius.h:139
long int nzlim
Definition: struc.h:19
double totlin(int chInfo)
long int itermx
Definition: iterations.h:26
realnum gas_phase[LIMELM]
Definition: dense.h:71
double dlnenp
Definition: colden.h:46
double Conv2PrtInten
Definition: radius.h:147
bool lgSortLines
Definition: prt.h:101
#define ASSERT(exp)
Definition: cddefines.h:582
realnum covaper
Definition: geometry.h:44
bool lgLastIt
Definition: iterations.h:36
double * anu
Definition: rfield.h:58
double sound
Definition: timesc.h:27
t_peimbt peimbt
Definition: peimbt.cpp:5
double cdB21cm()
Definition: cddrive.cpp:1561
long int nComment
Definition: lines.h:69
long int cdLine(const char *chLabel, realnum wavelength, double *relint, double *absint)
Definition: cddrive.cpp:1228
double extin_mag_B_point
Definition: rfield.h:277
realnum o3enro
Definition: oxy.h:33
double extin_mag_V_extended
Definition: rfield.h:281
long int ipNormWavL
Definition: lines.h:81
const int ipH_LIKE
Definition: iso.h:62
multi_arr< double, 4 > TempIonMean
Definition: mean.h:21
char chDenseLaw[5]
Definition: dense.h:158
#define DEBUG_ENTRY(funcname)
Definition: cddefines.h:688
const int ipHELIUM
Definition: cddefines.h:310
void PrintRatio(double q1, double q2)
Definition: prt_final.cpp:66
vector< GrainBin * > bin
Definition: grainvar.h:583
realnum AverEdenError
Definition: conv.h:178
multi_arr< double, 2 > TempMean
Definition: mean.h:33
bool lgPrnPump
Definition: prt.h:147
void DatabasePrintReference()
Definition: service.cpp:1745
char chHTopType[5]
Definition: hydrogenic.h:80
realnum ** TauAbsGeo
Definition: opacity.h:82
t_oxy oxy
Definition: oxy.cpp:5
bool lgPrintFluxEarth
Definition: prt.h:134
bool lgPrintColumns
Definition: prt.h:116
multi_arr< double, 4 > xIonMean
Definition: mean.h:14
realnum o3ex23
Definition: oxy.h:33
sys_float SDIV(sys_float x)
Definition: cddefines.h:956
long int n_initial_relax
Definition: dynamics.h:126
double dlnenHepp
Definition: colden.h:52
double FreeFreeTotHeat
Definition: thermal.h:161
realnum xMassTotal
Definition: dense.h:107
long int nsum
Definition: lines.h:62
realnum * testr
Definition: struc.h:25
bool lgSizeSet
Definition: geometry.h:70
void caps(char *chCard)
Definition: service.cpp:280
char chCardSav[NKRD][INPUT_LINE_LENGTH]
Definition: input.h:32
GrainVar gv
Definition: grainvar.cpp:5
t_hmi hmi
Definition: hmi.cpp:5
double r1r0sq
Definition: radius.h:22
long int ipxry
Definition: rt.h:250
bool lgUSphON
Definition: rfield.h:370
char chHoldComments[NHOLDCOMMENTS][INPUT_LINE_LENGTH]
Definition: lines.h:78
realnum xMassDensity
Definition: dense.h:91
void PrintE82(FILE *, double)
Definition: service.cpp:739
double time_therm_long
Definition: timesc.h:19
bool lgPrnColl
Definition: prt.h:147
bool lgDustOn() const
Definition: grainvar.h:471
const int ipHYDROGEN
Definition: cddefines.h:309
realnum WavlenErrorGet(realnum wavelength)
realnum BigEdenError
Definition: conv.h:220
long int nflux
Definition: rfield.h:43
realnum * hiistr
Definition: struc.h:25
realnum acldr
Definition: wind.h:46
realnum colden[NCOLD]
Definition: colden.h:38
realnum tbcthn
Definition: peimbt.h:9
double H2_itrzn(void)
Definition: mole_h2.cpp:240
long int numLevels_local
Definition: iso.h:498
long int ipass
Definition: lines.h:75
t_called called
Definition: called.cpp:5
realnum * o3str
Definition: struc.h:25
bool lgPrnInwd
Definition: prt.h:147
bool lgAbort
Definition: cddefines.cpp:10
bool lgSortLineWavelength
Definition: prt.h:105
void PrtColumns(FILE *ioMEAN, const char *chType, long int ipPun)
Definition: prt_columns.cpp:14
void spsort(realnum x[], long int n, long int iperm[], int kflag, int *ier)
Definition: service.cpp:1100
const double PI
Definition: physconst.h:29
double ScaleNormLine
Definition: lines.h:94
bool lgPrtLineArray
Definition: prt.h:217
long int StuffComment(const char *chComment)
Definition: prt_final.cpp:1925
t_rt rt
Definition: rt.cpp:5