cloudy  trunk
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
hydro_vs_rates.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 /* CS_VS80 compute thermally averaged collision strength for collisional deexcitation
4  * of hydrogenic atoms, from
5  * >>refer H1 collision Vriens, L., & Smeets, A.H.M. 1980, Phys Rev A 22, 940
6  *hydro_vs_ioniz generate hydrogenic collisional ionization rate coefficients */
7 /*Hion_coll_ioniz_ratecoef calculate hydrogenic ionization rates for ions
8  * with all n, and Z*/
9 #include "cddefines.h"
10 #include "dense.h"
11 #include "phycon.h"
12 #include "iso.h"
13 #include "hydro_vs_rates.h"
14 #include "thirdparty.h"
15 #include "lines_service.h"
16 #include "integrate.h"
17 
18 STATIC double hydro_vs_coll_str( long nHi, long gHi, double IP_Ryd_Hi, long nLo, long gLo, double IP_Ryd_Lo, double Aul, long nelem, long Collider, double energy );
19 
20 namespace {
21  class my_Integrand : public std::unary_function<double, double>
22  {
23  public:
24  long nelem, Collider;
25  double Aul;
26  double temp;
27  long nHi, gHi, nLo, gLo;
28  double IP_Ryd_Hi, IP_Ryd_Lo;
29 
30  double operator() (double EOverKT) const
31  {
32  double col_str = hydro_vs_coll_str( nHi, gHi, IP_Ryd_Hi, nLo, gLo, IP_Ryd_Lo,
33  Aul, nelem, Collider, EOverKT * EVRYD * temp/TE1RYD );
34  return exp( -1.*EOverKT ) * col_str;
35  }
36  };
37 }
38 
39 /*
40  Neither of these rates can be modified to account for impact by non-electrons because they
41  are fits to thermally-averaged rates for electron impact...it can not be unravelled to
42  expose a projectile energy that can then be scaled to account for other projectiles.
43  Instead, we have included the original cross section formula (eq 14) from
44  Vriens & Smeets (1980) below.
45 */
46 
47 /* VS80 stands for Vriens and Smeets 1980 */
48 /* This routine calculates thermally-averaged collision strengths. */
49 double CS_VS80( long nHi, long gHi, double IP_Ryd_Hi, long nLo, long gLo, double IP_Ryd_Lo, double Aul, long nelem, long Collider, double temp )
50 {
51  double coll_str;
52 
53  if( Collider == ipELECTRON )
54  {
55  coll_str = hydro_vs_deexcit( nHi, gHi, IP_Ryd_Hi, nLo, gLo, IP_Ryd_Lo, Aul );
56  }
57  else
58  {
59  /* evaluate collision strength, two options,
60  * do thermal average (very slow) if set with
61  * SET COLLISION STRENGTH AVERAGE command,
62  * default just do point at kT
63  * tests show no impact on test suite, much faster */
65  {
66  my_Integrand func;
67 
68  func.nHi = nHi;
69  func.gHi = gHi;
70  func.IP_Ryd_Hi = IP_Ryd_Hi;
71  func.nLo = nLo;
72  func.gLo = gLo;
73  func.IP_Ryd_Lo = IP_Ryd_Lo;
74  func.nelem = nelem;
75  func.temp = temp;
76  func.Collider = Collider;
77  func.Aul = Aul;
78 
80  /* do average over Maxwellian */
81  coll_str = VS80.sum( 0., 1. );
82  coll_str += VS80.sum( 1., 10. );
83  }
84  else
85  {
86  /* the argument to the function is equivalent to evaluating the function at
87  * hnu = kT */
88  coll_str = hydro_vs_coll_str( nHi, gHi, IP_Ryd_Hi, nLo, gLo, IP_Ryd_Lo,
89  Aul, nelem, Collider, EVRYD*temp/TE1RYD );
90  }
91  }
92 
93  ASSERT( coll_str >= 0. );
94  return coll_str;
95 }
96 
97 /*hydro_vs_coll_str compute collision strength for collisional deexcitation for hydrogen atom,
98  * from Vriens and Smeets */
99 STATIC double hydro_vs_coll_str( long nHi, long gHi, double IP_Ryd_Hi, long nLo, long gLo, double IP_Ryd_Lo, double Aul, long nelem, long Collider, double energy )
100 {
101  DEBUG_ENTRY( "hydro_vs_coll_str()" );
102 
103  // number of colliders is 4 in def, should be macro
104  ASSERT( Collider >= 0.&& Collider <4 );
105  double reduced_mass = dense.AtomicWeight[nelem]*colliders.list[Collider].mass_amu/
106  (dense.AtomicWeight[nelem]+colliders.list[Collider].mass_amu)*ATOMIC_MASS_UNIT;
107 
108  /* This comes from equations 14,15, and 16 of Vriens and Smeets. */
109  /* >>refer he-like cs Vriens, L. \& Smeets, A. H. M. Phys. Rev. A, 22, 940 */
110  /* Computes the Vriens and Smeets
111  * rate coeff. for collisional dexcitation between any two levels of H.
112  * valid for all nhigh, nlow
113  * at end converts this excitation rate to collision strength */
114 
115  double n = (double)nHi;
116  double p = (double)nLo;
117 
118  double g_n = (double)gHi;
119  double g_p = (double)gLo;
120 
121  double ryd = EVRYD;
122  double s = fabs(n-p);
123  ASSERT( s > 0. );
124 
125  double Epn = EVRYD * (IP_Ryd_Lo - IP_Ryd_Hi);
126  double Epi = EVRYD * IP_Ryd_Lo;
127 
128  /* This is an absorption oscillator strength. */
129  double abs_osc_str = GetGF( Aul, Epn*RYD_INF/EVRYD, g_n)/g_p;
130  double rEpn = 1./Epn;
131  double Apn = 2.*ryd*rEpn*abs_osc_str;
132 
133  double rp = 1./p;
134  double bp = rp*(1.4*log(p) - .7 + rp*(- .51 + rp*(1.16*rp - 0.55*rp)));
135 
136  double Bpn = 4.*ryd*ryd/pow3(n)*rEpn*rEpn*(1. + Epi*rEpn*(4./3. + bp*Epi*rEpn));
137 
138  double delta = exp(-Bpn/Apn) - 0.4*Epn/ryd;
139 
140 
141  /* Scale the energy to get an equivalent electron energy. */
142  energy *= colliders.list[ipELECTRON].mass_amu/colliders.list[Collider].mass_amu;
143 
144  double cross_section;
145  /* cross section in units of PI*a_o^2 */
146  if( energy/2./ryd+delta <= 0 /*|| energy < Epn*/ )
147  {
148  cross_section = 0.;
149  }
150  else
151  {
152  double gamma = ryd*(8. + 23.*POW2(s*rp))*s*s/
153  ( s*s*(8. + 1.1*n*s) + 0.8 + 0.4*powpq(n*s,3,2)*fabs(s-1.0) );
154  cross_section = 2.*ryd/(energy + gamma)*(Apn*log(energy/2./ryd+delta) + Bpn);
155  cross_section = MAX2( cross_section, 0. );
156  }
157 
158  /* convert to collision strength */
159  double coll_str = ConvCrossSect2CollStr( cross_section * PI*BOHR_RADIUS_CM*BOHR_RADIUS_CM, g_n, energy/EVRYD, reduced_mass );
160 
161  ASSERT( coll_str >= 0. );
162 
163  return( coll_str );
164 }
165 
166 /*hydro_vs_coll_recomb generate hydrogenic collisional recombination rate coefficients */
167 double hydro_vs_coll_recomb( double ionization_energy_Ryd, double Te, double stat_level, double stat_ion )
168 {
169  double coef,
170  denom,
171  epi,
172  t_eV;
173 
174  DEBUG_ENTRY( "hydro_vs_coll_recomb()" );
175 
176  /* This is equation 9 of
177  * >>refer H1 collision recomb Vriens, L., & Smeets, A.H.M. 1980, Phys Rev A 22, 940 */
178 
179  /* this is kT in eV */
180  t_eV = Te/EVDEGK;
181 
182  /* this is the ionization energy relative to kT, dimensionless */
183  epi = ionization_energy_Ryd * EVRYD / t_eV;
184 
185  /* this is the denominator of equation 8 of VS80. */
186  denom = pow(epi,2.33) + 4.38*pow(epi,1.72) + 1.32*epi;
187 
188  /* this is equation 9 of VS80 */
189  coef = 3.17e-27 / pow3(t_eV) * stat_level / stat_ion / denom;
190 
191  ASSERT( coef >= 0. );
192  return( coef );
193 }
194 
195 
196 /*hydro_vs_ioniz generate hydrogenic collisional ionization rate coefficients */
197 double hydro_vs_ioniz( double ionization_energy_Ryd, double Te )
198 {
199  double coef,
200  denom,
201  epi,
202  t_eV;
203 
204  DEBUG_ENTRY( "hydro_vs_ioniz()" );
205 
206  /* a function written to calculate the rate coefficients
207  * for hydrogen collisional ionizations from
208  * Jason Ferguson, summer 94
209  * valid for all n
210  * >>refer H1 collision Vriens, L., & Smeets, A.H.M. 1980, Phys Rev A 22, 940
211  * */
212 
213  /* this is kT in eV */
214  t_eV = Te/EVDEGK;
215 
216  /* this is the ionization energy relative to kT, dimensionless */
217  epi = ionization_energy_Ryd * EVRYD / t_eV;
218 
219  /* this is the denominator of equation 8 of VS80. */
220  denom = pow(epi,2.33) + 4.38*pow(epi,1.72) + 1.32*epi;
221 
222  /* this is equation 8 of VS80 */
223  coef = 9.56e-6 / powpq(t_eV,3,2) * dsexp( epi ) / denom;
224 
225  ASSERT( coef >= 0. );
226  return( coef );
227 }
228 
229 /*Hion_coll_ioniz_ratecoef calculate hydrogenic ionization rates for all n, and Z*/
231  /* the isoelectronic sequence */
232  long int ipISO ,
233  /* element, >=1 since only used for ions
234  * nelem = 1 is helium the least possible charge */
235  long int nelem,
236  /* principal quantum number, > 1
237  * since only used for excited states */
238  long int n,
239  double ionization_energy_Ryd,
240  double Te )
241 {
242  double H,
243  HydColIon_v,
244  Rnp,
245  charge,
246  chim,
247  eone,
248  etwo,
249  efour,
250  g,
251  rate,
252  rate2,
253  boltz,
254  t1,
255  t2,
256  t3,
257  t4,
258  tev,
259  xn,
260  y;
261  static const double arrH[4] = {1.48,3.64,5.93,8.32};
262  static const double arrRnp[8] = {2.20,1.90,1.73,1.65,1.60,1.56,1.54,1.52};
263  static const double arrg[10] = {0.8675,0.932,0.952,0.960,0.965,0.969,0.972,0.975,0.978,0.981};
264 
265  static double small = 0.;
266 
267  DEBUG_ENTRY( "Hion_coll_ioniz_ratecoef()" );
268  /*calculate hydrogenic ionization rates for all n, and Z
269  * >>refer HI cs Allen 1973, Astro. Quan. for low Te.
270  * >>refer HI cs Sampson and Zhang 1988, ApJ, 335, 516 for High Te.
271  * */
272 
273  charge = nelem - ipISO;
274  /* this routine only for ions, nelem=0 is H, nelem=1 he, etc */
275  ASSERT( charge > 0);
276  ASSERT( n>1 );
277 
278  if( n > 4 )
279  {
280  H = 2.15*n;
281  }
282  else
283  {
284  H = arrH[n-1];
285  }
286 
287  if( n > 8 )
288  {
289  Rnp = 1.52;
290  }
291  else
292  {
293  Rnp = arrRnp[n-1];
294  }
295 
296  if( n > 10 )
297  {
298  g = arrg[9];
299  }
300  else
301  {
302  g = arrg[n-1];
303  }
304 
305  tev = EVRYD/TE1RYD*Te;
306  xn = (double)n;
307  chim = EVRYD * ionization_energy_Ryd;
308  y = chim/tev;
309  boltz = dsexp( chim/tev );
310 
311  eone = e1(y);
312  etwo = e2(y);
313  efour = expn(4,y);
314 
315  t1 = 1./xn*eone;
316  t2 = 1./xn*efour;
317  t3 = 3.*H/xn/(3. - Rnp)*(y*etwo - 2.*y*eone + boltz);
318  t4 = 3.36*y*(eone - etwo);
319  rate = 7.69415e-9*sqrt(Te)*9.28278e-3*powi(xn/(charge+1),4)*g*y;
320  rate *= t1 - t2 + t3 + t4;
321  rate2 = 2.1e-8*sqrt(Te)/chim/chim*dsexp(2.302585*5040.*chim/Te);
322 
323  /* don't let the rates go negative */
324  rate = MAX2(rate,small);
325  rate2 = MAX2(rate2,small);
326 
327  /* Take the lowest of the two, they fit nicely together... */
328  /* >>chng 10 Sept 02, sometimes one of these is zero and the other is positive.
329  * in that case take the bigger one. */
330  if( rate==0. || rate2==0. )
331  HydColIon_v = MAX2(rate,rate2);
332  else
333  HydColIon_v = MIN2(rate,rate2);
334 
335  ASSERT( HydColIon_v >= 0. );
336  return( HydColIon_v );
337 }
338 
339 /*hydro_vs_deexcit compute collisional deexcitation rates for hydrogen atom,
340  * from Vriens and Smeets 1980 */
341 double hydro_vs_deexcit( long nHi, long gHi, double IP_Ryd_Hi, long nLo, long gLo, double IP_Ryd_Lo, double Aul )
342 {
343  DEBUG_ENTRY( "hydro_vs_deexcit()" );
344 
345  double kT_eV = EVRYD * phycon.te / TE1RYD;
346 
347  /* This comes from equations 24 of Vriens and Smeets. */
348  /* >>refer he-like cs Vriens, L. \& Smeets, A. H. M. Phys. Rev. A, 22, 940 */
349  /* Computes the Vriens and Smeets
350  * rate coeff. for collisional dexcitation between any two levels of H.
351  * valid for all nhigh, nlow
352  * at end converts this excitation rate to collision strength */
353 
354  double n = (double)nLo;
355  double p = (double)nHi;
356 
357  ASSERT( n!=p );
358 
359  double g_n = (double)gLo;
360  double g_p = (double)gHi;
361 
362  double ryd = EVRYD;
363  double s = fabs(n-p);
364 
365  double Enp = EVRYD * (IP_Ryd_Lo - IP_Ryd_Hi);
366  double rEnp = 1./Enp;
367  double Eni = EVRYD * IP_Ryd_Hi;
368 
369  ASSERT( Enp > 0. );
370 
371  /* This is an absorption oscillator strength. */
372  double abs_osc_str = GetGF( Aul, Enp*RYD_INF/EVRYD, g_p)/g_n;
373  double Anp = 2.*ryd*rEnp*abs_osc_str;
374 
375  double rn = 1./n;
376  double bn = rn*( 1.4*log(n) - .7 +rn*(- .51 + rn*(1.16 - 0.55*rn)));
377 
378  double Bnp = 4.*ryd*ryd/pow3(p)*rEnp*rEnp*(1. + Eni*rEnp*(4./3. + bn*Eni*rEnp));
379 
380  double delta_np = exp(-Bnp/Anp) + 0.06 * s*s / (p*n*n);
381 
382  double rate;
383 
384  if( 0.3*kT_eV/ryd+delta_np <= 0 )
385  {
386  rate = 0.;
387  }
388  else
389  {
390  double Gamma_np = ryd*log(1. + n*n*n*kT_eV/ryd) * (3. + 11.*s*s*rn*rn) * s * s /
391  ( s*s* (6. + 1.6*p*s) + 0.3 + 0.8*powpq(p*s,3,2)*fabs(s-0.6) );
392 
393  rate = 1.6E-7 * sqrt(kT_eV) * g_n / (g_p * ( kT_eV + Gamma_np ) ) *
394  ( Anp * log(0.3*kT_eV/ryd + delta_np) + Bnp );
395  }
396 
397  double col_str = rate / COLL_CONST * phycon.sqrte * g_p;
398 
399  return col_str ;
400 }
401 
STATIC double hydro_vs_coll_str(long nHi, long gHi, double IP_Ryd_Hi, long nLo, long gLo, double IP_Ryd_Lo, double Aul, long nelem, long Collider, double energy)
t_isoCTRL iso_ctrl
Definition: iso.cpp:9
double e1(double x)
double hydro_vs_ioniz(double ionization_energy_Ryd, double Te)
t_phycon phycon
Definition: phycon.cpp:6
T pow3(T a)
Definition: cddefines.h:988
double expn(int n, double x)
#define MIN2(a, b)
Definition: cddefines.h:803
double dsexp(double x)
Definition: service.cpp:1038
t_dense dense
Definition: global.cpp:15
ColliderList colliders(dense)
double CS_VS80(long nHi, long gHi, double IP_Ryd_Hi, long nLo, long gLo, double IP_Ryd_Lo, double Aul, long nelem, long Collider, double temp)
#define POW2
Definition: cddefines.h:979
double energy(const genericState &gs)
#define STATIC
Definition: cddefines.h:118
double powi(double, long int)
Definition: service.cpp:594
double sum(double min, double max) const
Definition: integrate.h:44
realnum AtomicWeight[LIMELM]
Definition: dense.h:80
#define ASSERT(exp)
Definition: cddefines.h:613
double GetGF(double trans_prob, double enercm, double gup)
vector< t_collider > list
Definition: collision.h:41
#define DEBUG_ENTRY(funcname)
Definition: cddefines.h:723
double powpq(double x, int p, int q)
Definition: service.cpp:630
STATIC double cross_section(double EgammaRyd, double EthRyd, long nelem, long n, long l, long s)
double ConvCrossSect2CollStr(double CrsSectCM2, double gLo, double E_ProjectileRyd, double reduced_mass_grams)
#define MAX2(a, b)
Definition: cddefines.h:824
bool lgCollStrenThermAver
Definition: iso.h:371
double e2(double x)
double hydro_vs_coll_recomb(double ionization_energy_Ryd, double Te, double stat_level, double stat_ion)
double hydro_vs_deexcit(long nHi, long gHi, double IP_Ryd_Hi, long nLo, long gLo, double IP_Ryd_Lo, double Aul)
double sqrte
Definition: phycon.h:58
double te
Definition: phycon.h:21
double Hion_coll_ioniz_ratecoef(long int ipISO, long int nelem, long int n, double ionization_energy_Ryd, double Te)