cloudy  trunk
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
hypho.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 /*hypho - create hydrogenic photoionization cross sections */
4 #include "cddefines.h"
5 #include "hypho.h"
6 
7 /* some numbers used below */
8 static const int NCM = 3000;
9 static const int NFREQ = NCM;
10 /*exp1 routine from ucl group to compute 1-exp(-x)
11  * mod implicit none, and f77 control, gfj '96 jul 11 */
12 
13 STATIC double exp1(double x)
14 {
15  double dx,
16  exp1_v;
17 
18  DEBUG_ENTRY( "exp1()" );
19 
20  dx = fabs(x);
21  if( dx < 1.0e-9 )
22  {
23  exp1_v = -x;
24  }
25  else if( dx < 1.0e-5 )
26  {
27  exp1_v = ((-x*0.5) - 1.0)*x;
28  }
29  else if( dx < 1.0e-3 )
30  {
31  exp1_v = (((-x*0.1666666667) - 0.5)*x - 1.0)*x;
32  }
33  else
34  {
35  exp1_v = 1.0 - exp(x);
36  }
37 
38  return exp1_v;
39 }
40 
41 /*hypho create hydrogenic photoionization cross sections */
42 void hypho(
43  /* Z-Nelec, the residual charge, 1 for hydrogen, 2 for helium */
44  double zed,
45  /* principal quantum number */
46  long int n,
47  /* lowest angular momentum */
48  long int lmin,
49  /* highest angular momentum */
50  long int lmax,
51  /* scaled lowest energy, in units of zed^2/n^2, at which the cs will be done */
52  double en,
53  /* number of points to do */
54  long int ncell,
55  /* array of energies (in units given above) */
56  realnum anu[],
57  /* calculated photoionization cross section in cm^-2 */
58  realnum bfnu[])
59 {
60  long int i,
61  ifp,
62  il,
63  ilmax,
64  j,
65  k,
66  l,
67  lg,
68  ll,
69  llk,
70  lll,
71  llm,
72  lm,
73  lmax1,
74  m,
75  mulp,
76  mulr;
77  double a,
78  ai,
79  al,
80  alfac,
81  con2,
82  e,
83  ee,
84  fll,
85  flm,
86  fn,
87  fth,
88  gl,
89  gn0,
90  gn1e,
91  gne,
92  gnt,
93  p,
94  p1,
95  p2,
96  se,
97  sl,
98  sl4,
99  sm,
100  sm4,
101  sn,
102  sn4,
103  sum,
104  zed2;
105 
106  static double ab[NFREQ],
107  alo[7000],
108  fal[7000],
109  freq[NFREQ],
110  g2[2][NFREQ],
111  g3[2][NFREQ];
112 
113  double anl,
114  con3,
115  fac,
116  x;
117  static int first = true;
118  static const double zero = 0.;
119  static const double one = 1.;
120  static const double two = 2.;
121  static const double four = 4.;
122  static const double con1 = 0.8559;
123 
124  DEBUG_ENTRY( "hypho()" );
125 
126  /*generate hydrogenic photoionization cross sections */
127  /* *************************************************************
128  * GENERATE HYDROGENIC PHOTOIONIZATION CROSS SECTIONS
129  *
130  * Hypho calculates Hydrogenic bound-free (BF) xsectns for each n,l .
131  * For Opacity work we calculate l-weighted average for each n .
132  * BF xsectns for Hydorgenic ion are tabulated at E/z**2. E is
133  * the energy in Ry corresponding to the frequencies on the Opacity
134  * mesh. It can changed accoding to need.
135  *
136  * zed=Z-Nelc,
137  * n=principal quantum number
138  * lmin=lowest angular momentum considered of level n
139  * lmx=highest angular momentum considered of level n
140  * en=zed*zed/(n*n) lowest energy at which the hydrogenic cross sections are
141  * to be calculated
142  * anu = photon energy
143  * bfnu=photoionization cross section in cm^-2
144  *
145  * local variables */
146  /* CON1=conversion factor from a0**2 to Mb, x-sectns in megabarns
147  * CON1=8.5594e-19 * 1.e+18 */
148 
149  vector<long> mm(NFREQ);
150 
151  if( ncell > NCM )
152  {
153  fprintf( stderr, " increase ncm in hypho to at least%5ld\n",
154  ncell );
156  }
157 
158  if( first )
159  {
160  fal[0] = zero;
161  for( i=1; i < 7000; i++ )
162  {
163  ai = (double)(i);
164  alo[i-1] = log10(ai);
165  fal[i] = alo[i-1] + fal[i-1];
166  }
167  first = false;
168  }
169 
170  /* these may not be redefined, and so will crash */
171  ll = -INT_MAX;
172  lm = -INT_MAX;
173  anl = -DBL_MAX;
174 
175  /* CALCULATION OF HYDROGENIC PHOTOIONIZATION CROSS SECTION
176  *
177  * INITIALIZATION FOR N
178  * * con2=(a0**2*1.e+18)*(n/zed)**2, zed=z-nelc
179  * * for hydrogen, the threshold, fth=1/n**2, and for hydrogenic atom,it is
180  * zed**2/n**2. */
181 
182  zed2 = zed*zed;
183  fn = (double)(n);
184  sn = fn*fn;
185  sn4 = four*sn;
186  con2 = con1*POW2(fn/ zed);
187  fth = one/sn;
188 
189  gn0 = 2.3052328943 - 2.302585093*fal[n+n-1] - fn*0.61370563888 +
190  alo[n-1]*(fn + one)*2.30258093;
191  lmax1 = MIN2(lmax,n-1);
192  ilmax = n - lmin;
193 
194  /* * calculate top-up st.wt for given n and lmin=lmax+1 (R-matrix). subtract
195  * the sum from 2n**2. */
196  gl = 0.;
197  if( lmin != 0 )
198  {
199  for( i=0; i < lmin; i++ )
200  {
201  lg = i;
202  gl += 2.*lg + 1;
203  }
204  }
205 
206  gnt = 2.*(POW2( (double)n ) - gl);
207 
208  /* define photon energies epnu corresponding to hydrogenic atom with charge
209  * z and freq to hydrogen atom; INITIALIZE G'S */
210  for( i=0; i < ncell; i++ )
211  {
212  mm[i] = 0;
213  bfnu[i] = (realnum)zero;
214  freq[i] = anu[i]*zed2;
215  for( j=0; j < 2; j++ )
216  {
217  g2[j][i] = zero;
218  g3[j][i] = zero;
219  }
220  }
221 
222  /* gjf Aug 95 change
223  * original code returned total &(*(*$# if freq(1)<en */
224  freq[0] = MAX2(freq[0],en);
225 
226  /* calculate cross section: L LOOP */
227 
228  for( il=1; il <= ilmax; il++ )
229  {
230  l = n - il;
231  m = 0;
232  al = (double)(l);
233  k = n - l - 2;
234  con3 = con2/(two*al + one);
235 
236  /* FREQUENCY LOOP (FREQ UNITS ARE RYD*ZED**2) */
237  for( ifp=0; ifp < ncell; ifp++ )
238  {
239  if( freq[ifp] < fth )
240  {
241  if( l <= lmax1 )
242  anl = 0.;
243  }
244  else
245  {
246  /* >>chng 99 jun 24, move m from below to end, change m-1 to m */
247  /*m += 1;*/
248  se = freq[ifp] - fth;
249  if( se < 0. )
250  {
251  fprintf( stderr, " %4ld%12.4e%12.4e\n", ifp,
252  freq[ifp], fth );
253  }
254 
255  /* if ( se .lt. -1.e-30) se = 1.e-06 */
256  e = sqrt(se);
257  x = one + sn*se;
258  if( k < 0 )
259  {
260  if( e >= 0.314 )
261  {
262  ee = 6.2831853/e;
263  p = 0.5*log10(exp1(-ee));
264  }
265  else
266  {
267  p = zero;
268  }
269 
270  if( e > 1.0e-6 )
271  {
272  a = two*(fn - atan(fn*e)/e);
273  }
274  else
275  {
276  a = zero;
277  }
278 
279  ab[m] = (gn0 + a)/2.302585 - p - (fn + two)*
280  log10(x);
281  gne = 0.1;
282  gn1e = x*gne/(fn + fn);
283  g3[1][m] = gne;
284  g3[0][m] = gn1e;
285  g2[1][m] = gne*fn*x*(fn + fn - one);
286  g2[0][m] = gn1e*(fn + fn - one)*(four +
287  (fn - one)*x);
288  }
289 
290  double g11 = zero;
291  double g12 = zero;
292  double g22 = g2[1][m];
293  double g32 = g3[1][m];
294  double g21 = g2[0][m];
295  double g31 = g3[0][m];
296  double muls = mm[m];
297 
298  if( k < 0 )
299  {
300  /* l.eq.n-1
301  * */
302  g11 = g31;
303  if( l == 0 )
304  g11 = zero;
305  g12 = g32;
306  }
307 
308  else if( k == 0 )
309  {
310 
311  /* l.eq.n-2
312  * */
313  g11 = g21;
314  if( l == 0 )
315  g11 = zero;
316  g12 = g22;
317  }
318 
319  else
320  {
321 
322  /* l.lt.n-2
323  * */
324  if( k <= 1 )
325  {
326  ll = n - 1;
327  lm = n - 2;
328  }
329  sl = POW2( (double)ll );
330  sl4 = four*sl;
331  fll = (double)(ll);
332  g12 = (sn4 - sl4 + (two*sl - fll)*x)*g22 -
333  sn4*(sn - sl)*(one + POW2(fll + one)*se)*
334  g32;
335 
336  if( l != 0 )
337  {
338  sm = POW2( (double)lm );
339  sm4 = four*sm;
340  flm = (double)(lm);
341  g11 = (sn4 - sm4 + (two*sm + flm)*x)*g21 -
342  sn4*(sn - POW2(flm + one))*(one +
343  sm*se)*g31;
344  g31 = g21;
345  g21 = g11;
346  }
347 
348  g32 = g22;
349  g22 = g12;
350 
351  if( (m+1) == ncell )
352  {
353  ll -= 1;
354  if( l != 0 )
355  lm -= 1;
356  }
357 
358  if( g12 >= 1.e20 )
359  {
360  muls += 35;
361  g22 *= 1.e-35;
362  g32 *= 1.e-35;
363  g12 *= 1.e-35;
364 
365  if( l != 0 )
366  {
367  g11 *= 1.e-35;
368  g21 *= 1.e-35;
369  g31 *= 1.e-35;
370  }
371  }
372  }
373 
374  mm[m] = muls;
375  g2[1][m] = g22;
376  g3[1][m] = g32;
377  g2[0][m] = g21;
378  g3[0][m] = g31;
379 
380  alfac = fal[n+l] - fal[n-l-1] + two*(al - fn)*
381  alo[n*2-1];
382 
383  p1 = one;
384  lll = l + 1;
385  llm = l - 1;
386  mulr = 0;
387 
388  if( llm >= 1 )
389  {
390  for( i=1; i <= llm; i++ )
391  {
392  ai = (double)(i);
393  p1 *= one + ai*ai*se;
394  if( p1 >= 1.e20 )
395  {
396  p1 *= 1.e-10;
397  mulr += 10;
398  }
399  }
400  }
401 
402  p2 = p1;
403  llk = llm + 1;
404  if( llk < 1 )
405  llk = 1;
406 
407  for( i=llk; i <= lll; i++ )
408  {
409  ai = (double)(i);
410  p2 *= one + ai*ai*se;
411  }
412 
413  mulp = 0;
414  while( g12 >= one )
415  {
416  mulp -= 10;
417  g12 *= 1.e-10;
418  if( l != 0 )
419  g11 *= 1.e-10;
420  }
421 
422  sum = alfac + (realnum)(mulr) + two*(ab[m] + (realnum)(muls-
423  mulp+1));
424 
425  fac = zero;
426 
427  /* >>chng 96 apr 19, 35 had been 50 */
428  if( fabs(sum) < 35. )
429  fac = exp10(sum);
430  if( l != 0 )
431  g11 *= g11*p1;
432  g12 *= g12*p2;
433 
434  /* anl=con3*(g11 *al + g12 *(al+one))
435  * *x*fac */
436 
437  if( l <= lmax1 )
438  anl = fac*x*con3*(g11*al + g12*(al + 1.));
439  anl *= 2.*(2.*al + 1.);
440 
441  bfnu[ifp] += (realnum)(anl*1e-18);
442  /* >>chng 99 jun 24, move m inc to here */
443  ++m;
444  }
445  }
446  }
447 
448  /* bfmin = 1.e-03 * bfnu(1) / gnt */
449  for( i=0; i < ncell; i++ )
450  {
451  bfnu[i] /= (realnum)gnt;
452  }
453 
454  return;
455 }
double exp10(double x)
Definition: cddefines.h:1368
void zero(void)
Definition: zero.cpp:43
#define MIN2(a, b)
Definition: cddefines.h:803
static const int NFREQ
Definition: hypho.cpp:9
#define POW2
Definition: cddefines.h:979
#define STATIC
Definition: cddefines.h:118
float realnum
Definition: cddefines.h:124
#define EXIT_FAILURE
Definition: cddefines.h:168
#define cdEXIT(FAIL)
Definition: cddefines.h:482
void hypho(double zed, long int n, long int lmin, long int lmax, double en, long int ncell, realnum anu[], realnum bfnu[])
Definition: hypho.cpp:42
STATIC double exp1(double x)
Definition: hypho.cpp:13
#define DEBUG_ENTRY(funcname)
Definition: cddefines.h:723
static const int NCM
Definition: hypho.cpp:8
#define MAX2(a, b)
Definition: cddefines.h:824
int fprintf(const Output &stream, const char *format,...)
Definition: service.cpp:1121