cloudy  trunk
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
cont_setintensity.cpp
Go to the documentation of this file.
1 /* This file is part of Cloudy and is copyright (C)1978-2017 by Gary J. Ferland and
2  * others. For conditions of distribution and use see copyright notice in license.txt */
3 /*ContSetIntensity derive intensity of incident continuum */
4 /*extin do extinction of incident continuum as set by extinguish command */
5 /*sumcon sums L and Q for net incident continuum */
6 /*conorm normalize continuum to proper intensity */
7 /*qintr integrates Q for any continuum between two limits, used for normalization */
8 /*pintr integrates L for any continuum between two limits, used for normalization */
9 #include "cddefines.h"
10 #include "iso.h"
11 #include "noexec.h"
12 #include "ionbal.h"
13 #include "hextra.h"
14 #include "trace.h"
15 #include "oxy.h"
16 #include "conv.h"
17 #include "prt.h"
18 #include "heavy.h"
19 #include "rfield.h"
20 #include "phycon.h"
21 #include "called.h"
22 #include "hydrogenic.h"
23 #include "timesc.h"
24 #include "secondaries.h"
25 #include "opacity.h"
26 #include "thermal.h"
27 #include "ipoint.h"
28 #include "atmdat_adfa.h"
29 #include "rt.h"
30 #include "radius.h"
31 #include "geometry.h"
32 #include "grainvar.h"
33 #include "continuum.h"
34 #include "ion_trim.h"
35 #include "freebound.h"
36 #include "dense.h"
37 
38 /*conorm normalize continuum to proper intensity */
39 STATIC void conorm();
40 
41 /*pintr integrates L for any continuum between two limits, used for normalization */
42 STATIC double pintr(double penlo, double penhi);
43 
44 /*qintr integrates Q for any continuum between two limits, used for normalization */
45 STATIC double qintr(double qenlo, double qenhi);
46 
47 /*sumcon sums L and Q for net incident continuum */
48 STATIC void sumcon(long int il,
49  long int ih,
50  realnum *q,
51  realnum *p,
52  realnum *panu);
53 
54 /*extin do extinction of incident continuum as set by extinguish command */
55 STATIC void extin(realnum *ex1ryd);
56 
58 {
59 
60  DEBUG_ENTRY( "IncidentContinuumHere()" );
61  double frac_beam_time;
62  /* fraction of beamed continuum that is constant */
63  double frac_beam_const;
64  /* fraction of continuum that is isotropic */
65  double frac_isotropic;
66 
67  double BigLog = 0.;
68  for( long i = 0; i<rfield.nflux; ++i )
69  {
70  double flux_org = rfield.flux[0][i];
71  double flux_now = ffun( rfield.anu(i) ,
72  &frac_beam_time ,
73  &frac_beam_const ,
74  &frac_isotropic )*rfield.widflx(i)*rfield.ExtinguishFactor[i];
75 
76  double ratio = 1.;
77  if( flux_org>SMALLFLOAT && flux_now>SMALLFLOAT )
78  {
79  ratio = fabs( log10( flux_now / flux_org ) );
80  BigLog = max( ratio , BigLog );
81  }
82  }
83 
84  if( BigLog > 0.01 )
85  fprintf(ioQQQ , "DEBUG diff continua %.2e\n", BigLog );
86  return;
87 }
88 
89 /* called by Cloudy to set up continuum */
91 {
92  bool lgCheckOK;
93 
94  long int i,
95  ip,
96  n;
97 
98  realnum EdenHeav,
99  ex1ryd,
100  factor,
101  occ1,
102  p,
103  p1,
104  p2,
105  p3,
106  p4,
107  p5,
108  p6,
109  p7,
110  p8,
111  pgn,
112  phe,
113  pheii,
114  qgn;
115 
116  realnum xIoniz;
117 
118  double HCaseBRecCoeff,
119  ecrit,
120  tcompr,
121  tcomp,
122  RatioIonizToRecomb,
123  r3ov2;
124 
125  double peak;
126 
127  /* fraction of beamed continuum that is varies with time */
128  double frac_beam_time;
129  /* fraction of beamed continuum that is constant */
130  double frac_beam_const;
131  /* fraction of continuum that is isotropic */
132  double frac_isotropic;
133 
134  long int nelem , ion;
135 
136  DEBUG_ENTRY( "ContSetIntensity()" );
137 
138  /* set continuum */
139  if( trace.lgTrace )
140  {
141  fprintf( ioQQQ, " ContSetIntensity called.\n" );
142  }
143 
144  /* find normalization factors for the continua - this decides whether continuum is
145  * per unit area of luminosity, and which is desired final product */
146  conorm();
147 
148  /* define factors to convert rfeld.flux array into photon occupation array OCCNUM
149  * by multiplication */
150  factor = (realnum)(EN1RYD/PI4/FR1RYD/HNU3C2);
151 
152  /*------------------------------------------------------------- */
153  lgCheckOK = true;
154 
155  for( i=0; i < rfield.nflux_with_check; i++ )
156  {
157  double flux = ffun( rfield.anu(i), &frac_beam_time, &frac_beam_const, &frac_isotropic );
158  ASSERT( fabs(1.-frac_beam_time-frac_beam_const-frac_isotropic) < 10.*FLT_EPSILON );
159 
160  /* This is a fix for ticket #1 */
161  if( flux*rfield.widflx(i) > BIGFLOAT )
162  {
163  fprintf( ioQQQ, "\n Cannot continue. The continuum is far too intense.\n" );
165  }
166 
167  rfield.flux[0][i] = (realnum)(flux*rfield.widflx(i));
168 
169  /* save separation into isotropic constant and beamed, and possibly
170  * time-variable beamed continua */
171  rfield.flux_beam_const[i] = rfield.flux[0][i] * (realnum)frac_beam_const;
172  rfield.flux_beam_time[i] = rfield.flux[0][i] * (realnum)frac_beam_time;
173  rfield.flux_isotropic[i] = rfield.flux[0][i] * (realnum)frac_isotropic;
174 
175  if( rfield.flux[0][i] < 0. )
176  {
177  fprintf( ioQQQ, " negative continuum returned at%6ld%10.2e%10.2e\n",
178  i, rfield.anu(i), rfield.flux[0][i] );
179  lgCheckOK = false;
180  }
181 
182  rfield.ContBoltz[i] = 0.;
183  rfield.ContBoltzHelp1[i] = 0.;
184  rfield.ContBoltzHelp2[i] = 0.;
185  rfield.ContBoltzAvg[i] = 0.;
186  rfield.ConEmitReflec[0][i] = 0.;
187  rfield.ConEmitOut[0][i] = 0.;
188  rfield.convoc[i] = factor/rfield.widflx(i)/rfield.anu2(i);
189  }
190 
191  if( !lgCheckOK )
192  {
193  ShowMe();
195  }
196 
197  if( trace.lgTrace && trace.lgComBug )
198  {
199  fprintf( ioQQQ, "\n\n Compton heating, cooling coefficients \n" );
200  for( i=0; i < rfield.nflux_with_check; i += 2 )
201  {
202  fprintf( ioQQQ, "%6ld%10.2e%10.2e%10.2e", i, rfield.anu(i),
203  rfield.csigh[i], rfield.csigc[i] );
204  }
205  fprintf( ioQQQ, "\n" );
206  }
207 
208  /* extinguish continuum if set on */
209  extin(&ex1ryd);
210 
211  /* now find peak of hydrogen ionizing continuum - for PDR calculations
212  * this will remain equal to 1 since the loop will not execute */
213  prt.ipeak = 1;
214  peak = 0.;
215 
216  for( i=iso_sp[ipH_LIKE][ipHYDROGEN].fb[ipH1s].ipIsoLevNIonCon-1; i < rfield.nflux_with_check; i++ )
217  {
218  if( rfield.flux[0][i]*rfield.anu(i)/rfield.widflx(i) > (realnum)peak )
219  {
220  /* prt.ipeak points to largest f_nu at H-ionizing energies
221  * and is passed to other parts of code */
222  /* i+1 to keep ipeak on fortran version of energy array */
223  prt.ipeak = i+1;
224  peak = rfield.flux[0][i]*rfield.anu(i)/rfield.widflx(i);
225  }
226  }
227 
228  /* find highest energy to consider in continuum flux array
229  * peak is the peak product nu*flux */
230  peak = rfield.flux[0][prt.ipeak-1]/rfield.widflx(prt.ipeak-1)*
231  rfield.anu2(prt.ipeak-1);
232 
233  /* say what type of cpu this is, if desired */
234  if( trace.lgTrace )
235  {
236  fprintf( ioQQQ, " ContSetIntensity: The peak of the H-ion continuum is at %.3e Ryd - its value is %.2e\n",
237  rfield.anu(prt.ipeak-1) , peak);
238  }
239 
240  if( peak > 1e38 )
241  {
242  fprintf( ioQQQ, " PROBLEM DISASTER The continuum is too intense to compute. Use a fainter continuum. (This is the nu*f_nu test)\n" );
243  fprintf( ioQQQ, " Sorry.\n" );
245  }
246 
247  /* >>chng 04 oct 10, add this limit - arrays will malloc to nupper, but will add unit
248  * continuum to [nflux] - this must be within array */
251 
252  /* check that continuum defined everywhere - look for zero's and comment if present */
253  continuum.lgCon0 = false;
254  ip = 0;
255  for( i=0; i < rfield.nflux; i++ )
256  {
257  if( rfield.flux[0][i] == 0. )
258  {
259  if( called.lgTalk && !continuum.lgCon0 )
260  {
261  fprintf( ioQQQ, " NOTE Setcon: continuum has zero intensity starting at %11.4e Ryd.\n",
262  rfield.anu(i) );
263  continuum.lgCon0 = true;
264  }
265  ++ip;
266  }
267  }
268 
269  if( continuum.lgCon0 && called.lgTalk )
270  {
271  fprintf( ioQQQ,
272  "%6ld cells in the incident continuum have zero intensity. Problems???\n\n",
273  ip );
274  }
275 
276  /* check for devastating error in the continuum mesh or intensity */
277  lgCheckOK = true;
278  for( i=1; i < rfield.nflux; i++ )
279  {
280  if( rfield.flux[0][i] < 0. )
281  {
282  fprintf( ioQQQ,
283  " PROBLEM DISASTER Continuum has negative intensity at %.4e Ryd=%.2e %4.4s %4.4s\n",
284  rfield.anu(i), rfield.flux[0][i], rfield.chLineLabel[i].c_str(), rfield.chContLabel[i].c_str() );
285  lgCheckOK = false;
286  }
287  else if( rfield.anu(i) <= rfield.anu(i-1) )
288  {
289  fprintf( ioQQQ,
290  " PROBLEM DISASTER cont_setintensity - internal error - continuum energies not in increasing order: energies follow\n" );
291  fprintf( ioQQQ,
292  "%ld %e %ld %e %ld %e\n",
293  i -1 , rfield.anu(i-1), i, rfield.anu(i), i +1, rfield.anu(i+1) );
294  lgCheckOK = false;
295  }
296  }
297 
298  /* either of the ways lgCheckOK would be set true would be a major internal error */
299  if( !lgCheckOK )
300  {
301  ShowMe();
303  }
304 
305  /* turn off recoil ionization if high energy < 190R */
306  if( rfield.anu(rfield.nflux-1) <= 190 )
307  {
308  ionbal.lgCompRecoil = false;
309  }
310 
311  /* sum photons and energy, save mean */
312 
313  /* sum from low energy to Balmer edge */
314  sumcon(1,iso_sp[ipH_LIKE][ipHYDROGEN].fb[ipH2p].ipIsoLevNIonCon-1,&rfield.qrad,&prt.pradio,&p1);
315 
316  /* sum over Balmer continuum */
317  sumcon(iso_sp[ipH_LIKE][ipHYDROGEN].fb[ipH2p].ipIsoLevNIonCon,iso_sp[ipH_LIKE][ipHYDROGEN].fb[ipH1s].ipIsoLevNIonCon-1,&rfield.qbal,&prt.pbal,&p2);
318 
319  /* sum from Lyman edge to HeI edge */
320  sumcon(iso_sp[ipH_LIKE][ipHYDROGEN].fb[ipH1s].ipIsoLevNIonCon,
321  iso_sp[ipHE_LIKE][ipHELIUM].fb[0].ipIsoLevNIonCon-1,&prt.q,&p,&p3);
322 
323  /* sum from HeI to HeII edges */
324  sumcon(iso_sp[ipHE_LIKE][ipHELIUM].fb[0].ipIsoLevNIonCon,
325  iso_sp[ipH_LIKE][ipHELIUM].fb[ipH1s].ipIsoLevNIonCon-1,&rfield.qhe,&phe,&p4);
326 
327  /* sum from Lyman edge to carbon k-shell */
328  sumcon(iso_sp[ipH_LIKE][ipHELIUM].fb[ipH1s].ipIsoLevNIonCon,opac.ipCKshell-1,&rfield.qheii,&pheii,&p5);
329 
330  /* sum from c k-shell to gamma ray - where pairs start */
332  &prt.xpow , &p6);
333 
334  /* complete sum up to high-energy limit */
336 
337  /* find to estimate photoerosion timescale */
338  n = ipoint(7.35e5);
339  sumcon(n,rfield.nflux,&qgn,&pgn,&p8);
340  timesc.TimeErode = qgn;
341 
342  /* find Compton temp */
343  double TotalPower = (prt.pradio + prt.pbal +
344  p + phe + pheii + prt.xpow + prt.GammaLumin);
345  if( TotalPower>SMALLFLOAT )
346  {
347  tcompr = (p1 + p2 + p3 + p4 + p5 + p6 + p7)/TotalPower;
348  tcomp = tcompr/(4.*6.272e-6);
349  }
350  else
351  {
352  tcompr = 0.;
353  tcomp = 0.;
354  }
355 
356  if( trace.lgTrace )
357  {
358  fprintf( ioQQQ,
359  " mean photon energy=%10.3eR =%10.3eK low, high nu=%12.4e%12.4e\n",
360  tcompr, tcomp, rfield.anumin(0), rfield.anumax(rfield.nflux-1) );
361  }
362 
363  /* this is total power in ionizing radiation, per unit area */
364  prt.powion = p + phe + pheii + prt.xpow + prt.GammaLumin;
365 
366  /* this is the total radiation intensity, erg cm-2 s-1 */
368 
369  /* this is placed into the line stack on the first zone, then
370  * reset to zero, to end up with luminosity in the emission lines array.
371  * at end of iteration it is reset to TotalLumin */
373 
374  /* total H-ionizing photon number, */
376 
377  /* ftotal photon number, all energies */
379 
380  if( prt.powion <= 0. && called.lgTalk )
381  {
382  rfield.lgHionRad = true;
383  fprintf( ioQQQ, " NOTE There is no hydrogen-ionizing radiation.\n" );
384  fprintf( ioQQQ, " Was this intended?\n\n" );
385  /* check if any Balmer ionizing radiation since even metals will be
386  * totally neutral */
387  if( prt.pbal <=0. && called.lgTalk )
388  {
389  fprintf( ioQQQ, " NOTE There is no Balmer continuum radiation.<<<<\n" );
390  fprintf( ioQQQ, " Was this intended?\n\n" );
391  }
392  }
393 
394  else
395  {
396  rfield.lgHionRad = false;
397  }
398 
399  /* option to add energy deposition due to fast neutrons,
400  * entered as fraction of total photon luminosity */
401  if( hextra.lgNeutrnHeatOn )
402  {
403  /* hextra.totneu is erg cm-2 s-1 in neutrons
404  * hextra.effneu - efficiency default is unity */
406  exp10(hextra.frcneu));
407  }
408  else
409  {
410  hextra.totneu = (realnum)0.;
411  }
412 
413  /* temp correspond to energy density, printed in STARTR */
414  phycon.TEnerDen = powpq(continuum.TotalLumin/(4.*STEFAN_BOLTZ),1,4);
415 
416  /* sanity check for single blackbody, that energy density temperature
417  * is smaller than black body temperature */
418  if( rfield.nShape==1 &&
419  strcmp( rfield.chSpType[rfield.nShape-1], "BLACK" )==0 )
420  {
421  /* single black body, now confirm that TEnerDen is less than this temperature,
422  * >>>chng 99 may 02,
423  * in lte these are very very close, factor of 1.00001 allows for numerical
424  * errors, and apparently slightly different atomic coef in different parts
425  * of code. eventaully all mustuse physonst.h and agree exactly */
426  if( phycon.TEnerDen > 1.0001f*rfield.slope[rfield.nShape-1] )
427  {
428  fprintf( ioQQQ,
429  "\n WARNING: The energy density temperature (%g) is greater than the"
430  " black body temperature (%g). This is unphysical.\n\n",
432  }
433  }
434 
435  /* incident continuum nu*f_nu at Hbeta and Ly-alpha */
436  continuum.cn4861 = (realnum)(ffun(0.1875)*HPLANCK*FR1RYD*0.1875*0.1875);
437  continuum.cn1216 = (realnum)(ffun(0.75)*HPLANCK*FR1RYD*0.75*0.75);
440  /* flux density in V, erg / s / cm2 / hz */
441  continuum.fluxv = (realnum)(ffun(0.1643)*HPLANCK*0.1643);
442  continuum.fbeta = (realnum)(ffun(0.1875)*HPLANCK*0.1875*6.167e14);
443 
444  /* flux density nu*Fnu = erg / s / cm2
445  * EX1RYD is optional extinction factor at 1 ryd */
446  prt.fx1ryd = (realnum)(ffun(1.000)*HPLANCK*ex1ryd*FR1RYD);
447 
448  realnum plsFrqConstant = (realnum)(ELEM_CHARGE_ESU/sqrt(PI*ELECTRON_MASS)/FR1RYD);
449  ASSERT( plsFrqConstant > 2.7e-12 && plsFrqConstant < 2.8e-12 );
450 
451  /* check for plasma frequency - then zero out incident continuum
452  * for energies below this
453  * this is critical electron density, shielding of incident continuum
454  * if electron density is greater than this */
455  ecrit = POW2(rfield.anu(0)/plsFrqConstant);
456 
457  if( dense.gas_phase[ipHYDROGEN]*1.2 > ecrit )
458  {
459  rfield.lgPlasNu = true;
460  // This should be electron density, but we don't know that yet.
461  // We use n_H (with 1.2 factor for He) as an ansatz.
462  rfield.plsfrq = plsFrqConstant*sqrt(dense.gas_phase[ipHYDROGEN]*1.2f);
465 
466  /* save max pointer too */
468 
469  /* now loop over all affected energies, setting incident continuum
470  * to zero there, and counting all as reflected */
471  /* >>chng 01 jul 14, from i < ipPlasma to ipPlasma-1 -
472  * when ipPlasma is 1 plasma freq is not on energy scale */
473  for( i=0; i < rfield.ipPlasma-1; i++ )
474  {
475  /* count as reflected incident continuum */
476  rfield.ConRefIncid[0][i] = rfield.flux[0][i];
477  /* set continuum to zero there */
478  rfield.flux_beam_const[i] = 0.;
479  rfield.flux_beam_time[i] = 0.;
480  rfield.flux_isotropic[i] = 0.;
483  }
484  }
485  else
486  {
487  rfield.lgPlasNu = false;
488  /* >>chng 01 jul 14, from 0 to 1 - 1 is the first array element on the F scale,
489  * ipoint would return this, so rest of code assumes ipPlasma is 1 plus correct index */
490  rfield.ipPlasma = 1;
491  rfield.plsfrqmax = 0.;
492  rfield.plsfrq = 0.;
493  }
494 
495  if( rfield.ipPlasma > 1 && called.lgTalk )
496  {
497  fprintf( ioQQQ,
498  " !The plasma frequency is %.2e Ryd. The incident continuum is set to 0 below this.\n",
499  rfield.plsfrq );
500  }
501 
502  rfield.occmax = 0.;
503  rfield.tbrmax = 0.;
504  for( i=0; i < rfield.nflux_with_check; i++ )
505  {
506  /* set up occupation number array */
509  {
511  rfield.occmnu = rfield.anu(i);
512  }
513  /* following product is continuum brightness temperature */
514  if( rfield.OccNumbIncidCont[i]*TE1RYD*rfield.anu(i) > rfield.tbrmax )
515  {
517  rfield.tbrmnu = rfield.anu(i);
518  }
519  /* save continuum for next iteration */
520  rfield.flux_total_incident[0][i] = rfield.flux[0][i];
524  /*fprintf(ioQQQ,"DEBUG type cont %li\t%.3e\t%.2e\t%.2e\t%.2e\t%.2e\n",
525  i, rfield.anu(i),
526  rfield.flux[0][i],rfield.flux_beam_const[i],rfield.flux_beam_time[i],
527  rfield.flux_isotropic[i]);
528  fflush(ioQQQ);*/
529  }
530 
531  /* if continuum brightness temp is large, where does it fall below
532  * 1e4k??? */
533  if( rfield.tbrmax > 1e4 )
534  {
535  i = ipoint(rfield.tbrmnu)-1;
536  while( i < rfield.nflux_with_check-1 && (rfield.OccNumbIncidCont[i]*TE1RYD*
537  rfield.anu(i) > 1e4) )
538  {
539  ++i;
540  }
541  rfield.tbr4nu = rfield.anu(i);
542  }
543  else
544  {
545  rfield.tbr4nu = 0.;
546  }
547 
548  /* if continuum occ num is large, where does it fall below 1? */
549  if( rfield.occmax > 1. )
550  {
551  i = ipoint(rfield.occmnu)-1;
552  while( i < rfield.nflux_with_check && (rfield.OccNumbIncidCont[i] > 1.) )
553  {
554  ++i;
555  }
556  rfield.occ1nu = rfield.anu(i);
557  }
558  else
559  {
560  rfield.occ1nu = 0.;
561  }
562 
563  /* remember if incident radiation field is less than 10*Habing ISM */
564  /* >>chng 06 aug 01, change this test from continuum.TotalLumin to
565  * energy in balmer and ionizing continuum, since this is the true habing field
566  * and is the continuum that interacts with gas. When CMB set this
567  * tests on total did not trigger due to cold blackbody, which has little
568  * effect on gas, other than compton */
569  if( (prt.powion + prt.pbal) < 1.8e-2 )
570  {
571  /* thermal.ConstTemp def is zero, set pos when constant temperature is set */
572  rfield.lgHabing = true;
573  /* >>chng 06 aug 01 also print warning if substantially below Habing, this may be a mistake */
574  if( ((prt.powion + prt.pbal) < 1.8e-12) &&
575  /* this is test for not constant temperature */
577  {
578  fprintf( ioQQQ, "\n >>>\n"
579  " >>> NOTE The incident continuum is surprisingly faint.\n" );
580  fprintf( ioQQQ,
581  " >>> The total energy in the Balmer and Lyman continua is %.2e erg cm-2 s-1.\n"
582  ,(prt.powion + prt.pbal));
583  fprintf( ioQQQ, " >>> This is many orders of magnitude fainter than the ISM galactic background.\n" );
584  fprintf( ioQQQ, " >>> This seems unphysical - please check that the continuum intensity has been properly set.\n" );
585  fprintf( ioQQQ, " >>> YOU MAY BE MAKING A BIG MISTAKE!!\n >>>\n\n\n\n" );
586  }
587  }
588 
589  /* fix ionization parameter (per hydrogen) at inner edge */
591  (dense.gas_phase[ipHYDROGEN]*SPEEDLIGHT));
593  (dense.gas_phase[ipHYDROGEN]*SPEEDLIGHT));
594  if( rfield.uh > 1e10 )
595  {
596  fprintf( ioQQQ, "\n\n"
597  " CAUTION The incident radiation field is surprisingly intense.\n" );
598  fprintf( ioQQQ,
599  " The dimensionless hydrogen ionization parameter is %.2e.\n"
600  , rfield.uh );
601  fprintf( ioQQQ, " This is many orders of magnitude brighter than commonly seen.\n" );
602  fprintf( ioQQQ, " This seems unphysical - please check that the radiation field intensity has been properly set.\n" );
603  fprintf( ioQQQ, " YOU MAY BE MAKING A BIG MISTAKE!!\n\n\n\n\n" );
604  }
605 
606  /* guess first temperature and neutral h density */
607  double TeNew;
608  if( thermal.ConstTemp > 0. )
609  {
610  TeNew = thermal.ConstTemp;
611  }
612  else
613  {
614  if( rfield.uh > 0. )
615  {
616  TeNew = (20000.+log10(rfield.uh)*5000.);
617  TeNew = MAX2(8000. , TeNew );
618  }
619  else
620  {
621  TeNew = 1000.;
622  }
623  }
624  TempChange( TeNew );
625 
626  /* this is an option to stop after printing header only */
627  if( noexec.lgNoExec )
628  return;
629 
630  /* estimate secondary ionization rate - probably 0, but possible extra
631  * SetCsupra set with "set csupra" */
632  /* >>>chng 99 apr 29, added cosmic ray ionization since this is used to get
633  * helium ionization fraction, and was zero in pdr, so He turned off at start,
634  * and never turned back on */
635  /* coef on cryden is from highen.c */
636  for( nelem=ipHYDROGEN; nelem<LIMELM; ++nelem )
637  {
638  for( ion=0; ion<nelem+1; ++ion )
639  {
640  secondaries.csupra[nelem][ion] =
642  }
643  }
644 
645  /*********************************************************************
646  * *
647  * estimate hydrogen's level of ionization *
648  * *
649  *********************************************************************/
650 
651  /* create fake ionization balance, but will conserve number of hydrogens */
652  dense.xIonDense[ipHYDROGEN][0] = 0.;
654  /* this must be zero since PresTotCurrent will do radiation pressure due to H */
655  iso_sp[ipH_LIKE][ipHYDROGEN].st[ipH1s].Pop() = 0.;
656 
657  /* "extra" electrons from command line, or assumed residual electrons */
658  double EdenExtraLocal = dense.EdenExtra +
659  /* if we are in a molecular cloud the current logic could badly fail
660  * do not let electron density fall below 1e-7 of H density */
661  1e-7*dense.gas_phase[ipHYDROGEN];
662  EdenChange( dense.xIonDense[ipHYDROGEN][1] + EdenExtraLocal );
663 
664  /* hydrogen case B recombination coefficient */
665  HCaseBRecCoeff = (-9.9765209 + 0.158607055*phycon.telogn[0] + 0.30112749*
666  phycon.telogn[1] - 0.063969007*phycon.telogn[2] + 0.0012691546*
667  phycon.telogn[3])/(1. + 0.035055422*phycon.telogn[0] -
668  0.037621619*phycon.telogn[1] + 0.0076175048*phycon.telogn[2] -
669  0.00023432613*phycon.telogn[3]);
670  HCaseBRecCoeff = exp10(HCaseBRecCoeff)/phycon.te;
671 
672  double CollIoniz = t_ADfA::Inst().coll_ion_wrapper(0,0,phycon.te);
673 
674  // mean H-ionizing photon energy
675  double PhotonEnergy = 1.;
676  if( rfield.qhtot>SMALLFLOAT )
677  PhotonEnergy = prt.powion/rfield.qhtot/EN1RYD;
678 
679  double OtherIonization = rfield.qhtot*6.3e-18/POW3(PhotonEnergy) +
681 
682  double newEden = dense.eden;
683  long loopCount = 0;
684 
685  do
686  {
687  /* update electron density */
688  EdenChange( newEden );
689  double RatioIoniz =
690  (CollIoniz*dense.eden+OtherIonization)/(HCaseBRecCoeff*dense.eden);
691  if( RatioIoniz<1e-3 )
692  {
693  /* very low ionization solution */
697  ASSERT( dense.xIonDense[ipHYDROGEN][0]>=0. &&
699  ASSERT( dense.xIonDense[ipHYDROGEN][1]>=0. &&
701  //fprintf(ioQQQ,"DEBUG br 1 H0 %.2e\n", dense.xIonDense[ipHYDROGEN][0]);
702  }
703  else if( RatioIoniz>1e3 )
704  {
705  /* very high ionization solution */
709  ASSERT( dense.xIonDense[ipHYDROGEN][0]>=0. &&
711  ASSERT( dense.xIonDense[ipHYDROGEN][1]>=0. &&
713  //fprintf(ioQQQ,"DEBUG br 2 H0 %.2e rat %.2e\n", dense.xIonDense[ipHYDROGEN][0],
714  // dense.gas_phase[ipHYDROGEN]/RatioIoniz);
715  }
716  else
717  {
718  /* intermediate ionization - solve quadratic */
719  double alpha = HCaseBRecCoeff + CollIoniz ;
720  double beta = HCaseBRecCoeff*EdenExtraLocal + OtherIonization +
721  (EdenExtraLocal - dense.gas_phase[ipHYDROGEN])*CollIoniz;
722  double gamma = -dense.gas_phase[ipHYDROGEN]*(OtherIonization+EdenExtraLocal*CollIoniz);
723 
724  double discriminant = POW2(beta) - 4.*alpha*gamma;
725  if( discriminant <0 )
726  {
727  /* oops */
728  fprintf(ioQQQ," DISASTER PROBLEM cont_initensity found negative discriminant.\n");
729  TotalInsanity();
730  }
731 
732  dense.xIonDense[ipHYDROGEN][1] = (realnum)((-beta + sqrt(discriminant))/(2.*alpha));
734  {
735  /* oops */
736  fprintf(ioQQQ," DISASTER PROBLEM cont_initensity found n(H+)>n(H).\n");
737  TotalInsanity();
738  }
741  if( dense.xIonDense[ipHYDROGEN][0]<= 0 )
742  {
743  /* oops */
744  fprintf(ioQQQ," DISASTER PROBLEM cont_initensity found n(H0)<0.\n");
745  TotalInsanity();
746  }
747  //fprintf(ioQQQ,"DEBUG br 3 H0 %.2e\n", dense.xIonDense[ipHYDROGEN][0]);
748  }
749 
750 
751  if( dense.xIonDense[ipHYDROGEN][1] > 1e-30 )
752  {
754  }
755  else
756  {
757  iso_sp[ipH_LIKE][ipHYDROGEN].st[ipH1s].Pop() = 0.;
758  }
759 
760  /* now save estimates of whether induced recombination is going
761  * to be important -this is a code pacesetter since GammaBn is slower
762  * than GammaK */
763  hydro.lgHInducImp = false;
764  for( i=ipH1s; i < iso_sp[ipH_LIKE][ipHYDROGEN].numLevels_max; i++ )
765  {
766  if( rfield.OccNumbIncidCont[iso_sp[ipH_LIKE][ipHYDROGEN].fb[i].ipIsoLevNIonCon-1] > 0.01 )
767  hydro.lgHInducImp = true;
768  }
769 
770  /*******************************************************************
771  * *
772  * estimate helium's level of ionization *
773  * *
774  *******************************************************************/
775 
776  /* only if helium is turned on */
777  if( dense.lgElmtOn[ipHELIUM] )
778  {
779  /* next estimate level of helium singly ionized */
780  xIoniz = (realnum)t_ADfA::Inst().coll_ion_wrapper(1,0,phycon.te);
781  /* >>chng 05 jan 05, add cosmic rays */
782  xIoniz = (realnum)(xIoniz*dense.eden + rfield.qhe*1e-18 + secondaries.csupra[ipHELIUM][1] );
783  double RecTot = HCaseBRecCoeff*dense.eden;
784  RatioIonizToRecomb = xIoniz/RecTot;
785 
786  /* now estimate level of helium doubly ionized */
787  xIoniz = (realnum)t_ADfA::Inst().coll_ion_wrapper(1,1,phycon.te);
788  /* >>chng 05 jan 05, add cosmic rays */
789  xIoniz = (realnum)(xIoniz*dense.eden + rfield.qheii*1e-18 + ionbal.CosRayIonRate );
790 
791  /* rough charge dependence */
792  RecTot *= 4.;
793  r3ov2 = xIoniz/RecTot;
794 
795  /* now set level of helium ionization */
796  if( RatioIonizToRecomb > 0. )
797  {
798  double r1 = dense.gas_phase[ipHELIUM]/(1./RatioIonizToRecomb + 1. + r3ov2);
799  dense.xIonDense[ipHELIUM][1] = (realnum)(r1);
800  dense.xIonDense[ipHELIUM][0] = (realnum)(r1/RatioIonizToRecomb);
801  dense.xIonDense[ipHELIUM][2] = (realnum)(r1*r3ov2);
802  }
803  else
804  {
805  /* no He ionizing radiation */
808  }
809 
810  if( dense.xIonDense[ipHELIUM][2] > 1e-30 )
811  {
813  }
814  else
815  {
816  iso_sp[ipH_LIKE][ipHELIUM].st[ipH1s].Pop() = 0.;
817  }
818  }
819  else
820  {
821  /* case where helium is turned off */
822  dense.xIonDense[ipHELIUM][1] = 0.;
823  dense.xIonDense[ipHELIUM][0] = 0.;
824  dense.xIonDense[ipHELIUM][2] = 0.;
825  iso_sp[ipH_LIKE][ipHELIUM].st[ipH1s].Pop() = 0.;
826  }
827 
828  /* update electron density */
829  newEden = dense.xIonDense[ipHYDROGEN][1] + EdenExtraLocal + dense.xIonDense[ipHELIUM][1] + 2.*dense.xIonDense[ipHELIUM][2];
830 
831  loopCount++;
832  }
833  /* repeat above until guessed and calculated eden agree to at least 0.1%. */
834  while( loopCount < 10 && fabs(newEden/dense.eden - 1.) > 0.001 );
835 
836  if( dense.xIonDense[ipHYDROGEN][0]<0.)
837  TotalInsanity();
838  else if( dense.xIonDense[ipHYDROGEN][0] == 0. )
839  {
840  fprintf(ioQQQ,"PROBLEM the derived atomic hydrogen density is zero.\n");
841  if( dense.gas_phase[ipHYDROGEN]<1e-5 && rfield.uh > 1e10)
842  {
843  fprintf(ioQQQ,"This is almost certainly due to floating point "
844  "limits on this computer.\nThe ionization parameter is very large,"
845  " the density is very small,\nand the H^0 density cannot be"
846  " stored in a double.\n");
847  //cdEXIT( EXIT_FAILURE );
848  }
849  }
850  //ASSERT( dense.xIonDense[ipHYDROGEN][0] >0 && dense.xIonDense[ipHYDROGEN][1]>= 0.);
851 
852  /* update electron density */
853  EdenChange( newEden );
854 
855  if( dense.eden <= SMALLFLOAT )
856  {
857  /* no electrons! */
858  fprintf(ioQQQ,"\n PROBLEM DISASTER - this simulation has no source"
859  " of ionization. The electron density is zero. Consider "
860  "adding a source of ionization such as cosmic rays.\n\n");
862  }
863 
864  /* fix range of stages of ionization */
865  ion_trim_init();
866 
867  // make first estimate of iso continuum lowering
868  for( long ipISO=ipH_LIKE; ipISO<NISO; ++ipISO )
869  {
870  for( long nelem=ipISO; nelem<LIMELM; ++nelem)
871  {
872  if( nelem < 2 || dense.lgElmtOn[nelem] )
873  {
875  iso_continuum_lower( ipISO, nelem );
876  }
877  }
878  }
879 
880  /* estimate electrons from heavies, assuming each at least
881  * 1 times ionized */
882  EdenHeav = 0.;
885  for( nelem=ipLITHIUM; nelem < LIMELM; nelem++ )
886  {
887  if( dense.lgElmtOn[nelem] )
888  {
889  if( dense.IonLow[nelem] == 0 && dense.IonHigh[nelem] >=1)
890  {
891  realnum low2dens = dense.xIonDense[nelem][0]+dense.xIonDense[nelem][1];
892  dense.xIonDense[nelem][0] = low2dens * atomFrac;
893  dense.xIonDense[nelem][1] = low2dens * firstIonFrac;
894  }
895  for (long ion=1;ion<dense.IonHigh[nelem];++ion)
896  {
897  EdenHeav += ion*dense.xIonDense[nelem][ion];
898  }
899  }
900  }
901 
902  /* modify estimate of electron density */
903  dense.eden += EdenHeav;
904 
905  /* >>chng 05 jan 05, insure positive eden */
907 
908  if( dense.EdenSet > 0. )
909  {
911  }
912 
915 
916  if( dense.eden < 0. )
917  {
918  fprintf( ioQQQ, " PROBLEM DISASTER Negative electron density results in ContSetIntensity.\n" );
919  fprintf( ioQQQ, "%10.2e%10.2e%10.2e%10.2e%10.2e%10.2e\n",
922  TotalInsanity();
923  }
924 
925  if( dense.EdenSet > 0. )
926  {
928  }
929  else
931 
932  if( trace.lgTrace )
933  {
934  fprintf( ioQQQ,
935  " ContSetIntensity sets initial EDEN to %.4e, contributors H+=%.2e He+, ++= %.2e %.2e Heav %.2e extra %.2e\n",
936  dense.eden ,
939  2.*dense.xIonDense[ipHELIUM][2],
940  EdenHeav,
941  dense.EdenExtra);
942  }
943 
944  // photon occupation number at 1 Ryd - used for printout
945  occ1 = (realnum)(prt.fx1ryd/HNU3C2/PI4/FR1RYD);
946  if( occ1 > 1. )
947  rfield.lgOcc1Hi = true;
948  else
949  rfield.lgOcc1Hi = false;
950 
951  if( trace.lgTrace && trace.lgConBug )
952  {
953  fprintf(ioQQQ,"\ntrace continuum print of %li incident spectral "
954  "components\n", rfield.nShape);
955  fprintf(ioQQQ," # type Illum Beam? 1/cos TimeVary?\n");
957  {
958  fprintf(ioQQQ,"%3li %6s %5i %c %.3f %c\n",
959  rfield.ipSpec ,
965  }
966  fprintf(ioQQQ,"\n");
967 
968  /* print some useful pointers to ionization edges */
969  fprintf( ioQQQ, " H2,1=%5ld%5ld NX=%5ld IRC=%5ld\n",
970  iso_sp[ipH_LIKE][ipHYDROGEN].fb[2].ipIsoLevNIonCon,
971  iso_sp[ipH_LIKE][ipHYDROGEN].fb[ipH1s].ipIsoLevNIonCon,
972  opac.ipCKshell,
974  fprintf( ioQQQ, " CARBON" );
975  for( i=0; i < 6; i++ )
976  fprintf( ioQQQ, "%5ld", Heavy.ipHeavy[ipCARBON][i] );
977  fprintf( ioQQQ, "\n" );
978 
979  fprintf( ioQQQ, " OXY" );
980  for( i=0; i < 8; i++ )
981  fprintf( ioQQQ, "%5ld", Heavy.ipHeavy[ipOXYGEN][i] );
982  fprintf( ioQQQ, "%5ld%5ld%5ld\n", opac.ipo3exc[0],
983  oxy.i2d, oxy.i2p );
984 
985  double sum = 0.;
987  for( i=rfield.ipG0_DB96_lo; i < rfield.ipG0_DB96_hi; i++ )
988  sum += rfield.flux[0][i];
989  fprintf(ioQQQ,"\n Sum DB96 photons %.2e", sum);
990  sum = 0.;
991  for( i=(Heavy.ipHeavy[ipHYDROGEN][0] - 1); i<rfield.nflux; i++ )
992  sum += rfield.flux[0][i];
993  fprintf(ioQQQ,", sum H-ioniz photons %.2e\n", sum);
994 
995 
996  fprintf( ioQQQ, "\n\n PHOTONS PER CELL (NOT RYD)\n" );
997  fprintf( ioQQQ, " nu, flux, wid, occ \n" );
998  for( i=0; i < rfield.nflux; i++ )
999  {
1000  fprintf( ioQQQ, "%4ld%10.2e%10.2e%10.2e%10.2e\n", i,
1001  rfield.anu(i), rfield.flux[0][i], rfield.widflx(i),
1002  rfield.OccNumbIncidCont[i] );
1003  }
1004  fprintf( ioQQQ, " \n" );
1005  }
1006 
1007  /* zero out some continua related to the ots rates,
1008  * prototype and routine in RT_OTS_Update. This is done here since summed cont will
1009  * be set to rfield */
1010  RT_OTS_Zero();
1011 
1012  if( trace.lgTrace )
1013  {
1014  fprintf( ioQQQ, " ContSetIntensity returns, nflux=%5ld anu(nflux)=%11.4e eden=%10.2e\n",
1016  }
1017 
1018  return;
1019 }
1020 
1021 /*sumcon sums L and Q for net incident continuum */
1022 STATIC void sumcon(long int il,
1023  long int ih,
1024  realnum *q,
1025  realnum *p,
1026  realnum *panu)
1027 {
1028  long int i,
1029  iupper; /* used as upper limit to the sum */
1030 
1031  DEBUG_ENTRY( "sumcon()" );
1032 
1033  *q = 0.;
1034  *p = 0.;
1035  *panu = 0.;
1036 
1037  /* soft continua may not go as high as the requested bin */
1038  iupper = MIN2(rfield.nflux,ih);
1039 
1040  for( i=il-1; i < iupper; i++ )
1041  {
1042  /* sum photon number */
1043  *q += rfield.flux[0][i];
1044  /* en1ryd is needed to stop overflow */
1045  /* sum flux */
1046  *p += (realnum)(rfield.flux[0][i]*(rfield.anu(i)*EN1RYD));
1047  /* this sum needed for means */
1048  *panu += (realnum)(rfield.flux[0][i]*(rfield.anu2(i)*EN1RYD));
1049  }
1050 
1051  return;
1052 }
1053 
1054 /*extin do extinction of incident continuum as set by extinguish command */
1055 STATIC void extin(realnum *ex1ryd)
1056 {
1057 
1058  DEBUG_ENTRY( "extin()" );
1059 
1060  /* modify input continuum by leaky absorber
1061  * power law fit to
1062  * >>refer XUV extinction Cruddace, R., Paresce, F., Bowyer, S., & Lampton, M. 1974, ApJ, 187, 497. */
1063  if( rfield.ExtinguishColumnDensity == 0. )
1064  {
1065  *ex1ryd = 1.;
1066 
1067  for( long i=0; i<rfield.nflux_with_check; ++i )
1068  rfield.ExtinguishFactor[i] = 1.;
1069  }
1070  else
1071  {
1072  double absorb = 1. - rfield.ExtinguishLeakage;
1073  double factor = rfield.ExtinguishColumnDensity*
1075  /* extinction at 1 4 Ryd */
1076  *ex1ryd = (realnum)(rfield.ExtinguishLeakage + absorb*sexp(factor));
1077 
1078  // low energy limit of extinction
1080 
1081  for( long i=0; i<low-1; ++i )
1082  rfield.ExtinguishFactor[i] = 1.;
1083 
1084  for( long i=low-1; i < rfield.nflux_with_check; i++ )
1085  {
1086  realnum extfactor = (realnum)(rfield.ExtinguishLeakage + absorb*
1087  sexp(factor*(pow(rfield.anu(i),(double)rfield.ExtinguishEnergyPowerLow))));
1088 
1089  rfield.ExtinguishFactor[i] = extfactor;
1090  rfield.flux_beam_const[i] *= extfactor;
1091  rfield.flux_beam_time[i] *= extfactor;
1092  rfield.flux_isotropic[i] *= extfactor;
1093 
1096  }
1097  }
1098  return;
1099 }
1100 
1101 /*conorm normalize continuum to proper intensity */
1103 {
1104  long int i;
1105  double
1106  diff,
1107  f,
1108  flx1,
1109  flx2,
1110  pentrd,
1111  qentrd;
1112 
1113  DEBUG_ENTRY( "conorm()" );
1114 
1115  /* this is a sanity check, it can't happen */
1116  for( i=0; i < rfield.nShape; i++ )
1117  {
1118  if( strcmp(rfield.chRSpec[i],"UNKN") == 0 )
1119  {
1120  fprintf( ioQQQ, " UNKN spectral normalization cannot happen.\n" );
1121  fprintf( ioQQQ, " conorm punts.\n" );
1123  }
1124 
1125  else if( strcmp(rfield.chRSpec[i],"SQCM") != 0 &&
1126  strcmp(rfield.chRSpec[i],"4 PI") != 0 )
1127  {
1128  fprintf( ioQQQ, " chRSpec must be SQCM or 4 PI, and it was %4.4s. This cannot happen.\n",
1129  rfield.chRSpec[i] );
1130  fprintf( ioQQQ, " conorm punts.\n" );
1132  }
1133 
1134 
1135  /* this sanity check makes sure that atlas.mod or werner.mod grids
1136  * are for the current version of the code */
1137  if( strcmp(rfield.chSpType[i],"VOLK ") == 0 )
1138  {
1140  {
1141  fprintf( ioQQQ,"\n\n PROBLEM DISASTER At least one of the compiled stellar atmosphere"
1142  " grids has been compiled with a different energy grid resolution factor.\n" );
1143  fprintf( ioQQQ, " Please recompile this file using the COMPILE STARS command "
1144  "and make sure that you use the correct SET CONTINUUM RESOLUTION factor.\n" );
1146  }
1147  }
1148  else if( strcmp(rfield.chSpType[i],"READ ") == 0 )
1149  {
1151  {
1152  fprintf( ioQQQ,"\n\n PROBLEM DISASTER The file read by the TABLE READ command "
1153  "has been compiled with a different energy grid resolution factor.\n" );
1154  fprintf( ioQQQ, " Please recompile this file using the SAVE TRANSMITTED CONTINUUM "
1155  "command and use the correct SET CONTINUUM RESOLUTION factor.\n" );
1157  }
1158  }
1159  }
1160 
1161  /* this sanity check is that the grains we have read in from opacity files agree
1162  * with the energy grid in this version of cloudy */
1163  for( size_t nd=0; nd < gv.bin.size(); nd++ )
1164  {
1165  if( !fp_equal( gv.bin[nd]->RSFCheck, rfield.getResolutionScaleFactor() ) )
1166  {
1167  fprintf( ioQQQ,"\n\n PROBLEM DISASTER At least one of the grain opacity files "
1168  "has been compiled with a different energy grid resolution factor.\n" );
1169  fprintf( ioQQQ, " Please recompile this file using the COMPILE GRAINS command "
1170  "and make sure that you use the correct SET CONTINUUM RESOLUTION factor.\n" );
1172  }
1173  }
1174 
1175  /* default is is to predict line intensities,
1176  * but if any continuum specified as luminosity then would override this -
1177  * following two values are correct for intensities */
1178  radius.pirsq = 0.;
1179  radius.lgPredLumin = false;
1180 
1181  /* check whether ANY luminosities are present */
1182  for( i=0; i < rfield.nShape; i++ )
1183  {
1184  if( strcmp(rfield.chRSpec[i],"4 PI") == 0 )
1185  {
1186  if (radius.rinner == 0.)
1187  {
1188  fprintf(ioQQQ,"PROBLEM: need to specify inner radius with luminosity\n");
1190  }
1191  double xLog_radius_inner = log10(radius.rinner);
1192 
1193  radius.pirsq = (realnum)(1.0992099 + 2.*xLog_radius_inner);
1194  radius.lgPredLumin = true;
1195  /* convert down to intensity */
1196  rfield.totpow[i] -= radius.pirsq;
1197 
1198  if( trace.lgTrace )
1199  {
1200  fprintf( ioQQQ,
1201  " conorm converts continuum %ld from luminosity to intensity.\n",
1202  i );
1203  }
1204  }
1205  }
1206 
1207  /* if total luminosities are present, must have specified a starting radius */
1209  {
1210  fprintf(ioQQQ,"PROBLEM DISASTER conorm: - A continuum source was specified as a luminosity, but the inner radius of the cloud was not set.\n");
1211  fprintf(ioQQQ,"Please set an inner radius.\nSorry.\n");
1213  }
1214 
1215  /* convert ionization parameters to number of photons, called "q(h)"
1216  * at this stage q(h) and "PHI " are the same */
1217  for( i=0; i < rfield.nShape; i++ )
1218  {
1219  if( strcmp(rfield.chSpNorm[i],"IONI") == 0 )
1220  {
1221  /* the log of the ionization parameter was stored here, this converts
1222  * it to the log of the number of photons per sq cm */
1223  rfield.totpow[i] += log10(dense.gas_phase[ipHYDROGEN]) + log10(SPEEDLIGHT);
1224  strcpy( rfield.chSpNorm[i], "Q(H)" );
1225  if( trace.lgTrace )
1226  {
1227  fprintf( ioQQQ,
1228  " conorm converts continuum %ld from ionizat par to q(h).\n",
1229  i );
1230  }
1231  }
1232  }
1233 
1234  /* convert x-ray ionization parameter xi to intensity */
1235  for( i=0; i < rfield.nShape; i++ )
1236  {
1237  if( strcmp(rfield.chSpNorm[i],"IONX") == 0 )
1238  {
1239  /* this converts it to an intensity */
1240  rfield.totpow[i] += log10(dense.gas_phase[ipHYDROGEN]) - log10(PI4);
1241  strcpy( rfield.chSpNorm[i], "LUMI" );
1242  if( trace.lgTrace )
1243  {
1244  fprintf( ioQQQ, " conorm converts continuum%3ld from x-ray ionizat par to I.\n",
1245  i );
1246  }
1247  }
1248  }
1249 
1250  /* indicate whether we ended up with luminosity or intensity */
1251  if( trace.lgTrace )
1252  {
1253  if( radius.lgPredLumin )
1254  {
1255  fprintf( ioQQQ, " Cloudy will predict lumin into 4pi\n" );
1256  }
1257  else
1258  {
1259  fprintf( ioQQQ, " Cloudy will do surface flux for lumin\n" );
1260  }
1261  }
1262 
1263  /* if intensity per unit area is predicted then geometric
1264  * covering factor must be unity
1265  * variable can also be set elsewhere */
1266  if( !radius.lgPredLumin )
1267  {
1268  geometry.covgeo = 1.;
1269  }
1270 
1271  /* main loop over all continuum shapes to find continuum normalization
1272  * for each one */
1273  for( i=0; i < rfield.nShape; i++ )
1274  {
1275  rfield.ipSpec = i;
1276 
1277  /* check that, if laser, bounds include laser energy */
1278  if( strcmp(rfield.chSpType[rfield.ipSpec],"LASER") == 0 )
1279  {
1280  if( !( rfield.range[rfield.ipSpec][0] < rfield.slope[rfield.ipSpec] &&
1282  {
1283  fprintf(ioQQQ,"PROBLEM DISASTER, a continuum source is a laser at %f Ryd, but the intensity was specified over a range from %f to %f Ryd.\n",
1285  rfield.range[rfield.ipSpec][0],
1286  rfield.range[rfield.ipSpec][1]);
1287  fprintf(ioQQQ,"Please specify the continuum flux where the laser is active.\n");
1289  }
1290  }
1291 
1292  if( trace.lgTrace )
1293  {
1294  long int jj;
1295  fprintf( ioQQQ, " conorm continuum number %ld is shape %s range is %.2e %.2e\n",
1296  i,
1297  rfield.chSpType[i],
1298  rfield.range[i][0],
1299  rfield.range[i][1] );
1300  fprintf( ioQQQ, "the continuum points follow\n");
1301  for( jj=0; jj < min(rfield.ncont[rfield.nShape],100); ++jj )
1302  {
1303  fprintf( ioQQQ, "%li %e %e\n",
1304  jj ,
1305  rfield.tNu[rfield.ipSpec][jj].Ryd(),
1306  rfield.tslop[rfield.ipSpec][jj] );
1307  }
1308  }
1309 
1310  if( strcmp(rfield.chSpNorm[i],"RATI") == 0 )
1311  {
1312  /* option to scale relative to previous continua
1313  * this must come first since otherwise may be too late
1314  * BUT ratio cannot be the first continuum source */
1315  if( trace.lgTrace )
1316  {
1317  fprintf( ioQQQ, " conorm this is ratio to 1st con\n" );
1318  }
1319 
1320  /* check that this is not the first continuum source, we must ratio */
1321  if( i == 0 )
1322  {
1323  fprintf( ioQQQ, " I cant form a ratio if continuum is first source.\n" );
1325  }
1326 
1327  /* first find photon flux and Q of previous continuum */
1328  rfield.ipSpec -= 1;
1329  flx1 = ffun1(rfield.range[i][0])*rfield.spfac[rfield.ipSpec]*
1330  rfield.range[i][0];
1331 
1332  /* check that previous continua were not zero where ratio is formed */
1333  if( flx1 <= 0. )
1334  {
1335  fprintf( ioQQQ, " Previous continua were zero where ratio is desired.\n" );
1337  }
1338 
1339  /* return pointer to previous (correct) value, find F, Q */
1340  rfield.ipSpec += 1;
1341 
1342  /* we want a continuum totpow as powerful, flx is now desired flx */
1343  flx1 *= rfield.totpow[i];
1344 
1345  /*. find flux of this new continuum at that point */
1346  flx2 = ffun1(rfield.range[i][1])*rfield.range[i][1];
1347 
1348  /* this is ratio of desired to actual */
1349  rfield.spfac[i] = flx1/flx2;
1350  if( trace.lgTrace )
1351  {
1352  fprintf( ioQQQ, " conorm ratio will set scale fac to%10.3e at%10.2e Ryd.\n",
1353  rfield.totpow[i], rfield.range[i][0] );
1354  }
1355  }
1356 
1357  else if( strcmp(rfield.chSpNorm[i],"FLUX") == 0 )
1358  {
1359  /* specify flux density
1360  * option to use arbitrary frequency or range */
1361  f = ffun1(rfield.range[i][0]);
1362 
1363  /* make sure this is positive, could be zero if out of range of table,
1364  * or for various forms of insanity */
1365  if( f<=SMALLDOUBLE )
1366  {
1367  fprintf( ioQQQ, "\n\n PROBLEM DISASTER\n The intensity of continuum source %ld is non-positive at the energy used to normalize it (%.3e Ryd). Something is seriously wrong.\n",
1368  i , rfield.range[i][0]);
1369  /* is this a table? if so, is ffun within its bounds? */
1370  if( strcmp(rfield.chSpType[i],"INTER") == 0 )
1371  fprintf( ioQQQ, " This continuum shape given by a table of points - check that the intensity is specified at an energy within the range of that table.\n");
1372  fprintf( ioQQQ, " Also check that the numbers used to specify the shape and intensity do not under or overflow on this cpu.\n\n");
1373 
1375  }
1376 
1377  /* now convert to log in continuum units we shall use */
1378  // EN1RYD/FR1RYD == HPLANCK
1379  f = log10(f) + log10(rfield.range[i][0]*EN1RYD/FR1RYD);
1380  f = rfield.totpow[i] - f;
1381  rfield.spfac[i] = exp10(f);
1382 
1383  if( trace.lgTrace )
1384  {
1385  fprintf( ioQQQ, " conorm will set log fnu to%10.3e at%10.2e Ryd. Factor=%11.4e\n",
1386  rfield.totpow[i], rfield.range[i][0], rfield.spfac[i] );
1387  }
1388  }
1389 
1390  else if( strcmp(rfield.chSpNorm[i],"Q(H)") == 0 ||
1391  strcmp(rfield.chSpNorm[i],"PHI ") == 0 )
1392  {
1393  /* some type of photon density entered */
1394  if( trace.lgTrace )
1395  {
1396  fprintf( ioQQQ, " conorm calling qintr range=%11.3e %11.3e desired val is %11.3e\n",
1397  rfield.range[i][0],
1398  rfield.range[i][1] ,
1399  rfield.totpow[i]);
1400  }
1401 
1402  /* the total number of photons over the specified range in
1403  * the arbitrary system of units that the code save the continuum shape */
1404  ASSERT( rfield.range[i][0] < rfield.range[i][1] );
1405  qentrd = qintr(rfield.range[i][0],rfield.range[i][1]);
1406  /* this is the log of the scale factor that must multiply the
1407  * continuum shape to get the final set of numbers */
1408  diff = rfield.totpow[i] - qentrd;
1409 
1410  if( diff < log10(SMALLDOUBLE) || diff > log10(BIGDOUBLE) )
1411  {
1412  fprintf( ioQQQ, " PROBLEM DISASTER Continuum source specified is too extreme.\n" );
1413  fprintf( ioQQQ,
1414  " The integral over the continuum shape gave (log) %.3e photons, and the command requested (log) %.3e.\n" ,
1415  qentrd , rfield.totpow[i]);
1416  fprintf( ioQQQ,
1417  " The difference in the log is %.3e.\n" ,
1418  diff );
1419  if( diff>0. )
1420  {
1421  fprintf( ioQQQ, " The continuum source is too bright.\n" );
1422  }
1423  else
1424  {
1425  fprintf( ioQQQ, " The continuum source is too faint.\n" );
1426  }
1427  /* explain what happened */
1428  fprintf( ioQQQ, " The usual cause for this problem is an incorrect continuum intensity/luminosity or radius command.\n" );
1429  fprintf( ioQQQ, " There were a total of %li continuum shape commands entered - the problem is with number %li.\n",
1430  rfield.nShape , i+1 );
1432  }
1433 
1434  else
1435  {
1436  rfield.spfac[i] = exp10(diff);
1437  }
1438 
1439  if( trace.lgTrace )
1440  {
1441  fprintf( ioQQQ, " conorm finds Q over range from%11.4e-%11.4e Ryd, integral= %10.4e Factor=%11.4e\n",
1442  rfield.range[i][0],
1443  rfield.range[i][1],
1444  qentrd ,
1445  rfield.spfac[i] );
1446  }
1447  }
1448 
1449  else if( strcmp(rfield.chSpNorm[i],"LUMI") == 0 )
1450  {
1451  /* luminosity entered, special since default is TOTAL lumin */
1452  /*pintr integrates L for any continuum between two limits, used for normalization,
1453  * return units are log of ryd cm-2 s-1, last log conv to ergs */
1454  pentrd = pintr(rfield.range[i][0],rfield.range[i][1]) + log10(EN1RYD);
1455  f = rfield.totpow[i] - pentrd;
1456  rfield.spfac[i] = exp10(f);
1457 
1458  if( trace.lgTrace )
1459  {
1460  fprintf( ioQQQ, " conorm finds luminosity range is %10.3e to %9.3e Ryd, factor is %11.4e\n",
1461  rfield.range[i][0], rfield.range[i][1],
1462  rfield.spfac[i] );
1463  }
1464  }
1465 
1466  else
1467  {
1468  fprintf( ioQQQ, "PROBLEM DISASTER What chSpNorm label is this? =%s=\n", rfield.chSpNorm[i]);
1469  TotalInsanity();
1470  }
1471 
1472  /* spfac used to renormalize SED into flux */
1473  if( fabs(rfield.spfac[i]) <=SMALLDOUBLE )
1474  {
1475  fprintf( ioQQQ, "PROBLEM DISASTER conorm finds infinite continuum scale factor.\n" );
1476  fprintf( ioQQQ, "The continuum is too intense to compute with this cpu.\n" );
1477  fprintf( ioQQQ, "Were the intensity and luminosity commands switched?\n" );
1478  fprintf( ioQQQ, "Sorry, but I cannot go on.\n" );
1480  }
1481  }
1482 
1483  /* this is conversion factor for final units of line intensities or luminosities in printout,
1484  * will be intensities (==0) unless luminosity is to be printed, or flux at Earth
1485  * pirsq is the log of 4 pi r_in^2 */
1486  radius.Conv2PrtInten = exp10((double)radius.pirsq);
1487 
1488  /* >>chng 02 apr 25, add option for slit on aperture command */
1489  if( geometry.iEmissPower == 1 )
1490  {
1491  if( radius.lgPredLumin )
1492  {
1493  /* factor should be divided by 2 r_in (so that 2pi*r_in remains) */
1494  radius.Conv2PrtInten /= (2. * radius.rinner);
1495  }
1496  else if( !radius.lgPredLumin )
1497  {
1498  /* this is an error - slit requested but radius is not known */
1499  fprintf( ioQQQ, "PROBLEM DISASTER conorm: Aperture slit specified, but not predicting luminosity.\n" );
1500  fprintf( ioQQQ, "conorm: Please specify an inner radius to determine L.\nSorry\n" );
1502  }
1503  }
1504  if( geometry.iEmissPower == 0 && radius.lgPredLumin )
1505  {
1506  /* leave Conv2PrtInten at zero if not predicting luminosity */
1507  radius.Conv2PrtInten = 2.;
1508  }
1509 
1510  /* this is option to give final absolute results as flux observed at Earth */
1512  {
1513  /* this implements the conversion from Q_alpha -> F_alpha
1514  * described in the section on the APERTURE command in Hazy 1 */
1515  if( geometry.iEmissPower == 0 )
1516  radius.Conv2PrtInten *= double(geometry.size)/SQAS_SKY;
1517  else if( geometry.iEmissPower == 1 )
1518  radius.Conv2PrtInten *= double(geometry.size)/(PI4*AS1RAD*radius.distance);
1519  else if( geometry.iEmissPower == 2 )
1521  else
1522  TotalInsanity();
1523  }
1524 
1525  /* normally lines are into 4pi, this is option to do per sr or arcsec^2 */
1526  if( prt.lgSurfaceBrightness )
1527  {
1528  if( radius.pirsq != 0. )
1529  {
1530  /* make sure we are predicting line intensities, not luminosity */
1531  fprintf( ioQQQ, " PROBLEM DISASTER Sorry, but both luminosity and surface brightness have been requested for lines.\n" );
1532  fprintf( ioQQQ, " the PRINT LINE SURFACE BRIGHTNESS command can only be used when lines are predicted per unit cloud area.\n" );
1534  }
1536  {
1537  /* we want final units to be per sr */
1538  radius.Conv2PrtInten /= PI4;
1539  }
1540  else
1541  {
1542  /* we want final units to be per square arcsec */
1543  radius.Conv2PrtInten /= SQAS_SKY;
1544  }
1545  }
1546  return;
1547 }
1548 
1549 /*qintr integrates Q for any continuum between two limits, used for normalization */
1550 STATIC double qintr(double qenlo, double qenhi)
1551 {
1552  DEBUG_ENTRY( "qintr()" );
1553 
1554  /* returns LOG of number of photons over energy interval */
1555 
1556  /* this is copy of logic that occurs three times across code */
1557  ASSERT( qenhi > qenlo );
1558  long ipLo = rfield.ipointC( qenlo );
1559  long ipHi = rfield.ipointC( qenhi );
1560  /* this is actual sum of photons within band */
1561  double sum = 0.;
1562  for( long i=ipLo; i < ipHi; i++ )
1563  sum += ffun1(rfield.anu(i))*rfield.widflx(i);
1564 
1565  if( sum <= 0. )
1566  {
1567  fprintf( ioQQQ, " PROBLEM DISASTER Photon number sum in QINTR is %.3e\n",
1568  sum );
1569  fprintf( ioQQQ, " This source has no ionizing radiation, and the number of ionizing photons was specified.\n" );
1570  fprintf( ioQQQ, " This was continuum source number%3ld\n",
1571  rfield.ipSpec );
1572  fprintf( ioQQQ, " Sorry, but I cannot go on. ANU and FLUX arrays follow. Enjoy.\n" );
1573  fprintf( ioQQQ, "\n\n This error is also caused by an old table read file whose energy mesh does not agree with the code.\n" );
1574  for( long i=0; i < rfield.nflux_with_check; i++ )
1575  {
1576  fprintf( ioQQQ, "%.2e\t%.2e\n",
1577  rfield.anu(i),
1578  rfield.flux[0][i] );
1579  }
1581  }
1582 
1583  return log10(sum);
1584 }
1585 
1586 /*pintr integrates L for any continuum between two limits, used for normalization,
1587  * return units are log of ryd cm-2 s-1 */
1588 STATIC double pintr(double penlo, double penhi)
1589 {
1590  DEBUG_ENTRY( "pintr()" );
1591 
1592  /* computes log of luminosity in radiation over some integral
1593  * answer is in Ryd per sec */
1594 
1595  double sum = 0.;
1596  /* >>chng 02 oct 27, do not call qg32, do same type sum as
1597  * final integration */
1598  /* laser is special since delta function, this is center of laser */
1599  /* >>chng 01 jul 01, was +-21 cells, change to call to ipoint */
1600  long ip1 = rfield.ipointC( penlo );
1601  long ip2 = rfield.ipointC( penhi );
1602 
1603  for( long i=ip1; i < ip2; i++ )
1604  sum += ffun1(rfield.anu(i))*rfield.anu(i)*rfield.widflx(i);
1605 
1606  return ( sum > 0. ) ? log10(sum) : -38.;
1607 }
double TEnerDen
Definition: phycon.h:108
realnum * csigh
Definition: rfield.h:271
realnum q
Definition: prt.h:280
bool lgBeamed[LIMSPC]
Definition: rfield.h:296
t_thermal thermal
Definition: thermal.cpp:6
realnum * flux_isotropic
Definition: rfield.h:73
bool lgContinuumLoweringEnabled[NISO]
Definition: iso.h:378
realnum TimeErode
Definition: timesc.h:61
realnum size
Definition: geometry.h:77
qList st
Definition: iso.h:482
double ffun(double anu)
Definition: cont_ffun.cpp:14
double exp10(double x)
Definition: cddefines.h:1383
realnum sv4861
Definition: continuum.h:75
const int ipHE_LIKE
Definition: iso.h:65
void iso_continuum_lower(long ipISO, long nelem)
realnum qtot
Definition: rfield.h:339
long int ipG0_DB96_hi
Definition: rfield.h:250
NORETURN void TotalInsanity(void)
Definition: service.cpp:1067
double widflx(size_t i) const
Definition: mesh.h:147
double EdenHCorr
Definition: dense.h:227
realnum qbal
Definition: rfield.h:339
realnum * flux_beam_const_save
Definition: rfield.h:202
const double BIGDOUBLE
Definition: cpu.h:249
t_opac opac
Definition: opacity.cpp:5
double * ContBoltzAvg
Definition: rfield.h:137
realnum ** flux
Definition: rfield.h:70
t_Heavy Heavy
Definition: heavy.cpp:5
realnum occ1nu
Definition: rfield.h:453
vector< string > chContLabel
Definition: rfield.h:215
const realnum SMALLFLOAT
Definition: cpu.h:246
t_isoCTRL iso_ctrl
Definition: iso.cpp:9
const int NISO
Definition: cddefines.h:310
double totpow[LIMSPC]
Definition: rfield.h:286
long int IonHigh[LIMELM+1]
Definition: dense.h:130
char chRSpec[LIMSPC][5]
Definition: rfield.h:333
realnum ** flux_total_incident
Definition: rfield.h:201
realnum sv1216
Definition: continuum.h:75
char TorF(bool l)
Definition: cddefines.h:753
const int ipOXYGEN
Definition: cddefines.h:355
bool lgOcc1Hi
Definition: rfield.h:461
long int iEmissPower
Definition: geometry.h:71
const double SMALLDOUBLE
Definition: cpu.h:250
bool lgComBug
Definition: trace.h:37
t_hextra hextra
Definition: hextra.cpp:5
bool lgNeutrnHeatOn
Definition: hextra.h:81
double distance
Definition: radius.h:70
realnum qhe
Definition: rfield.h:339
t_phycon phycon
Definition: phycon.cpp:6
long int i2d
Definition: oxy.h:38
realnum fluxv
Definition: continuum.h:80
realnum effneu
Definition: hextra.h:85
double RSFCheck[LIMSPC]
Definition: rfield.h:325
double coll_ion_wrapper(long int z, long int n, double t)
vector< Energy > tNu[LIMSPC]
Definition: rfield.h:316
double ffun1(double xnu)
Definition: cont_ffun.cpp:110
realnum cn4861
Definition: continuum.h:75
sys_float sexp(sys_float x)
Definition: service.cpp:1095
double CosRayIonRate
Definition: ionbal.h:124
long int ipo3exc[3]
Definition: opacity.h:222
t_noexec noexec
Definition: noexec.cpp:4
bool lgTemperatureConstant
Definition: thermal.h:44
void ion_trim_init()
Definition: ion_trim.cpp:34
bool lgHInducImp
Definition: hydrogenic.h:131
long int ipEnerGammaRay
Definition: rfield.h:447
realnum covgeo
Definition: geometry.h:45
realnum pradio
Definition: prt.h:280
FILE * ioQQQ
Definition: cddefines.cpp:7
long ncont[LIMSPC]
Definition: rfield.h:321
double spfac[LIMSPC]
Definition: rfield.h:286
vector< realnum > tslop[LIMSPC]
Definition: rfield.h:317
bool lgTalk
Definition: called.h:12
vector< freeBound > fb
Definition: iso.h:481
#define MIN2(a, b)
Definition: cddefines.h:807
double anu(size_t i) const
Definition: mesh.h:111
void TempChange(double TempNew, bool lgForceUpdate)
Definition: temp_change.cpp:31
bool lgNoExec
Definition: noexec.h:14
realnum ExtinguishEnergyPowerLow
Definition: rfield.h:83
realnum frcneu
Definition: hextra.h:83
t_dense dense
Definition: global.cpp:15
bool lgTimeVary[LIMSPC]
Definition: rfield.h:292
realnum fx1ryd
Definition: prt.h:280
static t_ADfA & Inst()
Definition: cddefines.h:209
double range[LIMSPC][2]
Definition: rfield.h:329
bool lgHabing
Definition: rfield.h:359
t_iso_sp iso_sp[NISO][LIMELM]
Definition: iso.cpp:11
long int nflux_with_check
Definition: rfield.h:51
realnum ExtinguishConvertColDen2OptDepth
Definition: rfield.h:83
realnum SetCsupra
Definition: secondaries.h:45
double xIonDense[LIMELM][LIMELM+1]
Definition: dense.h:135
t_trace trace
Definition: trace.cpp:5
bool fp_equal(sys_float x, sys_float y, int n=3)
Definition: cddefines.h:858
void RT_OTS_Zero(void)
Definition: rt_ots.cpp:571
t_ionbal ionbal
Definition: ionbal.cpp:8
double rinner
Definition: radius.h:31
realnum ExtinguishLeakage
Definition: rfield.h:83
long int ipG0_DB96_lo
Definition: rfield.h:250
t_geometry geometry
Definition: geometry.cpp:5
size_t ipointC(double anu) const
Definition: mesh.h:152
long ipoint(double energy_ryd)
Definition: cont_ipoint.cpp:15
bool lgConBug
Definition: trace.h:97
long int IonLow[LIMELM+1]
Definition: dense.h:129
double slope[LIMSPC]
Definition: rfield.h:286
realnum pbal
Definition: prt.h:280
#define POW2
Definition: cddefines.h:983
realnum tbrmax
Definition: rfield.h:453
const int ipH1s
Definition: iso.h:29
#define STATIC
Definition: cddefines.h:118
bool lgTrace
Definition: trace.h:12
long int ipPlasma
Definition: rfield.h:434
STATIC void extin(realnum *ex1ryd)
t_continuum continuum
Definition: continuum.cpp:6
long int ipCKshell
Definition: opacity.h:310
bool lgSurfaceBrightness
Definition: prt.h:179
realnum qhtot
Definition: rfield.h:339
double EdenTrue
Definition: dense.h:232
t_rfield rfield
Definition: rfield.cpp:9
realnum * flux_time_beam_save
Definition: rfield.h:202
STATIC double pintr(double penlo, double penhi)
realnum * convoc
Definition: rfield.h:115
float realnum
Definition: cddefines.h:124
realnum uh
Definition: rfield.h:347
#define EXIT_FAILURE
Definition: cddefines.h:168
realnum GammaLumin
Definition: prt.h:289
const realnum BIGFLOAT
Definition: cpu.h:244
Illuminate::IlluminationType Illumination[LIMSPC]
Definition: rfield.h:302
realnum uheii
Definition: rfield.h:350
long max(int a, long b)
Definition: cddefines.h:821
bool lgSurfaceBrightness_SR
Definition: prt.h:179
t_hydro hydro
Definition: hydrogenic.cpp:5
#define cdEXIT(FAIL)
Definition: cddefines.h:484
STATIC double qintr(double qenlo, double qenhi)
bool lgRadiusKnown
Definition: radius.h:121
double * ContBoltz
Definition: rfield.h:126
long min(int a, long b)
Definition: cddefines.h:766
double anu2(size_t i) const
Definition: mesh.h:115
realnum * OccNumbIncidCont
Definition: rfield.h:119
vector< string > chLineLabel
Definition: rfield.h:212
char chSpNorm[LIMSPC][5]
Definition: rfield.h:333
realnum cryden
Definition: hextra.h:24
t_radius radius
Definition: radius.cpp:5
t_timesc timesc
Definition: timesc.cpp:7
double anumin(size_t i) const
Definition: mesh.h:139
t_prt prt
Definition: prt.cpp:14
realnum pirsq
Definition: radius.h:148
realnum ** ConEmitOut
Definition: rfield.h:153
bool lgElmtOn[LIMELM]
Definition: dense.h:160
realnum totneu
Definition: hextra.h:79
bool lgPredLumin
Definition: radius.h:144
realnum gas_phase[LIMELM]
Definition: dense.h:76
double Conv2PrtInten
Definition: radius.h:152
const int ipH2p
Definition: iso.h:31
double TotalLumin
Definition: continuum.h:71
realnum xpow
Definition: prt.h:280
#define ASSERT(exp)
Definition: cddefines.h:617
realnum fbeta
Definition: continuum.h:81
double * ContBoltzHelp1
Definition: rfield.h:129
realnum ConstTemp
Definition: thermal.h:56
bool lgCon0
Definition: continuum.h:67
const int ipH_LIKE
Definition: iso.h:64
const int LIMELM
Definition: cddefines.h:307
T pow2(T a)
Definition: cddefines.h:985
void IncidentContinuumHere()
STATIC void sumcon(long int il, long int ih, realnum *q, realnum *p, realnum *panu)
realnum * flux_isotropic_save
Definition: rfield.h:202
#define DEBUG_ENTRY(funcname)
Definition: cddefines.h:729
double powpq(double x, int p, int q)
Definition: service.cpp:726
const int ipHELIUM
Definition: cddefines.h:349
realnum qgam
Definition: prt.h:280
realnum powion
Definition: prt.h:280
realnum ExtinguishColumnDensity
Definition: rfield.h:83
realnum qheii
Definition: rfield.h:339
realnum * csigc
Definition: rfield.h:271
bool lgHionRad
Definition: rfield.h:450
vector< GrainBin * > bin
Definition: grainvar.h:585
realnum EdenHCorr_f
Definition: dense.h:229
double * ContBoltzHelp2
Definition: rfield.h:130
double eden
Definition: dense.h:201
double totlsv
Definition: continuum.h:71
t_oxy oxy
Definition: oxy.cpp:5
bool lgPrintFluxEarth
Definition: prt.h:175
#define MAX2(a, b)
Definition: cddefines.h:828
bool lgCompRecoil
Definition: ionbal.h:150
realnum * ExtinguishFactor
Definition: rfield.h:82
int fprintf(const Output &stream, const char *format,...)
Definition: service.cpp:1217
realnum ** csupra
Definition: secondaries.h:33
realnum OpticalDepthScaleFactor[LIMSPC]
Definition: rfield.h:300
long int ipPlasmax
Definition: rfield.h:434
STATIC void conorm()
double pow(double x, int i)
Definition: cddefines.h:782
double telogn[7]
Definition: phycon.h:86
const int ipCARBON
Definition: cddefines.h:353
long int nShape
Definition: rfield.h:308
long int ipSpec
Definition: rfield.h:308
long int numLevels_max
Definition: iso.h:524
realnum EdenSet
Definition: dense.h:214
double anumax(size_t i) const
Definition: mesh.h:143
realnum occmnu
Definition: rfield.h:453
void EdenChange(double EdenNew)
Definition: eden_change.cpp:11
realnum ** ConEmitReflec
Definition: rfield.h:147
realnum * flux_beam_time
Definition: rfield.h:76
GrainVar gv
Definition: grainvar.cpp:5
t_secondaries secondaries
Definition: secondaries.cpp:5
#define POW3
Definition: cddefines.h:990
void ShowMe(void)
Definition: service.cpp:205
realnum * flux_beam_const
Definition: rfield.h:76
double te
Definition: phycon.h:21
long int i2p
Definition: oxy.h:38
realnum plsfrqmax
Definition: rfield.h:428
realnum qrad
Definition: rfield.h:339
realnum qx
Definition: prt.h:280
const int ipHYDROGEN
Definition: cddefines.h:348
realnum plsfrq
Definition: rfield.h:428
long int nflux
Definition: rfield.h:48
const int ipLITHIUM
Definition: cddefines.h:350
bool lgPlasNu
Definition: rfield.h:426
realnum ** ConRefIncid
Definition: rfield.h:159
long int nPositive
Definition: rfield.h:55
realnum tbr4nu
Definition: rfield.h:453
realnum EdenExtra
Definition: dense.h:217
double getResolutionScaleFactor() const
Definition: mesh.h:92
char chSpType[LIMSPC][6]
Definition: rfield.h:333
t_called called
Definition: called.cpp:4
long int ipHeavy[LIMELM][LIMELM]
Definition: heavy.h:11
realnum cn1216
Definition: continuum.h:75
realnum ExtinguishLowEnergyLimit
Definition: rfield.h:83
long int ** ipCompRecoil
Definition: ionbal.h:156
realnum occmax
Definition: rfield.h:453
void ContSetIntensity()
long int ipeak
Definition: prt.h:288
realnum tbrmnu
Definition: rfield.h:453