cloudy  trunk
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
mole_h2_io.cpp
Go to the documentation of this file.
1 /* This file is part of Cloudy and is copyright (C)1978-2022 by Gary J. Ferland and
2  * others. For conditions of distribution and use see copyright notice in license.txt */
3 /*H2_ParseSave parse the save h2 command */
4 /*H2_PunchDo save some properties of the large H2 molecule */
5 /*chMolBranch returns a char with the spectroscopic branch of a transition */
6 /*H2_PunchLineStuff include H2 lines in punched optical depths, etc, called from SaveLineStuff */
7 /*H2_Punch_line_data save line data for H2 molecule */
8 /*H2_Read_hminus_distribution read distribution function for H2 population following formation from H minus */
9 /*H2_ReadDissprob read dissociation probabilities and kinetic energies for all electronic levels */
10 /*H2_ReadEnergies read energies for all electronic levels */
11 /*H2_ReadTransprob read transition probabilities */
12 /*H2_Prt_Zone print H2 info into zone results, called from prtzone for each printed zone */
13 /*H2_ParseSave parse the save h2 command */
14 /*H2_Prt_column_density print H2 info into zone results, called from prtzone for each printed zone */
15 /*H2_LinesAdd add in explicit lines from the large H2 molecule, called by lines_molecules */
16  /*cdH2_Line returns 1 if we found the line,
17  * or false==0 if we did not find the line because ohoto-para transition
18  * or upper level has lower energy than lower level */
19 #include "cddefines.h"
20 #include "cddrive.h"
21 #include "save.h"
22 #include "hmi.h"
23 #include "prt.h"
24 #include "secondaries.h"
25 #include "grainvar.h"
26 #include "input.h"
27 #include "phycon.h"
28 #include "rfield.h"
29 #include "hyperfine.h"
30 #include "thermal.h"
31 #include "lines.h"
32 #include "dense.h"
33 #include "radius.h"
34 #include "colden.h"
35 #include "h2.h"
36 #include "doppvel.h"
37 #include "parser.h"
38 #include "mole.h"
39 
41 
42 /*H2_LinesAdd add in explicit lines from the large H2 molecule, called by lines_molecules */
44 {
45  /* H2 not on, so space not allocated */
46  if( !lgEnabled )
47  return;
48 
49  DEBUG_ENTRY( "H2_LinesAdd()" );
50 
51  for( TransitionList::iterator tr = trans.begin(); tr != rad_end; ++tr )
52  {
53  qList::iterator Hi = ( (*tr).Hi() );
54  if( (*Hi).n() >= nElecLevelOutput ) continue;
55  qList::iterator Lo = ( (*tr).Lo() );
56  /* all ground vib state rotation lines - first is J to J-2 */
57  PutLine( *tr, "diatoms lines", label.c_str() );
58  if( LineSave.ipass == 0 )
59  {
60  H2_SaveLine[(*Hi).n()][(*Hi).v()][(*Hi).J()][(*Lo).n()][(*Lo).v()][(*Lo).J()] = 0.;
61  }
62  else if( LineSave.ipass == 1 )
63  {
64  H2_SaveLine[(*Hi).n()][(*Hi).v()][(*Hi).J()][(*Lo).n()][(*Lo).v()][(*Lo).J()] +=
65  (realnum)( radius.dVeffAper * (*tr).Emis().xObsIntensity() );
66  }
67  }
68 
69  return;
70 }
71 
72 /*H2_ParseSave parse the save h2 command */
74  ostringstream &chHeader)
75 {
76  DEBUG_ENTRY( "H2_ParseSave()" );
77 
78  save.whichDiatomToPrint[save.nsave] = &(*this);
79 
80  /* this provides info on the large H2 molecule */
81  if( p.nMatch("COLU") )
82  {
83  /* save column density */
84  strcpy( save.chSave[save.nsave], "H2cl" );
85 
86  /* this is an option to scan off highest vib and rot states
87  * to save pops - first is limit to vibration, then rotation
88  * if no number is entered then 0 is set and all levels punched */
89  /* now get vib limit */
91  "H2 vibration state",0.0);
92 
93  /* highest rotation */
95  "H2 rotation state",0.0);
96  /* this says whether to save triplets or a matrix for output -
97  * default is triplets, so only check for matrix */
98  if( p.nMatch( "MATR" ) )
99  {
100  /* matrix */
101  save.punarg[save.nsave][2] = 1;
102  sncatf( chHeader, "#vib\trot\tcolumn density\n" );
103  }
104  else
105  {
106  /* triplets */
107  save.punarg[save.nsave][2] = -1;
108  sncatf( chHeader,
109  "#vib\trot\tEner(K)\tcolden\tcolden/stat wght\tLTE colden\tLTE colden/stat wght\n" );
110  }
111  }
112 
113  else if( p.nMatch("COOL") && p.nMatch("MOLE") )
114  {
115  /* net cooling rate per particle */
116  strcpy( save.chSave[save.nsave], "H2cm" );
117  sncatf( chHeader,
118  "#Temp\tLTE cooling per molecule\tNet cooling per molecule\n" );
119  }
120 
121  else if( p.nMatch("COOL") )
122  {
123  /* heating and cooling rates */
124  strcpy( save.chSave[save.nsave], "H2co" );
125  sncatf( chHeader,
126  "#H2 depth\tTemp\ttot cool\tTH Sol\tBig Sol\tTH pht dis\tpht dis\tTH Xcool\tXcool\tNet cool per H2\n" );
127  }
128 
129  else if( p.nMatch("CREA") )
130  {
131  /* H2 creation rates */
132  fprintf( ioQQQ, " This command has been superseded by the \"creation\" option of the \"save chemistry rates\" command.\n" );
133  fprintf( ioQQQ, " Sorry.\n" );
135  }
136  else if( p.nMatch("DEST") )
137  {
138  /* save H2 destruction - output destruction rates */
139  fprintf( ioQQQ, " This command has been superseded by the \"destruction\" option of the \"save chemistry rates\" command.\n" );
140  fprintf( ioQQQ, " Sorry.\n" );
142  }
143 
144  else if( p.nMatch("HEAT") )
145  {
146  /* heating and cooling rates */
147  strcpy( save.chSave[save.nsave], "H2he" );
148  sncatf( chHeader,
149  "#H2 depth\ttot Heat\tHeat(big)\tHeat(TH85)\tDissoc(Big)\tDissoc(TH85) \n" );
150  }
151 
152  else if( p.nMatch("LEVE") )
153  {
154  /* save H2 level energies */
155  strcpy( save.chSave[save.nsave], "H2le" );
156  sncatf( chHeader,
157  "#H2 v\tJ\tenergy(wn)\tstat wght\tSum As" );
158  for( int nColl=0; nColl<N_X_COLLIDER; ++nColl )
159  {
160  /* labels for all colliders */
161  sncatf(chHeader,
162  "\tq(u,l,%s)",chH2ColliderLabels[nColl]);
163  }
164  sncatf( chHeader, "\n" );
165  }
166 
167  else if( p.nMatch("LINE") )
168  {
169  /* save H2 lines - all in X */
170  strcpy( save.chSave[save.nsave], "H2ln" );
171  sncatf( chHeader,
172  "#H2 line\tEhi\tVhi\tJhi\tElo\tVlo\tJlo\twl(mic)\twl(lab)\tlog L or I\tI/Inorm\tExcit(hi, K)\tg_u h nu * Aul\n" );
173  /* first optional number changes the threshold of weakest line to print*/
174  /* fe2thresh is intensity relative to normalization line,
175  * normally Hbeta, and is set to zero in zero.c */
176 
177  /* threshold for faintest line to save, default is 1e-4 of norm line */
179  "faintest line to save",1e-4);
180 
181  /* lines from how many electronic states? default is one, just X, and is
182  * obtained with GROUND keyword. ALL will produce all lines from all levels.
183  * else, if a number is present, will be the number. if no number, no keyword,
184  * appear then just ground */
185  if( p.nMatch( "ELEC" ) )
186  {
187  if( p.nMatch(" ALL") )
188  {
189  /* all electronic levels - when done, will set upper limit, the
190  * number of electronic levels actually computed, don't know this yet,
191  * so signify with negative number */
192  nElecLevelOutput = -1;
193  }
194  else if( p.nMatch("GROU") )
195  {
196  /* just the ground electronic state */
197  nElecLevelOutput = 1;
198  }
199  else
200  {
202  "electronic levels for output",1.0);
203  }
204  }
205  }
206 
207  else if( p.nMatch(" PDR") )
208  {
209  /* creation and destruction processes */
210  strcpy( save.chSave[save.nsave], "H2pd" );
211  sncatf( chHeader, "#depth\tn(o-H2)\tn(p-H2)\tSolomon rate TH85\tSolomon rate BD96\tSolomon rate H2 model\n" );
212  }
213  else if( p.nMatch("POPU") )
214  {
215  /* save populations */
216  strcpy( save.chSave[save.nsave], "H2po" );
217 
218  /* this is an option to scan off highest vib and rot states
219  * to save pops - first is limit to vibration, then rotation
220  * if no number is entered then 0 is set and all levels punched */
221  /* now get vib lim */
223  "highest H2 save vibration state",0.0);
224 
225  /* this is limit to rotation quantum index */
227  "highest H2 save rotation state",0.0);
228 
229  if( p.nMatch( "ZONE" ) )
230  {
231  /* save v=0 pops for each zone, all along one line */
232  save.punarg[save.nsave][2] = 0;
233  sncatf( chHeader,
234  "#depth\torth\tpar\te=1 rel pop\te=2 rel pop\tv,J rel pops\n" );
235  }
236  else
237  {
238  /* will not do zone output, only output at the end of the calculation
239  * now check whether to save triplets or a matrix for output -
240  * default is triplets, so only check for matrix */
241  if( p.nMatch( "MATR" ) )
242  {
243  /* matrix */
244  save.punarg[save.nsave][2] = 1;
245  sncatf( chHeader, "#vib\trot\tpops\n" );
246  }
247  else
248  {
249  /* triplets */
250  save.punarg[save.nsave][2] = -1;
251  sncatf( chHeader,
252  "#vib\trot\ts\tenergy(wn)\tpops/H2\told/H2\tpops/g/H2\tdep coef\tFin(Col)\tFout(col)\tRCout\tRRout\tRCin\tRRin\n" );
253  }
254  }
255  }
256 
257  else if( p.nMatch("RATE") )
258  {
259  /* save h2 rates - creation and destruction rates */
260  strcpy( save.chSave[save.nsave], "H2ra" );
261  sncatf( chHeader,
262  "#depth\tN(H2)\tN(H2)/u(H2)\tA_V(star)\tn(Eval)"
263  "\tH2/Htot\trenorm\tfrm grn\tfrmH-\tdstTH85\tBD96\tELWERT\tBigH2\telec->H2g\telec->H2s"
264  "\tG(TH85)\tG(DB96)\tCR\tEleclife\tShield(BD96)\tShield(H2)\tBigh2/G0(spc)\ttot dest"
265  "\tHeatH2Dish_TH85\tHeatH2Dexc_TH85\tHeatDish_BigH2\tHeatDexc_BigH2\thtot\n" );
266  }
267  else if( p.nMatch("SOLO") )
268  {
269  /* rate of Solomon process then fracs of exits from each v, J level */
270  strcpy( save.chSave[save.nsave], "H2so" );
271  sncatf( chHeader,
272  "#depth\tSol tot\tpump/dissoc\tpump/dissoc BigH2\tavH2g\tavH2s\tH2g chem/big H2\tH2s chem/big H2\tfrac H2g BigH2\tfrac H2s BigH2\teHi\tvHi\tJHi\tvLo\tJLo\tfrac\twl(A)\n" );
273  }
274  else if( p.nMatch("SPEC") )
275  {
276  /* special save command*/
277  strcpy( save.chSave[save.nsave], "H2sp" );
278  sncatf( chHeader,
279  "#depth\tspecial\n" );
280  }
281  else if( p.nMatch("TEMP") )
282  {
283  /* various temperatures for neutral/molecular gas */
284  strcpy( save.chSave[save.nsave], "H2te" );
285  sncatf( chHeader,
286  "#depth\tH2/H\tn(1/0)\tn(ortho/para)\tT(1/0)\tT(2/0)\tT(3/0)\tT(3/1)\tT(4/0)\tT(kin)\tT(21cm)\tT_sum(1/0)\tT_sum(2/0)\tT_sum(3/0)\tT_sum(3/1)\tT_sum(4/0) \n");
287  }
288  else if( p.nMatch("THER") )
289  {
290  /* thermal heating cooling processes involving H2 */
291  strcpy( save.chSave[save.nsave], "H2th" );
292  sncatf( chHeader,
293  "#depth\tH2/H\tn(1/0)\tn(ortho/para)\tT(1/0)\tT(2/0)\tT(3/0)\tT(3/1)\tT(4/0)\tT(kin)\tT(21cm)\tT_sum(1/0)\tT_sum(2/0)\tT_sum(3/0)\tT_sum(3/1)\tT_sum(4/0) \n");
294  }
295  else
296  {
297  fprintf( ioQQQ,
298  " There must be a second key; they are RATE, LINE, COOL, COLUMN, _PDR, SOLOmon, TEMP, and POPUlations\n" );
300  }
301  return;
302 }
303 
304 
305 /*H2_Prt_Zone print H2 info into zone results, called from prtzone for each printed zone */
307 {
308  /* no print if H2 not turned on, or not computed for these conditions */
309  if( !lgEnabled || !nCall_this_zone )
310  return;
311 
312  DEBUG_ENTRY( "H2_Prt_Zone()" );
313 
314  fprintf( ioQQQ, " %s density ", label.c_str() );
315  fprintf(ioQQQ,PrintEfmt("%9.2e", (*dense_total)));
316 
317  fprintf( ioQQQ, " orth/par");
319 
320  fprintf( ioQQQ, " v0 J=0,3");
321  fprintf(ioQQQ,PrintEfmt("%9.2e", states[ ipEnergySort[0][0][0] ].Pop() / (*dense_total)));
322  fprintf(ioQQQ,PrintEfmt("%9.2e", states[ ipEnergySort[0][0][1] ].Pop() / (*dense_total)));
323  fprintf(ioQQQ,PrintEfmt("%9.2e", states[ ipEnergySort[0][0][2] ].Pop() / (*dense_total)));
324  fprintf(ioQQQ,PrintEfmt("%9.2e", states[ ipEnergySort[0][0][3] ].Pop() / (*dense_total)));
325 
326  fprintf( ioQQQ, " TOTv=0,3");
327  fprintf(ioQQQ,PrintEfmt("%9.2e", pops_per_vib[0][0] / (*dense_total)));
328  fprintf(ioQQQ,PrintEfmt("%9.2e", pops_per_vib[0][1] / (*dense_total)));
329  fprintf(ioQQQ,PrintEfmt("%9.2e", pops_per_vib[0][2] / (*dense_total)));
330  fprintf(ioQQQ,PrintEfmt("%9.2e", pops_per_vib[0][3] / (*dense_total)));
331  fprintf( ioQQQ, "\n");
332  return;
333 }
334 
336 {
337  /* no print if H2 not turned on, or not computed for these conditions */
338  if( !lgEnabled || !nCall_this_zone )
339  return;
340 
341  DEBUG_ENTRY( "H2_PrtDepartCoef()" );
342 
343  // print departure coefficients
344  fprintf( ioQQQ, " %s departure coefficients\n", label.c_str() );
345  for( long iElec=0; iElec<n_elec_states; ++iElec )
346  {
347  fprintf( ioQQQ, "%li electronic\n", iElec );
348  for( long iVib=0; iVib<=nVib_hi[iElec]; ++iVib )
349  {
350  for( long iRot=0; iRot<Jlowest[iElec]; ++iRot )
351  fprintf( ioQQQ, " -----" );
352  for( long iRot=Jlowest[iElec]; iRot<=nRot_hi[iElec][iVib]; ++iRot )
353  {
354  long i = ipEnergySort[iElec][iVib][iRot];
355  fprintf( ioQQQ, " %5.3f", depart[i] );
356  }
357  fprintf( ioQQQ, "\n" );
358  }
359  fprintf( ioQQQ, "\n" );
360  if( iElec==0 )
361  break;
362  }
363 
364  return;
365 }
366 
367 /*H2_Prt_column_density print H2 info into zone results, called from prtzone for each printed zone */
369  /* this is stream used for io, is stdout when called by final,
370  * is save unit when save output generated */
371  FILE *ioMEAN )
372 
373 {
374  int iVibHi;
375 
376  /* no print if H2 not turned on, or not computed for these conditions */
377  if( !lgEnabled || !nCall_this_zone )
378  return;
379 
380  DEBUG_ENTRY( "H2_Prt_column_density()" );
381 
382  fprintf( ioMEAN, " H2 total ");
383  fprintf(ioMEAN,"%7.3f", log10(SDIV(ortho_colden + para_colden)));
384 
385  fprintf( ioMEAN, " H2 ortho ");
386  fprintf(ioMEAN,"%7.3f", log10(SDIV(ortho_colden)));
387 
388  fprintf( ioMEAN, " para");
389  fprintf(ioMEAN,"%7.3f", log10(SDIV(para_colden)));
390 
391  iVibHi = 0;
392  fprintf( ioMEAN, " v0 J=0,3");
393  fprintf(ioMEAN,"%7.3f", log10(SDIV(H2_X_colden[iVibHi][0])));
394  fprintf(ioMEAN,"%7.3f", log10(SDIV(H2_X_colden[iVibHi][1])));
395  fprintf(ioMEAN,"%7.3f", log10(SDIV(H2_X_colden[iVibHi][2])));
396  fprintf(ioMEAN,"%7.3f", log10(SDIV(H2_X_colden[iVibHi][3])));
397 
398  return;
399 }
400 
401 
402 /*H2_ReadTransprob read transition probabilities */
403 void diatomics::H2_ReadTransprob( long int nelec , TransitionList &trns)
404 {
405  const char* cdDATAFILE[N_ELEC] =
406  {
407  "transprob_X.dat",
408  "transprob_B.dat",
409  "transprob_C_plus.dat",
410  "transprob_C_minus.dat",
411  "transprob_B_primed.dat",
412  "transprob_D_plus.dat",
413  "transprob_D_minus.dat"
414  };
415  FILE *ioDATA;
416  char chLine[FILENAME_PATH_LENGTH_2];
417  long int i, n1, n2, n3;
418  long int iVibHi , iVibLo , iRotHi , iRotLo , iElecHi , iElecLo;
419  bool lgEOL;
420 
421  DEBUG_ENTRY( "H2_ReadTransprob()" );
422 
423  /* now open the data file */
424  char chPath[FILENAME_PATH_LENGTH_2];
425  strcpy( chPath, path.c_str() );
426  strcat( chPath, input.chDelimiter );
427  strcat( chPath, cdDATAFILE[nelec] );
428  ioDATA = open_data( chPath , "r" );
429 
430  /* read the first line and check that magic number is ok */
431  if( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) == NULL )
432  {
433  fprintf( ioQQQ, " H2_ReadTransprob could not read first line of %s\n", cdDATAFILE[nelec]);
435  }
436  i = 1;
437  /* magic number */
438  n1 = (long)FFmtRead(chLine,&i,sizeof(chLine),&lgEOL);
439  n2 = (long)FFmtRead(chLine,&i,sizeof(chLine),&lgEOL);
440  n3 = (long)FFmtRead(chLine,&i,sizeof(chLine),&lgEOL);
441 
442  /* magic number
443  * the following is the set of numbers that appear at the start of level1.dat 01 08 10 */
444  if( ( n1 != 2 ) || ( n2 != 4 ) || ( n3 != 29 ) )
445  {
446  fprintf( ioQQQ,
447  " H2_ReadTransprob: the version of %s is not the current version.\n", cdDATAFILE[nelec] );
448  fprintf( ioQQQ,
449  " I expected to find the number 2 4 29 and got %li %li %li instead.\n" ,
450  n1 , n2 , n3 );
451  fprintf( ioQQQ, "Here is the line image:\n==%s==\n", chLine );
453  }
454 
455  while( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) != NULL )
456  {
457  /* skip comment */
458  if( chLine[0]=='#' )
459  continue;
460  if( chLine[0]=='\n' || chLine[0]=='\0' || chLine[0]==' ' )
461  break;
462 
463  double Aul;
464  if( sscanf(chLine,"%li\t%li\t%li\t%li\t%li\t%li\t%le",
465  &iElecHi , &iVibHi ,&iRotHi , &iElecLo , &iVibLo , &iRotLo , &Aul ) != 7 )
466  {
467  fprintf( ioQQQ, "failed to read correct number of data values from %s\n", chPath );
469  }
470  ASSERT( iElecHi == nelec );
471  ASSERT( iElecHi < N_ELEC );
472  ASSERT( iElecLo < N_ELEC );
473 
474  /* check that we actually included the levels in the model representation */
475  if( iVibHi <= nVib_hi[iElecHi] &&
476  iVibLo <= nVib_hi[iElecLo] &&
477  iRotHi <= nRot_hi[iElecHi][iVibHi] &&
478  iRotLo <= nRot_hi[iElecLo][iVibLo])
479  {
480  long ipHi = ipEnergySort[iElecHi][iVibHi][iRotHi];
481  long ipLo = ipEnergySort[iElecLo][iVibLo][iRotLo];
482  double ener = states[ipHi].energy().WN() - states[ipLo].energy().WN();
483  long lineIndex = ipTransitionSort[ipHi][ipLo];
484 
485  if( lgH2_radiative[ipHi][ipLo] )
486  {
487  // Could be multiple components (e.g., E2 and M1) for the same transition.
488  ASSERT( trns[lineIndex].hasEmis() );
489  trns[lineIndex].Emis().Aul() += (realnum)Aul;
490  }
491  else
492  {
493  /* only lines that have real Aul are added to stack. */
494  trns[lineIndex].AddLine2Stack();
495  trns[lineIndex].Emis().Aul() = (realnum)Aul;
496 
497  /* say that this line exists */
498  lgH2_radiative[ipHi][ipLo] = true;
499  }
500 
501  /* prints transitions with negative energies - should not happen */
502  if( ener <= 0. )
503  {
504  fprintf(ioQQQ,"negative energy H2 transition\t%li\t%li\t%li\t%li\t%.2e\t%.2e\n",
505  iVibHi,iVibLo,iRotHi,iRotLo,Aul,ener);
506  ShowMe();
508  }
509  }
510  }
511 
512  fclose( ioDATA );
513  return;
514 }
515 
516 #if 0
517 /*H2_Read_Cosmicray_distribution read distribution function for H2 population following cosmic ray collisional excitation */
518 void H2_Read_Cosmicray_distribution(void)
519 {
520  //CR_PRINT (false), CR_X (1), CR_VIB(15), CR_J(10), CR_EXIT(3)
521 
522  /*>>refer H2 cr excit Tine, S., Lepp, S., Gredel, R., & Dalgarno, A. 1997, ApJ, 481, 282 */
523  FILE *ioDATA;
524  char chLine[FILENAME_PATH_LENGTH_2];
525  long int i, n1, n2, n3, iVib , iRot;
526  long neut_frac;
527  bool lgEOL;
528 
529  DEBUG_ENTRY( "H2_Read_Cosmicray_distribution()" );
530 
531  /* now open the data file */
532  char chPath[FILENAME_PATH_LENGTH_2];
533  strcpy( chPath, path.c_str() );
534  strcat( chPath, input.chDelimiter );
535  strcat( chPath, "H2_CosmicRay_collision.dat" );
536  ioDATA = open_data( chPath, "r" );
537 
538  /* read the first line and check that magic number is ok */
539  if( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) == NULL )
540  {
541  fprintf( ioQQQ, " H2_Read_Cosmicray_distribution could not read first line of %s\n", "H2_Cosmic_collision.dat");
543  }
544 
545  i = 1;
546  /* magic number */
547  n1 = (long)FFmtRead(chLine,&i,sizeof(chLine),&lgEOL);
548  n2 = (long)FFmtRead(chLine,&i,sizeof(chLine),&lgEOL);
549  n3 = (long)FFmtRead(chLine,&i,sizeof(chLine),&lgEOL);
550 
551  /* magic number
552  * the following is the set of numbers that appear at the start of H2_Cosmic_collision.dat 01 21 03 */
553  if( ( n1 != 1 ) || ( n2 != 21 ) || ( n3 != 3 ) )
554  {
555  fprintf( ioQQQ,
556  " H2_Read_Cosmicray_distribution: the version of %s is not the current version.\n", "H2_Cosmic_collision.dat" );
557  fprintf( ioQQQ,
558  " I expected to find the number 1 21 3 and got %li %li %li instead.\n" ,
559  n1 , n2 , n3 );
560  fprintf( ioQQQ, "Here is the line image:\n==%s==\n", chLine );
562  }
563 
564  /* read until not a comment */
565  if( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) == NULL )
566  BadRead();
567 
568  while( chLine[0]=='#' )
569  {
570  if( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) == NULL )
571  BadRead();
572  }
573 
574  iRot = 1;
575  iVib = 1;
576  neut_frac = 0;
577  while( iVib >= 0 )
578  {
579  long int j_minus_ji;
580  double a[10];
581 
582  sscanf(chLine,"%li\t%li\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf",
583  &iVib ,&j_minus_ji , &a[0],&a[1],&a[2],&a[3],&a[4],&a[5],&a[6],&a[7],&a[8],&a[9]
584  );
585  /* negative iVib says end of data */
586  if( iVib < 0 )
587  continue;
588 
589  /* cr_rate[CR_X][CR_VIB][CR_J][CR_EXIT];*/
590  /* check that we actually included the levels in the model representation */
591  ASSERT( iVib < CR_VIB );
592  ASSERT( j_minus_ji == -2 || j_minus_ji == +2 || j_minus_ji == 0 );
593  ASSERT( neut_frac < CR_X );
594 
595  /* now make i_minus_ji an array index */
596  j_minus_ji = 1 + j_minus_ji/2;
597  ASSERT( j_minus_ji>=0 && j_minus_ji<=2 );
598 
599  /* option to add Gaussian random mole */
600  for( iRot=0; iRot<CR_J; ++iRot )
601  {
602  cr_rate[neut_frac][iVib][iRot][j_minus_ji] = (realnum)a[iRot];
603  }
604  if( lgH2_NOISECOSMIC )
605  {
606  realnum r;
607  r = (realnum)RandGauss( xMeanNoise , xSTDNoise );
608 
609  for( iRot=0; iRot<CR_J; ++iRot )
610  {
611  cr_rate[neut_frac][iVib][iRot][j_minus_ji] *= (realnum)exp10((double)r);
612  }
613  }
614 
615  if( CR_PRINT )
616  {
617  fprintf(ioQQQ,"cr rate\t%li\t%li", iVib , j_minus_ji );
618  for( iRot=0; iRot<CR_J; ++iRot )
619  {
620  fprintf(ioQQQ,"\t%.3e", cr_rate[neut_frac][iVib][iRot][j_minus_ji] );
621  }
622  fprintf(ioQQQ,"\n" );
623  }
624 
625  /* now get next line */
626  if( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) == NULL )
627  BadRead();
628  while( chLine[0]=='#' )
629  {
630  if( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) == NULL )
631  BadRead();
632  }
633  }
634  fclose( ioDATA );
635 
636  return;
637 }
638 #endif
639 
641 {
642 public:
643  bool operator<( const level_tmp& second ) const
644  {
645  if( eWN < second.eWN )
646  return true;
647  else
648  return false;
649  }
650  long n, v, J;
651  double eWN;
652 };
653 
654 /*H2_ReadEnergies read energies for all electronic levels */
656 {
657  DEBUG_ENTRY( "H2_ReadEnergies()" );
658 
659  vector<int> n, v, J;
660  vector<double>eWN;
661 
662  for( long nelec=0; nelec<n_elec_states; ++nelec )
663  {
664  /* get energies out of files */
665  H2_ReadEnergies(nelec,n,v,J,eWN);
666  }
667 
668  vector<level_tmp> levels;
669  levels.resize( n.size() );
670  ASSERT( levels.size() > 0 );
671  for( unsigned i = 0; i < n.size(); ++i )
672  {
673  levels[i].n = n[i];
674  levels[i].v = v[i];
675  levels[i].J = J[i];
676  levels[i].eWN = eWN[i];
677  }
678 
679  // now get levels in energy order (comparison done by operator< of level_tmp class)
680  sort( levels.begin(), levels.end() );
681 
682  // populate states
683  states.init(sp->label.c_str(),0);
684  for( vector<level_tmp>::iterator lev = levels.begin(); lev != levels.end(); ++lev )
685  {
686  states.addone( );
687  long i = states.size() - 1;
688  states[i].n() = lev->n;
689  states[i].v() = lev->v;
690  states[i].J() = lev->J;
691  states[i].energy().set( lev->eWN, "cm^-1" );
692  /* NB this must be kept parallel with nelem and ionstag in transition struc,
693  * since that struc expects to find the abundances here - abund set in hmole.c */
694  states[i].nelem() = -1;
695  /* this does not mean anything for a molecule */
696  states[i].IonStg() = -1;
697  ostringstream oss;
698  oss << "n=" << lev->n << ',' << "v=" << lev->v << ',' << "J=" << lev->J;
699  states[i].chConfig() = oss.str();
700  }
701 
702  ASSERT( states.size() > 0 );
703  ASSERT( states.size() == levels.size() );
704 
705  for( long nelec=0; nelec<n_elec_states; ++nelec )
706  {
707  ASSERT( nLevels_per_elec[nelec] > 0 );
708  ASSERT( nVib_hi[nelec] > 0 );
709  ASSERT( nVib_hi[nelec] > Jlowest[nelec] );
710 
711  nRot_hi[nelec].resize( nVib_hi[nelec]+1 );
712  nRot_hi[nelec] = 0;
713  }
714 
715  for( qList::const_iterator st = states.begin(); st != states.end(); ++st )
716  {
717  nRot_hi[ (*st).n() ][ (*st).v() ] = MAX2( nRot_hi[ (*st).n() ][ (*st).v() ], (*st).J() );
718  }
719 
720  return;
721 }
722 
723 void diatomics::H2_ReadEnergies( long int nelec, vector<int>& n, vector<int>& v, vector<int>&J, vector<double>& eWN )
724 {
725  DEBUG_ENTRY( "diatomics::H2_ReadEnergies()" );
726  const char* cdDATAFILE[N_ELEC] =
727  {
728  "energy_X.dat",
729  "energy_B.dat",
730  "energy_C_plus.dat",
731  "energy_C_minus.dat",
732  "energy_B_primed.dat",
733  "energy_D_plus.dat",
734  "energy_D_minus.dat"
735  };
736  /* now open the data file */
737  char chPath[FILENAME_PATH_LENGTH_2];
738  strcpy( chPath, path.c_str() );
739  strcat( chPath, input.chDelimiter );
740  strcat( chPath, cdDATAFILE[nelec] );
741  FILE *ioDATA = open_data( chPath, "r" );
742 
743  char chLine[FILENAME_PATH_LENGTH_2];
744  long int i, n1, n2, n3;
745  bool lgEOL;
746 
747  /* read the first line and check that magic number is ok */
748  if( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) == NULL )
749  {
750  fprintf( ioQQQ, " H2_ReadEnergies could not read first line of %s\n", cdDATAFILE[nelec]);
752  }
753  i = 1;
754  /* magic number */
755  n1 = (long)FFmtRead(chLine,&i,sizeof(chLine),&lgEOL);
756  n2 = (long)FFmtRead(chLine,&i,sizeof(chLine),&lgEOL);
757  n3 = (long)FFmtRead(chLine,&i,sizeof(chLine),&lgEOL);
758 
759  /* magic number
760  * the following is the set of numbers that appear at the start of level1.dat 01 08 10 */
761  if( ( n1 != 2 ) || ( n2 != 4 ) || ( n3 != 29 ) )
762  {
763  fprintf( ioQQQ,
764  " H2_ReadEnergies: the version of %s is not the current version.\n", cdDATAFILE[nelec] );
765  fprintf( ioQQQ,
766  " I expected to find the number 2 4 29 and got %li %li %li instead.\n" ,
767  n1 , n2 , n3 );
768  fprintf( ioQQQ, "Here is the line image:\n==%s==\n", chLine );
770  }
771 
772  /* this will count the number of levels within each electronic state */
773  nLevels_per_elec[nelec] = 0;
774  nVib_hi[nelec] = 0;
775  Jlowest[nelec] = LONG_MAX;
776 
777  while( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) != NULL )
778  {
779  /* skip comment */
780  if( chLine[0]=='#' )
781  continue;
782  if( chLine[0]=='\n' || chLine[0]=='\0' || chLine[0]==' ' )
783  break;
784  long iVib, iRot;
785  double energyWN;
786  if( sscanf(chLine,"%li\t%li\t%le", &iVib, &iRot, &energyWN ) != 3 )
787  {
788  fprintf( ioQQQ, "failed to read correct number of data values from %s\n", chPath );
790  }
791  ASSERT( iVib >= 0 );
792  ASSERT( iRot >= 0 );
793  ASSERT( energyWN > 0. || (nelec==0 && iVib==0 && iRot==0 ) );
794 
795  n.push_back( nelec );
796  v.push_back( iVib );
797  J.push_back( iRot );
798  eWN.push_back( energyWN );
799 
800  // update limits
801  nVib_hi[nelec] = MAX2( nVib_hi[nelec], iVib );
802  Jlowest[nelec] = MIN2( Jlowest[nelec], iRot );
803  /* increment number of levels within this electronic state */
804  ++nLevels_per_elec[nelec];
805  }
806 
807  ASSERT( n.size() > 0 );
808  ASSERT( nLevels_per_elec[nelec] > 0 );
809  ASSERT( nVib_hi[nelec] > 0 );
810  ASSERT( nVib_hi[nelec] > Jlowest[nelec] );
811 
812  fclose( ioDATA );
813 
814  return;
815 }
816 
817 /*H2_ReadDissocEnergies read energies for all electronic levels */
819 {
820  const char* cdDATAFILE = "energy_dissoc.dat";
821  FILE *ioDATA;
822  char chLine[FILENAME_PATH_LENGTH_2];
823  long int i, n1, n2, n3;
824  bool lgEOL;
825 
826  DEBUG_ENTRY( "H2_ReadDissocEnergies()" );
827 
828  /* now open the data file */
829  char chPath[FILENAME_PATH_LENGTH_2];
830  strcpy( chPath, path.c_str() );
831  strcat( chPath, input.chDelimiter );
832  strcat( chPath, cdDATAFILE );
833  ioDATA = open_data( chPath, "r" );
834 
835  /* read the first line and check that magic number is ok */
836  if( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) == NULL )
837  {
838  fprintf( ioQQQ, " H2_ReadDissocEnergies could not read first line of %s\n", cdDATAFILE );
840  }
841  i = 1;
842  /* magic number */
843  n1 = (long)FFmtRead(chLine,&i,sizeof(chLine),&lgEOL);
844  n2 = (long)FFmtRead(chLine,&i,sizeof(chLine),&lgEOL);
845  n3 = (long)FFmtRead(chLine,&i,sizeof(chLine),&lgEOL);
846 
847  /* magic number
848  * the following is the set of numbers that appear at the start of level1.dat 01 08 10 */
849  if( ( n1 != 2 ) || ( n2 != 4 ) || ( n3 != 29 ) )
850  {
851  fprintf( ioQQQ,
852  " H2_ReadDissocEnergies: the version of %s is not the current version.\n", cdDATAFILE );
853  fprintf( ioQQQ,
854  " I expected to find the number 2 4 29 and got %li %li %li instead.\n" ,
855  n1 , n2 , n3 );
856  fprintf( ioQQQ, "Here is the line image:\n==%s==\n", chLine );
858  }
859 
860  while( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) != NULL )
861  {
862  /* skip comment */
863  if( chLine[0]=='#' )
864  continue;
865  if( chLine[0]=='\n' || chLine[0]=='\0' || chLine[0]==' ' )
866  break;
867  long iElec;
868  double energyWN;
869  if( sscanf(chLine,"%li\t%le", &iElec, &energyWN ) != 2 )
870  {
871  fprintf( ioQQQ, "failed to read correct number of data values from %s\n", chPath );
873  }
874  ASSERT( iElec >= 0 );
875  ASSERT( iElec < N_ELEC );
876  ASSERT( energyWN > 0. );
877  H2_DissocEnergies[iElec] = energyWN;
878  }
879  fclose( ioDATA );
880 
881  return;
882 }
883 
884 /*H2_ReadDissprob read dissociation probabilities and kinetic energies for all electronic levels */
885 void diatomics::H2_ReadDissprob( long int nelec )
886 {
887  const char* cdDATAFILE[N_ELEC] =
888  {
889  "dissprob_X.dat",/* this does not exist and nelec == 0 is not valid */
890  "dissprob_B.dat",
891  "dissprob_C_plus.dat",
892  "dissprob_C_minus.dat",
893  "dissprob_B_primed.dat",
894  "dissprob_D_plus.dat",
895  "dissprob_D_minus.dat"
896  };
897  char chLine[FILENAME_PATH_LENGTH_2];
898  bool lgEOL;
899 
900  DEBUG_ENTRY( "H2_ReadDissprob()" );
901 
902  ASSERT( nelec > 0 );
903 
904  /* now open the data file */
905  char chPath[FILENAME_PATH_LENGTH_2];
906  strcpy( chPath, path.c_str() );
907  strcat( chPath, input.chDelimiter );
908  strcat( chPath, cdDATAFILE[nelec] );
909  FILE *ioDATA = open_data( chPath, "r" );
910 
911  /* read the first line and check that magic number is ok */
912  if( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) == NULL )
913  {
914  fprintf( ioQQQ, " H2_ReadDissprob could not read first line of %s\n", cdDATAFILE[nelec]);
916  }
917  long i = 1;
918  /* magic number */
919  long n1 = (long)FFmtRead(chLine,&i,sizeof(chLine),&lgEOL);
920  long n2 = (long)FFmtRead(chLine,&i,sizeof(chLine),&lgEOL);
921  long n3 = (long)FFmtRead(chLine,&i,sizeof(chLine),&lgEOL);
922 
923  /* magic number
924  * the following is the set of numbers that appear at the start of level1.dat 01 08 10 */
925  if( ( n1 != 3 ) || ( n2 != 2 ) || ( n3 != 11 ) )
926  {
927  fprintf( ioQQQ,
928  " H2_ReadDissprob: the version of %s is not the current version.\n", cdDATAFILE[nelec] );
929  fprintf( ioQQQ,
930  " I expected to find the number 3 2 11 and got %li %li %li instead.\n" ,
931  n1 , n2 , n3 );
932  fprintf( ioQQQ, "Here is the line image:\n==%s==\n", chLine );
934  }
935 
936  while( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) != NULL )
937  {
938  /* skip comment */
939  if( chLine[0]=='#' )
940  continue;
941  if( chLine[0]=='\n' || chLine[0]=='\0' || chLine[0]==' ' )
942  break;
943 
944  long iVib, iRot;
945  double a, b;
946  i = 1;
947  sscanf(chLine,"%li\t%li\t%le\t%le",
948  &iVib, &iRot,
949  /* dissociation probability */
950  &a ,
951  /* dissociation kinetic energy - eV not ergs */
952  &b);
953 
954  /* these have to agree if data file is valid */
955  //ASSERT( iVib >= 0 );
956  //ASSERT( iVib <= nVib_hi[nelec] );
957  //ASSERT( iRot >= Jlowest[nelec] );
958  //ASSERT( iRot <= nRot_hi[nelec][iVib] );
959  if( ( iVib < 0 ) ||
960  ( iVib > nVib_hi[nelec] ) ||
961  ( iRot < Jlowest[nelec] ) ||
962  ( iRot > nRot_hi[nelec][iVib] ) )
963  continue;
964 
965  /* dissociation probability */
966  H2_dissprob[nelec][iVib][iRot] = (realnum)a;
967  /* dissociation kinetic energy - eV not ergs */
968  H2_disske[nelec][iVib][iRot] = (realnum)b;
969  }
970  fclose( ioDATA );
971  return;
972 }
973 
974 
975 /*H2_Read_hminus_distribution read distribution function for H2 population following formation from H minus */
977 {
978  FILE *ioDATA;
979  char chLine[FILENAME_PATH_LENGTH_2];
980  long int i, n1, n2, n3, iVib , iRot;
981  bool lgEOL;
982  double sumrate[nTE_HMINUS] = {0};
983  /* set true for lots of printout */
984  const bool lgH2HMINUS_PRT = false;
985 
986  DEBUG_ENTRY( "H2_Read_hminus_distribution()" );
987 
988  /* now open the data file */
989  char chPath[FILENAME_PATH_LENGTH_2];
990  strcpy( chPath, path.c_str() );
991  strcat( chPath, input.chDelimiter );
992  strcat( chPath, "hminus_deposit.dat" );
993  ioDATA = open_data( chPath, "r" );
994 
995  /* read the first line and check that magic number is ok */
996  if( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) == NULL )
997  {
998  fprintf( ioQQQ, " H2_Read_hminus_distribution could not read first line of %s\n", chPath );
1000  }
1001 
1002  i = 1;
1003  /* magic number */
1004  n1 = (long)FFmtRead(chLine,&i,sizeof(chLine),&lgEOL);
1005  n2 = (long)FFmtRead(chLine,&i,sizeof(chLine),&lgEOL);
1006  n3 = (long)FFmtRead(chLine,&i,sizeof(chLine),&lgEOL);
1007 
1008  /* magic number
1009  * the following is the set of numbers that appear at the start of H2_hminus_deposit.dat 01 08 10 */
1010  if( ( n1 != 2 ) || ( n2 != 10 ) || ( n3 != 17 ) )
1011  {
1012  fprintf( ioQQQ,
1013  " H2_Read_hminus_distribution: the version of %s is not the current version.\n", chPath );
1014  fprintf( ioQQQ,
1015  " I expected to find the number 2 10 17 and got %li %li %li instead.\n" ,
1016  n1 , n2 , n3 );
1017  fprintf( ioQQQ, "Here is the line image:\n==%s==\n", chLine );
1019  }
1020 
1021  /* read until not a comment */
1022  if( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) == NULL )
1023  BadRead();
1024 
1025  while( chLine[0]=='#' )
1026  {
1027  if( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) == NULL )
1028  BadRead();
1029  }
1030 
1031  iRot = 1;
1032  iVib = 1;
1033  while( iVib >= 0 )
1034  {
1035  /* set true to print rates */
1036 
1037  double a[nTE_HMINUS] , ener;
1038  sscanf(chLine,"%li\t%li\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf\t%lf",
1039  &iVib ,&iRot , &ener, &a[0],&a[1],&a[2] , &a[3],&a[4],&a[5] ,&a[6]
1040  );
1041  /* negative iVib says end of data */
1042  if( iVib < 0 )
1043  continue;
1044 
1045  /* check that we actually included the levels in the model representation */
1046  ASSERT( iVib <= nVib_hi[0] &&
1047  iRot <= nRot_hi[0][iVib] );
1048 
1049  if( lgH2HMINUS_PRT )
1050  fprintf(ioQQQ,"hminusss\t%li\t%li", iVib , iRot );
1051  for( i=0; i<nTE_HMINUS; ++i )
1052  {
1053  H2_X_hminus_formation_distribution[i][iVib][iRot] = (realnum)exp10(-a[i]);
1054  sumrate[i] += H2_X_hminus_formation_distribution[i][iVib][iRot];
1055  if( lgH2HMINUS_PRT )
1056  fprintf(ioQQQ,"\t%.3e", H2_X_hminus_formation_distribution[i][iVib][iRot] );
1057  }
1058  if( lgH2HMINUS_PRT )
1059  fprintf(ioQQQ,"\n" );
1060 
1061  if( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) == NULL )
1062  BadRead();
1063  while( chLine[0]=='#' )
1064  {
1065  if( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) == NULL )
1066  BadRead();
1067  }
1068  }
1069  fclose( ioDATA );
1070 
1071  if( lgH2HMINUS_PRT )
1072  {
1073  /* print total rate */
1074  fprintf(ioQQQ," total H- formation rate ");
1075  /* convert temps to log */
1076  for(i=0; i<nTE_HMINUS; ++i )
1077  {
1078  fprintf(ioQQQ,"\t%.3e" , sumrate[i]);
1079  }
1080  fprintf(ioQQQ,"\n" );
1081  }
1082 
1083  /* convert to dimensionless factors that add to unity */
1084  for( iVib=0; iVib<=nVib_hi[0]; ++iVib )
1085  {
1086  for( iRot=Jlowest[0]; iRot<=nRot_hi[0][iVib]; ++iRot )
1087  {
1088  for(i=0; i<nTE_HMINUS; ++i )
1089  {
1090  H2_X_hminus_formation_distribution[i][iVib][iRot] /= (realnum)sumrate[i];
1091  }
1092  }
1093  }
1094 
1095  if( lgH2HMINUS_PRT )
1096  {
1097  /* print total rate */
1098  fprintf(ioQQQ," H- distribution function ");
1099  for( iVib=0; iVib<=nVib_hi[0]; ++iVib )
1100  {
1101  for( iRot=Jlowest[0]; iRot<=nRot_hi[0][iVib]; ++iRot )
1102  {
1103  fprintf(ioQQQ,"%li\t%li", iVib , iRot );
1104  for(i=0; i<nTE_HMINUS; ++i )
1105  {
1106  fprintf(ioQQQ,"\t%.3e", H2_X_hminus_formation_distribution[i][iVib][iRot] );
1107  }
1108  fprintf(ioQQQ,"\n" );
1109  }
1110  }
1111  }
1112  return;
1113 }
1114 
1115 /* ===================================================================== */
1116 /*H2_Punch_line_data save line data for H2 molecule */
1118  /* io unit for save */
1119  FILE* ioPUN ,
1120  /* save all levels if true, only subset if false */
1121  bool lgDoAll )
1122 {
1123  if( !lgEnabled )
1124  return;
1125 
1126  DEBUG_ENTRY( "H2_Punch_line_data()" );
1127 
1128  if( lgDoAll )
1129  {
1130  fprintf( ioQQQ,
1131  " H2_Punch_line_data ALL option not implemented in H2_Punch_line_data yet 1\n" );
1133  }
1134  else
1135  {
1136  fprintf( ioPUN, "#Eu\tVu\tJu\tEl\tVl\tJl\tWL\tgl\tgu\tgf\tA\tCS\tn(crt)\n" );
1137  /* save line date, looping over all possible lines */
1138  for( TransitionList::iterator tr = trans.begin(); tr != trans.end(); ++tr )
1139  {
1140  if( (*tr).ipCont() <= 0 )
1141  continue;
1142  (*tr).Coll().col_str() = 0.;
1143  qList::iterator Hi = ( (*tr).Hi() );
1144  qList::iterator Lo = ( (*tr).Lo() );
1145  /* print quantum indices */
1146  fprintf(ioPUN,"%2li\t%2li\t%2li\t%2li\t%2li\t%2li\t",
1147  (*Hi).n(), (*Hi).v(), (*Hi).J(),
1148  (*Lo).n(), (*Lo).v(), (*Lo).J() );
1149  Save1LineData( *tr, ioPUN, false );
1150  }
1151 
1152  fprintf( ioPUN , "\n");
1153  }
1154  return;
1155 }
1156 
1157 /*H2_PunchLineStuff include H2 lines in punched optical depths, etc, called from SaveLineStuff */
1158 void diatomics::H2_PunchLineStuff( FILE * io , realnum xLimit , long index)
1159 {
1160  if( !lgEnabled )
1161  return;
1162 
1163  DEBUG_ENTRY( "H2_PunchLineStuff()" );
1164 
1165  /* loop over all possible lines */
1166  for( TransitionList::iterator tr = trans.begin(); tr != trans.end(); ++tr )
1167  {
1168  if( (*tr).ipCont() <= 0 )
1169  continue;
1170  Save1Line( *tr, io, xLimit, index, GetDopplerWidth(2.f*dense.AtomicWeight[ipHYDROGEN]));
1171  }
1172 
1173  return;
1174 }
1175 
1176 
1177 /*chMolBranch returns a char with the spectroscopic branch of a transition */
1178 STATIC char chMolBranch( long iRotHi , long int iRotLo )
1179 {
1180  /* these are the spectroscopic branches */
1181  char chBranch[5] = {'O','P','Q','R','S'};
1182  /* this is the index within the chBranch array */
1183  int ip = 2 + (iRotHi - iRotLo);
1184  if( ip<0 || ip>=5 )
1185  {
1186  fprintf(ioQQQ," chMolBranch called with insane iRotHi=%li iRotLo=%li ip=%i\n",
1187  iRotHi , iRotLo , ip );
1188  ip = 0;
1189  }
1190 
1191  return( chBranch[ip] );
1192 }
1193 
1194 /*H2_PunchDo save some properties of the large H2 molecule */
1195 void diatomics::H2_PunchDo( FILE* io , char chJOB[] , const char chTime[] , long int ipPun )
1196 {
1197  DEBUG_ENTRY( "H2_PunchDo()" );
1198 
1199  if( !lgEnabled )
1200  {
1201  fprintf( io, "%s model is not enabled. This save command is therefore disabled.\n", label.c_str() );
1202  return;
1203  }
1204 
1205  /* which job are we supposed to do? This routine is active even when H2 is not turned on
1206  * so do not test on lgEnabled initially */
1207 
1208  /* H2 populations computed in last zone -
1209  * give all of molecule in either matrix or triplet format */
1210  if( (strcmp( chJOB , "H2po" ) == 0) && (strcmp(chTime,"LAST") == 0) &&
1211  (save.punarg[ipPun][2] != 0) )
1212  {
1213  /* >>chng 04 feb 19, do not save if H2 not yet evaluated */
1214  if( lgEnabled && lgEvaluated )
1215  {
1216  long iVibHi= 0;
1217  long iRotHi = 0;
1218  long iElecHi=0;
1219  long LimVib, LimRot;
1220  /* the limit to the number of vibration levels punched -
1221  * default is all, but first two numbers on save h2 pops command
1222  * reset limit */
1223  /* this is limit to vibration */
1224  if( save.punarg[ipPun][0] > 0 )
1225  {
1226  LimVib = (long)save.punarg[ipPun][0];
1227  }
1228  else
1229  {
1230  LimVib = nVib_hi[iElecHi];
1231  }
1232 
1233  /* first save the current ortho, para, and total H2 density */
1234  fprintf(io,"%i\t%i\t%.3e\tortho\n",
1235  103 ,
1236  103 ,
1237  ortho_density );
1238  fprintf(io,"%i\t%i\t%.3e\tpara\n",
1239  101 ,
1240  101 ,
1241  para_density );
1242  fprintf(io,"%i\t%i\t%.3e\ttotal\n",
1243  0 ,
1244  0 ,
1245  (*dense_total) );
1246 
1247  /* now save the actual populations, first part both matrix and triplets */
1248  for( iVibHi=0; iVibHi<=LimVib; ++iVibHi )
1249  {
1250  /* this is limit to rotation quantum index */
1251  if( save.punarg[ipPun][1] > 0 )
1252  {
1253  LimRot = (long)MIN2(
1254  save.punarg[ipPun][1] , (realnum)nRot_hi[iElecHi][iVibHi]);
1255  }
1256  else
1257  {
1258  LimRot = nRot_hi[iElecHi][iVibHi];
1259  }
1260  if( save.punarg[ipPun][2] > 0 )
1261  {
1262  long int i;
1263  /* this option save matrix */
1264  if( iVibHi == 0 )
1265  {
1266  fprintf(io,"vib\\rot");
1267  /* this is first vib, so make row of rot numbs */
1268  for( i=0; i<=LimRot; ++i )
1269  {
1270  fprintf(io,"\t%li",i);
1271  }
1272  fprintf(io,"\n");
1273  }
1274  fprintf(io,"%li",iVibHi );
1275  for( iRotHi=Jlowest[iElecHi]; iRotHi<=LimRot; ++iRotHi )
1276  {
1277  fprintf(io,"\t%.3e",
1278  states[ ipEnergySort[iElecHi][iVibHi][iRotHi] ].Pop()/(*dense_total) );
1279  }
1280  fprintf(io,"\n" );
1281  }
1282  else if( save.punarg[ipPun][2] < 0 )
1283  {
1284  /* this option save triplets - the default */
1285  for( iRotHi=Jlowest[iElecHi]; iRotHi<=LimRot; ++iRotHi )
1286  {
1287  /* this will say whether ortho or para,
1288  * H2_lgOrtho is 0 or 1 depending on whether or not ortho,
1289  * so chlgPara[H2_lgOrtho] gives P or O for printing */
1290  const char chlgPara[2]={'P','O'};
1291  const long ipHi = ipEnergySort[iElecHi][iVibHi][iRotHi];
1292 
1293  /* intensity, relative to normalization line, for faintest line to save */
1294  fprintf(io,"%li\t%li\t%c\t%.1f\t%.3e\t%.3e\t%.3e\t%.3e\t%.3e\t%.3e\t%.3e\t%.3e\t%.3e\t%.3e\n",
1295  /* upper vibration and rotation quantum numbers */
1296  iVibHi , iRotHi ,
1297  /* an 'O' or 'P' for ortho or para */
1298  chlgPara[H2_lgOrtho[iElecHi][iVibHi][iRotHi]],
1299  /* the level excitation energy in wavenumbers */
1300  states[ipHi].energy().WN(),
1301  /* actual population relative to total H2 */
1302  states[ipHi].Pop()/(*dense_total) ,
1303  /* old level populations for comparison */
1304  H2_old_populations[iElecHi][iVibHi][iRotHi]/(*dense_total) ,
1305  /* populations per h2 and per statistical weight */
1306  states[ipHi].Pop()/(*dense_total)/states[ipHi].g() ,
1307  /* LTE departure coefficient */
1308  /* >>chng 05 jan 26, missing factor of H2 abundance LTE is norm to unity, not tot abund */
1309  states[ipHi].Pop()/SDIV(H2_populations_LTE[iElecHi][iVibHi][iRotHi]*(*dense_total) ) ,
1310  /* fraction of exits that were collisional */
1311  H2_col_rate_out[iVibHi][iRotHi]/SDIV(H2_col_rate_out[iVibHi][iRotHi]+H2_rad_rate_out[0][iVibHi][iRotHi]) ,
1312  /* fraction of entries that were collisional */
1313  H2_col_rate_in[iVibHi][iRotHi]/SDIV(H2_col_rate_in[iVibHi][iRotHi]+H2_rad_rate_in[iVibHi][iRotHi]),
1314  /* collisions out */
1315  H2_col_rate_out[iVibHi][iRotHi],
1316  /* radiation out */
1317  H2_rad_rate_out[0][iVibHi][iRotHi] ,
1318  /* radiation out */
1319  H2_col_rate_in[iVibHi][iRotHi],
1320  /* radiation in */
1321  H2_rad_rate_in[iVibHi][iRotHi]
1322  );
1323  }
1324  }
1325  }
1326  }
1327  }
1328  /* save H2 populations for each zone
1329  * populations of v=0 for each zone */
1330  else if( (strcmp( chJOB , "H2po" ) == 0) && (strcmp(chTime,"LAST") != 0) &&
1331  (save.punarg[ipPun][2] == 0) )
1332  {
1333  /* >>chng 04 feb 19, do not save if h2 not yet evaluated */
1334  if( lgEnabled && lgEvaluated )
1335  {
1336  fprintf(io,"%.5e\t%.3e\t%.3e", radius.depth_mid_zone ,
1338  /* rel pops of first two excited electronic states */
1339  fprintf(io,"\t%.3e\t%.3e",
1340  pops_per_elec[1] , pops_per_elec[2]);
1341  long iElecHi = 0;
1342  long iVibHi = 0;
1343  long LimVib, LimRot;
1344  /* this is limit to vibration quantum index */
1345  if( save.punarg[ipPun][0] > 0 )
1346  {
1347  LimVib = (long)save.punarg[ipPun][1];
1348  }
1349  else
1350  {
1351  LimVib = nRot_hi[iElecHi][iVibHi];
1352  }
1353  LimVib = MIN2( LimVib , nVib_hi[iElecHi] );
1354  /* this is limit to rotation quantum index */
1355  if( save.punarg[ipPun][1] > 0 )
1356  {
1357  LimRot = (long)save.punarg[ipPun][1];
1358  }
1359  else
1360  {
1361  LimRot = nRot_hi[iElecHi][iVibHi];
1362  }
1363  for( iVibHi = 0; iVibHi<=LimVib; ++iVibHi )
1364  {
1365  fprintf(io,"\tv=%li",iVibHi);
1366  long int LimRotVib = MIN2( LimRot , nRot_hi[iElecHi][iVibHi] );
1367  for( long iRotHi=Jlowest[iElecHi]; iRotHi<=LimRotVib; ++iRotHi )
1368  {
1369  fprintf(io,"\t%.3e",
1370  states[ ipEnergySort[iElecHi][iVibHi][iRotHi] ].Pop()/(*dense_total) );
1371  }
1372  }
1373  fprintf(io,"\n");
1374  }
1375  }
1376 
1377  /* save column densities */
1378  else if( (strcmp( chJOB , "H2cl" ) == 0) && (strcmp(chTime,"LAST") == 0) )
1379  {
1380  long iVibHi= 0;
1381  long iRotHi = 0;
1382  long iElecHi=0;
1383  long LimVib, LimRot;
1384  /* the limit to the number of vibration levels punched -
1385  * default is all, but first two numbers on save h2 pops command
1386  * reset limit */
1387  /* this is limit to vibration */
1388  if( save.punarg[ipPun][0] > 0 )
1389  {
1390  LimVib = (long)save.punarg[ipPun][0];
1391  }
1392  else
1393  {
1394  LimVib = nVib_hi[iElecHi];
1395  }
1396 
1397  /* first save ortho and para populations */
1398  fprintf(io,"%i\t%i\t%.3e\tortho\n",
1399  103 ,
1400  103 ,
1401  ortho_colden );
1402  fprintf(io,"%i\t%i\t%.3e\tpara\n",
1403  101 ,
1404  101 ,
1405  para_colden );
1406  /* total H2 column density */
1407  fprintf(io,"%i\t%i\t%.3e\ttotal\n",
1408  0 ,
1409  0 ,
1410  mole.species[sp->index].column + (sp_star->index > 0 ? mole.species[sp_star->index].column : 0) );
1411 
1412  /* save level column densities */
1413  for( iVibHi=0; iVibHi<=LimVib; ++iVibHi )
1414  {
1415  if( lgEnabled )
1416  {
1417  /* this is limit to rotation quantum index */
1418  if( save.punarg[ipPun][1] > 0 )
1419  {
1420  LimRot = (long)save.punarg[ipPun][1];
1421  }
1422  else
1423  {
1424  LimRot = nRot_hi[iElecHi][iVibHi];
1425  }
1426  if( save.punarg[ipPun][2] > 0 )
1427  {
1428  long int i;
1429  /* save matrix */
1430  if( iVibHi == 0 )
1431  {
1432  fprintf(io,"vib\\rot");
1433  /* this is first vib, so make row of rot numbs */
1434  for( i=0; i<=LimRot; ++i )
1435  {
1436  fprintf(io,"\t%li",i);
1437  }
1438  fprintf(io,"\n");
1439  }
1440  fprintf(io,"%li",iVibHi );
1441  for( iRotHi=Jlowest[iElecHi]; iRotHi<=LimRot; ++iRotHi )
1442  {
1443  fprintf(io,"\t%.3e",
1444  H2_X_colden[iVibHi][iRotHi]/(*dense_total) );
1445  }
1446  fprintf(io,"\n" );
1447  }
1448  else
1449  {
1450  /* save triplets - the default */
1451  for( iRotHi=Jlowest[iElecHi]; iRotHi<=LimRot; ++iRotHi )
1452  {
1453  fprintf(io,"%li\t%li\t%.1f\t%.3e\t%.3e\t%.3e\t%.3e\n",
1454  iVibHi ,
1455  iRotHi ,
1456  /* energy relative to 0,0, T1CM converts wavenumber to K */
1457  states[ ipEnergySort[iElecHi][iVibHi][iRotHi] ].energy().K(),
1458  /* these are column densities for actual molecule */
1459  H2_X_colden[iVibHi][iRotHi] ,
1460  H2_X_colden[iVibHi][iRotHi]/states[ ipEnergySort[iElecHi][iVibHi][iRotHi] ].g() ,
1461  /* these are same column densities but for LTE populations */
1462  H2_X_colden_LTE[iVibHi][iRotHi] ,
1463  H2_X_colden_LTE[iVibHi][iRotHi]/states[ ipEnergySort[iElecHi][iVibHi][iRotHi] ].g());
1464  }
1465  }
1466  }
1467  }
1468  }
1469  else if( (strcmp(chJOB , "H2pd" ) == 0) && (strcmp(chTime,"LAST") != 0) )
1470  {
1471  /* save PDR
1472  * output some PDR information (densities, rates) for each zone */
1473  fprintf(io,"%.5e\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\n",
1474  /* depth in cm */
1476  /* the computed ortho and para densities */
1477  ortho_density ,
1478  para_density ,
1479  /* the Lyman Werner band dissociation, Tielens & Hollenbach */
1481  /* the Lyman Werner band dissociation, Bertoldi & Draine */
1483  /* the Lyman Werner band dissociation, big H2 mole */
1485  }
1486  else if( (strcmp(chJOB , "H2cm" ) == 0) && (strcmp(chTime,"LAST") != 0) )
1487  {
1488  /* save H2 cooling per particle */
1489  fprintf(io,"%.5e\t%.5e\t%.5e\n",
1490  /* temperature in zone */
1491  phycon.te,
1492  /* LTE cooling */
1494  /* net H2 cooling per particle */
1495  -HeatDexc / Abund()
1496  );
1497  }
1498 
1499  else if( (strcmp(chJOB , "H2co" ) == 0) && (strcmp(chTime,"LAST") != 0) )
1500  {
1501  /* save H2 cooling - do heating cooling for each zone old new H2 */
1502  fprintf(io,"%.5e\t%.5e\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\t%.5e\n",
1503  /* depth in cm */
1505  /* temperature in zone */
1506  phycon.te,
1507  /* total cooling, equal to total heating */
1508  thermal.ctot ,
1509  /* H2 destruction by Solomon process, TH85 rate */
1511  /* H2 destruction by Solomon process, big H2 model rate */
1514  /* H2 photodissociation heating, eqn A9 of Tielens & Hollenbach 1985a */
1516  /* heating due to dissociation of electronic excited states */
1517  HeatDiss ,
1518  /* cooling (usually neg and so heating) due to collisions within X */
1520  HeatDexc,
1521  -HeatDexc / Abund()
1522  );
1523  }
1524 
1525  else if( (strcmp(chJOB , "H2le" ) == 0) && (strcmp(chTime,"LAST") == 0) )
1526  {
1527  /* save H2 levels */
1528  for( long int ipHi=0; ipHi < nLevels_per_elec[0]; ipHi++ )
1529  {
1530  long iRotHi = ipRot_H2_energy_sort[ipHi];
1531  long iVibHi = ipVib_H2_energy_sort[ipHi];
1532  long int nColl;
1533  double Asum , Csum[N_X_COLLIDER];
1534  Asum = 0;
1535  for( nColl=0; nColl<N_X_COLLIDER; ++nColl )
1536  Csum[nColl] = 0.;
1537  for( long int ipLo=0; ipLo<ipHi; ++ipLo )
1538  {
1539  /* radiative decays down */
1540  if( lgH2_radiative[ipHi][ipLo] )
1541  {
1542  EmissionProxy em = trans[ ipTransitionSort[ipHi][ipLo] ].Emis();
1543  Asum += em.Aul() * ( em.Ploss() );
1544  }
1545  /* all collisions down */
1546  mr3ci H2cr = CollRateCoeff.begin(ipHi,ipLo);
1547  for( nColl=0; nColl<N_X_COLLIDER; ++nColl )
1548  Csum[nColl] += H2cr[nColl];
1549  }
1550 
1551  /* save H2 level energies */
1552  fprintf(io,"%li\t%li\t%.2f\t%li\t%.3e",
1553  iVibHi , iRotHi,
1554  states[ipHi].energy().WN(),
1555  (long)states[ipHi].g(),
1556  Asum );
1557  for( nColl=0; nColl<N_X_COLLIDER; ++nColl )
1558  /* sum over all lower levels */
1559  fprintf(io,"\t%.3e",Csum[nColl]);
1560  fprintf(io,"\n");
1561  }
1562  }
1563 
1564  else if( (strcmp(chJOB , "H2ra" ) == 0) && (strcmp(chTime,"LAST") != 0) )
1565  {
1566  /* save h2 rates - some rates and lifetimes */
1567  double sumpop = 0. , sumlife = 0.;
1568 
1569  /* this block, find lifetime against photo excitation into excited electronic states */
1570  if( lgEnabled && lgEvaluated )
1571  {
1572  /* only do if radiative transition exists */
1573  for( TransitionList::iterator tr = trans.begin(); tr != rad_end; ++tr )
1574  {
1575  qList::iterator Lo = ( (*tr).Lo() );
1576  if( (*Lo).n() > 0 || (*Lo).v() > 0 )
1577  continue;
1578  sumlife += (*tr).Emis().pump() * (*(*tr).Lo()).Pop();
1579  sumpop += (*(*tr).Lo()).Pop();
1580  }
1581  }
1582 
1583  /* continue output from save h2 rates command */
1584  /* find photoexcitation rates from v=0 */
1585  /* PDR information for each zone */
1586  fprintf(io,
1587  "%.5e\t%.3e\t%.3e\t%.3e\t%li",
1588  /* depth in cm */
1590  /* the column density (cm^-2) in H2 */
1592  /* this is a special form of column density - should be proportional
1593  * to total shielding */
1595  /* visual extinction due to dust alone, of point source (star)*/
1597  /* number of large molecule evaluations in this zone */
1598  nCall_this_zone );
1599  fprintf(io,
1600  "\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e",
1601  /* total H2 fraction */
1603  /* chemistry renorm factor */
1605  /* rate H2 forms on grains */
1607  /* rate H2 forms by H minus route */
1608  findspecieslocal("H-")->den*1.35e-9,
1609  /* H2 destruction by Solomon process, TH85 rate */
1611  /* H2 destruction by Solomon process, Bertoldi & Draine rate */
1613  /* H2 destruction by Solomon process, Elwert et al. in preparation */
1615  /* H2 destruction by Solomon process, big H2 model rate */
1617  /* rate s-1 H2 electronic excit states decay into H2g */
1619  /* rate s-1 H2 electronic excit states decay into H2s */
1621  );
1622  fprintf(io,
1623  "\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e",
1624  /* The TH85 estimate of the radiation field relative to the Habing value */
1626  /* The DB96 estimate of the radiation field relative to the Habing value */
1628  /* cosmic ray ionization rate */
1629  secondaries.csupra[ipHYDROGEN][0]*0.93,
1630  sumlife/SDIV( sumpop ) ,
1635  fprintf(io,
1636  "\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\n",
1639  HeatDiss,
1640  HeatDexc,
1641  thermal.htot);
1642  }
1643  /* save h2 solomon */
1644  else if( (strcmp(chJOB , "H2so" ) == 0) && (strcmp(chTime,"LAST") != 0) )
1645  {
1646  /* remember as many as nSOL lines contributing to total Solomon process */
1647  const int nSOL = 100;
1648  double sum, one;
1649  long int jlosave[nSOL] , ivlosave[nSOL],
1650  iehisave[nSOL] ,jhisave[nSOL] , ivhisave[nSOL],
1651  nsave,
1652  ipOrdered[nSOL];
1653  int nFail;
1654  realnum fsave[nSOL], wlsave[nSOL];
1655  /* Solomon process, and where it came from */
1656  fprintf(io,"%.5e\t%.3e",
1657  /* depth in cm */
1659  /* H2 destruction by Solomon process, big H2 model rate */
1662  sum = 0.;
1663  /* find sum of all radiative exits from X into excited electronic states */
1664  if( lgEnabled && lgEvaluated )
1665  {
1666  for( TransitionList::iterator tr = trans.begin(); tr != rad_end; ++tr )
1667  {
1668  qList::iterator Lo = ( (*tr).Lo() );
1669  if( (*Lo).n() > 0 )
1670  continue;
1671  sum += (*(*tr).Lo()).Pop() * (*tr).Emis().pump();
1672  }
1673 
1674  /* make sure it is safe to div by sum */
1675  sum = SDIV( sum );
1676  nsave = 0;
1677  /* now loop back over X and print all those which contribute more than frac of the total */
1678  const double frac = 0.01;
1679  /* only do if radiative transition exists */
1680  for( TransitionList::iterator tr = trans.begin(); tr != rad_end; ++tr )
1681  {
1682  qList::iterator Lo = ( (*tr).Lo() );
1683  if( (*Lo).n() > 0 )
1684  continue;
1685  one = (*(*tr).Lo()).Pop() * (*tr).Emis().pump();
1686  if( one/sum > frac && nsave<nSOL)
1687  {
1688  qList::iterator Hi = ( (*tr).Hi() );
1689  fsave[nsave] = (realnum)(one/sum);
1690  jlosave[nsave] = (*Lo).J();
1691  ivlosave[nsave] = (*Lo).v();
1692  jhisave[nsave] = (*Hi).J();
1693  ivhisave[nsave] = (*Hi).v();
1694  iehisave[nsave] = (*Hi).n();
1695  wlsave[nsave] = (*tr).WLAng();
1696  ++nsave;
1697  }
1698  }
1699 
1700  /* now sort by decreasing importance */
1701  /*spsort netlib routine to sort array returning sorted indices */
1702  spsort(
1703  /* input array to be sorted */
1704  fsave,
1705  /* number of values in x */
1706  nsave,
1707  /* permutation output array */
1708  ipOrdered,
1709  /* flag saying what to do - 1 sorts into increasing order, not changing
1710  * the original routine */
1711  -1,
1712  /* error condition, should be 0 */
1713  &nFail);
1714 
1715  /* print ratio of pumps to dissociations - this is 9:1 in TH85 */
1716  /*>>chng 05 jul 20, TE, save average energy in H2s and renormalization factors for H2g and H2s */
1717  /* >>chng 05 sep 16, TE, chng denominator to do g and s with proper dissoc rates */
1718  fprintf(io,"\t%.3f\t%.3f\t%.3e\t%.3e\t%.3e\t%.3e\t%.3e\t%.3e",
1719  /* this is sum of photons and CRs */
1720  (sum + secondaries.csupra[ipHYDROGEN][0]*2.02f)/SDIV((Solomon_dissoc_rate_g * findspecieslocal("H2")->den +
1721  Solomon_dissoc_rate_s * findspecieslocal("H2*")->den) ),
1722  /* this is sum of photons and CRs */
1726  findspecieslocal("H2")->den/SDIV(H2_den_g), findspecieslocal("H2*")->den/SDIV(H2_den_s),
1727  H2_den_g/SDIV((*dense_total)), H2_den_s/SDIV((*dense_total))
1728  );
1729  for( long i=0; i<nsave; ++i )
1730  {
1731  long ip = ipOrdered[i];
1732  /*lint -e644 not init */
1733  fprintf(io,"\t%li\t%li\t%li\t%li\t%li\t%.3f\t%.3f",
1734  iehisave[ip],ivhisave[ip],jhisave[ip],ivlosave[ip] , jlosave[ip] , fsave[ip] , wlsave[ip] );
1735  /*lint +e644 not init */
1736  }
1737  fprintf(io,"\n");
1738  }
1739  }
1740 
1741  else if( (strcmp(chJOB , "H2te" ) == 0) && (strcmp(chTime,"LAST") != 0) )
1742  {
1743  /* save h2 temperatures */
1744  double pop_ratio10,pop_ratio20,pop_ratio30,pop_ratio31,pop_ratio40;
1745  double T10,T20,T30,T31,T40;
1746  /* subscript"sum" denotes integrated quantities */
1747  double T10_sum,T20_sum,T30_sum,T31_sum,T40_sum;
1748  double pop_ratio20_sum,pop_ratio30_sum,pop_ratio31_sum,pop_ratio40_sum;
1749  if( lgEnabled && nCall_this_zone )
1750  {
1751  double pop0 = states[0].Pop();
1752  double pop1 = states[1].Pop();
1753  double pop2 = states[2].Pop();
1754  double pop3 = states[3].Pop();
1755  double pop4 = states[4].Pop();
1756 
1757  double energyK = states[1].energy().K() - states[0].energy().K();
1758  /* the ratio of populations of J=1 to 0 */
1759  pop_ratio10 = pop1/SDIV(pop0);
1760  double pop_ratio10_sum = H2_X_colden[0][1]/SDIV(H2_X_colden[0][0]);
1761  /* the corresponding temperature */
1762  T10 = -170.5/log(SDIV(pop_ratio10) * states[0].g()/states[1].g());
1763  T10_sum = -170.5/log(SDIV(pop_ratio10_sum) * states[0].g()/states[1].g());
1764 
1765  energyK = states[2].energy().K() - states[0].energy().K();
1766  pop_ratio20 = pop2/SDIV(pop0);
1767  T20 = -energyK/log(SDIV(pop_ratio20) * states[0].g()/states[2].g());
1768 
1769  pop_ratio20_sum = H2_X_colden[0][2]/SDIV(H2_X_colden[0][0]);
1770  T20_sum = -energyK/log(SDIV(pop_ratio20_sum) * states[0].g()/states[2].g());
1771 
1772  energyK = states[3].energy().K() - states[0].energy().K();
1773  pop_ratio30 = pop3/SDIV(pop0);
1774  T30 = -energyK/log(SDIV(pop_ratio30) * states[0].g()/states[3].g());
1775 
1776  pop_ratio30_sum = H2_X_colden[0][3]/SDIV(H2_X_colden[0][0]);
1777  T30_sum = -energyK/log(SDIV(pop_ratio30_sum) * states[0].g()/states[3].g());
1778 
1779  energyK = states[3].energy().K() - states[1].energy().K();
1780  pop_ratio31 = pop3/SDIV(pop1);
1781  T31 = -energyK/log(SDIV(pop_ratio31) * states[1].g()/states[3].g());
1782 
1783  pop_ratio31_sum = H2_X_colden[0][3]/SDIV(H2_X_colden[0][1]);
1784  T31_sum = -energyK/log(SDIV(pop_ratio31_sum) * states[1].g()/states[3].g());
1785 
1786  energyK = states[4].energy().K() - states[0].energy().K();
1787  pop_ratio40 = pop4/SDIV(pop0);
1788  T40 = -energyK/log(SDIV(pop_ratio40) * states[0].g()/states[4].g());
1789 
1790  pop_ratio40_sum = H2_X_colden[0][4]/SDIV(H2_X_colden[0][0]);
1791  T40_sum = -energyK/log(SDIV(pop_ratio40_sum) * states[0].g()/states[4].g());
1792  }
1793  else
1794  {
1795  pop_ratio10 = 0.;
1796  T10 = 0.;
1797  T20 = 0.;
1798  T30 = 0.;
1799  T31 = 0.;
1800  T40 = 0.;
1801  T10_sum = 0.;
1802  T20_sum = 0.;
1803  T30_sum = 0.;
1804  T31_sum = 0.;
1805  T40_sum = 0.;
1806  }
1807 
1808  /* various temperatures for neutral/molecular gas */
1809  fprintf( io,
1810  "%.5e\t%.3e\t%.3e\t%.3e\t%.3e\t%.3e\t%.3e\t%.3e\t%.3e\t%.3e\t%.3e\t%.3e\t%.3e\t%.3e\t%.3e\t%.3e\n" ,
1811  /* depth in cm */
1813  /* total H2 fraction */
1815  /* ratio of populations of 1 to 0 only */
1816  pop_ratio10 ,
1817  /* sum of all ortho and para */
1819  T10,T20,T30,T31,T40,
1820  phycon.te ,
1821  hyperfine.Tspin21cm,T10_sum,T20_sum,T30_sum,T31_sum,T40_sum );
1822  }
1823  else if( (strcmp(chJOB , "H2ln" ) == 0) && (strcmp(chTime,"LAST") == 0) )
1824  {
1825  /* save H2 lines - output the full emission-line spectrum */
1826  double thresh;
1827  double renorm;
1828  /* first test, is H2 turned on? Second test, have lines arrays
1829  * been set up - nsum is negative if abort occurs before lines
1830  * are set up */
1831  if( lgEnabled && LineSave.nsum > 0)
1832  {
1833  ASSERT( LineSave.ipNormWavL >= 0 );
1834  /* get the normalization line */
1835  if( LineSave.lines[LineSave.ipNormWavL].SumLine(0) > SMALLFLOAT )
1836  renorm = LineSave.ScaleNormLine/
1837  LineSave.lines[LineSave.ipNormWavL].SumLine(0);
1838  else
1839  renorm = 1.;
1840 
1841  if( renorm > SMALLFLOAT )
1842  {
1843  /* this is threshold for faintest line, normally 0, set with
1844  * number on save H2 command */
1845  thresh = thresh_punline_h2/(realnum)renorm;
1846  }
1847  else
1848  thresh = 0.f;
1849 
1850  /* save H2 line intensities at end of iteration
1851  * nElecLevelOutput is electronic level with 1 for ground, so this loop is < nElecLevelOutput */
1852  for( TransitionList::iterator tr = trans.begin(); tr != rad_end; ++tr )
1853  {
1854  qList::iterator Hi = ( (*tr).Hi() );
1855  qList::iterator Lo = ( (*tr).Lo() );
1856  long iElecHi = (*Hi).n();
1857  long iVibHi = (*Hi).v();
1858  long iRotHi = (*Hi).J();
1859  long iElecLo = (*Lo).n();
1860  long iVibLo = (*Lo).v();
1861  long iRotLo = (*Lo).J();
1862  if( iElecHi >= nElecLevelOutput )
1863  continue;
1864  if( H2_SaveLine[iElecHi][iVibHi][iRotHi][iElecLo][iVibLo][iRotLo] > thresh )
1865  {
1866  /* air wavelength in microns */
1867  /* WLAng contains correction for index of refraction of air */
1868  double wl = (*tr).WLAng()/1e4;
1869  fprintf(io, "%li-%li %c(%li)", iVibHi, iVibLo, chMolBranch( iRotHi, iRotLo ), iRotLo );
1870  fprintf( io, "\t%ld\t%ld\t%ld\t%ld\t%ld\t%ld", iElecHi , iVibHi , iRotHi , iElecLo , iVibLo , iRotLo);
1871  /* WLAng contains correction for index of refraction of air */
1872  fprintf( io, "\t%.7f\t", wl );
1873  /*prt_wl print floating wavelength in Angstroms, in output format */
1874  prt_wl( io , (*tr).WLAng() );
1875  /* the log of the line intensity or luminosity */
1876  fprintf( io, "\t%.3f\t%.3e",
1877  log10( MAX2(1e-37, H2_SaveLine[iElecHi][iVibHi][iRotHi][iElecLo][iVibLo][iRotLo]*radius.Conv2PrtInten) ),
1878  H2_SaveLine[iElecHi][iVibHi][iRotHi][iElecLo][iVibLo][iRotLo]*renorm );
1879  /* excitation energy of upper level in K */
1880  fprintf( io, "\t%.3f", (*Hi).energy().K() );
1881  /* the product g_hi h nu * Aul */
1882  fprintf( io, "\t%.3e", (*tr).Emis().Aul() * (*tr).EnergyErg() * (*(*tr).Hi()).g() );
1883  fprintf( io, "\n");
1884  }
1885  }
1886  }
1887  }
1888  else if( (strcmp(chJOB , "H2sp" ) == 0) )
1889  {
1890  fprintf( io, "PUT SOMETHING HERE!\n" );
1891  }
1892  return;
1893 }
1894  /*cdH2_Line determines intensity and luminosity of and H2 line. The first
1895  * six arguments give the upper and lower quantum designation of the levels.
1896  * The function returns 1 if we found the line,
1897  * and false==0 if we did not find the line because ohoto-para transition
1898  * or upper level has lower energy than lower level */
1899 long int cdH2_Line(
1900  /* indices for the upper level */
1901  long int iElecHi,
1902  long int iVibHi ,
1903  long int iRotHi ,
1904  /* indices for lower level */
1905  long int iElecLo,
1906  long int iVibLo ,
1907  long int iRotLo ,
1908  /* linear intensity relative to normalization line*/
1909  double *relint,
1910  /* luminosity or intensity of line */
1911  double *absint )
1912 {
1913  DEBUG_ENTRY( "cdH2_Line()" );
1914  return h2.getLine( iElecHi, iVibHi, iRotHi, iElecLo, iVibLo, iRotLo, relint, absint );
1915 }
1916 
1917 long int diatomics::getLine( long iElecHi, long iVibHi, long iRotHi, long iElecLo, long iVibLo, long iRotLo, double *relint, double *absint )
1918 {
1919 
1920  DEBUG_ENTRY( "diatomics::getline()" );
1921 
1922  /* these will be return values if we can't find the line */
1923  *relint = 0.;
1924  *absint = 0.;
1925 
1926  /* for now both electronic levels must be zero */
1927  if( iElecHi!=0 || iElecLo!=0 )
1928  {
1929  return 0;
1930  }
1931 
1932  long ipHi = ipEnergySort[iElecHi][iVibHi][iRotHi];
1933  long ipLo = ipEnergySort[iElecLo][iVibLo][iRotLo];
1934 
1935  /* check that energy of first level is higher than energy of second level */
1936  if( states[ipHi].energy().WN() < states[ipLo].energy().WN() )
1937  {
1938  return 0;
1939  }
1940 
1941  /* check that ortho-para does not change */
1942  if( H2_lgOrtho[iElecHi][iVibHi][iRotHi] != H2_lgOrtho[iElecLo][iVibLo][iRotLo] )
1943  {
1944  return 0;
1945  }
1946 
1947  /* exit if lines does not exist */
1948  if( !lgH2_radiative[ipHi][ipLo] )
1949  {
1950  return 0;
1951  }
1952 
1953  ASSERT( LineSave.ipNormWavL >= 0 );
1954  /* does the normalization line have a positive intensity*/
1955  if( LineSave.lines[LineSave.ipNormWavL].SumLine(0) > 0. )
1956  {
1957  *relint = H2_SaveLine[iElecHi][iVibHi][iRotHi][iElecLo][iVibLo][iRotLo]/
1959  }
1960  else
1961  {
1962  *relint = 0.;
1963  }
1964 
1965  /* return log of line intensity if it is positive */
1966  if( H2_SaveLine[iElecHi][iVibHi][iRotHi][iElecLo][iVibLo][iRotLo] > 0. )
1967  {
1968  *absint = H2_SaveLine[iElecHi][iVibHi][iRotHi][iElecLo][iVibLo][iRotLo] *
1970  }
1971  else
1972  {
1973  *absint = 0.;
1974  }
1975  /* this indicates success */
1976  return 1;
1977 }
1978 
1979 void diatomics::set_numLevelsMatrix( long numLevels )
1980 {
1981  if( !lgREAD_DATA )
1982  nXLevelsMatrix = numLevels;
1983 }
1984 
1985 /* Read LTE cooling per molecule */
1987 {
1988  const char *cdDATAFILE = "lte_cooling.dat";
1989  char chLine[FILENAME_PATH_LENGTH_2];
1990 
1991  DEBUG_ENTRY( "H2_Read_LTE_cooling_per_H2()" );
1992 
1993  /* now open the data file */
1994  char chPath[FILENAME_PATH_LENGTH_2];
1995  strcpy( chPath, path.c_str() );
1996  strcat( chPath, input.chDelimiter );
1997  strcat( chPath, cdDATAFILE );
1998  FILE * ioDATA = open_data( chPath , "r" );
1999 
2000  LTE_Temp.resize( 0 );
2001  LTE_cool.resize( 0 );
2002 
2003  int nlines = 0;
2004  while( read_whole_line( chLine , (int)sizeof(chLine) , ioDATA ) != NULL )
2005  {
2006  /* skip comment */
2007  if( chLine[0]=='#' )
2008  continue;
2009  if( chLine[0]=='\n' || chLine[0]=='\0' || chLine[0]==' ' )
2010  break;
2011 
2012  double temp, cool;
2013  if( sscanf(chLine,"%lf\t%le", &temp, &cool) != 2 )
2014  TotalInsanity();
2015  // printf("%g\t %10e\n", temp, cool);
2016 
2017  LTE_Temp.push_back( temp );
2018  LTE_cool.push_back( cool );
2019  // printf("%g\t %10e\n", LTE_Temp[nlines], LTE_cool[nlines] );
2020 
2021  nlines++;
2022  }
2023 
2024  fclose( ioDATA );
2025 
2026  {
2027  enum { DEBUG_LOC = false };
2028  if( DEBUG_LOC )
2029  {
2030  for( int i = 0; i < nlines; i++ )
2031  {
2032  fprintf(stdout, "%i\t %f\t %e\n",
2033  i, log10( LTE_Temp[i] ), LTE_cool[i] );
2034  }
2035  cdEXIT( EXIT_SUCCESS );
2036  }
2037  }
2038 
2039  return;
2040 }
2041 
multi_arr< double, 2 > H2_rad_rate_in
Definition: h2_priv.h:514
char chH2ColliderLabels[N_X_COLLIDER][chN_X_COLLIDER]
Definition: h2_priv.h:455
static realnum thresh_punline_h2
Definition: mole_h2_io.cpp:40
iterator begin(size_type i1)
multi_arr< double, 2 > H2_col_rate_out
Definition: h2_priv.h:513
const int N_ELEC
Definition: h2_priv.h:34
bool nMatch(const char *chKey) const
Definition: parser.h:150
multi_arr< realnum, 3 > H2_dissprob
Definition: h2_priv.h:496
realnum punarg[LIMPUN][3]
Definition: save.h:372
double htot
Definition: thermal.h:169
void prt_wl(FILE *ioOUT, realnum wl)
Definition: prt.cpp:44
FILE * open_data(const char *fname, const char *mode, access_scheme scheme)
Definition: cpu.cpp:765
t_thermal thermal
Definition: thermal.cpp:6
t_colden colden
Definition: colden.cpp:5
STATIC long int ipPun
Definition: save_do.cpp:367
double H2_DissocEnergies[N_ELEC]
Definition: h2_priv.h:473
double exp10(double x)
Definition: cddefines.h:1368
void H2_Punch_line_data(FILE *ioPUN, bool lgDoAll)
const int FILENAME_PATH_LENGTH_2
Definition: cddefines.h:296
NORETURN void TotalInsanity(void)
Definition: service.cpp:971
t_input input
Definition: input.cpp:12
long int n_elec_states
Definition: h2_priv.h:416
t_hyperfine hyperfine
Definition: hyperfine.cpp:5
vector< double > LTE_cool
Definition: h2_priv.h:589
const realnum SMALLFLOAT
Definition: cpu.h:246
double Abund() const
Definition: h2_priv.h:75
double eWN
Definition: mole_h2_io.cpp:651
size_t sncatf(char *buf, size_t bufSize, const char *fmt,...)
Definition: service.cpp:716
void H2_ParseSave(Parser &p, ostringstream &chHeader)
Definition: mole_h2_io.cpp:73
double average_energy_s
Definition: h2_priv.h:294
multi_arr< double, 2 > pops_per_vib
Definition: h2_priv.h:464
double H2_rate_destroy
Definition: hmi.h:30
void Save1LineData(const TransitionProxy &t, FILE *io, bool lgCS_2)
#define PrintEfmt(F, V)
Definition: cddefines.h:1349
molecule * sp_star
Definition: h2_priv.h:428
bool lgREAD_DATA
Definition: h2_priv.h:259
valarray< long > ipVib_H2_energy_sort
Definition: h2_priv.h:548
long int Jlowest[N_ELEC]
Definition: h2_priv.h:480
double ortho_colden
Definition: h2_priv.h:335
const int nTE_HMINUS
Definition: h2_priv.h:31
double H2_Solomon_dissoc_rate_TH85_H2s
Definition: hmi.h:110
bool lgEvaluated
Definition: h2_priv.h:317
t_phycon phycon
Definition: phycon.cpp:6
t_LineSave LineSave
Definition: lines.cpp:10
void H2_Prt_column_density(FILE *ioMEAN)
Definition: mole_h2_io.cpp:368
vector< double > LTE_Temp
Definition: h2_priv.h:589
double H2_Solomon_dissoc_rate_BD96_H2g
Definition: hmi.h:106
multi_arr< realnum, 3 >::const_iterator mr3ci
iterator begin(void)
Definition: transition.h:339
int nElecLevelOutput
Definition: h2_priv.h:356
FILE * ioQQQ
Definition: cddefines.cpp:7
double H2_den_g
Definition: h2_priv.h:543
molezone * findspecieslocal(const char buf[])
double HeatH2Dish_TH85
Definition: hmi.h:140
void H2_Read_hminus_distribution(void)
Definition: mole_h2_io.cpp:976
double H2_Solomon_dissoc_rate_BD96_H2s
Definition: hmi.h:112
TransitionList trans
Definition: h2_priv.h:430
#define MIN2(a, b)
Definition: cddefines.h:803
Definition: parser.h:43
vector< LinSv > lines
Definition: lines.h:132
long int nsave
Definition: save.h:318
double H2_Solomon_dissoc_rate_TH85_H2g
Definition: hmi.h:104
t_dense dense
Definition: global.cpp:15
double Solomon_dissoc_rate_g
Definition: h2_priv.h:271
multi_arr< realnum, 3 > CollRateCoeff
Definition: h2_priv.h:485
const double *const dense_total
Definition: h2_priv.h:453
multi_arr< long int, 3 > ipEnergySort
Definition: h2_priv.h:551
multi_arr< double, 3 > H2_old_populations
Definition: h2_priv.h:501
double LTE_Cooling_per_H2()
molecule * sp
Definition: h2_priv.h:427
multi_arr< realnum, 3 > H2_disske
Definition: h2_priv.h:497
double ortho_density
Definition: h2_priv.h:326
bool operator<(const level_tmp &second) const
Definition: mole_h2_io.cpp:643
void H2_ReadEnergies()
Definition: mole_h2_io.cpp:655
double para_density
Definition: h2_priv.h:326
multi_arr< realnum, 3 > H2_X_hminus_formation_distribution
Definition: h2_priv.h:546
double energy(const genericState &gs)
long int nLevels_per_elec[N_ELEC]
Definition: h2_priv.h:482
#define STATIC
Definition: cddefines.h:118
bool lgEnabled
Definition: h2_priv.h:352
realnum Ploss() const
Definition: emission.h:130
double H2_den_s
Definition: h2_priv.h:543
long int cdH2_Line(long int iElecHi, long int iVibHi, long int iRotHi, long int iElecLo, long int iVibLo, long int iRotLo, double *relint, double *absint)
multi_arr< double, 3 > H2_populations_LTE
Definition: h2_priv.h:502
string label
Definition: h2_priv.h:435
long int nCall_this_zone
Definition: h2_priv.h:348
string path
Definition: h2_priv.h:437
t_mole_local mole
Definition: mole.cpp:8
void H2_Prt_Zone(void)
Definition: mole_h2_io.cpp:306
t_rfield rfield
Definition: rfield.cpp:9
const int N_X_COLLIDER
Definition: h2_priv.h:20
float realnum
Definition: cddefines.h:124
valarray< class molezone > species
Definition: mole.h:468
#define EXIT_FAILURE
Definition: cddefines.h:168
multi_arr< realnum, 2 > H2_X_colden_LTE
Definition: h2_priv.h:523
multi_arr< bool, 2 > lgH2_radiative
Definition: h2_priv.h:574
long int nXLevelsMatrix
Definition: h2_priv.h:556
size_t size() const
Definition: quantumstate.h:121
void H2_PrtDepartCoef(void)
Definition: mole_h2_io.cpp:335
void H2_LinesAdd(void)
Definition: mole_h2_io.cpp:43
#define cdEXIT(FAIL)
Definition: cddefines.h:482
int index
Definition: mole.h:194
multi_arr< realnum, 6 > H2_SaveLine
Definition: h2_priv.h:570
multi_arr< double, 3 > H2_rad_rate_out
Definition: h2_priv.h:498
diatomics h2("h2", 4100.,&hmi.H2_total, Yan_H2_CS)
realnum GetDopplerWidth(realnum massAMU)
double depth_mid_zone
Definition: radius.h:31
double HeatH2Dexc_TH85
Definition: hmi.h:140
double column(const genericState &gs)
double average_energy_g
Definition: h2_priv.h:293
double RandGauss(double xMean, double s)
Definition: service.cpp:1696
t_radius radius
Definition: radius.cpp:5
double extin_mag_V_point
Definition: rfield.h:258
double HeatDexc
Definition: h2_priv.h:297
realnum gas_phase[LIMELM]
Definition: dense.h:76
realnum UV_Cont_rel2_Draine_DB96_depth
Definition: hmi.h:84
iterator end(void)
Definition: transition.h:343
double Conv2PrtInten
Definition: radius.h:153
iterator end()
Definition: quantumstate.h:373
realnum AtomicWeight[LIMELM]
Definition: dense.h:80
void PutLine(const TransitionProxy &t, const char *chComment, const char *chLabelTemp, const ExtraInten &extra)
Definition: transition.cpp:318
double levels(const genericState &gs)
#define ASSERT(exp)
Definition: cddefines.h:613
double HeatDiss
Definition: h2_priv.h:296
double Tspin21cm
Definition: hyperfine.h:56
void H2_ReadTransprob(long int nelec, TransitionList &trans)
Definition: mole_h2_io.cpp:403
long int ipNormWavL
Definition: lines.h:102
STATIC char chMolBranch(long iRotHi, long int iRotLo)
realnum coldenH2_ov_vel
Definition: colden.h:37
long int getLine(long iElecHi, long iVibHi, long iRotHi, long iElecLo, long iVibLo, long iRotLo, double *relint, double *absint)
qList states
Definition: h2_priv.h:429
void H2_PunchLineStuff(FILE *io, realnum xLimit, long index)
#define DEBUG_ENTRY(funcname)
Definition: cddefines.h:723
realnum UV_Cont_rel2_Habing_spec_depth
Definition: hmi.h:74
void H2_Read_LTE_cooling_per_H2()
double Solomon_dissoc_rate_s
Definition: h2_priv.h:272
iterator begin()
Definition: quantumstate.h:365
char chDelimiter[3]
Definition: input.h:83
multi_arr< long int, 2 > ipTransitionSort
Definition: h2_priv.h:552
void H2_PunchDo(FILE *io, char chJOB[], const char chTime[], long int ipPun)
diatomics * whichDiatomToPrint[LIMPUN]
Definition: save.h:322
double getNumberDefault(const char *chDesc, double fdef)
Definition: parser.cpp:401
string label
Definition: mole.h:156
double Solomon_elec_decay_g
Definition: h2_priv.h:275
bool lgEOL(void) const
Definition: parser.h:113
#define MAX2(a, b)
Definition: cddefines.h:824
realnum UV_Cont_rel2_Habing_TH85_depth
Definition: hmi.h:74
TransitionList::iterator rad_end
Definition: h2_priv.h:431
int fprintf(const Output &stream, const char *format,...)
Definition: service.cpp:1121
void H2_ReadDissocEnergies(void)
Definition: mole_h2_io.cpp:818
realnum ** csupra
Definition: secondaries.h:33
valarray< long > nRot_hi[N_ELEC]
Definition: h2_priv.h:477
double pops_per_elec[N_ELEC]
Definition: h2_priv.h:484
double Solomon_elec_decay_s
Definition: h2_priv.h:276
sys_float SDIV(sys_float x)
Definition: cddefines.h:1002
double para_colden
Definition: h2_priv.h:335
double H2_renorm_chemistry
Definition: h2_priv.h:467
valarray< long > ipRot_H2_energy_sort
Definition: h2_priv.h:550
char * read_whole_line(char *chLine, int nChar, FILE *ioIN)
Definition: service.cpp:70
long int nsum
Definition: lines.h:87
GrainVar gv
Definition: grainvar.cpp:5
t_secondaries secondaries
Definition: secondaries.cpp:5
t_hmi hmi
Definition: hmi.cpp:5
void set_numLevelsMatrix(long numLevels)
void ShowMe(void)
Definition: service.cpp:205
t_save save
Definition: save.cpp:5
double te
Definition: phycon.h:21
double frac(double d)
double H2_Solomon_dissoc_rate_ELWERT_H2g
Definition: hmi.h:107
void H2_ReadDissprob(long int nelec)
Definition: mole_h2_io.cpp:885
void addone()
Definition: quantumstate.h:113
const int ipHYDROGEN
Definition: cddefines.h:349
realnum & Aul() const
Definition: emission.h:690
double getNumberDefaultNegImplLog(const char *chDesc, double fdef)
Definition: parser.cpp:455
vector< double > depart
Definition: h2_priv.h:562
long int nVib_hi[N_ELEC]
Definition: h2_priv.h:475
char chSave[LIMPUN][5]
Definition: save.h:321
long int ipass
Definition: lines.h:96
NORETURN void BadRead(void)
Definition: service.cpp:986
EmissionList & Emis()
Definition: transition.h:363
multi_arr< double, 2 > H2_col_rate_in
Definition: h2_priv.h:512
double dVeffAper
Definition: radius.h:93
double rate_h2_form_grains_used_total
Definition: grainvar.h:574
void init(const char *label, size_t i)
Definition: quantumstate.h:108
multi_arr< realnum, 2 > H2_X_colden
Definition: h2_priv.h:521
void spsort(realnum x[], long int n, long int iperm[], int kflag, int *ier)
Definition: service.cpp:1222
double ctot
Definition: thermal.h:130
double ScaleNormLine
Definition: lines.h:117
void Save1Line(const TransitionProxy &t, FILE *io, realnum xLimit, long index, realnum DopplerWidth)
Definition: save_do.cpp:3711
#define EXIT_SUCCESS
Definition: cddefines.h:166
double FFmtRead(const char *chCard, long int *ipnt, long int last, bool *lgEOL)
Definition: service.cpp:381
multi_arr< bool, 3 > H2_lgOrtho
Definition: h2_priv.h:504