cloudy  trunk
mole_drive.cpp
Go to the documentation of this file.
1 /* This file is part of Cloudy and is copyright (C)1978-2013 by Gary J. Ferland and
2  * others. For conditions of distribution and use see copyright notice in license.txt */
3 /*mole_drive - public routine, calls mole_solve to converge molecules */
4 #include "cddefines.h"
5 #include "taulines.h"
6 #include "dense.h"
7 #include "hmi.h"
8 #include "conv.h"
9 #include "doppvel.h"
10 #include "thermal.h"
11 #include "gammas.h"
12 #include "iso.h"
13 #include "opacity.h"
14 #include "phycon.h"
15 #include "physconst.h"
16 #include "radius.h"
17 #include "rfield.h"
18 #include "secondaries.h"
19 #include "timesc.h"
20 #include "trace.h"
21 #include "thermal.h"
22 #include "called.h"
23 #include "hcmap.h"
24 #include "coolheavy.h"
25 #include "mole.h"
26 #include "mole_priv.h"
27 #include "dynamics.h"
28 #include "h2.h"
29 #include "co.h"
30 #include "ionbal.h"
31 
32 /* this is the error tolerance for reporting non-convergence */
33 static const double MOLETOLER = 0.10;
34 
35 STATIC void mole_effects(void);
37 STATIC void mole_ion_trim(void);
39 
40 /*mole_drive main driver for heavy molecular equilibrium routines */
41 void mole_drive(void)
42 {
43  DEBUG_ENTRY( "mole_drive()" );
44 
45  mole_update_species_cache(); /* Update densities of species controlled outside the chemical network */
46 
48 
50 
51  double error = mole_solve();
52 
53  bool lgConverged = (error < MOLETOLER);
54 
55  if( !lgConverged )
56  {
57  // should something be done with this?
58  }
59 
60  mole_ion_trim();
61 
62  mole_effects();
63 
64  return;
65 }
66 
68 {
69  for (ChemAtomList::iterator atom = unresolved_atom_list.begin();
70  atom != unresolved_atom_list.end(); ++atom)
71  {
72  const long int nelem=(*atom)->el->Z-1;
73  if( !dense.lgElmtOn[nelem] )
74  continue;
75 
76  for (long int ion=0;ion<nelem+2;ion++)
77  {
78  if ((*atom)->ipMl[ion] != -1)
79  {
80  if (dense.IonLow[nelem] > ion )
81  {
82  if( dense.xIonDense[nelem][ion] > ( ionbal.trimlo * dense.gas_phase[nelem] ) )
83  dense.IonLow[nelem] = ion;
84  else
85  {
86  dense.xIonDense[nelem][dense.IonLow[nelem]] += dense.xIonDense[nelem][ion];
87  dense.xIonDense[nelem][ion] = 0.;
88  }
89  }
90 
91  if (dense.IonHigh[nelem] < ion )
92  {
93  if( dense.xIonDense[nelem][ion] > ( ionbal.trimhi * dense.gas_phase[nelem] ) )
94  dense.IonHigh[nelem] = ion;
95  else
96  {
97  dense.xIonDense[nelem][dense.IonHigh[nelem]] += dense.xIonDense[nelem][ion];
98  dense.xIonDense[nelem][ion] = 0.;
99  }
100  }
101  }
102  }
103  }
104 }
105 
107 {
108  DEBUG_ENTRY( "mole_update_sources()" );
109 
112 }
113 
115 {
116  double
117  plte;
118 
119  DEBUG_ENTRY( "mole_effects()" );
120 
122 
123  co.CODissHeat = (realnum)(mole.findrate("PHOTON,CO=>C,O")*1e-12);
124 
125  thermal.heating[0][9] = co.CODissHeat;
126 
127  /* total H2 - all forms */
129  hmi.HD_total = findspecieslocal("HD")->den;
130  /* first guess at ortho and para densities */
131  h2.ortho_density = 0.75*hmi.H2_total;
132  h2.para_density = 0.25*hmi.H2_total;
133  {
137  }
138 
139  /* save rate H2 is destroyed units s-1 */
140  /* >>chng 05 mar 18, TE, add terms -
141  total destruction rate is: dest_tot = n_H2g/n_H2tot * dest_H2g + n_H2s/n_H2tot * dest_H2s */
142  /* as reactions that change H2s to H2g and vice versa are not counted destruction processes, the terms c[ipMH2g][ipMH2s] *
143  and c[ipMH2s][ipMH2g], which have a different sign than [ipMH2g][ipMH2g] and [ipMH2s][ipMH2s], have to be added */
145 
146  /* establish local timescale for H2 molecule destruction */
148  {
149  /* units are now seconds */
151  }
152  else
153  {
155  }
156 
157  /* local timescale for H2 formation
158  * both grains and radiative attachment
159  * >>chng 08 mar 15 rjrw -- ratio formation rate to density of _H2_ so comparable with destruction rate,
160  * use full rates not rate coefficients so have correct units */
161  timesc.time_H2_Form_here = (mole.findrate("H,H,grn=>H2*,grn")+mole.findrate("H,H,grn=>H2,grn"));
162  /* timescale is inverse of this rate */
164  {
165  /* units are now seconds */
167  }
168  else
169  {
171  }
172 
173 
174  /* heating due to H2 dissociation */
175 
176  /* H2 photodissociation heating, eqn A9 of Tielens & Hollenbach 1985a */
177  /*hmi.HeatH2Dish_TH85 = (float)(1.36e-23*findspecieslocal("H2")->den*h2esc*hmi.UV_Cont_rel2_Habing_TH85_depth);*/
178  /* >>chng 04 feb 07, more general to express heating in terms of the assumed
179  * photo rates - the 0.25 was obtained by inverting A8 & A9 of TH85 to find that
180  * there are 0.25 eV per dissociative pumping, ie, 10% of total
181  * this includes both H2g and H2s - TH85 say just ground but they include
182  * process for both H2 and H2s - as we did above - both must be in
183  * heating term */
184  /* >>chng 05 mar 11, TE, old had used H2_Solomon_dissoc_rate_used, which was only
185  * H2g. in regions where Solomon process is fast, H2s has a large population
186  * and the heating rate was underestimated. */
187  /* >>chng 05 jun 23,
188  * >>chng 05 dec 05, TE, modified to approximate the heating better for the
189  * new approximation */
190  /* >>chng 00 nov 25, explicitly break out this heat agent */
191  /* 2.6 eV of heat per deexcitation, consider difference
192  * between deexcitation (heat) and excitation (cooling) */
193  /* >>chng 04 jan 27, code moved here and simplified */
194  /* >>chng 05 jul 10, GS*/
195  /* average collisional rate for H2* to H2g calculated from big H2, GS*/
196 
197  /* TH85 dissociation heating - this is ALWAYS defined for reference
198  * may be output for comparison with other rates*/
199  hmi.HeatH2Dish_TH85 = 0.25 * EN1EV *
202 
203  /* TH85 deexcitation heating */
204  hmi.HeatH2Dexc_TH85 = ((mole.findrate("H2*,H2=>H2,H2") + mole.findrate("H2*,H=>H2,H"))
205  - (mole.findrate("H2,H2=>H2*,H2") + mole.findrate("H2,H=>H2*,H"))) * 4.17e-12;
206  /* this is derivative wrt temperature, only if counted as a cooling source */
208 
209  if( hmi.chH2_small_model_type == 'H' )
210  {
211  /* Burton et al. 1990 */
212  hmi.HeatH2Dish_BHT90 = 0.25 * EN1EV *
215 
216  /* Burton et al. 1990 heating */
217  hmi.HeatH2Dexc_BHT90 = ((mole.findrate("H2*,H2=>H2,H2") + mole.findrate("H2*,H=>H2,H"))
218  - (mole.findrate("H2,H2=>H2*,H2") + mole.findrate("H2,H=>H2*,H"))) * 4.17e-12;
219  /* this is derivative wrt temperature, only if counted as a cooling source */
221  }
222  else if( hmi.chH2_small_model_type == 'B')
223  {
224  /* Bertoldi & Draine */
225  hmi.HeatH2Dish_BD96 = 0.25 * EN1EV *
228  /* Bertoldi & Draine heating, same as TH85 */
229  hmi.HeatH2Dexc_BD96 = ((mole.findrate("H2*,H2=>H2,H2") + mole.findrate("H2*,H=>H2,H"))
230  - (mole.findrate("H2,H2=>H2*,H2") + mole.findrate("H2,H=>H2*,H"))) * 4.17e-12;
231  /* this is derivative wrt temperature, only if counted as a cooling source */
233  }
234  else if(hmi.chH2_small_model_type == 'E')
235  {
236  /* heating due to dissociation of H2
237  * >>chng 05 oct 19, TE, define new approximation for the heating due to the destruction of H2
238  * use this approximation for the specified cloud parameters, otherwise
239  * use limiting cases for 1 <= G0, G0 >= 1e7, n >= 1e7, n <= 1 */
240 
241  double log_density,
242  f1, f2,f3, f4, f5;
243  static double log_G0_face = -1;
244  static double k_f4;
245 
246 
247  /* test for G0
248  * this is a constant so only do it in zone 0 */
249  if( !nzone )
250  {
252  {
253  log_G0_face = 0.;
254  }
255  else if(hmi.UV_Cont_rel2_Draine_DB96_face >= 1e7)
256  {
257  log_G0_face = 7.;
258  }
259  else
260  {
261  log_G0_face = log10(hmi.UV_Cont_rel2_Draine_DB96_face);
262  }
263  /*>>chng 06 oct 24 TE change Go face for spherical geometry*/
264  log_G0_face /= radius.r1r0sq;
265  }
266 
267  /* test for density */
268  if(dense.gas_phase[ipHYDROGEN] <= 1.)
269  {
270  log_density = 0.;
271  }
272  else if(dense.gas_phase[ipHYDROGEN] >= 1e7)
273  {
274  log_density = 7.;
275  }
276  else
277  {
278  log_density = log10(dense.gas_phase[ipHYDROGEN]);
279  }
280 
281  f1 = 0.15 * log_density + 0.75;
282  f2 = -0.5 * log_density + 10.;
283 
284  hmi.HeatH2Dish_ELWERT = 0.25 * EN1EV * f1 *
288 
289  /*fprintf( ioQQQ, "f1: %.2e, f2: %.2e,heat Solomon: %.2e",f1,f2,hmi.HeatH2Dish_TH85);*/
290 
291 
292  /* heating due to collisional deexcitation within X of H2
293  * >>chng 05 oct 19, TE, define new approximation for the heating due to the destruction of H2
294  * use this approximation for the specified cloud parameters, otherwise
295  * use limiting cases for 1 <= G0, G0 >= 1e7, n >= 1e7, n <= 1 */
296 
297  /* set value of k_f4 by testing on value of G0 */
299  {
300  log_G0_face = 0.;
301  }
302  else if(hmi.UV_Cont_rel2_Draine_DB96_face >= 1e7)
303  {
304  log_G0_face = 7.;
305  }
306  else
307  {
308  log_G0_face = log10(hmi.UV_Cont_rel2_Draine_DB96_face);
309  }
310  /* 06 oct 24, TE introduce effects of spherical geometry */
311  log_G0_face /= radius.r1r0sq;
312 
313  /* terms only dependent on G0_face */
314  k_f4 = -0.25 * log_G0_face + 1.25;
315 
316  /* test for density */
317  if(dense.gas_phase[ipHYDROGEN] <= 1.)
318  {
319  log_density = 0.;
320  f4 = 0.;
321  }
322  else if(dense.gas_phase[ipHYDROGEN] >= 1e7)
323  {
324  log_density = 7.;
325  f4 = pow2(k_f4) * pow( 10. , 2.2211 * log_density - 29.8506);
326  }
327  else
328  {
329  log_density = log10(dense.gas_phase[ipHYDROGEN]);
330  f4 = pow2(k_f4) * pow( 10., 2.2211 * log_density - 29.8506);
331  }
332 
333  f3 = MAX2(0.1, -4.75 * log_density + 24.25);
334  f5 = MAX2(1.,0.95 * log_density - 1.45) * 0.2 * log_G0_face;
335 
336  hmi.HeatH2Dexc_ELWERT = ((mole.findrate("H2*,H2=>H2,H2") + mole.findrate("H2*,H=>H2,H"))
337  - (mole.findrate("H2,H2=>H2*,H2") + mole.findrate("H2,H=>H2*,H"))) * 4.17e-12 * f3 +
340 
341  if(log_G0_face == 0.&& dense.gas_phase[ipHYDROGEN] > 1.)
343 
344  /* >>chng 06 oct 24, TE introduce effects of spherical geometry */
345  /*if(radius.depth/radius.rinner >= 1.0) */
347 
348  /* this is derivative wrt temperature, only if counted as a cooling source */
350 
351  /*fprintf( ioQQQ, "\tf3: %.2e, f4: %.2e, f5: %.2e, heat coll dissoc: %.2e\n",f3,f4,f5,hmi.HeatH2Dexc_TH85);*/
352  }
353  /* end Elwert branch for photo rates */
354  else
355  TotalInsanity();
356 
357 
358  if( findspecieslocal("H-")->den > 0. && hmi.rel_pop_LTE_Hmin > 0. )
359  {
360  hmi.hmidep = (double)findspecieslocal("H-")->den/ SDIV(
362  }
363  else
364  {
365  hmi.hmidep = 1.;
366  }
367 
368  /* this will be net volume heating rate, photo heat - induc cool */
370 
371  /* H2+ + HNU => H+ + H */
372  t_phoHeat photoHeat;
373  (void) GammaK(opac.ih2pnt[0],opac.ih2pnt[1],opac.ih2pof,1.,&photoHeat); /* Now used entirely for side-effect. Yuk */
374  hmi.h2plus_heat = photoHeat.HeatNet*findspecieslocal("H2+")->den;
375 
376  /* departure coefficient for H2 defined rel to n(1s)**2
377  * (see Littes and Mihalas Solar Phys 93, 23) */
378  plte = (double)dense.xIonDense[ipHYDROGEN][0] * hmi.rel_pop_LTE_H2g * (double)dense.xIonDense[ipHYDROGEN][0];
379  if( plte > 0. )
380  {
381  hmi.h2dep = findspecieslocal("H2")->den/plte;
382  }
383  else
384  {
385  hmi.h2dep = 1.;
386  }
387 
388  /* departure coefficient of H2+ defined rel to n(1s) n(p)
389  * sec den was HI before 85.34 */
390  plte = (double)dense.xIonDense[ipHYDROGEN][0]*hmi.rel_pop_LTE_H2p*(double)dense.xIonDense[ipHYDROGEN][1];
391  if( plte > 0. )
392  {
393  hmi.h2pdep = findspecieslocal("H2+")->den/plte;
394  }
395  else
396  {
397  hmi.h2pdep = 1.;
398  }
399 
400  /* departure coefficient of H3+ defined rel to N(H2+) N(p) */
401  if( hmi.rel_pop_LTE_H3p > 0. )
402  {
404  }
405  else
406  {
407  hmi.h3pdep = 1.;
408  }
409 
411 
412  return;
413 }
414 #if defined(__HP_aCC)
415 #pragma OPTIMIZE OFF
416 #pragma OPTIMIZE ON
417 #endif
419 {
420  int i;
421  double
422  rate;
423 
424  /* identify dominant H2 formation process */
425  {
426  /* following should be set true to identify H2 formation and destruction processes */
427  /*@-redef@*/
428  enum {DEBUG_LOC=false};
429  /*@+redef@*/
430  if( DEBUG_LOC && (nzone>50) )
431  {
432  double createsum ,create_from_Hn2 , create_3body_Ho, create_h2p,
433  create_h3p, create_h3pe, create_grains, create_hminus;
434  double destroysum, destroy_hm ,destroy_solomon ,destroy_2h ,destroy_hp,
435  destroy_h,destroy_hp2,destroy_h3p;
436 
437  create_from_Hn2 = mole.findrate("H,H=>H2"); /* H(n=2) + H(n=1) -> H2 */
438  create_3body_Ho = mole.findrate("H,H,H=>H2,H");
439  create_h2p = mole.findrate("H,H2+=>H+,H2*");
440  create_h3p = mole.findrate("H,H3+=>H2,H2+");
441  create_h3pe = mole.findrate("e-,H3+=>H2,H");
442  create_grains = mole.findrate("H,H,grn=>H2*,grn")+mole.findrate("H,H,grn=>H2,grn");
443  create_hminus = (mole.findrate("H,H-=>H2,e-")+mole.findrate("H,H-=>H2*,e-"));
444 
445  createsum = create_from_Hn2 + create_3body_Ho + create_h2p +
446  create_h3p + create_h3pe + create_grains + create_hminus;
447 
448  fprintf(ioQQQ,"H2 create zone\t%.2f \tsum\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\n",
449  fnzone,
450  createsum,
451  create_hminus / createsum,
452  create_from_Hn2 / createsum,
453  create_3body_Ho / createsum,
454  create_h2p / createsum,
455  create_h3p / createsum,
456  create_h3pe / createsum,
457  create_grains / createsum );
458 
459  /* all h2 molecular hydrogen destruction processes */
460  /* >>chng 04 jan 28, had wrong Boltzmann factor,
461  * caught by gargi Shaw */
462  destroy_hm = (mole.findrate("H2,e-=>H,H-")+mole.findrate("H2*,e-=>H,H-"));
463  /*destroy_hm2 = eh2hhm;*/
464  destroy_solomon = hmi.H2_Solomon_dissoc_rate_used_H2g * findspecieslocal("H2")->den;
465  destroy_2h = (mole.findrate("H2,e-=>H,H,e-")+mole.findrate("H2*,e-=>H,H,e-"));
466  destroy_hp = mole.findrate("H2,H+=>H3+");
467  destroy_h = mole.findrate("H,H2=>H,H,H");
468  destroy_hp2 = mole.findrate("H2,H+=>H2+,H");
469  destroy_h3p = mole.findrate("H2,H3+=>H2,H2+,H");
470  destroysum = destroy_hm + /*destroy_hm2 +*/ destroy_solomon + destroy_2h +
471  destroy_hp+ destroy_h+ destroy_hp2+ destroy_h3p;
472 
473  fprintf(ioQQQ,"H2 destroy\t%.3f \t%.2e\tsum\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\n",
474  fnzone,
475  destroysum,
476  destroy_hm / destroysum ,
477  destroy_solomon / destroysum ,
478  destroy_2h / destroysum ,
479  destroy_hp / destroysum ,
480  destroy_h / destroysum ,
481  destroy_hp2 / destroysum ,
482  destroy_h3p / destroysum );
483 
484  }
485  }
486 
487  {
488  /* following should be set true to identify H- formation and destruction processes */
489  /*@-redef@*/
490  enum {DEBUG_LOC=false};
491  /*@+redef@*/
492  if( DEBUG_LOC && (nzone>140) )
493  {
494  double create_from_Ho,create_3body_Ho,create_batach,destroy_photo,
495  destroy_coll_heavies,destroy_coll_electrons,destroy_Hattach,destroy_fhneut,
496  destsum , createsum;
497 
498  create_from_Ho = mole.findrate("H,e-=>H-,PHOTON");
499  create_3body_Ho = mole.findrate("H,e-,e-=>H-,e-");
500  /* total formation is sum of g and s attachment */
501  create_batach = (mole.findrate("H2,e-=>H,H-") + mole.findrate("H2*,e-=>H,H-"));
502  destroy_photo = mole.findrate("H-,PHOTON=>H,e-");
503  destroy_coll_heavies = 0.;
504  for( i=ipLITHIUM; i < LIMELM; i++ )
505  {
506  char react[32];
507  if (dense.lgElmtOn[i])
508  {
509  sprintf(react,"H-,%s=>H,%s",mole_global.list[unresolved_atom_list[i]->ipMl[1]]->label.c_str(),unresolved_atom_list[i]->label().c_str() );
510  destroy_coll_heavies += mole.findrate(react);
511  }
512  }
513  destroy_coll_electrons = mole.findrate("H-,e-=>H-,e-,e-");
514  destroy_Hattach = (mole.findrate("H,H-=>H2,e-")+mole.findrate("H,H-=>H2*,e-"));
515  destroy_fhneut = mole.findrate("H-,H+=>H,H");
516 
517  destsum = destroy_photo + destroy_coll_heavies + destroy_coll_electrons +
518  destroy_Hattach + destroy_fhneut;
519  fprintf(ioQQQ,"H- destroy zone\t%.2f\tTe\t%.4e\tsum\t%.2e\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\n",
520  fnzone,
521  phycon.te,
522  destsum,
523  destroy_photo/destsum ,
524  destroy_coll_heavies/destsum,
525  destroy_coll_electrons/destsum,
526  destroy_Hattach/destsum,
527  destroy_fhneut/destsum );
528 
529  createsum = create_from_Ho+create_3body_Ho+create_batach;
530  fprintf(ioQQQ,"H- create\t%.2f\tTe\t%.4e\tsum\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\n",
531  fnzone,
532  phycon.te,
533  createsum,
534  dense.eden,
535  create_from_Ho/createsum,
536  create_3body_Ho/createsum,
537  create_batach/createsum);
538  }
539  }
540  {
541  /* following should be set true to print populations */
542  /*@-redef@*/
543  enum {DEBUG_LOC=false};
544  /*@+redef@*/
545  if( DEBUG_LOC )
546  {
547  /* these are the raw results */
548  fprintf( ioQQQ, " MOLE raw; hi\t%.2e" , dense.xIonDense[ipHYDROGEN][0]);
549  for( i=0; i < mole_global.num_calc; i++ )
550  {
551  fprintf( ioQQQ, "\t%-4.4s\t%.2e", mole_global.list[i]->label.c_str(), mole.species[i].den );
552  }
553  fprintf( ioQQQ, " \n" );
554  }
555  }
556 
557  if( trace.lgTrace && trace.lgTraceMole )
558  {
559  /* these are the raw results */
560  fprintf( ioQQQ, " raw; " );
561  for( i=0; i < mole_global.num_calc; i++ )
562  {
563  fprintf( ioQQQ, " %-4.4s:%.2e", mole_global.list[i]->label.c_str(), mole.species[i].den );
564  }
565  fprintf( ioQQQ, " \n" );
566 
567  }
568 
569  /* option to print rate H2 forms */
570  /* trace.lgTraceMole is trace molecules option,
571  * punch htwo */
572  if( (trace.lgTrace && trace.lgTraceMole) )
573  {
575  double H2_rate_create = mole.source_rate_tot("H2") + mole.source_rate_tot("H2*");
576 
577  if( H2_rate_create > SMALLFLOAT )
578  {
579  fprintf( ioQQQ, " Create H2, rate=%10.2e grain;%5.3f hmin;%5.3f bhedis;%5.3f h2+;%5.3f hmi.radasc:%5.3f hmi.h3ph2p:%5.3f hmi.h3petc:%5.3f\n",
580  H2_rate_create,
581  (mole.findrate("H,H,grn=>H2*,grn")+mole.findrate("H,H,grn=>H2,grn"))/H2_rate_create,
582  (mole.findrate("H,H-=>H2,e-")+mole.findrate("H,H-=>H2*,e-"))/H2_rate_create,
583  mole.findrate("H,H,H=>H2,H")/H2_rate_create,
584  mole.findrate("H,H2+=>H+,H2*")/H2_rate_create,
585  mole.findrate("H,H=>H2")/H2_rate_create,
586  mole.findrate("H,H3+=>H2,H2+")/H2_rate_create,
587  mole.findrate("H2,H3+=>H2,H2+,H")/H2_rate_create );
588  }
589  else
590  {
591  fprintf( ioQQQ, " Create H2, rate=0\n" );
592  }
593  }
594 
595  /* this is H2+ */
596  if( trace.lgTrace && trace.lgTraceMole )
597  {
598  rate = mole.findrate("H2,H+=>H2+,H") + mole.findrate("H,H+,e-=>H2+,e-") +
599  mole.findrate("H,H3+=>H2,H2+") + mole.findrate("H2,H3+=>H2,H2+,H");
600  if( rate > 1e-25 )
601  {
602  fprintf( ioQQQ, " Create H2+, rate=%10.2e hmi.rh2h2p;%5.3f b2pcin;%5.3f hmi.h3ph2p;%5.3f hmi.h3petc+;%5.3f\n",
603  rate, mole.findrate("H2,H+=>H2+,H")/rate,
604  mole.findrate("H,H+,e-=>H2+,e-")/rate, mole.findrate("H,H3+=>H2,H2+")/rate, mole.findrate("H2,H3+=>H2,H2+,H")/rate );
605  }
606  else
607  {
608  fprintf( ioQQQ, " Create H2+, rate=0\n" );
609  }
610  }
611 
612  if( trace.lgTrace && trace.lgTraceMole )
613  {
614 
615  double destroy_coll_heavies = 0.;
616 
617  for( i=ipLITHIUM; i < LIMELM; i++ )
618  {
619  char react[32];
620  if (dense.lgElmtOn[i])
621  {
622  sprintf(react,"H-,%s=>H,%s",mole_global.list[unresolved_atom_list[i]->ipMl[1]]->label.c_str(),unresolved_atom_list[i]->label().c_str() );
623  destroy_coll_heavies += mole.findrate(react);
624  }
625  }
626  fprintf( ioQQQ, " MOLE, Dep Coef, H-:%10.2e H2:%10.2e H2+:%10.2e\n",
628  fprintf( ioQQQ, " H- creat: Rad atch%10.3e Induc%10.3e bHneut%10.2e 3bod%10.2e b=>H2%10.2e N(H-);%10.2e b(H-);%10.2e\n",
629  mole.findrate("H,e-=>H-,PHOTON"), hmi.HMinus_induc_rec_rate*findspecieslocal("H-")->den, mole.findrate("H,H=>H-,H+"),
630  mole.findrate("H,e-,e-=>H-,e-"),
631  mole.findrate("H2,e-=>H,H-"), findspecieslocal("H-")->den, hmi.hmidep );
632 
633  fprintf( ioQQQ, " H- destr: Photo;%10.3e mut neut%10.2e e- coll ion%10.2e =>H2%10.2e x-ray%10.2e p+H-%10.2e\n",
634  mole.findrate("H-,PHOTON=>H,e-"), destroy_coll_heavies,
635  mole.findrate("H-,e-=>H-,e-,e-"),
636  (mole.findrate("H,H-=>H2,e-")+mole.findrate("H,H-=>H2*,e-")), iso_sp[ipH_LIKE][ipHYDROGEN].fb[ipH1s].gamnc*findspecieslocal("H-")->den,
637  mole.findrate("H-,H+=>H,H") );
638  fprintf( ioQQQ, " H- heating:%10.3e Ind cooling%10.2e Spon cooling%10.2e\n",
640  }
641 
642  /* identify creation and destruction processes for H2+ */
643  if( trace.lgTrace && trace.lgTraceMole )
644  {
645  rate = findspecieslocal("H2+")->snk;
646  if( rate != 0. )
647  {
648  rate *= findspecieslocal("H2+")->den;
649  if( rate > 0. )
650  {
651  fprintf( ioQQQ,
652  " Destroy H2+: rate=%10.2e e-;%5.3f phot;%5.3f hard gam;%5.3f H2col;%5.3f h2phhp;%5.3f pion;%5.3f bh2h2p:%5.3f\n",
653  rate, mole.findrate("H2+,e-=>H,H+,e-")/rate, mole.findrate("H2+,PHOTON=>H,H+")/rate,
654  mole.findrate("H2+,CRPHOT=>H,H+")/rate, mole.findrate("H2,H2+=>H,H3+")/rate, mole.findrate("H2+,H2=>H,H+,H2")/rate,
655  mole.findrate("H2+,H+=>H,H+,H+")/rate, mole.findrate("H,H2+=>H+,H2*")/rate );
656 
657  fprintf( ioQQQ,
658  " Create H2+: rate=%.2e HII HI;%.3f Col H2;%.3f HII H2;%.3f HI HI;%.3f\n",
659  rate,
660  mole.findrate("H+,H=>H2+,PHOTON")/rate,
661  mole.findrate("H2,CRPHOT=>H2+,e-")/rate,
662  mole.findrate("H2,H+=>H2+,H")/rate,
663  mole.findrate("H,H+,e-=>H2+,e-")/rate );
664  }
665  else
666  {
667  fprintf( ioQQQ, " Create H2+: rate= is zero\n" );
668  }
669  }
670  }
671 
672  {
673  /* following should be set true to print populations */
674  /*@-redef@*/
675  enum {DEBUG_LOC=false};
676  /*@+redef@*/
677  if( DEBUG_LOC )
678  {
679  fprintf(ioQQQ,"mole bugg\t%.3f\t%.2e\t%.2e\t%.2e\t%.2e\t%.2e\n",
680  fnzone,
681  iso_sp[ipH_LIKE][ipHYDROGEN].fb[0].gamnc,
683  findspecieslocal("H2")->den ,
684  findspecieslocal("H-")->den ,
685  findspecieslocal("H+")->den);
686  }
687  }
688 
689  {
690  /*@-redef@*/
691  /* this debug print statement compares H2 formation through grn vs H- */
692  enum {DEBUG_LOC=false};
693  /*@+redef@*/
694  if( DEBUG_LOC && nzone>140 )
695  {
696  fprintf(ioQQQ," debuggggrn grn\t%.2f\t%.3e\t%.3e\tfrac\t%.3e\tH-\t%.3e\t%.3e\tfrac\t%.3e\t%.3e\t%.3e\t%.3e\n",
697  fnzone ,
698  mole.findrate("H,H,grn=>H2*,grn")+mole.findrate("H,H,grn=>H2,grn") ,
700  mole.findrate("H,H,grn=>H2*,grn")/SDIV(mole.findrate("H,H,grn=>H2*,grn")+mole.findrate("H,H,grn=>H2,grn")),
701  (mole.findrate("H,H-=>H2,e-")+mole.findrate("H,H-=>H2*,e-")),
704  (mole.findrate("H,H-=>H2,e-")+mole.findrate("H,H-=>H2*,e-")),findspecieslocal("H")->den,findspecieslocal("H-")->den
705  );
706  }
707  }
708 
709  {
710  /*@-redef@*/
711  /* often the H- route is the most efficient formation mechanism for H2,
712  * will be through rate called mole_global.list[unresolved_atom_list[ipHYDROGEN]->ipMl]->den*hmi.assoc_detach
713  * this debug print statement is to trace h2 oscillations */
714  enum {DEBUG_LOC=false};
715  /*@+redef@*/
716  if( DEBUG_LOC && nzone>140/*&& iteration > 1*/)
717  {
718  /* rapid increase in H2 density caused by rapid increase in hmi.rel_pop_LTE_H2g */
719  fprintf(ioQQQ,
720  "hmi.assoc_detach_backwards_grnd\t%.2f\t%.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\n",
721  /* total forward rate */
722  fnzone,
723  phycon.te,
724  dense.eden,
725  (mole.findrate("H,H-=>H2,e-")+mole.findrate("H,H-=>H2*,e-")),
726  mole.findrate("H2,e-=>H,H-"),
727  mole.findrate("H2*,e-=>H,H-"),
728  mole.findrate("H,e-=>H-,PHOTON"),
732  findspecieslocal("H-")->den,
733  hmi.H2_total,
737  );
738  }
739  }
740 
741  if( (trace.lgTrace && trace.lgTraceMole) )
742  {
744  {
745  fprintf( ioQQQ,
746  " H2 destroy rate=%.2e DIS;%.3f bat;%.3f h2dis;%.3f photoionize_rate;%.3f h2h2p;%.3f E-h;%.3f hmi.h2hph3p;%.3f sec;%.3f\n",
749  mole.findrate("H2,e-=>H,H-") / (hmi.H2_total*hmi.H2_rate_destroy),
750  mole.findrate("H,H2=>H,H,H") / (hmi.H2_total*hmi.H2_rate_destroy),
752  mole.findrate("H2,H+=>H2+,H") / (hmi.H2_total* hmi.H2_rate_destroy),
753  (mole.findrate("H2,e-=>H,H,e-")+mole.findrate("H2*,e-=>H,H,e-")) / (hmi.H2_total* hmi.H2_rate_destroy),
754  mole.findrate("H2,H+=>H3+") / (hmi.H2_total* hmi.H2_rate_destroy) ,
756  );
757  }
758  else
759  {
760  fprintf( ioQQQ, " Destroy H2: rate=0\n" );
761  }
762  }
763 
764  {
765  /* following should be set true to print populations */
766  /*@-redef@*/
767  enum {DEBUG_LOC=false};
768  /*@+redef@*/
769  if( DEBUG_LOC )
770  {
771  if( DEBUG_LOC && (nzone > 570) )
772  {
773  fprintf(ioQQQ,"Temperature %g\n",phycon.te);
774  fprintf(ioQQQ," Net mol ion rate [%g %g] %g\n",mole.source[ipHYDROGEN][1],mole.sink[ipHYDROGEN][1],
776  }
777  }
778  }
779 }
780 
782 {
783  DEBUG_ENTRY( "mole_update_limiting_reactants()" );
784 
785  /* largest fraction of atoms in molecules */
786  for( long i=0; i<mole_global.num_calc; ++i )
787  {
788  mole.species[i].xFracLim = 0.;
789  mole.species[i].nAtomLim = -1;
790  for (molecule::nAtomsMap::iterator atom = mole_global.list[i]->nAtom.begin();
791  atom != mole_global.list[i]->nAtom.end(); ++atom)
792  {
793  long nelem = atom->first->el->Z-1;
794  if( dense.lgElmtOn[nelem])
795  {
796  realnum dens_elemsp = (realnum)( mole.species[i].den * atom->second * atom->first->frac );
797  if (mole.species[i].xFracLim*dense.gas_phase[nelem] < dens_elemsp )
798  {
799  mole.species[i].xFracLim = dens_elemsp/dense.gas_phase[nelem];
800  mole.species[i].nAtomLim = nelem;
801  }
802  }
803  }
804  //fprintf( ioQQQ, "DEBUGGG mole_update_limiting_reactants %li\t%s\t%i\t%.12e\n", i, mole_global.list[i]->label.c_str(), mole.species[i].nAtomLim, mole.species[i].xFracLim );
805  }
806 
807  return;
808 }
809 
t_hmi::HMinus_photo_rate
double HMinus_photo_rate
Definition: hmi.h:42
mole_solve
double mole_solve(void)
Definition: mole_solve.cpp:49
thermal.h
t_hmi::HeatH2Dish_BD96
double HeatH2Dish_BD96
Definition: hmi.h:131
co
t_co co
Definition: co.cpp:5
findspecieslocal
molezone * findspecieslocal(const char buf[])
Definition: mole_species.cpp:833
t_hmi::HMinus_induc_rec_rate
double HMinus_induc_rec_rate
Definition: hmi.h:55
h2
diatomics h2("h2", 4100., &hmi.H2_total, Yan_H2_CS)
t_dense::eden
double eden
Definition: dense.h:190
mole_update_limiting_reactants
STATIC void mole_update_limiting_reactants()
Definition: mole_drive.cpp:781
t_hmi::HeatH2Dish_ELWERT
double HeatH2Dish_ELWERT
Definition: hmi.h:133
t_ionbal::trimlo
double trimlo
Definition: ionbal.h:92
t_hmi::h2pdep
double h2pdep
Definition: hmi.h:35
dense
t_dense dense
Definition: dense.cpp:24
t_hmi::UV_Cont_rel2_Draine_DB96_face
realnum UV_Cont_rel2_Draine_DB96_face
Definition: hmi.h:73
secondaries.h
t_hmi::HeatH2Dexc_BD96
double HeatH2Dexc_BD96
Definition: hmi.h:139
ioQQQ
FILE * ioQQQ
Definition: cddefines.cpp:7
mole_drive
void mole_drive(void)
Definition: mole_drive.cpp:41
t_mole_local::source_rate_tot
double source_rate_tot(const char chSpecies[]) const
Definition: mole_reactions.cpp:4076
t_hmi::rel_pop_LTE_H2g
double rel_pop_LTE_H2g
Definition: hmi.h:203
t_hmi::rel_pop_LTE_H3p
double rel_pop_LTE_H3p
Definition: hmi.h:205
t_hmi::H2star_forms_grains
double H2star_forms_grains
Definition: hmi.h:155
t_timesc::time_H2_Form_here
double time_H2_Form_here
Definition: timesc.h:38
t_opac::ih2pnt
long int ih2pnt[2]
Definition: opacity.h:229
realnum
float realnum
Definition: cddefines.h:103
conv.h
rfield.h
STATIC
#define STATIC
Definition: cddefines.h:97
ipLITHIUM
const int ipLITHIUM
Definition: cddefines.h:307
unresolved_atom_list
ChemAtomList unresolved_atom_list
Definition: mole_species.cpp:70
diatomics::para_density_f
realnum para_density_f
Definition: h2_priv.h:325
mole.h
t_dense::lgElmtOn
bool lgElmtOn[LIMELM]
Definition: dense.h:146
t_hmi::HeatH2Dexc_BHT90
double HeatH2Dexc_BHT90
Definition: hmi.h:140
phycon
t_phycon phycon
Definition: phycon.cpp:6
t_timesc::time_H2_Dest_here
double time_H2_Dest_here
Definition: timesc.h:37
trace.h
t_mole_global::list
MoleculeList list
Definition: mole.h:317
t_trace::lgTraceMole
bool lgTraceMole
Definition: trace.h:55
diatomics::photoionize_rate
double photoionize_rate
Definition: h2_priv.h:254
SDIV
sys_float SDIV(sys_float x)
Definition: cddefines.h:952
mole_update_sources
void mole_update_sources(void)
Definition: mole_drive.cpp:106
mole_effects
STATIC void mole_effects(void)
Definition: mole_drive.cpp:114
t_dense::gas_phase
realnum gas_phase[LIMELM]
Definition: dense.h:71
t_secondaries::x12tot
realnum x12tot
Definition: secondaries.h:53
t_hmi::hmicol
double hmicol
Definition: hmi.h:26
dynamics.h
diatomics::ortho_density
double ortho_density
Definition: h2_priv.h:319
diatomics::ortho_density_f
realnum ortho_density_f
Definition: h2_priv.h:324
t_hmi::H2_total
double H2_total
Definition: hmi.h:16
iso.h
ipHYDROGEN
const int ipHYDROGEN
Definition: cddefines.h:305
t_hmi::HMinus_induc_rec_cooling
double HMinus_induc_rec_cooling
Definition: hmi.h:54
opac
t_opac opac
Definition: opacity.cpp:5
mole_h_rate_diagnostics
STATIC void mole_h_rate_diagnostics(void)
Definition: mole_drive.cpp:418
POW2
#define POW2
Definition: cddefines.h:929
t_mole_local::findrate
double findrate(const char buf[]) const
Definition: mole_reactions.cpp:3900
t_mole_local::sink
double ** sink
Definition: mole.h:394
nzone
long int nzone
Definition: cddefines.cpp:14
timesc
t_timesc timesc
Definition: timesc.cpp:5
t_hmi::deriv_HeatH2Dexc_ELWERT
realnum deriv_HeatH2Dexc_ELWERT
Definition: hmi.h:149
radius
t_radius radius
Definition: radius.cpp:5
t_hmi::chH2_small_model_type
char chH2_small_model_type
Definition: hmi.h:168
t_phoHeat::HeatNet
double HeatNet
Definition: thermal.h:172
t_hmi::H2_Solomon_dissoc_rate_used_H2s
double H2_Solomon_dissoc_rate_used_H2s
Definition: hmi.h:98
frac_H2star_hminus
double frac_H2star_hminus()
Definition: mole_reactions.cpp:690
dense.h
coolheavy.h
mole
t_mole_local mole
Definition: mole.cpp:7
trace
t_trace trace
Definition: trace.cpp:5
t_ionbal::trimhi
double trimhi
Definition: ionbal.h:88
cddefines.h
mole_ion_trim
STATIC void mole_ion_trim(void)
Definition: mole_drive.cpp:67
EN1EV
const UNUSED double EN1EV
Definition: physconst.h:192
t_hmi::H2star_forms_hminus
double H2star_forms_hminus
Definition: hmi.h:156
t_hmi::h3pdep
double h3pdep
Definition: hmi.h:36
thermal
t_thermal thermal
Definition: thermal.cpp:5
t_mole_local::sink_rate_tot
double sink_rate_tot(const char chSpecies[]) const
Definition: mole_reactions.cpp:3922
t_hmi::HeatH2Dish_TH85
double HeatH2Dish_TH85
Definition: hmi.h:130
t_mole_global::num_total
int num_total
Definition: mole.h:314
TotalInsanity
NORETURN void TotalInsanity(void)
Definition: service.cpp:886
diatomics::para_density
double para_density
Definition: h2_priv.h:321
t_hmi::hmihet
double hmihet
Definition: hmi.h:24
GammaK
double GammaK(long int ipLoEnr, long int ipHiEnr, long int ipOpac, double yield1, t_phoHeat *photoHeat)
Definition: cont_gammas.cpp:359
t_hmi::deriv_HeatH2Dexc_TH85
realnum deriv_HeatH2Dexc_TH85
Definition: hmi.h:146
t_thermal::heating
double heating[LIMELM][LIMELM]
Definition: thermal.h:158
radius.h
t_hmi::deriv_HeatH2Dexc_BD96
realnum deriv_HeatH2Dexc_BD96
Definition: hmi.h:147
mole_update_rks
void mole_update_rks(void)
Definition: mole_reactions.cpp:2840
hmi.h
t_iso_sp::fb
vector< freeBound > fb
Definition: iso.h:452
t_hmi::HMinus_photo_heat
double HMinus_photo_heat
Definition: hmi.h:56
MAX2
#define MAX2
Definition: cddefines.h:782
ionbal
t_ionbal ionbal
Definition: ionbal.cpp:5
LIMELM
const int LIMELM
Definition: cddefines.h:258
t_hmi::HeatH2Dexc_ELWERT
double HeatH2Dexc_ELWERT
Definition: hmi.h:141
pow2
T pow2(T a)
Definition: cddefines.h:931
t_hmi::hmidep
double hmidep
Definition: hmi.h:33
t_dense::IonLow
long int IonLow[LIMELM+1]
Definition: dense.h:119
t_hmi::rel_pop_LTE_Hmin
double rel_pop_LTE_Hmin
Definition: hmi.h:194
t_mole_local::source
double ** source
Definition: mole.h:394
co.h
t_dense::IonHigh
long int IonHigh[LIMELM+1]
Definition: dense.h:120
t_dense::xIonDense
double xIonDense[LIMELM][LIMELM+1]
Definition: dense.h:125
t_radius::r1r0sq
double r1r0sq
Definition: radius.h:49
t_opac::ih2pof
long int ih2pof
Definition: opacity.h:230
doppvel.h
t_secondaries::csupra
realnum ** csupra
Definition: secondaries.h:21
timesc.h
t_hmi::H2_Solomon_dissoc_rate_used_H2g
double H2_Solomon_dissoc_rate_used_H2g
Definition: hmi.h:92
ionbal.h
gammas.h
molezone::snk
double snk
Definition: mole.h:352
hmi
t_hmi hmi
Definition: hmi.cpp:5
t_hmi::HeatH2Dexc_TH85
double HeatH2Dexc_TH85
Definition: hmi.h:138
physconst.h
secondaries
t_secondaries secondaries
Definition: secondaries.cpp:5
t_co::CODissHeat
realnum CODissHeat
Definition: co.h:13
t_phoHeat
Definition: thermal.h:169
taulines.h
MOLETOLER
static const double MOLETOLER
Definition: mole_drive.cpp:33
t_mole_local::species
valarray< class molezone > species
Definition: mole.h:398
hcmap.h
phycon.h
t_hmi::h2dep
double h2dep
Definition: hmi.h:34
ipH1s
const int ipH1s
Definition: iso.h:27
t_hmi::deriv_HeatH2Dexc_BHT90
realnum deriv_HeatH2Dexc_BHT90
Definition: hmi.h:148
opacity.h
iso_sp
t_iso_sp iso_sp[NISO][LIMELM]
Definition: iso.cpp:8
called.h
mole_priv.h
t_hmi::h2plus_heat
double h2plus_heat
Definition: hmi.h:39
h2.h
t_thermal::halfte
double halfte
Definition: thermal.h:123
fnzone
double fnzone
Definition: cddefines.cpp:15
molezone::den
double den
Definition: mole.h:358
t_thermal::tsq1
double tsq1
Definition: thermal.h:122
mole_update_species_cache
void mole_update_species_cache(void)
Definition: mole_species.cpp:866
t_phycon::te
double te
Definition: phycon.h:11
t_hmi::HD_total
double HD_total
Definition: hmi.h:18
t_hmi::H2_forms_grains
double H2_forms_grains
Definition: hmi.h:153
t_hmi::HeatH2Dish_BHT90
double HeatH2Dish_BHT90
Definition: hmi.h:132
mole_global
t_mole_global mole_global
Definition: mole.cpp:6
t_hmi::H2_rate_destroy
double H2_rate_destroy
Definition: hmi.h:21
t_mole_global::num_calc
int num_calc
Definition: mole.h:314
DEBUG_ENTRY
#define DEBUG_ENTRY(funcname)
Definition: cddefines.h:684
ipH_LIKE
const int ipH_LIKE
Definition: iso.h:62
t_trace::lgTrace
bool lgTrace
Definition: trace.h:12
SMALLFLOAT
const realnum SMALLFLOAT
Definition: cpu.h:191
t_hmi::H2_forms_hminus
double H2_forms_hminus
Definition: hmi.h:154
t_hmi::rel_pop_LTE_H2s
double rel_pop_LTE_H2s
Definition: hmi.h:197
t_hmi::rel_pop_LTE_H2p
double rel_pop_LTE_H2p
Definition: hmi.h:200
t_hmi::H2_total_f
realnum H2_total_f
Definition: hmi.h:17
mole_eval_sources
void mole_eval_sources(long int num_total)
Definition: mole_eval_balance.cpp:149