43 static double MIN_CONV_FRAC=1e-4;
56 for (
long ion = 0; ion <= nelem+1; ++ion)
70 bool lgConverg_v =
false;
83 double abundold=0. , abundnew=0.;
106 for(
long ion=0; ion <= (nelem+1); ++ion )
109 if( OldFracs[nelem][ion]/Abund > MIN_CONV_FRAC &&
115 OldFracs[nelem][ion];
116 change =
MAX2(change, one );
118 if( change>bigchange )
121 abundold = OldFracs[nelem][ion]/Abund;
130 if( change >= delta )
135 ASSERT( abundold>0. && abundnew>0. );
143 for(
long ion=0; ion <= (nelem+1); ++ion )
153 fprintf(
ioQQQ,
" nz %ld loop %ld element %li converged? %c worst %ld change %g\n",
154 nzone, loop_ion, nelem,
TorF(lgConverg_v),ionchg,bigchange);
155 for(
long ion=0; ion<(nelem+1); ++ion )
165 double dground(
long nelem,
long ion)
168 if( ! ( nelem >=
ipHYDROGEN && nelem < LIMELM &&
169 ion >= 0 && ion <= nelem+1 ) )
172 "ERROR: Invalid ionization stage in dground()."
173 " nelem= %ld\t ion= %ld\n",
177 long ipISO = nelem - ion;
178 if (ipISO >= 0 && ipISO <
NISO)
179 return iso_sp[ipISO][nelem].
st[0].Pop();
199 static double SecondOld;
200 static long int nzoneOTS=-1;
201 const int LOOP_ION_LIMIT = 10;
203 static double SumOTS=0. , OldSumOTS[2]={0.,0.};
205 long int oldIonRange[
LIMELM][2];
207 IonizConverg lgIonizConverg;
211 bool lgIonizWidened =
false;
215 static double wide_te_used = -1.;
216 static long int nZoneIonizWidenCalled = 0;
218 bool lgWiden = ( nZoneIonizWidenCalled !=
nzone ||
223 nZoneIonizWidenCalled =
nzone;
225 lgIonizWidened =
true;
241 # if !defined(NDEBUG)
298 for(
long nelem=ipISO; nelem<
LIMELM;++nelem )
303 save_iso_grnd[ipISO][nelem] =
iso_sp[ipISO][nelem].
st[0].Pop();
319 " ConvBase called. %.2f Te:%.3e HI:%.3e HII:%.3e H2:%.3e Ne:%.3e htot:%.3e CSUP:%.2e Conv?%c\n",
371 static long int nZoneIonizTrimCalled = 0;
374 nZoneIonizTrimCalled = 0;
382 bool lgIonizTrimCalled =
false;
402 lgIonizTrimCalled =
true;
413 nZoneIonizTrimCalled =
nzone;
417 # if !defined(NDEBUG)
471 (*diatom)->CalcPhotoionizationRate();
482 double xIonDense0[nconv][
LIMELM][LIMELM+1];
483 double xIonDense_prev[
LIMELM][LIMELM+1];
485 for (
long nelem=0; nelem <
LIMELM; ++nelem)
489 lgOscill[nelem] =
false;
536 for (
long ion = 0; ion <= nelem+1; ++ion)
538 xIonDense_prev[nelem][ion] = xIonDense0[0][nelem][ion];
544 bool lgShortCircuit =
false;
545 for( ion_loop=0; ion_loop<nconv && !lgShortCircuit; ++ion_loop)
553 for (
long ion = 0; ion <= nelem+1; ++ion)
562 for (
long nhi=0; nhi<
LIMELM; ++nhi)
563 netion[nlo][nhi] = 0.0;
577 long nlo =
MIN2(nelem, n2);
578 long nhi =
MAX2(nelem, n2);
579 if (nlo >= t_atmdat::NCX)
582 double dl1 = dground(nlo,0);
583 double ul1 = dground(nlo,1);
584 double dl2 = dground(nhi,0);
585 double ul2 = dground(nhi,1);
591 netion[nlo][nhi] += hion;
595 netion[nlo][nhi] -= hion;
609 for (
long nhi = nlo+1; nhi <
LIMELM; ++nhi)
613 double dl1 = dground(nlo,0);
614 double ul1 = dground(nlo,1);
615 double dl2 = dground(nhi,0);
616 double ul2 = dground(nhi,1);
622 bool lgCheckAll =
false;
624 fabs(netion[nlo][nhi]) > ion_cmp && ul1*ul2 > 1e-8*dl1*dl2 )
628 <<
" CX inconsistency";
636 bool lgCanShortCircuit = (ion_loop+1 < nconv);
637 for(
long nelem=
ipHYDROGEN; nelem<LIMELM && lgCanShortCircuit; ++nelem )
644 double x0 = xIonDense0[ion_loop][nelem][ion];
648 lgCanShortCircuit =
false;
653 lgShortCircuit = lgCanShortCircuit;
663 double tot0 = 0., tot1 = 0.;
664 double xIonNew[LIMELM+1];
665 for (
long ion = 0; ion <= nelem+1; ++ion)
667 double x0 = xIonDense0[nconv-2][nelem][ion];
668 double x1 = xIonDense0[nconv-1][nelem][ion];
676 double step0 = x1-
x0, step1 = x2-
x1, abs1 = fabs(step1);
678 if ( abs1 > 1000.0*((
double)DBL_EPSILON)*x2 )
680 double denom = fabs(step1-step0);
681 double sgn = (step1*step0 > 0)? 1.0 : -1.0;
684 const double MAXACC=100.0;
685 double extfac = 1.0/(denom/abs1 + 1.0/MAXACC);
686 double extstep = sgn*extfac*step1;
688 double predict = x2+extstep;
690 xIonNew[ion] = predict;
693 fprintf(
ioQQQ,
"Extrap %3ld %3ld %13.6g %13.6g %13.6g %13.6g %13.6g %13.6g\n",
695 x0,x0-xIonDense0[nconv-3][nelem][ion],x1-x0,x2-x1,extstep,predict);
697 tot1 += xIonNew[ion];
701 double scal = tot0/tot1;
702 for (
long ion = 0; ion <= nelem+1; ++ion)
708 long ion = nelem-ipISO;
726 bool lgPostExtrapSolve =
true;
727 if (lgPostExtrapSolve)
746 for (
long ion = 0; ion <= nelem+1; ++ion)
752 long ion = nelem-ipISO;
783 vector<const molecule*>debug_list;
794 for (
long ion = 0; ion <= nelem+1; ++ion)
797 (xIonDense0[0][nelem][ion]-xIonDense_prev[nelem][ion]) < 0)
799 lgOscill[nelem] =
true;
820 bool lgPopsConverged =
true;
821 double old_val, new_val;
822 (*diatom)->H2_LevelPops( lgPopsConverged, old_val, new_val );
823 if( !lgPopsConverged )
839 static double OldDeut[2] = {0., 0.};
840 for(
long ion=0; ion<2; ++ion )
860 for(
long nelem=ipISO; nelem<
LIMELM; ++nelem )
891 if ( loop_ion == 0 && lgIonizWidened )
907 " ConvBase4 ionization driver loop_ion %li converged? %c reason not converged %s\n" ,
951 OldSumOTS[0] = OldSumOTS[1];
952 OldSumOTS[1] = SumOTS;
979 if( (OldSumOTS[0]-OldSumOTS[1]) * ( OldSumOTS[1] - SumOTS ) < 0. )
1001 enum {DEBUG_LOC=
false};
1002 if( DEBUG_LOC && (
nzone>110) )
1032 bool lgCheckEsc =
false;
1083 hminus_old = hminus_den;
1116 " ConvBase return. fnzone %.2f nPres2Ioniz %li Te:%.3e HI:%.3e HII:%.3e H2:%.3e Ne:%.3e htot:%.3e CSUP:%.2e Conv?%c reason:%s\n",
1140 fprintf(
ioQQQ,
" PROBLEM ConvBase sets lgAbort since nPres2Ioniz exceeds limPres2Ioniz. ");
1143 fprintf(
ioQQQ,
" Reset this limit with the SET PRES IONIZ command.\n");
1181 (EdenFromMolecOld-EdenFromGrainsOld),
1219 for(
long nelem=ipISO; nelem<
LIMELM;++nelem )
1227 if( fabs(
iso_sp[ipISO][nelem].st[0].Pop()-save_iso_grnd[ipISO][nelem])/
SDIV(
iso_sp[ipISO][nelem].st[0].Pop())-1. >
1231 sprintf( chConvIoniz,
"iso %2li %2li",ipISO, nelem );
1233 save_iso_grnd[ipISO][nelem],
1234 iso_sp[ipISO][nelem].st[0].Pop());
1258 fprintf(
ioQQQ ,
"ABORT flag set since STOP nTotalIoniz was set and reached.\n");
1266 static int iter_punch=-1;
1273 "%li\t%.4e\t%.4e\t%.4e\n",
1288 for(
long nelem=0; nelem<
LIMELM; ++nelem )
1290 for(
long ion=0; ion<nelem+1; ++ion )
1304 ionbal.
UTA_heat_rate[(*UTALines[i].Hi()).nelem()-1][(*UTALines[i].Hi()).IonStg()-1] += rateone*UTALines[i].Coll().heat();
1308 enum {DEBUG_LOC=
false};
1312 fprintf(
ioQQQ,
"DEBUG UTA %3i %3i %.3f %.2e %.2e %.2e\n",
1313 (*UTALines[i].Hi()).nelem() , (*UTALines[i].Hi()).IonStg() , UTALines[i].WLAng() ,
1314 rateone, UTALines[i].Coll().heat(),
1315 UTALines[i].Coll().heat()*
dense.
xIonDense[(*UTALines[i].Hi()).nelem()-1][(*UTALines[i].Hi()).IonStg()-1] );
1328 fixit(
"lgNetEdenSrcSmall needs to be enabled");
1333 fixit(
"grain rates not well tested below");
1339 double ionsrc = 0., ionsnk = 0.;
1340 for(
long nelem=0; nelem <
LIMELM; ++nelem )
1346 for(
long ion_from = 0; ion_from <= nelem + 1; ++ion_from )
1348 for(
long ion_to = 0; ion_to <= nelem + 1; ++ion_to )
1350 if( ion_to-ion_from > 0 )
1355 else if( ion_to-ion_from < 0 )
1364 const double totsrc = ionsrc +
mole.
species[ipMElec].src;
1366 const double diff = (totsrc - totsnk);
1367 const double ave = ( fabs(totsrc) + fabs(totsnk) )/2.;
1368 fixit(
"Need to tighten up e- population convergence criterion");
1369 const double error_allowed = 0.05 * ave;
1370 if( fabs(diff) > error_allowed )
1372 enum {DEBUG_LOC=
false};
1375 fprintf(
ioQQQ,
"PROBLEM large NetEdenSrc nzone %li\t%e\t%e\t%e\t%e\n",
1377 totsrc/
SDIV(totsnk),
void ion_trim(long int nelem)
t_mole_global mole_global
void RT_OTS_Update(double *SumOTS)
void DumpLine(const TransitionProxy &t)
void CoolSave(FILE *io, const char chJob[])
TransitionList UTALines("UTALines",&AnonStates)
bool lgFirstSweepThisZone
ConvergenceCounter register_(const string name)
void ion_widen(long nelem)
long int IonHigh[LIMELM+1]
void RT_OTS_PrtRate(double weak, int chFlag)
bool lgTimeDependentStatic
STATIC bool lgNetEdenSrcSmall(void)
double ChargTranSumHeat(void)
void CoolEvaluate(double *tot)
char chHashString[INPUT_LINE_LENGTH]
bool lgTemperatureConstant
molezone * findspecieslocal(const char buf[])
void RT_line_all_escape(realnum *error)
void lgStatesConserved(long nelem, long ionStage, qList states, long numStates, realnum err_tol, long loop_ion)
void mole_save(FILE *punit, const char speciesname[], const char args[], bool lgHeader, bool lgData, bool lgCoef, double depth)
t_elementnames elementnames
t_iso_sp iso_sp[NISO][LIMELM]
void PresTotCurrent(void)
STATIC void ion_trim_from_set(long nelem)
double xIonDense[LIMELM][LIMELM+1]
bool fp_equal(sys_float x, sys_float y, int n=3)
void iso_multiplet_opacities(void)
void iso_collapsed_update(void)
const char * chConvIoniz() const
FILE * ipTraceConvergeBase
long int IonLow[LIMELM+1]
molecule * findspecies(const char buf[])
double ** UTA_ionize_rate
void OpacityAddTotal(void)
valarray< class molezone > species
realnum IonizErrorAllowed
const int INPUT_LINE_LENGTH
vector< diatomics * > diatoms
void ion_recom_calculate(void)
void iso_solve(long ipISO, long nelem, double &maxerr)
realnum HeatCoolRelErrorAllowed
void iso_update_rates(void)
char chElementSym[LIMELM][CHARS_ELEMENT_SYM]
realnum gas_phase[LIMELM]
void mole_update_sources(void)
void SetDeuteriumIonization(const double &xNeutral, const double &xIonized)
void mole_dominant_rates(const vector< const molecule * > &debug_list, FILE *ioOut, bool lgPrintReagents, size_t NPRINT, double fprint)
#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,...)
void ion_wrapper(long nelem)
sys_float SDIV(sys_float x)
void setConvIonizFail(const char *reason, double oldval, double newval)
bool lgElemsConserved(void)
t_secondaries secondaries
bool lgTraceConvergeBaseHash
double CharExcIonOf[NCX][LIMELM][LIMELM+1]
void ion_trim_validate(long nelem, bool lgIonizTrimCalled)
realnum GrainChTrRate[LIMELM][LIMELM+1][LIMELM+1]
double CharExcRecTo[NCX][LIMELM][LIMELM+1]
void ion_trim2(long int nelem, long int oldIonRange[2])
vector< diatomics * >::iterator diatom_iter
const bool lgConvBaseHeatTest