29 const long int ipISO,
const long int nelem);
32 void iso_level(
const long int ipISO,
const long int nelem,
double &renorm,
47 double HighestPColOut = 0.;
49 static vector<int32> ipiv;
50 ipiv.resize(numlevels_local);
52 double source=0., sink=0.;
53 static vector<double> PopPerN;
88 fprintf(
ioQQQ,
" iso_level iso=%2ld nelem=%2ld simple II/I=%10.2e so not doing equilibrium, doing %s.\n",
95 for(
long n=1; n < numlevels_local; n++ )
104 static vector<double> creation, error, work, Save_creation;
105 creation.resize(numlevels_local);
106 error.resize(numlevels_local);
107 work.resize(numlevels_local);
108 Save_creation.resize(numlevels_local);
111 for( level=0; level < numlevels_local; level++ )
114 creation[level] = sp->
fb[level].RateCont2Level *
dense.
xIonDense[nelem][nelem+1-ipISO];
117 double ctsource=0.0, ctsink=0.0, ctrec=0.0;
165 z.
alloc(numlevels_local,numlevels_local);
171 long SpinUsed[
NISO] = {2,1};
178 fprintf(
ioQQQ,
" iso_level iso=%2ld nelem=%2ld doing regular matrix inversion, %s\n",
184 static vector<double> Boltzmann_overg;
185 Boltzmann_overg.resize(numlevels_local-1);
186 for (
unsigned lev = 0; lev < Boltzmann_overg.size(); ++lev)
187 Boltzmann_overg[lev] = 1.0/(
double)StElm[lev].g();
192 static vector<double> coll_down, RadDecay, pump;
193 coll_down.resize(numlevels_local);
194 RadDecay.resize(numlevels_local);
195 pump.resize(numlevels_local);
198 for( level=1; level < numlevels_local; level++ )
200 fixit(
"Wouldn't need to mask this out if levels were in order");
203 vexp( arg.ptr0(), bstep.
ptr0(), 1, numlevels_local );
207 enum { DEBUG_RATES =
false };
210 fprintf( stdout,
"# ipISO\tnelem\tlevel\tcollDown\tcollIonz\tradRecom\tRadDecay\n" );
213 for( level=0; level < numlevels_local; level++ )
215 double coll_down_total = 0.;
219 z[level][level] += sp->
fb[level].RateLevel2Cont;
223 for ( ipLo = 0; ipLo < level; ++ipLo )
224 Boltzmann_overg[ipLo] *= bstep[level];
228 for( ipLo=0; ipLo < level; ipLo++ )
233 coll_down_total += coll_down[ipLo];
251 for( ipLo=0; ipLo < level; ipLo++ )
253 coll_down[ipLo] *= sp->
ex[level][ipLo].ErrorFactor[
IPCOLLIS];
254 RadDecay[ipLo] *= sp->
ex[level][ipLo].ErrorFactor[
IPRAD];
255 pump[ipLo] *= sp->
ex[level][ipLo].ErrorFactor[
IPRAD];
259 double glev = (double)StElm[level].g(), rglev = 1.0/glev;
260 for( ipLo=0; ipLo < level; ipLo++ )
262 double coll_up = coll_down[ipLo] * glev *
263 Boltzmann_overg[ipLo];
265 z[ipLo][ipLo] += coll_up + pump[ipLo] ;
266 z[ipLo][level] -= coll_up + pump[ipLo] ;
268 double pump_down = pump[ipLo] *
269 (double)StElm[ipLo].g() * rglev;
271 z[level][level] += RadDecay[ipLo] + pump_down + coll_down[ipLo];
272 z[level][ipLo] -= RadDecay[ipLo] + pump_down + coll_down[ipLo];
273 if( level == indexNmaxP )
275 HighestPColOut += coll_down[ipLo];
277 if( ipLo == indexNmaxP )
279 HighestPColOut += coll_up;
283 if( (level == 1) && (ipLo==0) )
287 if( (ipLo == 1) && (ipISO==
ipH_LIKE || StElm[level].S()==1) )
305 1. /
iso_sp[ipISO][nelem].
st[level].lifetime() );
317 if( HighestPColOut < 1./sp->st[indexNmaxP].lifetime() )
325 for( vector<two_photon>::iterator tnu = sp->
TwoNu.begin(); tnu != sp->
TwoNu.end(); ++tnu )
331 fixit(
"need Pesc or the equivalent to multiply AulTotal?");
333 z[tnu->ipHi][tnu->ipLo] -= tnu->AulTotal;
334 z[tnu->ipHi][tnu->ipHi] += tnu->AulTotal;
340 for( vector<two_photon>::iterator tnu = sp->
TwoNu.begin(); tnu != sp->
TwoNu.end(); ++tnu )
346 z[tnu->ipHi][tnu->ipLo] -= tnu->induc_dn;
347 z[tnu->ipHi][tnu->ipHi] += tnu->induc_dn;
350 z[tnu->ipLo][tnu->ipHi] -= tnu->induc_up;
351 z[tnu->ipLo][tnu->ipLo] += tnu->induc_up;
358 if( ion!=nelem-ipISO )
373 sink +=
mole.
sink[nelem][nelem-ipISO];
395 for( level=0; level < numlevels_local; level++ )
412 if( ion_from == nelem-1-ipISO )
423 creation[0] += source;
436 for ( level = 0; level < numlevels_local; level++ )
441 for( level=0; level < numlevels_local; level++ )
443 creation[level] += source*
445 z[level][level] += sink;
448 creation[0] += ctsource;
455 for( level=1; level < numlevels_local; level++ )
457 double RateUp , RateDown;
460 RateDown = RateUp * (double)sp->
st[
ipH1s].g() /
461 (double)sp->
st[level].g();
467 z[level][
ipH1s] -= RateDown;
470 z[
ipH1s][level] -= RateUp;
472 z[level][level] += RateDown;
484 for( ipLo=0; ipLo < numlevels_local; ipLo++ )
485 Save_creation[ipLo] = creation[ipLo];
489 const long numlevels_print = numlevels_local;
491 for(
long n=0; n < numlevels_print; n++ )
494 for(
long j=0; j < numlevels_print; j++ )
500 fprintf(
ioQQQ,
" recomb ct %.2e co %.2e hectr %.2e hctr %.2e\n",
506 for(
long n=0; n < numlevels_print; n++ )
516 valarray<double> c(
get_ptr(creation), creation.size() );
523 z.
data(),numlevels_local,&ipiv[0],&nerror);
526 &creation[0],numlevels_local,&nerror);
530 fprintf(
ioQQQ,
" iso_level: dgetrs finds singular or ill-conditioned matrix\n" );
536 for( level=
ipH1s; level < numlevels_local; level++ )
538 double qn = 0., qx = 0.;
540 for(
long n=
ipH1s; n < numlevels_local; n++ )
542 double q = SaveZ[n][level]*creation[n];
558 error[level] = (error[level] - Save_creation[level])/qx;
570 for( level=
ipH1s; level < numlevels_local; level++ )
573 abserror = fabs( error[level]);
575 if( abserror > BigError )
584 if( BigError > FLT_EPSILON )
590 " iso_level zone %.2f - largest residual in iso=%li %s nelem=%li matrix inversion is %g "
591 "level was %li Search?%c \n",
606 for ( level = 0; level < numlevels_local; level++ )
611 for ( level = 0; level < numlevels_local; level++ )
613 creation[level] = sp->
st[level].
Boltzmann()*sp->
st[level].g()*scale;
617 for( level = numlevels_local-1; level > 0; --level )
620 if( creation[level] < 0. )
629 for( level = 1; level < numlevels_local; ++level )
630 creation[level] = 0.;
637 for( level=0; level < numlevels_local; level++ )
639 ASSERT( creation[level] >= 0. );
640 sp->
st[level].Pop() = creation[level];
645 "PROBLEM non-positive level pop for iso = %li, nelem = "
646 "%li = %s, level=%li val=%.3e nTotalIoniz %li\n",
651 sp->
st[level].Pop() ,
657 for( level=numlevels_local; level < sp->
numLevels_max; level++ )
659 sp->
st[level].Pop() = 0.;
668 double TotalPopExcited = 0.;
670 for( level=1; level < numlevels_local; level++ )
671 TotalPopExcited += sp->
st[level].Pop();
672 ASSERT( TotalPopExcited >= 0. );
673 double TotalPop = TotalPopExcited + sp->
st[0].Pop();
682 for( level=0; level < numlevels_local; level++ )
683 sp->
st[level].Pop() *=
703 " DISASTER iso_level finds negative ion fraction for iso=%2ld nelem=%2ld "
704 "%s using solver %s, IonFrac=%.3e simple=%.3e TE=%.3e ZONE=%4ld\n",
715 for( i=0; i < numlevels_local; i++ )
726 for( ipHi=1; ipHi<numlevels_local; ++ipHi )
728 for( ipLo=0; ipLo<ipHi; ++ipLo )
735 sp->
st[ipLo].Pop() - sp->
st[ipHi].Pop()*
736 sp->
st[ipLo].g()/sp->
st[ipHi].g();
745 for( ipHi=numlevels_local; ipHi < sp->
numLevels_max; ++ipHi )
747 for( ipLo=0; ipLo<ipHi; ++ipLo )
774 const long int ipISO,
const long int nelem)
782 for(
long n=2; n <= nMax; ++n )
792 for(
long ipLo=0; ipLo < ipHi; ++ipLo )
795 MultOpacs[ sp->
st[ipHi].n() ][ sp->
st[ipLo].n() ] += tr.
Emis().
PopOpc() *
803 for(
long ipLo=0; ipLo < ipHi; ++ipLo )
818 double TotalPop = 0.;
820 for(
long level=0; level < numlevels_local; level++ )
825 sp->
st[level].Pop() * sp->
fb[level].RateLevel2Cont;
826 TotalPop += sp->
st[level].Pop();
831 fprintf(
ioQQQ,
"DISASTER RateIonizTot for Z=%li, ion %li is larger than BIGDOUBLE. This is a big problem.",
832 nelem+1, nelem-ipISO);
855 ratio = rateOutOf2TripS /
realnum & opacity() const
void getrs_wrapper(char trans, long N, long nrhs, double *A, long lda, int32 *ipiv, double *B, long ldb, int32 *info)
bool lgIsoTraceFull[NISO]
void prtRates(const long nlevels_local, const multi_arr< double, 2, C_TYPE > &a, valarray< double > &b)
long int IonHigh[LIMELM+1]
bool lgTimeDependentStatic
long int ipIsoTrace[NISO]
molezone * findspecieslocal(const char buf[])
t_elementnames elementnames
t_iso_sp iso_sp[NISO][LIMELM]
void vexp(const double x[], double y[], long nlo, long nhi)
double xIonDense[LIMELM][LIMELM+1]
long int n_HighestResolved_local
double CharExcRecTotal[NCX]
double CharExcIonTotal[NCX]
bool fp_equal(sys_float x, sys_float y, int n=3)
void iso_multiplet_opacities(void)
ColliderList colliders(dense)
vector< two_photon > TwoNu
long int n_HighestResolved_max
long int IonLow[LIMELM+1]
void getrf_wrapper(long M, long N, double *A, long lda, int32 *ipiv, int32 *info)
double energy(const genericState &gs)
double frac_he0dest_23S_photo
EmissionList::reference Emis() const
realnum rate_lu_nontherm() const
realnum *** xMoleChTrRate
realnum GetDopplerWidth(realnum massAMU)
char chElementNameShort[LIMELM][CHARS_ELEMENT_NAME_SHORT]
multi_arr< long, 3 > QuantumNumbers2Index
bool lgCritDensLMix[NISO]
TransitionProxy trans(const long ipHi, const long ipLo)
char chElementSym[LIMELM][CHARS_ELEMENT_SYM]
double *** CollIonRate_Ground
realnum AtomicWeight[LIMELM]
multi_arr< extra_tr, 2 > ex
STATIC void iso_multiplet_opacities_one(const long int ipISO, const long int nelem)
void reserve(size_type i1)
CollisionProxy Coll() const
double & mult_opac() const
#define DEBUG_ENTRY(funcname)
void iso_renorm(long nelem, long ipISO, double &renorm)
double RateIonizTot(long nelem, long ion) const
int fprintf(const Output &stream, const char *format,...)
sys_float SDIV(sys_float x)
char chElementName[LIMELM][CHARS_ELEMENT_NAME]
double CharExcIonOf[NCX][LIMELM][LIMELM+1]
realnum GrainChTrRate[LIMELM][LIMELM+1][LIMELM+1]
double CharExcRecTo[NCX][LIMELM][LIMELM+1]
void iso_set_ion_rates(long ipISO, long nelem)
double ColUL(const ColliderList &colls) const
void iso_level(const long ipISO, const long nelem, double &renorm, bool lgPrtMatrix)