cloudy  trunk
dense.cpp
Go to the documentation of this file.
1 /* This file is part of Cloudy and is copyright (C)1978-2013 by Gary J. Ferland and
2  * others. For conditions of distribution and use see copyright notice in license.txt */
3 #include "cddefines.h"
4 
5 #include "dense.h"
6 
7 #include "abund.h"
8 #include "colden.h"
9 #include "conv.h"
10 #include "dynamics.h"
11 #include "elementnames.h"
12 #include "deuterium.h"
13 #include "hmi.h"
14 #include "h2.h"
15 #include "mole.h"
16 #include "mole_priv.h"
17 #include "phycon.h"
18 #include "prt.h"
19 #include "radius.h"
20 #include "struc.h"
21 #include "thermal.h"
22 #include "trace.h"
23 
25 
27 {
29 }
30 
32 {
33  for (long nelem=ipHYDROGEN; nelem < LIMELM; ++nelem)
34  m_xMolecules[nelem] = 0.f;
35 }
36 
38 {
39  double edensave = dense.eden;
40 
41  for( long nelem=ipHYDROGEN; nelem < LIMELM; ++nelem )
42  {
43  if (dense.lgElmtOn[nelem])
44  {
45  ScaleIonDensities( nelem, factor );
46  dense.SetGasPhaseDensity( nelem, dense.gas_phase[nelem] * factor);
47  }
48  }
49 
50  EdenChange( dense.eden * factor );
51 
52  if( trace.lgTrace && trace.lgNeBug )
53  {
54  fprintf( ioQQQ, " EDEN change PressureChange from to %10.3e %10.3e %10.3e\n",
55  edensave, dense.eden, edensave/dense.eden );
56  }
57 
58  hmi.H2_total *= factor;
59  h2.ortho_density *= factor;
60  h2.para_density *= factor;
61  for( long mol=0; mol < mole_global.num_total; mol++ )
62  {
63  mole.species[mol].den *= factor;
64  }
66 
68 }
69 
70 void ScaleIonDensities( const long nelem, const realnum factor )
71 {
72  double renorm;
73  for( long ion=0; ion < (nelem + 2); ion++ )
74  {
75  dense.xIonDense[nelem][ion] *= factor;
76  if (nelem-ion >= 0 && nelem-ion < NISO)
77  iso_renorm(nelem, nelem-ion, renorm);
78  }
79 
80  if( nelem==ipHYDROGEN && deut.lgElmtOn )
81  ScaleDensitiesDeuterium( factor );
82 
83  return;
84 }
85 
86 void t_dense::SetGasPhaseDensity( const long nelem, const realnum density )
87 {
88  gas_phase[nelem] = density;
89 
90  if( nelem==ipHYDROGEN && deut.lgElmtOn )
91  {
92  // fractionation is taken care of inside called routine
93  SetGasPhaseDeuterium( density );
94  }
95 
96  return;
97 }
98 
99 bool lgElemsConserved (void)
100 {
101  bool lgOK=true;
102 
103  /* this checks all molecules and ions add up to abundance */
104  for( ChemAtomList::iterator atom = atom_list.begin(); atom != atom_list.end(); ++atom )
105  {
106  long nelem = (*atom)->el->Z-1;
107  /* check that species add up if element is turned on */
108  if( dense.lgElmtOn[nelem] )
109  {
110  /* this sum of over the molecules did not include the atom and first
111  * ion that is calculated in the molecular solver */
112  double sum_monatomic = 0.;
113  for( long ion=0; ion<nelem+2; ++ion )
114  {
115  sum_monatomic += dense.xIonDense[nelem][ion] * (*atom)->frac;
116  }
117  realnum sum_molecules = dense.xMolecules(nelem) * (*atom)->frac;
118  realnum sum_gas_phase = dense.gas_phase[nelem] * (*atom)->frac;
119  if( sum_monatomic + sum_molecules <= SMALLFLOAT &&
120  sum_gas_phase > SMALLFLOAT)
121  {
122  fprintf(ioQQQ,"PROBLEM non-conservation of nuclei %s\tions %g moles %g error %g of %g\n",
123  (*atom)->label().c_str(),
124  sum_monatomic,
125  sum_molecules,
126  sum_monatomic + sum_molecules-sum_gas_phase,
127  sum_gas_phase );
128  lgOK=false;
129  }
130 
131  /* check that sum agrees with total gas phase abundance */
135  if( fabs( sum_monatomic + sum_molecules - sum_gas_phase ) >
136  conv.GasPhaseAbundErrorAllowed * sum_gas_phase )
137  {
138  fprintf(ioQQQ,"PROBLEM non-conservation of nuclei %s\t nzone %li atoms %.12e moles %.12e sum %.12e tot gas %.12e rel err %.3e\n",
139  (*atom)->label().c_str(),
140  nzone,
141  sum_monatomic,
142  sum_molecules,
143  sum_monatomic + sum_molecules,
144  sum_gas_phase,
145  (sum_monatomic + sum_molecules - sum_gas_phase)/sum_gas_phase );
146  lgOK=false;
147  }
148 
149  if( 0 )
150  {
151  // print reactions involving the neutral
153  }
154  }
155  }
156 
157  return lgOK;
158 }
159 
160 void lgStatesConserved ( long nelem, long ionStage, qList states, long numStates, realnum err_tol, long loop_ion )
161 {
162  if( 0 && conv.lgConvIoniz() &&
163  dense.lgElmtOn[nelem] &&
164  dense.xIonDense[nelem][ionStage]/dense.eden > conv.EdenErrorAllowed/10. &&
165  dense.xIonDense[nelem][ionStage] > SMALLFLOAT )
166  {
167  double abund = 0.;
168  for (long ipLev=0; ipLev<numStates; ipLev++)
169  {
170  abund += states[ipLev].Pop();
171  }
172 
173  double rel_err = fabs(abund-dense.xIonDense[nelem][ionStage])/
174  SDIV(dense.xIonDense[nelem][ionStage]);
175 
176  //fprintf(ioQQQ,"Iso consistency error %ld %ld %g\n",nelem,ionStage,rel_err);
177 
178  if( rel_err > err_tol )
179  {
180  /* we'll set the flag for non-convergence, but don't bother complaining in printout for first sweeps */
181  if( 0 && nzone > 0 && loop_ion > 0 )
182  {
183  fprintf(ioQQQ,"PROBLEM Inconsistent states/stage pops nzone %3ld loop_ion %2ld nelem %2ld ion %2ld states = %e stage = %e error = %e\n",
184  nzone,
185  loop_ion,
186  nelem,
187  ionStage,
188  abund,
189  dense.xIonDense[nelem][ionStage],
190  rel_err );
191  }
192  char chConvIoniz[INPUT_LINE_LENGTH];
193  sprintf( chConvIoniz , "States!=stage pops nelem %ld ion %ld ", nelem, ionStage );
194  conv.setConvIonizFail( chConvIoniz, abund,
195  dense.xIonDense[nelem][ionStage] );
196  }
197  }
198 }
199 
200 void SumDensities( void )
201 {
202  realnum den_mole,
203  DenseAtomsIons;
204 
205  /* find total number of atoms and ions */
206  DenseAtomsIons = 0.;
207  for( long nelem=ipHYDROGEN; nelem<LIMELM; ++nelem )
208  {
209  if( dense.lgElmtOn[nelem] )
210  {
211  for( long ion=0; ion<=nelem+1; ++ion )
212  DenseAtomsIons += dense.xIonDense[nelem][ion];
213  }
214  }
215 
216  /* DensElements is sum of all gas-phase densities of all elements,
217  * DenseAtomsIons is sum of density of atoms and ions, does not
218  * include molecules */
219  ASSERT( DenseAtomsIons > 0. );
220 
221  /* find number of molecules of the heavy elements in the gas phase.
222  * Atoms and ions were counted above. Do not include ices, solids
223  * on grains */
224  den_mole = total_molecules_gasphase();
225 
226  /* total number of atoms, ions, and molecules in gas phase per unit vol */
227  dense.xNucleiTotal = den_mole + DenseAtomsIons;
228  if( dense.xNucleiTotal > BIGFLOAT )
229  {
230  fprintf(ioQQQ, "PROBLEM DISASTER SumDensities has found "
231  "dense.xNucleiTotal with an insane density.\n");
232  fprintf(ioQQQ, "The density was %.2e\n",
234  TotalInsanity();
235  }
236  ASSERT( dense.xNucleiTotal > 0. );
237 
238  /* particle density that enters into the pressure includes electrons
239  * cm-3 */
241 
242  /* dense.wmole is molecular weight, AtomicMassUnit per particle */
243  dense.wmole = 0.;
244  for( long i=0; i < LIMELM; i++ )
245  {
247  }
248  /* dense.wmole is now molecular weight, AtomicMassUnit per particle */
249  dense.wmole /= dense.pden;
250  ASSERT( dense.wmole > 0. && dense.pden > 0. );
251 
252  /* xMassDensity is density in grams per cc */
256 
257  /*>>chng 04 may 25, introduce following test on xMassDensity0
258  * WJH 21 may 04, this is the mass density that corresponds to the hden
259  * specified in the init file. It is used to calculate the mass flux in the
260  * dynamics models. It may not necessarily be the same as struc.DenMass[0],
261  * since the pressure solver may have jumped to a different density at the
262  * illuminated face from that specified.*/
263  if( dense.xMassDensity0 < 0.0 )
265 
266  return;
267 }
268 
269 bool AbundChange( )
270 {
271  DEBUG_ENTRY( "AbundChange()" );
272 
273  fixit(); // Breaks conservation if molecular abundance is finite
274 
275  // Suggested improved procedure:
276  // 1. Scale all molecules by the scaling for their most restrictive constituent
277  // 2. dense.updateXMolecules();
278  // 3. Scale ionic species so as to maintain conservation
279  // This will probably lead to material being dumped into the ionic species,
280  // but this should slosh back at the next molecular network solve. This
281  // procedure is at least a) conservative; b) consistent with the pure-ion case.
282 
283  /* this will be set true if density or abundances change in this zone */
284  bool lgChange = false;
285 
286  /* >>chng 97 jun 03, added variable abundances for element table command
287  * option to get abundances off a table with element read command */
288  if( abund.lgAbTaON )
289  {
290  lgChange = true;
291  for( long nelem=1; nelem < LIMELM; nelem++ )
292  {
293  if( abund.lgAbunTabl[nelem] )
294  {
295  double abun = AbundancesTable(radius.Radius,radius.depth,nelem+1)*
297 
298  double hold = abun/dense.gas_phase[nelem];
299  dense.SetGasPhaseDensity( nelem, (realnum)abun );
300 
301  for( long ion=0; ion < (nelem + 2); ion++ )
302  {
303  dense.xIonDense[nelem][ion] *= (realnum)hold;
304  }
305  }
306  }
307  }
308 
309  /* this is set false if fluctuations abundances command entered,
310  * when density variations are in place this is true,
311  * and dense.chDenseLaw is "SINE" */
312  double FacAbun = 1.;
313  if( !dense.lgDenFlucOn )
314  {
315  static double FacAbunSav;
316  double OldAbun = 0.0;
317  /* abundance variations are in place */
318  lgChange = true;
319  if( nzone > 1 )
320  {
321  OldAbun = FacAbunSav;
322  }
323 
324  /* rapid abundances fluctuation */
325  if( dense.lgDenFlucRadius )
326  {
327  /* cycle over radius */
328  FacAbunSav = dense.cfirst*cos(radius.depth*dense.flong+
330  }
331  else
332  {
333  /* cycle over column density */
334  FacAbunSav = dense.cfirst*cos( colden.colden[ipCOL_HTOT]*dense.flong+
336  }
337 
338  if( nzone > 1 )
339  {
340  FacAbun = FacAbunSav/OldAbun;
341  }
342  }
343 
344  if( FacAbun != 1. )
345  {
346  ASSERT(!dynamics.lgAdvection); // Local abundance change doesn't make sense with advective transport
347 
348  /* Li on up is affect by abundance variations */
349  for( long nelem=ipLITHIUM; nelem < LIMELM; nelem++ )
350  {
351  if (dense.lgElmtOn[nelem])
352  {
353  dense.SetGasPhaseDensity(nelem, dense.gas_phase[nelem] * (realnum) FacAbun);
354  ScaleIonDensities( nelem, (realnum)(FacAbun) );
355  }
356  }
357 
358  for( long mol=0; mol < mole_global.num_total; mol++ )
359  {
360  mole.species[mol].den *= (realnum)(FacAbun);
361  }
362  }
363 
364  if (lgChange)
365  {
366  /* must call TempChange since ionization has changed, there are some
367  * terms that affect collision rates (H0 term in electron collision) */
368  TempChange(phycon.te , false);
369  }
370 
371  return lgChange;
372 }
373 
374 namespace {
375  const int SCALE_NEW = 1;
376 }
377 
379 {
380  if (SCALE_NEW)
382  else
383  return dense.gas_phase[ipHYDROGEN];
384 }
386 {
387  if (SCALE_NEW)
389  else
390  return struc.hden[i];
391 }
colden.h
thermal.h
t_dense::pden
realnum pden
Definition: dense.h:98
h2
diatomics h2("h2", 4100., &hmi.H2_total, Yan_H2_CS)
t_dense::eden
double eden
Definition: dense.h:190
struc.h
dense
t_dense dense
Definition: dense.cpp:24
elementnames.h
t_dynamics::lgAdvection
bool lgAdvection
Definition: dynamics.h:60
t_dense::m_xMolecules
realnum m_xMolecules[LIMELM]
Definition: dense.h:80
t_deuterium::lgElmtOn
bool lgElmtOn
Definition: deuterium.h:19
ioQQQ
FILE * ioQQQ
Definition: cddefines.cpp:7
elementnames
t_elementnames elementnames
Definition: elementnames.cpp:5
TempChange
void TempChange(double TempNew, bool lgForceUpdate)
Definition: temp_change.cpp:51
t_dense::flcPhase
realnum flcPhase
Definition: dense.h:254
realnum
float realnum
Definition: cddefines.h:103
t_abund::lgAbunTabl
bool lgAbunTabl[LIMELM]
Definition: abund.h:70
conv.h
t_dense::xMassDensity0
realnum xMassDensity0
Definition: dense.h:95
t_conv::EdenErrorAllowed
double EdenErrorAllowed
Definition: conv.h:267
ipLITHIUM
const int ipLITHIUM
Definition: cddefines.h:307
ScaleIonDensities
void ScaleIonDensities(const long nelem, const realnum factor)
Definition: dense.cpp:70
t_dense::csecnd
realnum csecnd
Definition: dense.h:253
mole.h
abund.h
t_conv::setConvIonizFail
void setConvIonizFail(const char *reason, double oldval, double newval)
Definition: conv.h:107
t_dense::lgElmtOn
bool lgElmtOn[LIMELM]
Definition: dense.h:146
phycon
t_phycon phycon
Definition: phycon.cpp:6
trace.h
t_conv::GasPhaseAbundErrorAllowed
realnum GasPhaseAbundErrorAllowed
Definition: conv.h:285
t_dense::zero
void zero()
Definition: dense.cpp:31
t_dense::updateXMolecules
void updateXMolecules()
Definition: dense.cpp:26
SDIV
sys_float SDIV(sys_float x)
Definition: cddefines.h:952
mole_print_species_reactions
void mole_print_species_reactions(molecule *speciesToPrint)
Definition: newton_step.cpp:316
t_dense::gas_phase
realnum gas_phase[LIMELM]
Definition: dense.h:71
t_radius::depth
double depth
Definition: radius.h:38
dynamics.h
diatomics::ortho_density
double ortho_density
Definition: h2_priv.h:319
ASSERT
#define ASSERT(exp)
Definition: cddefines.h:578
t_hmi::H2_total
double H2_total
Definition: hmi.h:16
struc
t_struc struc
Definition: struc.cpp:6
t_abund::lgAbTaON
bool lgAbTaON
Definition: abund.h:76
ipHYDROGEN
const int ipHYDROGEN
Definition: cddefines.h:305
AbundancesTable
double AbundancesTable(double r0, double depth, long int iel)
Definition: abundances.cpp:460
total_molecule_elems
void total_molecule_elems(realnum total[LIMELM])
Definition: mole_species.cpp:1063
t_dense::flong
realnum flong
Definition: dense.h:251
ATOMIC_MASS_UNIT
const UNUSED double ATOMIC_MASS_UNIT
Definition: physconst.h:88
nzone
long int nzone
Definition: cddefines.cpp:14
radius
t_radius radius
Definition: radius.cpp:5
t_conv::lgConvIoniz
bool lgConvIoniz() const
Definition: conv.h:115
dense.h
mole
t_mole_local mole
Definition: mole.cpp:7
trace
t_trace trace
Definition: trace.cpp:5
cddefines.h
lgStatesConserved
void lgStatesConserved(long nelem, long ionStage, qList states, long numStates, realnum err_tol, long loop_ion)
Definition: dense.cpp:160
qList
Definition: quantumstate.h:40
scalingZoneDensity
realnum scalingZoneDensity(long i)
Definition: dense.cpp:385
ScaleAllDensities
void ScaleAllDensities(realnum factor)
Definition: dense.cpp:37
t_struc::DenMass
realnum * DenMass
Definition: struc.h:49
t_radius::Radius
double Radius
Definition: radius.h:25
t_mole_global::num_total
int num_total
Definition: mole.h:314
TotalInsanity
NORETURN void TotalInsanity(void)
Definition: service.cpp:886
diatomics::para_density
double para_density
Definition: h2_priv.h:321
t_elementnames::chElementSym
char chElementSym[LIMELM][CHARS_ELEMENT_SYM]
Definition: elementnames.h:25
EdenChange
void EdenChange(double EdenNew)
Definition: eden_change.cpp:12
radius.h
colden
t_colden colden
Definition: colden.cpp:5
deut
t_deuterium deut
Definition: deuterium.cpp:8
t_struc::hden
realnum * hden
Definition: struc.h:45
t_dense::xMassDensity
realnum xMassDensity
Definition: dense.h:91
t_dense::xMolecules
realnum xMolecules(long nelem)
Definition: dense.h:83
ScaleDensitiesDeuterium
void ScaleDensitiesDeuterium(const realnum &factor)
Definition: deuterium.cpp:10
AbundChange
bool AbundChange()
Definition: dense.cpp:269
hmi.h
t_colden::colden
realnum colden[NCOLD]
Definition: colden.h:38
iso_renorm
void iso_renorm(long nelem, long ipISO, double &renorm)
Definition: iso_solve.cpp:272
LIMELM
const int LIMELM
Definition: cddefines.h:258
BIGFLOAT
const UNUSED realnum BIGFLOAT
Definition: cpu.h:189
t_dense::wmole
realnum wmole
Definition: dense.h:101
t_dense::xIonDense
double xIonDense[LIMELM][LIMELM+1]
Definition: dense.h:125
abund
t_abund abund
Definition: abund.cpp:5
prt.h
INPUT_LINE_LENGTH
const int INPUT_LINE_LENGTH
Definition: cddefines.h:254
t_dense::AtomicWeight
realnum AtomicWeight[LIMELM]
Definition: dense.h:75
total_molecules_gasphase
realnum total_molecules_gasphase(void)
Definition: mole_species.cpp:1124
hmi
t_hmi hmi
Definition: hmi.cpp:5
dynamics
t_dynamics dynamics
Definition: dynamics.cpp:44
t_dense::xNucleiTotal
realnum xNucleiTotal
Definition: dense.h:104
conv
t_conv conv
Definition: conv.cpp:5
findspecies
molecule * findspecies(const char buf[])
Definition: mole_species.cpp:814
fixit
void fixit(void)
Definition: service.cpp:991
ipCOL_HTOT
#define ipCOL_HTOT
Definition: colden.h:12
t_dense::lgDenFlucRadius
bool lgDenFlucRadius
Definition: dense.h:248
SumDensities
void SumDensities(void)
Definition: dense.cpp:200
t_dense::cfirst
realnum cfirst
Definition: dense.h:252
t_mole_local::species
valarray< class molezone > species
Definition: mole.h:398
lgElemsConserved
bool lgElemsConserved(void)
Definition: dense.cpp:99
phycon.h
atom_list
ChemAtomList atom_list
Definition: mole_species.cpp:71
t_trace::lgNeBug
bool lgNeBug
Definition: trace.h:115
t_dense::lgDenFlucOn
bool lgDenFlucOn
Definition: dense.h:244
t_dense::SetGasPhaseDensity
void SetGasPhaseDensity(const long nelem, const realnum density)
Definition: dense.cpp:86
mole_priv.h
scalingDensity
realnum scalingDensity(void)
Definition: dense.cpp:378
h2.h
SetGasPhaseDeuterium
void SetGasPhaseDeuterium(const realnum &Hdensity)
Definition: deuterium.cpp:69
t_phycon::te
double te
Definition: phycon.h:11
NISO
const int NISO
Definition: cddefines.h:261
mole_global
t_mole_global mole_global
Definition: mole.cpp:6
t_dense
Definition: dense.h:29
DEBUG_ENTRY
#define DEBUG_ENTRY(funcname)
Definition: cddefines.h:684
t_trace::lgTrace
bool lgTrace
Definition: trace.h:12
SMALLFLOAT
const realnum SMALLFLOAT
Definition: cpu.h:191
deuterium.h