cloudy  trunk
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
prt_lines_hydro.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 /*lines_hydro put H-like iso sequence into line intensity stack */
4 #include "cddefines.h"
5 #include "atmdat.h"
6 #include "dense.h"
7 #include "prt.h"
8 #include "hydrogenic.h"
9 #include "iso.h"
10 #include "rfield.h"
11 #include "geometry.h"
12 #include "lines.h"
13 #include "phycon.h"
14 #include "radius.h"
15 #include "secondaries.h"
16 #include "trace.h"
17 #include "two_photon.h"
18 #include "lines_service.h"
19 #include "elementnames.h"
20 
21 static bool isSkipTransSet = false;
22 static vector< vector< pair<long, long> > > skipTrans( LIMELM );
23 
24 /* This loop is identical to the one in lines_hydro() that brings together
25  * the Balmer series, and resets all but one of the fine structure lines
26  * to a zero intensity. */
27 static void collectSkipTrans( void )
28 {
29  long ipISO = ipH_LIKE;
30 
31  for( long nelem=0; nelem < LIMELM; nelem++ )
32  {
33  if( dense.IonHigh[nelem] == nelem + 1 )
34  {
35  vector< pair<long, long> > thisElm_skipTrans;
36 
37  /* bring nL - n'L' emission together as n-n' emission. */
38  for( long ipHi=1; ipHi < iso_sp[ipH_LIKE][nelem].numLevels_max; ipHi++ )
39  {
40  long index_of_nHi_P;
41 
42  /* is ipHi is collapsed level, index_of_nHi_P is ipHi */
43  if( N_(ipHi) > iso_sp[ipH_LIKE][nelem].n_HighestResolved_max )
44  index_of_nHi_P = ipHi;
45  else
46  index_of_nHi_P = iso_sp[ipH_LIKE][nelem].QuantumNumbers2Index[ N_(ipHi) ][1][2];
47 
48  /* only need to consider resolved lower level here */
49  for( long ipLo=0; ipLo < ipHi; ipLo++ )
50  {
51  long index_of_nLo_S = iso_sp[ipH_LIKE][nelem].QuantumNumbers2Index[ N_(ipLo) ][0][2];
52 
53  /* jump out if ipLo is collapsed
54  * NB this must be up to n_HighestResolved_local and not n_HighestResolved_max */
55  if( N_(ipLo) > iso_sp[ipH_LIKE][nelem].n_HighestResolved_local || N_(ipLo) == N_(ipHi) )
56  break;
57 
58  if( iso_sp[ipH_LIKE][nelem].trans(ipHi,ipLo).Emis().Aul() <= iso_ctrl.SmallA )
59  continue;
60 
61  /* add everything into nP - n'S, skip if current indices are those levels. */
62  if( ipHi == index_of_nHi_P && ipLo == index_of_nLo_S )
63  continue;
64  else
65  {
66  thisElm_skipTrans.push_back( pair<long, long>( ipLo, ipHi ) );
67  if( 0 )
68  {
69  fprintf( ioQQQ,
70  "%2s\t index_of_nHi_P= %2ld (%5s)\t index_of_nLo_S= %2ld (%5s)\t"
71  " ipHi= %2ld (%5s)\t ipLo= %2ld (%5s)\t %10g %10g\t Dwl= %g\n",
72  elementnames.chElementSym[ nelem ],
73  index_of_nHi_P,
74  iso_sp[ipISO][nelem].st[index_of_nHi_P].chConfig().c_str(),
75  index_of_nLo_S,
76  iso_sp[ipISO][nelem].st[index_of_nLo_S].chConfig().c_str(),
77  ipHi,
78  iso_sp[ipISO][nelem].st[ipHi].chConfig().c_str(),
79  ipLo,
80  iso_sp[ipISO][nelem].st[ipLo].chConfig().c_str(),
81  iso_sp[ipISO][nelem].trans(index_of_nHi_P,index_of_nLo_S).WLAng(),
82  iso_sp[ipISO][nelem].trans(ipHi,ipLo).WLAng(),
83  iso_sp[ipISO][nelem].trans(index_of_nHi_P,index_of_nLo_S).WLAng() -
84  iso_sp[ipISO][nelem].trans(ipHi,ipLo).WLAng() );
85  }
86  }
87  }
88  }
89  skipTrans[ nelem ] = thisElm_skipTrans;
90  }
91  }
92 
93  isSkipTransSet = true;
94 }
95 
96 static long this_ipLo, this_ipHi;
97 static bool isSkipped( const pair< long, long > level_indices )
98 {
99  return level_indices.first == this_ipLo &&
100  level_indices.second == this_ipHi;
101 }
102 
103 static bool isTransSkipped( long nelem, long ipLo, long ipHi )
104 {
105  this_ipLo = ipLo;
106  this_ipHi = ipHi;
107 
108  vector< pair<long, long> >::iterator sti;
109  sti = find_if( skipTrans[ nelem ].begin(), skipTrans[ nelem ].end(), isSkipped );
110 
111  bool skippedTrans = true;
112  if( sti == skipTrans[ nelem ].end() )
113  skippedTrans = false;
114  return skippedTrans;
115 }
116 
117 string iso_comment_tran_levels( long ipISO, long nelem, long ipLo, long ipHi )
118 {
119  string isoSeq = "H-like, ";
120  if( ipISO == ipHE_LIKE )
121  isoSeq = "He-like, ";
122 
123  return isoSeq + db_comment_tran_levels( ipLo+1, ipHi+1 ) + ", "
124  + GenerateTransitionConfiguration( iso_sp[ipISO][nelem].trans(ipHi,ipLo) );
125 }
126 
127 void lines_hydro(void)
128 {
129  long ipISO = ipH_LIKE;
130  long int i, nelem, ipHi, ipLo;
131  string chLabel=" ";
132 
133  double hbetab,
134  em ,
135  caseb;
136 
137  DEBUG_ENTRY( "lines_hydro()" );
138 
139  if( trace.lgTrace )
140  fprintf( ioQQQ, " lines_hydro called\n" );
141 
142  // this can be changed with the atom levels command but must be at least 3
143  ASSERT( iso_sp[ipH_LIKE][ipHYDROGEN].n_HighestResolved_max >= 3 );
144  ASSERT( iso_sp[ipH_LIKE][ipHELIUM].n_HighestResolved_max >= 3 );
145 
146  i = StuffComment( "H-like iso-sequence" );
147  linadd( 0., (realnum)i , "####", 'i',
148  " start H -like iso sequence ");
149 
150  /*fprintf(ioQQQ," debugg\t%.2e\t%.2e\t%.2e\n",
151  radius.drad,
152  iso_sp[ipH_LIKE][ipHYDROGEN].xLineTotCool ,
153  iso_sp[ipH_LIKE][ipHYDROGEN].cLya_cool);*/
154 
155  /* >>chng 95 jun 25 changed from info to cooling to pick this up in primal.in */
156  linadd(MAX2(0.,iso_sp[ipH_LIKE][ipHYDROGEN].cLya_cool),1215.68,"Cool",'i',
157  "collisionally excited La cooling ");
158 
159  linadd(MAX2(0.,-iso_sp[ipH_LIKE][ipHYDROGEN].cLya_cool),1215.68,"Heat",'i',
160  " collisionally de-excited La heating ");
161 
162  linadd(MAX2(0.,iso_sp[ipH_LIKE][ipHYDROGEN].cLyrest_cool),960,"Crst",'i',
163  " cooling due to n>2 Lyman lines ");
164 
165  linadd(MAX2(0.,-iso_sp[ipH_LIKE][ipHYDROGEN].cLyrest_cool),960,"Hrst",'i',
166  " heating due to n>2 Lyman lines ");
167 
168  linadd(MAX2(0.,iso_sp[ipH_LIKE][ipHYDROGEN].cBal_cool),4861.36,"Crst",'i',
169  " cooling due to n>3 Balmer lines ");
170 
171  linadd(MAX2(0.,-iso_sp[ipH_LIKE][ipHYDROGEN].cBal_cool),4861.36,"Hrst",'i',
172  " heating due to n>3 Balmer lines ");
173 
174  linadd(MAX2(0.,iso_sp[ipH_LIKE][ipHYDROGEN].cRest_cool),0,"Crst",'i',
175  " cooling due to higher Paschen lines ");
176 
177  linadd(MAX2(0.,-iso_sp[ipH_LIKE][ipHYDROGEN].cRest_cool),0,"Hrst",'i',
178  " heating due to higher Paschen lines ");
179 
180  /* remember largest fractional ionization of H due to secondaries */
182 
183  /* remember fraction of H ionizations due to ct */
185 
186  /* remember largest fraction of thermal collisional ionization of H ground state */
187  hydro.HCollIonMax =
189 
190  linadd(secondaries.x12tot*iso_sp[ipH_LIKE][ipHYDROGEN].st[ipH1s].Pop()*1.634e-11,1215.68,"LA X" ,'i',
191  "Lya contribution from suprathermal secondaries from ground ");
192 
193  linadd(MAX2(0.,iso_sp[ipH_LIKE][ipHYDROGEN].coll_ion),0,"CION",'c',
194  "collision ionization cooling of hydrogen ");
195 
196  linadd(MAX2(-iso_sp[ipH_LIKE][ipHYDROGEN].coll_ion,0.),0,"3bHt",'h',
197  " this is the heating due to 3-body recombination ");
198 
199  linadd(MAX2(0.,iso_sp[ipH_LIKE][ipHELIUM].coll_ion),0,"He2C",'c',
200  "collision ionization cooling of He+ ");
201 
202  linadd(MAX2(-iso_sp[ipH_LIKE][ipHELIUM].coll_ion,0.),0,"He2H",'h',
203  " this is the heating due to 3-body recombination onto He+");
204 
205  fixit("why is there a zero here?");
206  linadd(iso_sp[ipH_LIKE][ipHYDROGEN].st[ipH2p].Pop()*0.*iso_sp[ipH_LIKE][ipHYDROGEN].ex[ipH2p][ipH1s].pestrk*1.634e-11,1215.68,"Strk",'i',
207  " Stark broadening contribution to line ");
208 
209  linadd(iso_sp[ipH_LIKE][ipHYDROGEN].st[ipH3s].Pop()*iso_sp[ipH_LIKE][ipHYDROGEN].ex[ipH3s][ipH2p].pestrk*3.025e-12,
210  6562.85,"Strk",'i',
211  " Stark broadening contribution to line ");
212 
213  linadd(iso_sp[ipH_LIKE][ipHYDROGEN].st[ipH4s].Pop()*iso_sp[ipH_LIKE][ipHYDROGEN].ex[ipH4s][ipH2p].pestrk*4.084e-12,
214  4861.36,"Strk",'i',
215  "Stark broadening contribution to line ");
216 
217  linadd(iso_sp[ipH_LIKE][ipHYDROGEN].st[ipH4p].Pop()*iso_sp[ipH_LIKE][ipHYDROGEN].ex[ipH4p][ipH3s].pestrk*1.059e-12,
218  18751,"Strk",'i',
219  " Stark broadening contribution to line ");
220 
221  /* pestrk[5,4] is A[4,5]*pest[4,5]
222  * Stark broadening contribution to line */
223  if( iso_sp[ipH_LIKE][ipHYDROGEN].n_HighestResolved_max >= 5 )
224  {
225  long ip5p = iso_sp[ipH_LIKE][ipHYDROGEN].QuantumNumbers2Index[5][1][2];
226  linadd(iso_sp[ipH_LIKE][ipHYDROGEN].st[ip5p].Pop()*iso_sp[ipH_LIKE][ipHYDROGEN].ex[ip5p][ipH4s].pestrk*4.900e-13,40512,"Strk",'i',
227  "Stark broadening part of line");
228  }
229  /* this can fail if RT_line_all never updates the ots rates, a logic error,
230  * but only assert this during actual calculation (ipass>0), */
231  ASSERT( LineSave.ipass <1 ||
233 
234  linadd(iso_sp[ipH_LIKE][ipHYDROGEN].trans(ipH2p,ipH1s).Emis().ots()*iso_sp[ipH_LIKE][ipHYDROGEN].trans(ipH2p,ipH1s).EnergyErg(), 1215.68,"Dest",'i',
235  " portion of line lost due to absorp by background opacity ");
236 
237  /* portion of line lost due to absorb by background opacity */
238  linadd(iso_sp[ipH_LIKE][ipHYDROGEN].trans(ipH3p,ipH2s).Emis().ots()*iso_sp[ipH_LIKE][ipHYDROGEN].trans(ipH3p,ipH2s).EnergyErg(), 6562.85,"Dest",'i',
239  "Ha destroyed by background opacity");
240 
241  /* portion of line lost due to absorp by background opacity */
242  if( iso_sp[ipH_LIKE][ipHYDROGEN].n_HighestResolved_max >= 5 )
243  {
244  long ip5p = iso_sp[ipH_LIKE][ipHYDROGEN].QuantumNumbers2Index[5][1][2];
245  linadd(iso_sp[ipH_LIKE][ipHYDROGEN].trans(ip5p,ipH4s).Emis().ots()*iso_sp[ipH_LIKE][ipHYDROGEN].trans(ip5p,ipH4s).EnergyErg(),40516, "Dest",'i',
246  "portion of line lost due to absorb by background opacity");
247  }
248 
249  /* portion of line lost due to absorb by background opacity */
250  if( iso_sp[ipH_LIKE][ipHYDROGEN].numLevels_max > ipH4p )
251  linadd(iso_sp[ipH_LIKE][ipHYDROGEN].trans(ipH4p,ipH2s).Emis().ots()*iso_sp[ipH_LIKE][ipHYDROGEN].trans(ipH4p,ipH2s).EnergyErg(), 4861.36,"Dest",'i',
252  "portion of line lost due to absorb by background opacity");
253 
254  /* portion of line lost due to absorb by background opacity */
255  if( iso_sp[ipH_LIKE][ipHYDROGEN].numLevels_max > ipH4p )
256  linadd(iso_sp[ipH_LIKE][ipHYDROGEN].trans(ipH4p,ipH3s).Emis().ots()*iso_sp[ipH_LIKE][ipHYDROGEN].trans(ipH4p,ipH3s).EnergyErg() ,18751, "Dest",'i',
257  "portion of line lost due to absorb by background opacity");
258 
259  linadd(iso_sp[ipH_LIKE][ipHYDROGEN].st[ipH2p].Pop()*iso_sp[ipH_LIKE][ipHYDROGEN].trans(ipH2p,ipH1s).Emis().Aul()*
260  hydro.dstfe2lya*iso_sp[ipH_LIKE][ipHYDROGEN].trans(ipH2p,ipH1s).EnergyErg() , 1215.68 , "Fe 2" , 'i',
261  "Ly-alpha destroyed by overlap with FeII " );
262 
263  linadd(iso_sp[ipH_LIKE][ipHYDROGEN].RadRec_caseB*dense.xIonDense[ipHYDROGEN][1]*dense.eden * 1.64e-11,1215.68,"Ca B",'i',
264  " simple high-density case b intensity of Ly-alpha, no two photon ");
265 
266  /* these entries only work correctly if the APERTURE command is not in effect */
267  if( geometry.iEmissPower == 2 )
268  {
269  /* H-beta computed from Q(H) and specified covering factor */
270  if( nzone == 1 )
271  {
272  /* evaluate the case b emissivity by interpolating on the hummer & storey tables */
273  caseb = rfield.qhtot*
275  /* the atmdat_HS_caseB returned -1 if the physical conditions were outside range of validity.
276  * In this case use simple approximation with no temperature or density dependence */
277  if( caseb < 0 )
278  {
279  caseb = rfield.qhtot*4.75e-13;
280  }
281  LineSave.lines[LineSave.nsum].SumLineZero();
282  }
283  else
284  {
285  caseb = 0.;
286  }
287  /* H-beta computed from Q(H) and specified covering factor */
288  linadd( caseb/radius.dVeffAper*geometry.covgeo , 4861.36 , "Q(H)" , 'i' ,
289  "Case B H-beta computed from Q(H) and specified covering factor");
290 
291  if( nzone == 1 )
292  {
293  // the cast to double prevents an FPE with Solaris Studio 12.4 (limit_compton_hi_t.in)
294  caseb = rfield.qhtot*double(iso_sp[ipH_LIKE][ipHYDROGEN].trans(ipH2p,ipH1s).EnergyErg());
295  LineSave.lines[LineSave.nsum].SumLineZero();
296  }
297  else
298  {
299  caseb = 0.;
300  }
301  /* >>chng 02 nov 05, better approximation for Lya for temperature of first zone */
302  linadd( caseb/radius.dVeffAper*geometry.covgeo , 1215.68 , "Q(H)" , 'i',
303  "Ly-alpha from Q(H), high-dens lim, specified covering factor" );
304  }
305 
306  /* this is the main printout, where line intensities are entered into the stack */
307  for( nelem=ipISO; nelem < LIMELM; nelem++ )
308  {
309  if( dense.lgElmtOn[nelem] )
310  {
311  ASSERT( iso_sp[ipH_LIKE][nelem].n_HighestResolved_max >= 3 );
312 
313  for( ipHi=1; ipHi < iso_sp[ipISO][nelem].numLevels_max; ipHi++ )
314  {
315  for( ipLo=0; ipLo < ipHi; ipLo++ )
316  {
317  if( iso_sp[ipISO][nelem].trans(ipHi,ipLo).Emis().Aul() <= iso_ctrl.SmallA )
318  continue;
319 
320  set_xIntensity( iso_sp[ipISO][nelem].trans(ipHi,ipLo) );
321  }
322  }
323  }
324  }
325 
326  if( ! isSkipTransSet )
327  {
329  }
330 
331  /* create emissivity or intensity for hydrogenic species,
332  * first combine/bring balmer series together */
333  for( nelem=0; nelem < LIMELM; nelem++ )
334  {
335  if( dense.IonHigh[nelem] == nelem + 1 )
336  {
337  /* bring nL - n'L' emission together as n-n' emission. */
338  for( ipHi=1; ipHi < iso_sp[ipH_LIKE][nelem].numLevels_max; ipHi++ )
339  {
340  long index_of_nHi_P;
341 
342  /* is ipHi is collapsed level, index_of_nHi_P is ipHi */
343  if( N_(ipHi) > iso_sp[ipH_LIKE][nelem].n_HighestResolved_max )
344  index_of_nHi_P = ipHi;
345  else
346  index_of_nHi_P = iso_sp[ipH_LIKE][nelem].QuantumNumbers2Index[ N_(ipHi) ][1][2];
347 
348  /* only need to consider resolved lower level here */
349  for( ipLo=0; ipLo < ipHi; ipLo++ )
350  {
351  long index_of_nLo_S = iso_sp[ipH_LIKE][nelem].QuantumNumbers2Index[ N_(ipLo) ][0][2];
352 
353  /* jump out if ipLo is collapsed
354  * NB this must be up to n_HighestResolved_local and not n_HighestResolved_max */
355  if( N_(ipLo) > iso_sp[ipH_LIKE][nelem].n_HighestResolved_local || N_(ipLo) == N_(ipHi) )
356  break;
357 
358  if( iso_sp[ipH_LIKE][nelem].trans(ipHi,ipLo).Emis().Aul() <= iso_ctrl.SmallA )
359  continue;
360 
361  /* add everything into nP - n'S, skip if current indices are those levels. */
362  if( ipHi == index_of_nHi_P && ipLo == index_of_nLo_S )
363  continue;
364  else
365  {
366  /* add resolved line to nP - n'S */
367  iso_sp[ipH_LIKE][nelem].trans(index_of_nHi_P,index_of_nLo_S).Emis().xIntensity() +=
368  iso_sp[ipH_LIKE][nelem].trans(ipHi,ipLo).Emis().xIntensity();
369  iso_sp[ipH_LIKE][nelem].trans(index_of_nHi_P,index_of_nLo_S).Emis().xObsIntensity() +=
370  iso_sp[ipH_LIKE][nelem].trans(ipHi,ipLo).Emis().xObsIntensity();
371  /* zero out the resolved line */
372  iso_sp[ipH_LIKE][nelem].trans(ipHi,ipLo).Emis().xIntensity() = 0;
373  iso_sp[ipH_LIKE][nelem].trans(ipHi,ipLo).Emis().xObsIntensity() = 0;
374  //ASSERT( iso_sp[ipH_LIKE][nelem].trans(index_of_nHi_P,index_of_nLo_S).Emis().xIntensity() >= 0. );
375  //ASSERT( iso_sp[ipH_LIKE][nelem].trans(index_of_nHi_P,index_of_nLo_S).Emis().xObsIntensity() >= 0. );
376  }
377  }
378  }
379  }
380  }
381 
382  /* H beta recombination, assuming old case B */
383  hbetab = (double)((exp10(-20.89 - 0.10612*POW2(phycon.alogte - 4.4)))/
384  phycon.te);
385  /* need to pass this assert if CaBo is to have valid array indices for ipCont */
386  /* 06 aug 28, from numLevels_max to _local. */
387  /* 06 dec 21, change from numLevels_max to _local was mistake for this entire file. Undo. */
388  ASSERT( iso_sp[ipH_LIKE][ipHYDROGEN].numLevels_max > 4 );
389  hbetab *= dense.xIonDense[ipHYDROGEN][1]*dense.eden;
390 
391  lindst(hbetab, -4861.36 ,"CaBo",
392  1 ,'i',false,
393  " this is old case b based on Ferland (1980) PASP ");
394 
395  if( dense.lgElmtOn[ipHELIUM] )
396  {
397  /* need to pass this assert if CaBo is to have valid array indices for ipCont */
398  /* 06 aug 28, from numLevels_max to _local. */
399  /* 06 dec 21, change from numLevels_max to _local was mistake for this entire file. Undo. */
400  ASSERT( iso_sp[ipH_LIKE][ipHELIUM].numLevels_max > 4 );
401  /* 1640 1640 1640 */
402  em = 2.03e-20/(phycon.te70*phycon.te10*phycon.te03);
403  em *= dense.xIonDense[ipHELIUM][2]*dense.eden;
404 
405  lindst(em,-1640,"CaBo",
406  1,'i',false,
407  " old prediction of He II 1640, Case B at low densities");
408 
409  /* hydrogenic helium */
410  /* old prediction of He II 4686, case B */
411  em = 2.52e-20/(pow(phycon.te,1.05881));
412  em *= dense.xIonDense[ipHELIUM][2]*dense.eden;
413 
414  lindst(em,-4686.01,"CaBo", 1,'i',false,
415  " old prediction of He II 4686, Case B at low densities");
416  }
417 
418  /* predict case b intensities of hydrogen lines */
419  if( LineSave.ipass <= 0 )
420  {
421  for(nelem=0; nelem<HS_NZ; ++nelem )
422  {
423  atmdat.lgHCaseBOK[0][nelem] = true;
424  atmdat.lgHCaseBOK[1][nelem] = true;
425  }
426  }
427  /* this is the main printout, where line intensities are entered into the stack */
428  for( nelem=0; nelem < LIMELM; nelem++ )
429  {
430  if( dense.lgElmtOn[nelem] )
431  {
432  /* HS_NZ is limit to charge of elements in HS predictions, now 8 == oxygen */
433  /* but don't do the minor elements, Li, Be, B - these were not read in and so should not be
434  * printed - remove equivalent if statement in atmdat_readin.cpp to read them in */
435  if( nelem < HS_NZ && (nelem<2 || nelem>4) )
436  {
437  int iCase;
438  for( iCase=0; iCase<2; ++iCase )
439  {
440  char chAB[2]={'A','B'};
441  char chLab[5]="Ca ";
442 
443  /* adding iCase means start from n=1 for case A, n=2 for Case B,
444  * note that principal quantum number is on physics scale, not C */
445  /* 06 aug 28, both of these from numLevels_max to _local. */
446  /* 06 dec 21, change from numLevels_max to _local was mistake for this entire file. Undo. */
447  /* HS data file extends to ipHi == atmdat.ncut[iCase][nelem]==25, report all possible values for comparisons */
448  for( ipLo=1+iCase; ipLo<MIN2(atmdat.ncut[iCase][nelem]-1,iso_sp[ipH_LIKE][nelem].n_HighestResolved_max + iso_sp[ipH_LIKE][nelem].nCollapsed_max); ++ipLo )
449  {
450  for( ipHi=ipLo+1; ipHi< MIN2(atmdat.ncut[iCase][nelem],iso_sp[ipH_LIKE][nelem].n_HighestResolved_max + iso_sp[ipH_LIKE][nelem].nCollapsed_max+1); ++ipHi )
451  {
452  realnum wl;
453  double case_b_Intensity;
454  long int ipCHi , ipCLo;
455  /* Put case b predictions into line stack
456  * NB NB NB each Hummer & Storey case b line must be
457  * explicitly clobbered by hand in routine final if
458  * atmdat.lgHCaseBOK[iCase][nelem] flag is set false
459  * since this indicates that we exceeded bounds of table,
460  * DO NOT want to print lines in that case */
461 
462  /* first do case b emissivity of balmer lines */
463 
464  /* get HS predictions */
465  case_b_Intensity = atmdat_HS_caseB( ipHi,ipLo , nelem+1, phycon.te , dense.eden, chAB[iCase] );
466  if( case_b_Intensity<=0. )
467  {
468  atmdat.lgHCaseBOK[iCase][nelem] = false;
469  case_b_Intensity = 0.;
470  }
471 
472  case_b_Intensity *= dense.xIonDense[nelem][nelem+1-ipISO]*dense.eden;
473 
474  if( iCase==0 && ipLo==1 )
475  {
476  /* get physical scal prin quant numbers onto cloudy c scale */
477  ipCHi = ipHi;
478  ipCLo = 0;
479  }
480  else
481  {
482  /* get physical scal prin quant numbers onto cloudy c scale */
483  ipCHi = ipHi;
484  ipCLo = ipLo;
485  }
486 
487  /* make label either Ca A or Ca B */
488  chLab[3] = chAB[iCase];
489 
490  /* new treatment is different from old for indices greater than 2. */
491  if( ipCHi > 2 )
492  {
493  if( ipCLo > 2 )
494  {
495  /* if both indices above two, just treat as nP to n'S transition. */
496  ipCHi = iso_sp[ipH_LIKE][nelem].QuantumNumbers2Index[ipCHi][1][2];
497  ipCLo = iso_sp[ipH_LIKE][nelem].QuantumNumbers2Index[ipCLo][0][2];
498  }
499  else if( ipCLo == 2 )
500  {
501  /* treat as nS to 2P transition. */
502  ipCHi = iso_sp[ipH_LIKE][nelem].QuantumNumbers2Index[ipCHi][0][2];
503  }
504  else if( ipCLo == 1 || ipCLo == 0 )
505  {
506  /* treat as nP to n'S transition. */
507  ipCHi = iso_sp[ipH_LIKE][nelem].QuantumNumbers2Index[ipCHi][1][2];
508  }
509  }
510 
511  /* this is wavelength of interpolated case b from HS tables */
512  wl = iso_sp[ipH_LIKE][nelem].trans(ipCHi,ipCLo).WLAng();
513  atmdat.WaveLengthCaseB[nelem][ipHi][ipLo] = wl;
514 
515  lindst(case_b_Intensity,wl,chLab,iso_sp[ipH_LIKE][nelem].trans(ipCHi,ipCLo).ipCont(),'i',false,
516  " case a or case b from Hummer & Storey tables" );
517  }
518  }
519  }
520  }
521 
522  // add two-photon details here
523  if( LineSave.ipass == 0 )
524  {
525  /* chIonLbl is function that generates a null terminated 4 char string, of form "C 2"
526  * the result, chLable, is only used when ipass == 0, can be undefined otherwise */
527  chLabel = chIonLbl(nelem+1, nelem+1-ipISO);
528  }
529  for( vector<two_photon>::iterator tnu = iso_sp[ipH_LIKE][nelem].TwoNu.begin(); tnu != iso_sp[ipH_LIKE][nelem].TwoNu.end(); ++tnu )
530  {
531  fixit("This was multiplied by Pesc when treated as a line, now what? Only used for printout?");
532  fixit("below should be 'i' instead of 'r' ?");
533 
534  string tpc_comment = "",
535  tpe_comment = "";
536  if( LineSave.ipass == 0 )
537  {
538  string comment_trans = iso_comment_tran_levels( ipISO, nelem, ipH1s, ipH2s );
539  tpc_comment = " two photon continuum, " + comment_trans;
540  tpe_comment = " induced two photon emission, " + comment_trans;
541  }
542  linadd( tnu->AulTotal * tnu->E2nu * EN1RYD * (*tnu->Pop),
543  0, chLabel.c_str(), 'r', tpc_comment.c_str() );
544 
545  linadd( tnu->induc_dn * tnu->E2nu * EN1RYD * (*tnu->Pop),
546  22, chLabel.c_str() ,'i', tpe_comment.c_str() );
547  }
548 
549  /* NB NB - low and high must be in this order so that all balmer, paschen,
550  * etc series line up correctly in final printout */
551  for( ipLo=ipH1s; ipLo < iso_sp[ipH_LIKE][nelem].numLevels_max-1; ipLo++ )
552  {
553  /* don't bother with decays to 2p since we set them to zero above */
554  if( ipLo==ipH2p )
555  continue;
556 
557  /* set number of levels we want to print, first is default,
558  * only print real levels, second is set with "print line
559  * iso collapsed" command */
560  long int nLoop = iso_sp[ipH_LIKE][nelem].numLevels_max - iso_sp[ipH_LIKE][nelem].nCollapsed_max;
561  if( prt.lgPrnIsoCollapsed )
562  nLoop = iso_sp[ipH_LIKE][nelem].numLevels_max;
563 
564  for( ipHi=ipLo+1; ipHi < nLoop; ipHi++ )
565  {
566  // skip non-radiative transitions
567  if( iso_sp[ipH_LIKE][nelem].trans(ipHi,ipLo).ipCont() < 1 )
568  continue;
569 
570  // skip 2s-1s, so that 2p-1s comes first and cdLine finds LyA instead of the M2 transition.
571  if( ipHi==1 && ipLo==0 )
572  continue;
573 
574  if( isTransSkipped( nelem, ipLo, ipHi ) )
575  continue;
576 
577  string comment_trans = "";
578  if( LineSave.ipass == 0 )
579  {
580  comment_trans = iso_comment_tran_levels( ipISO, nelem, ipLo, ipHi );
581  }
582  PutLine(iso_sp[ipH_LIKE][nelem].trans(ipHi,ipLo), comment_trans.c_str());
583  }
584  }
585  }
586  }
587 
588  if( trace.lgTrace )
589  {
590  fprintf( ioQQQ, " lines_hydro returns\n" );
591  }
592  return;
593 }
594 
realnum x12tot
Definition: secondaries.h:65
realnum WaveLengthCaseB[8][25][24]
Definition: atmdat.h:355
double & ots() const
Definition: emission.h:678
t_atmdat atmdat
Definition: atmdat.cpp:6
string chIonLbl(const TransitionProxy &t)
Definition: transition.cpp:230
realnum EnergyErg() const
Definition: transition.h:90
qList st
Definition: iso.h:482
double te03
Definition: phycon.h:58
double exp10(double x)
Definition: cddefines.h:1383
const int ipHE_LIKE
Definition: iso.h:65
realnum H_ion_frac_collis
Definition: hydrogenic.h:125
double RadRec_caseB
Definition: iso.h:544
t_isoCTRL iso_ctrl
Definition: iso.cpp:9
long int IonHigh[LIMELM+1]
Definition: dense.h:130
void set_xIntensity(const TransitionProxy &t)
void lindst(double xEmiss, realnum wavelength, const char *chLab, long int ipnt, char chInfo, bool lgOutToo, const char *chComment)
long int iEmissPower
Definition: geometry.h:71
long int nCollapsed_max
Definition: iso.h:518
realnum HCollIonMax
Definition: hydrogenic.h:122
t_phycon phycon
Definition: phycon.cpp:6
t_LineSave LineSave
Definition: lines.cpp:9
long int ncut[2][HS_NZ]
Definition: atmdat.h:337
string iso_comment_tran_levels(long ipISO, long nelem, long ipLo, long ipHi)
static void collectSkipTrans(void)
realnum covgeo
Definition: geometry.h:45
bool lgHCaseBOK[2][HS_NZ]
Definition: atmdat.h:342
static bool isSkipTransSet
FILE * ioQQQ
Definition: cddefines.cpp:7
long int nzone
Definition: cddefines.cpp:14
double HIonFracMax
Definition: atmdat.h:317
#define MIN2(a, b)
Definition: cddefines.h:807
vector< LinSv > lines
Definition: lines.h:132
realnum SecHIonMax
Definition: secondaries.h:42
t_dense dense
Definition: global.cpp:15
t_elementnames elementnames
Definition: elementnames.cpp:5
t_iso_sp iso_sp[NISO][LIMELM]
Definition: iso.cpp:11
realnum SmallA
Definition: iso.h:391
double xIonDense[LIMELM][LIMELM+1]
Definition: dense.h:135
t_trace trace
Definition: trace.cpp:5
t_geometry geometry
Definition: geometry.cpp:5
bool lgPrnIsoCollapsed
Definition: prt.h:195
vector< two_photon > TwoNu
Definition: iso.h:598
long int n_HighestResolved_max
Definition: iso.h:536
#define POW2
Definition: cddefines.h:983
const int ipH1s
Definition: iso.h:29
realnum sec2total
Definition: secondaries.h:39
bool lgTrace
Definition: trace.h:12
static bool isSkipped(const pair< long, long > level_indices)
void lines_hydro(void)
double & xIntensity() const
Definition: emission.h:528
EmissionList::reference Emis() const
Definition: transition.h:447
static vector< vector< pair< long, long > > > skipTrans(LIMELM)
LinSv * linadd(double xEmiss, realnum wavelength, const char *chLab, char chInfo, const char *chComment)
#define N_(A_)
Definition: iso.h:22
realnum qhtot
Definition: rfield.h:339
t_rfield rfield
Definition: rfield.cpp:9
float realnum
Definition: cddefines.h:124
const int ipH4p
Definition: iso.h:36
string GenerateTransitionConfiguration(const TransitionProxy &t)
Definition: transition.cpp:309
t_hydro hydro
Definition: hydrogenic.cpp:5
double atmdat_HS_caseB(long int iHi, long int iLo, long int iZ, double TempIn, double DenIn, char chCase)
static bool isTransSkipped(long nelem, long ipLo, long ipHi)
const int ipH3s
Definition: iso.h:32
t_radius radius
Definition: radius.cpp:5
multi_arr< long, 3 > QuantumNumbers2Index
Definition: iso.h:490
t_prt prt
Definition: prt.cpp:14
bool lgElmtOn[LIMELM]
Definition: dense.h:160
TransitionProxy trans(const long ipHi, const long ipLo)
Definition: iso.h:473
char chElementSym[LIMELM][CHARS_ELEMENT_SYM]
Definition: elementnames.h:25
const int ipH2p
Definition: iso.h:31
static long this_ipLo
#define HS_NZ
Definition: atmdat.h:267
void PutLine(const TransitionProxy &t, const char *chComment, const char *chLabelTemp, const ExtraInten &extra)
Definition: transition.cpp:315
#define ASSERT(exp)
Definition: cddefines.h:617
const int ipH2s
Definition: iso.h:30
const int ipH_LIKE
Definition: iso.h:64
const int LIMELM
Definition: cddefines.h:307
string db_comment_tran_levels(long ipLoFile, long ipHiFile)
Definition: atmdat.h:515
realnum dstfe2lya
Definition: hydrogenic.h:96
#define DEBUG_ENTRY(funcname)
Definition: cddefines.h:729
const int ipHELIUM
Definition: cddefines.h:349
double te10
Definition: phycon.h:58
double eden
Definition: dense.h:201
double HIonFrac
Definition: atmdat.h:314
#define MAX2(a, b)
Definition: cddefines.h:828
static long this_ipHi
int fprintf(const Output &stream, const char *format,...)
Definition: service.cpp:1217
double te70
Definition: phycon.h:58
double & xObsIntensity() const
Definition: emission.h:533
const int ipH4s
Definition: iso.h:35
double alogte
Definition: phycon.h:92
double pow(double x, int i)
Definition: cddefines.h:782
long int numLevels_max
Definition: iso.h:524
long int nsum
Definition: lines.h:87
#define fixit(a)
Definition: cddefines.h:416
t_secondaries secondaries
Definition: secondaries.cpp:5
double te
Definition: phycon.h:21
const int ipHYDROGEN
Definition: cddefines.h:348
const int ipH3p
Definition: iso.h:33
realnum & WLAng() const
Definition: transition.h:468
long int ipass
Definition: lines.h:96
double dVeffAper
Definition: radius.h:92
long int StuffComment(const char *chComment)
Definition: prt_final.cpp:1943