cloudy  trunk
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
parse_atom_h2.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 /*ParseDatabaseH2 parse information from the atom command line */
4 #include "cddefines.h"
5 #include "hmi.h"
6 #include "h2.h"
7 #include "parser.h"
8 #include "thirdparty.h"
9 
10 /*ParseDatabaseH2 parse information from the atom command line */
12 {
13  long int j;
14 
15  DEBUG_ENTRY( "ParseDatabaseH2()" );
16 
17  fixit("this must be generalized!!!");
18  // easiest way is to create and populate diatoms before parsing,
19  // so we can simply iterator of diatoms and match strings.
20  // probably will want to put label on command line in quotes
21  // and change command to, for example,
22  // diatom "H2"
23  // do that work before entering this routine.
24  diatomics *diatom = NULL;
25 
26  if( p.nMatch(" H2 " ) )
27  {
28  diatom = &h2;
29  /* this command has a 2 in the H2 label - must not parse the two by
30  * accident. Get the first number off the line image, and confirm that
31  * it is a 2 */
32  j = (long int)p.FFmtRead();
33  if( j != 2 )
34  {
35  fprintf( ioQQQ, " Something is wrong with the order of the numbers on this line.\n" );
36  fprintf( ioQQQ, " The first number I encounter should be a 2.\n Sorry.\n" );
38  }
39  }
40  else
41  {
42  TotalInsanity();
43  }
44 
45  /* the mere calling of this routine turns the large H2 molecule on */
46  diatom->lgEnabled = true;
47 
48  if( p.nMatch("LEVE") )
49  {
50  /* number of electronic levels */
51 
52  /* lgREAD_DATA is false at start of calculation, set true when
53  * space allocated for the H lines. Once done we must ignore all
54  * future changes in the number of levels */
55  if( !diatom->lgREAD_DATA )
56  {
57  diatom->n_elec_states = (long int)p.FFmtRead();
58  if( p.lgEOL() )
59  {
60  if( p.nMatch("LARG") )
61  {
62  /* LARGE is option to use the most number of electronic levels */
63  diatom->n_elec_states = N_ELEC;
64  }
65  else
66  {
67  p.NoNumb("number of electronic levels");
68  }
69  }
70 
71  /* do not allow fewer than 3 - that includes Lyman & Werner bands */
72  if( diatom->n_elec_states < 3 )
73  {
74  fprintf( ioQQQ, " This would be too few electronic levels - resetting to 3.\n" );
75  diatom->n_elec_states = 3;
76  }
77  /* N_ELEC is the greatest number of elec lev possible */
78  else if( diatom->n_elec_states > N_ELEC )
79  {
80  fprintf( ioQQQ,
81  " This would be too many levels, the limit is %i.\n" ,
82  N_ELEC);
84  }
85  }
86  }
87 
88  else if( p.nMatch("LIMI") )
89  {
90  /* the limit to the H2 / Htot ratio -
91  * if smaller than this, do not compute large H2 mole */
92  diatom->H2_to_H_limit = p.FFmtRead();
93  if( p.lgEOL() )
94  {
95  /* did not find a number, either mistake or key " off" */
96  if( p.nMatch( " OFF" ) )
97  {
98  /* turn off limit */
99  diatom->H2_to_H_limit = -1.;
100  }
101  else
102  {
103  p.NoNumb( "limit to the H2 / Htot ratio" );
104  }
105  }
106  else
107  {
108  /* got a number, check if negative and so a log */
109  /* a number <= 0 is the log of the ratio */
110  if( diatom->H2_to_H_limit <= 0. )
111  diatom->H2_to_H_limit = exp10( diatom->H2_to_H_limit);
112  }
113  }
114  else if( p.nMatch("GBAR" ) )
115  {
116  /* option to either use, or not use, gbar approximation for low X
117  * levels with no collision data - by default it is on */
118  if( p.nMatch(" OFF" ) )
119  {
120  diatom->lgColl_gbar = false;
121  }
122  else if( p.nMatch(" ON " ) )
123  {
124  diatom->lgColl_gbar = true;
125  }
126  else
127  {
128  fprintf( ioQQQ,
129  " The gbar approximation must be off (\" OFF\") or on (\" ON \").\n");
131  }
132  }
133  /* option to turn collisional effects off or on */
134  else if( p.nMatch("COLL" ) )
135  {
136  /* option to turn collisional dissociation off or on */
137  if( p.nMatch("DISS" ) )
138  {
139  /* option to turn collisions off */
140  if( p.nMatch(" ON " ) )
141  {
142  /* this is the default, leave collisions off */
143  diatom->lgColl_dissoc_coll = true;
144  }
145  else
146  {
147  /* default (and only reason for this command) is to turn off collisions */
148  diatom->lgColl_dissoc_coll = false;
149  }
150  }
151  /* option to turn collisional dissociation off or on
152  * >>chng 06 mar 01, had been simply if - so all collisions were turned off
153  * when dissociation collisions turned off -
154  * due to bucket else at end */
155  else if( p.nMatch("ORTH" ) && p.nMatch("PARA" ) )
156  {
157  /* option to turn ortho - para collisions with particles off */
158  if( p.nMatch(" ON " ) )
159  {
160  /* this is the default, leave collisions off */
161  diatom->lgH2_ortho_para_coll_on = true;
162  }
163  else
164  {
165  /* default (and only reason for this command) is to turn off
166  * ortho-para collisions */
167  diatom->lgH2_ortho_para_coll_on = false;
168  }
169  }
170 
171  /* option to turn collisional effects off or on */
172  else if( p.nMatch("GRAI" ) )
173  {
174  /* option to turn collisions off */
175  if( p.nMatch(" ON" ) )
176  {
177  /* this is the default, leave collisions off */
178  diatom->lgH2_grain_deexcitation = true;
179  }
180  else
181  {
182  /* default (and only reason for this command) is to turn off collisions */
183  diatom->lgH2_grain_deexcitation = false;
184  }
185  }
186  else if( p.nMatch(" H ") )
187  {
188  long int nYear = (long) p.FFmtRead();
189  if (p.lgEOL())
190  p.NoNumb("collision data set (year)");
191  if (nYear == 1999)
192  {
193  /* use the coefficients from
194  *>>refer H2 H collision Le Bourlot, J., Pineau des Forets,
195  *>>refercon G., & Flower, D.R. 1999, MNRAS, 305, 802 */
196  h2.lgH2_H_coll_07 = false;
197  h2.coll_source[0].filename = "coll_rates_H_99.dat";
198  }
199  else if (nYear == 2007)
200  {
201  /* use the coefficients from
202  *>>refer H2 H collision Wrathmall, S. A., Gusdorf A.,
203  *>>refercon & Flower, D.R. 2007, MNRAS, 382, 133 */
204  h2.lgH2_H_coll_07 = true;
205  h2.coll_source[0].filename = "coll_rates_H_07.dat";
206  }
207  else if (nYear == 2015)
208  {
209  /* use the coefficients from
210  *>>refer H2 H collision Lique, F., 2015, MNRAS, 453, 810 */
211  h2.lgH2_H_coll_07 = false;
212  h2.coll_source[0].filename = "coll_rates_H_15.dat";
213  }
214  else
215  {
216  /* not an option */
217  fprintf(ioQQQ,
218  " I did not find the dataset year on this DATABASE H2 H command"
219  " - I know the 1999, 2007, and 2015 datasets" );
221  }
222  }
223  else if( p.nMatch(" HE " ) )
224  {
225  if( diatom != &h2 )
226  {
227  fprintf( ioQQQ, " Sorry. This command only applies to H2. The keyword H2 must appear on the command.\n" );
229  }
230 
231  /* atom H2 He collisions ORNL (the default), Le BOURlot, and OFF
232  * which data set for He collisions,
233  * Teck Lee et al. ApJ to be submitted */
234  if( p.nMatch(" NEW" ) || p.nMatch("ORNL" ) )
235  {
236  /* use the new coefficients */
237  diatom->lgH2_He_ORNL = true;
238  diatom->coll_source[1].filename = "coll_rates_He_ORNL.dat";
239  }
240  else if( p.nMatch(" OLD" ) || p.nMatch("BOUR" ) )
241  {
242  /* use the coefficients from
243  *>>refer H2 collision Le Bourlot, J., Pineau des Forets,
244  *>>refercon G., & Flower, D.R. 1999, MNRAS, 305, 802*/
245  diatom->lgH2_He_ORNL = false;
246  diatom->coll_source[1].filename = "coll_rates_He_LeBourlot.dat";
247  }
248  else
249  {
250  fprintf( ioQQQ,
251  " I did not find a keyword on this DATABASE H2 HE command - I know about the keys ORNL and Le BOURlot\n");
253  }
254  }
255 
256  /*>>chng 08 feb 27, GS*/
257  else if( p.nMatch("ORH2" ) )
258  {
259  if( diatom != &h2 )
260  {
261  fprintf( ioQQQ, " Sorry. This command only applies to H2. The keyword H2 must appear on the command.\n" );
263  }
264 
265  /* atom H2 H2ortho collisions ORNL (the default), Le BOURlot, and OFF
266  * which data set for H2 collisions,
267  * Teck Lee et al. ApJ to be submitted */
268  if( p.nMatch("ORNL" ) )
269  {
270  /* use the new coefficients */
271  diatom->lgH2_ORH2_ORNL = true;
272  diatom->coll_source[2].filename = "coll_rates_H2ortho_ORNL.dat";
273  }
274  else if( p.nMatch("BOUR" ) )
275  {
276  /* use the coefficients from
277  *>>refer H2 collision Le Bourlot, J., Pineau des Forets,
278  *>>refercon G., & Flower, D.R. 1999, MNRAS, 305, 802*/
279  diatom->lgH2_ORH2_ORNL = false;
280  diatom->coll_source[2].filename = "coll_rates_H2ortho_LeBourlot.dat";
281  }
282  else
283  {
284  fprintf( ioQQQ,
285  " I did not find a keyword on this SPECIES H2 ohH2 command - I know about the keys ORNL and Le BOURlot\n");
287  }
288  }
289 
290  else if( p.nMatch("PAH2" ) )
291  {
292  /* atom H2 H2ortho collisions ORNL (the default), Le BOURlot, and OFF
293  * which data set for He collisions,
294  * Teck Lee et al. ApJ to be submitted */
295  if( p.nMatch("ORNL" ) )
296  {
297  /* use the new coefficients */
298  diatom->lgH2_PAH2_ORNL = true;
299  diatom->coll_source[3].filename = "coll_rates_H2para_ORNL.dat";
300  }
301  else if( p.nMatch("BOUR" ) )
302  {
303  /* use the coefficients from
304  *>>refer H2 collision Le Bourlot, J., Pineau des Forets,
305  *>>refercon G., & Flower, D.R. 1999, MNRAS, 305, 802*/
306  diatom->lgH2_PAH2_ORNL = false;
307  diatom->coll_source[3].filename = "coll_rates_H2para_LeBourlot.dat";
308  }
309  else
310  {
311  fprintf( ioQQQ,
312  " I did not find a keyword on this SPECIES H2 paH2 command - I know about the keys ORNL and Le BOURlot\n");
314  }
315  }
316 
317  else
318  {
319  /* option to turn all collisions off */
320  if( p.nMatch(" ON " ) )
321  {
322  /* this is the default, leave collisions on */
323  diatom->lgColl_deexec_Calc = true;
324  }
325  else
326  {
327  /* default (and only reason for this command) is to turn off collisions */
328  diatom->lgColl_deexec_Calc = false;
329  }
330  }
331  }
332 
333  /* set number of levels in matrix, but not trace matrix option */
334  else if( p.nMatch("MATR" ) && !p.nMatch("TRAC" ) )
335  {
336  /* matrix option sets the number of levels that will
337  * be included in the matrix solution */
338  long numLevels = (long)p.FFmtRead();
339  if( p.nMatch(" ALL") )
340  {
341  /* " all" means do all of X, but space has not yet been allocated,
342  * so we do know know how many levels are within X - set special
343  * flag that will be used then this is known */
344  numLevels = -1;
345  }
346  else if( p.lgEOL() && !(p.nMatch(" OFF") || p.nMatch("NONE") ) )
347  {
348  /* this branch hit eol but OFF or NONE is not on line - this is a mistake */
349  fprintf( ioQQQ,
350  " The total number of levels used in the matrix solver must be entered, or keywords ALL or NONE entered.\n Sorry.\n");
352  }
353 
354  diatom->set_numLevelsMatrix( numLevels );
355  /* cannot check less than total number of levels within x since not yet set
356  * We do not certify that matrix limits are greater than 1 -
357  * zero or <0 limits just turns if off, as did the off option */
358  }
359  else if( p.nMatch(" LTE" ) )
360  {
361  /* LTE option causes code to assume LTE for level populations */
362  diatom->lgLTE = true;
363  }
364 
365  else if( p.nMatch("TRAC" ) )
366  {
367  /* these are used to set trace levels of output
368  diatom->n_trace_final = 1;
369  diatom->n_trace_iterations = 2;
370  diatom->n_trace_full = 3;
371  diatom->n_trace_matrix = 4*/
372 
373  /* turns on trace printout - there are multiple levels */
374  if( p.nMatch("FINA" ) )
375  {
376  /* FINAL gives only final information when solver exits */
377  diatom->nTRACE = diatom->n_trace_final;
378  }
379  else if( p.nMatch("ITER" ) )
380  {
381  /* follow iterations within each call */
382  diatom->nTRACE = diatom->n_trace_iterations;
383  }
384  else if( p.nMatch("FULL" ) )
385  {
386  /* full details of solution - this is also the default*/
387  diatom->nTRACE = diatom->n_trace_full;
388  }
389  else if( p.nMatch("MATR" ) )
390  {
391  /* print the matrices used for X */
392  diatom->nTRACE = diatom->n_trace_matrix;
393  }
394  else
395  {
396  /* full details of solution is also the default*/
397  diatom->nTRACE = diatom->n_trace_full;
398  }
399  }
400  else if( p.nMatch("NOIS" ) )
401  {
402  unsigned int iseed;
403  /* check on effects of uncertainties in collision rates */
404  diatom->lgH2_NOISE = true;
405  diatom->lgH2_NOISECOSMIC = true;
406 
407  /* optional mean - default is 0 */
408  diatom->xMeanNoise = p.FFmtRead();
409  if( p.lgEOL() )
410  diatom->xMeanNoise = 0.;
411 
412  /* this is the standard deviation for the mole, with default */
413  diatom->xSTDNoise = p.FFmtRead();
414  if( p.lgEOL() )
415  diatom->xSTDNoise = 0.5;
416 
417  /* this may be a seed for the random number generator. if no seed is
418  * set then use system time, and always get different sequence */
419  iseed = (unsigned int)p.FFmtRead();
420  /* returned 0 if eol hit */
421  if( iseed > 0 )
422  {
423  /* user set seed */
424  init_genrand( iseed );
425  }
426  else
427  {
428  init_genrand( (unsigned)time( NULL ) );
429  }
430  }
431 
432  else if( p.nMatch("THER" ) )
433  {
434  /* change the treatment of the heating - cooling effects of H2,
435  * options are simple (use TH85 expressions) and full (use large molecule)*/
436  if( p.nMatch("SIMP" ) )
437  {
438  hmi.lgH2_Thermal_BigH2 = false;
439  }
440  else if( p.nMatch("FULL" ) )
441  {
442  /* this is the default - use big atom */
443  hmi.lgH2_Thermal_BigH2 = true;
444  }
445  }
446 
447  else if( p.nMatch("CHEM" ) )
448  {
449  /* atom h2 chemistry simple command
450  * change the treatment of the chemistry - formation and destruction,
451  * options are simple (use TH85 expressions) and full (use large molecule)*/
452  if( p.nMatch("SIMP" ) )
453  {
454  hmi.lgH2_Chemistry_BigH2 = false;
455  }
456  else if( p.nMatch("FULL" ) )
457  {
458  /* this is the default - use big atom */
459  hmi.lgH2_Chemistry_BigH2 = true;
460  }
461  }
462 
463  /* there is no final branch - if we do not find a keyword, simply
464  * turn on the H2 molecule */
465  return;
466 }
int nTRACE
Definition: h2_priv.h:406
const int N_ELEC
Definition: h2_priv.h:34
bool nMatch(const char *chKey) const
Definition: parser.h:150
double FFmtRead(void)
Definition: parser.cpp:472
double exp10(double x)
Definition: cddefines.h:1368
NORETURN void TotalInsanity(void)
Definition: service.cpp:971
bool lgH2_Chemistry_BigH2
Definition: hmi.h:171
long int n_elec_states
Definition: h2_priv.h:416
bool lgH2_H_coll_07
Definition: h2_priv.h:359
int n_trace_full
Definition: h2_priv.h:409
t_coll_source coll_source[N_X_COLLIDER]
Definition: h2_priv.h:323
void ParseDatabaseH2(Parser &p)
bool lgREAD_DATA
Definition: h2_priv.h:259
double xSTDNoise
Definition: h2_priv.h:398
double H2_to_H_limit
Definition: h2_priv.h:401
FILE * ioQQQ
Definition: cddefines.cpp:7
Definition: parser.h:43
int n_trace_matrix
Definition: h2_priv.h:409
bool lgH2_ortho_para_coll_on
Definition: h2_priv.h:379
int n_trace_iterations
Definition: h2_priv.h:409
bool lgLTE
Definition: h2_priv.h:376
bool lgColl_dissoc_coll
Definition: h2_priv.h:369
string filename
Definition: h2_priv.h:69
double xMeanNoise
Definition: h2_priv.h:398
bool lgEnabled
Definition: h2_priv.h:352
bool lgH2_PAH2_ORNL
Definition: h2_priv.h:387
bool lgH2_NOISE
Definition: h2_priv.h:390
#define EXIT_FAILURE
Definition: cddefines.h:168
bool lgH2_He_ORNL
Definition: h2_priv.h:383
#define cdEXIT(FAIL)
Definition: cddefines.h:482
NORETURN void NoNumb(const char *chDesc) const
Definition: parser.cpp:345
diatomics h2("h2", 4100.,&hmi.H2_total, Yan_H2_CS)
bool lgColl_deexec_Calc
Definition: h2_priv.h:366
bool lgH2_grain_deexcitation
Definition: h2_priv.h:373
#define DEBUG_ENTRY(funcname)
Definition: cddefines.h:723
bool lgH2_ORH2_ORNL
Definition: h2_priv.h:386
bool lgH2_Thermal_BigH2
Definition: hmi.h:171
bool lgColl_gbar
Definition: h2_priv.h:363
bool lgH2_NOISECOSMIC
Definition: h2_priv.h:392
bool lgEOL(void) const
Definition: parser.h:113
int fprintf(const Output &stream, const char *format,...)
Definition: service.cpp:1121
void init_genrand(unsigned long s)
#define fixit(a)
Definition: cddefines.h:417
t_hmi hmi
Definition: hmi.cpp:5
void set_numLevelsMatrix(long numLevels)
int n_trace_final
Definition: h2_priv.h:409