40 STATIC double TempInterp(
double* TempArray,
double* ValueArray,
long NumElements,
double temp );
46 double alpha,RecomIntegral=0.,b,E1,E2,step,OldRecomIntegral,TotChangeLastFive;
47 double change[5] = {0.,0.,0.,0.,0.};
49 DEBUG_ENTRY(
"iso_radrecomb_from_cross_section()" );
57 b = MILNE_CONST *
iso_sp[ipISO][nelem].
st[ipLo].g() *
powpq(temp,-3,2);
65 kTRyd = temp / TE1RYD;
91 OldRecomIntegral = RecomIntegral;
96 change[4] = change[3];
97 change[3] = change[2];
98 change[2] = change[1];
99 change[1] = change[0];
100 change[0] = (RecomIntegral - OldRecomIntegral)/RecomIntegral;
101 TotChangeLastFive = change[0] + change[1] + change[2] + change[3] + change[4];
109 alpha = b * RecomIntegral;
151 long ipFirstCollapsed, LastN=0L, ThisN=1L, ipLevel;
152 double topoff, TotMinusExplicitResolved,
153 TotRRThisN=0., TotRRLastN=0., Total_DR_Added=0.;
154 double RecExplictLevels, TotalRadRecomb, RecCollapsed;
156 {0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,
157 0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,
158 0.,0.,0.,0.,0.,0.,0.,0.,0.,0.},
159 {0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,
160 0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,
161 0.,0.,0.,0.,0.,0.,0.,0.,0.,0.}};
171 RecExplictLevels = 0.;
176 ASSERT( ipFirstCollapsed ==
iso_sp[ipISO][nelem].numLevels_local -
iso_sp[ipISO][nelem].nCollapsed_local );
181 for( ipLevel=0; ipLevel<ipFirstCollapsed; ++ipLevel )
206 Total_DR_Added +=
iso_sp[ipISO][nelem].
fb[ipLevel].DielecRecomb;
230 Total_DR_Added +=
iso_sp[ipISO][nelem].
fb[ipLevel].DielecRecomb;
235 iso_sp[ipISO][nelem].
fb[ipLevel].DielecRecomb = 0.;
240 if(
N_(ipLevel) == ThisN )
249 TotRRLastN = TotRRThisN;
255 enum {DEBUG_LOC=
false};
257 static long RUNONCE =
false;
259 if( !RUNONCE && DEBUG_LOC )
261 static long FIRSTTIME =
true;
265 fprintf(
ioQQQ,
"Sum of Radiative Recombination at current iso, nelem, temp = %li %li %.2f\n",
278 if(
iso_sp[ipISO][nelem].lgLevelsLowered )
282 TotalRadRecomb +=
iso_sp[ipISO][nelem].fb[ipLevel].RadRecomb[
ipRecRad];
290 TotalRadRecomb = RecCollapsed + RecExplictLevels;
298 for(
long nLo = NHYDRO_MAX_LEVEL; nLo<=
SumUpToThisN; nLo++ )
310 if(ipISO==0 && nelem==0 )
313 TeUsed[ipISO][nelem] =
phycon.
te*0.999;
348 if( !
iso_sp[ipISO][nelem].lgLevelsLowered )
353 TotMinusExplicitResolved = TotalRadRecomb - RecExplictLevels;
355 topoff = TotMinusExplicitResolved - RecCollapsed;
361 fabs( topoff/TotalRadRecomb ) > 0.01 )
363 fprintf(
ioQQQ,
" PROBLEM negative RR topoff for %li, rel error was %.2e, temp was %.2f\n",
364 nelem, topoff/TotalRadRecomb,
phycon.
te );
372 topoff =
MAX2( 0., topoff );
374 ASSERT( scale_factor >= 1. );
387 if( Total_DR_Added > TotalRadRecomb/100. )
393 fprintf(
ioQQQ,
" PROBLEM negative DR topoff for %li iso %li, tot1, tot2 = %.2e\t%.2e rel error was %.2e, temp was %.2e, eden was %.2e\n",
446 iso_sp[ipISO][nelem].fb[ipLevel].ConOpacRatio );
470 fprintf(
ioQQQ,
" iso_radiative_recomb trace ipISO=%3ld Z=%3ld\n", ipISO, nelem );
481 fprintf(
ioQQQ,
" iso_radiative_recomb recomb net effic" );
505 fprintf(
ioQQQ,
" iso_radiative_recomb rad rec coef " );
518 static double Tused = -1;
543 " PROBLEM iso_radiative_recomb non-positive recombination coefficient for ipISO=%3ld Z=%3ld lev n=%3ld rec=%11.2e te=%11.2e\n",
581 0.0009f,0.0037f,0.0003f,0.0003f,0.0003f,0.0018f,
582 0.0009f,0.0050f,0.0007f,0.0003f,0.0001f,0.0007f,
583 0.0045f,0.0071f,0.0005f,0.0005f,0.0004f,0.0005f,0.0004f,0.0009f,
584 0.0045f,0.0071f,0.0005f,0.0005f,0.0004f,0.0005f,0.0004f,0.0005f,0.0004f,0.0009f };
588 0.0100f,0.0060f,0.0080f,0.0080f,0.0080f,0.0200f,
589 0.0200f,0.0200f,0.0200f,0.0600f,0.0600f,0.0080f,
590 0.0200f,0.0200f,0.0070f,0.0100f,0.0100f,0.0020f,0.0030f,0.0070f,
591 0.0300f,0.0300f,0.0100f,0.0200f,0.0200f,0.0200f,0.0200f,0.0010f,0.0004f,0.0090f };
598 if( ipHi >=
iso_sp[ipISO][nelem].numLevels_max -
iso_sp[ipISO][nelem].nCollapsed_max )
623 iso_sp[ipISO][nelem].
fb[ipHi].RadEffec = 0.;
628 ASSERT(
iso_sp[ipISO][nelem].CascadeProb[ipHigher][ipHi] >= 0. );
640 enum {DEBUG_LOC=
false};
646 fprintf(
ioQQQ,
"Effective recombination, ipISO=%li, nelem=%li, Te = %e\n", ipISO, nelem,
phycon.
te );
649 for(
long i=0; i<maxPrt; i++ )
652 iso_sp[ipISO][nelem].fb[i].RadEffec,
653 MAX2( 0.,
iso_sp[ipISO][nelem].st[i].lifetime() ) );
662 dprintf(
ioQQQ,
"ipHi\tipLo\tWL\tEmiss\tSigmaEmiss\tRadEffec\tSigRadEff\tBrRat\tSigBrRat\n" );
667 iso_sp[ipISO][nelem].
fb[ipHi].SigmaRadEffec = 0.;
673 ASSERT(
iso_sp[ipISO][nelem].ex[ipHigher][ipHi].SigmaCascadeProb >= 0. );
677 iso_sp[ipISO][nelem].CascadeProb[ipHigher][ipHi] *
iso_sp[ipISO][nelem].fb[ipHigher].RadRecomb[
ipRecRad]) +
678 pow2(
iso_sp[ipISO][nelem].ex[ipHigher][ipHi].SigmaCascadeProb *
iso_sp[ipISO][nelem].fb[ipHigher].RadRecomb[ipRecRad]);
681 ASSERT(
iso_sp[ipISO][nelem].fb[ipHi].SigmaRadEffec >= 0. );
682 iso_sp[ipISO][nelem].
fb[ipHi].SigmaRadEffec = sqrt(
iso_sp[ipISO][nelem].fb[ipHi].SigmaRadEffec );
684 for(
long ipLo = 0; ipLo < ipHi; ipLo++ )
686 if( ((
L_(ipLo) ==
L_(ipHi) + 1 ) || (
L_(ipHi) ==
L_(ipLo) + 1 )) )
688 double EnergyInRydbergs =
iso_sp[ipISO][nelem].
fb[ipLo].xIsoLevNIonRyd -
iso_sp[ipISO][nelem].
fb[ipHi].xIsoLevNIonRyd;
690 double emissivity =
iso_sp[ipISO][nelem].
fb[ipHi].RadEffec *
iso_sp[ipISO][nelem].
BranchRatio[ipHi][ipLo] * EN1RYD * EnergyInRydbergs;
691 double sigma_emiss = 0., SigmaBranchRatio = 0.;
693 if( ( emissivity > 2.E-29 ) && ( wavelength < 1.E6 ) && (
N_(ipHi)<=5) )
697 pow2(
iso_sp[ipISO][nelem].fb[ipHi].SigmaAtot*
iso_sp[ipISO][nelem].st[ipHi].lifetime() ) );
699 sigma_emiss = EN1RYD * EnergyInRydbergs * sqrt(
700 pow2( (
double)
iso_sp[ipISO][nelem].fb[ipHi].SigmaRadEffec *
iso_sp[ipISO][nelem].BranchRatio[ipHi][ipLo] ) +
701 pow2( SigmaBranchRatio *
iso_sp[ipISO][nelem].fb[ipHi].RadEffec ) );
709 iso_sp[ipISO][nelem].fb[ipHi].RadEffec,
710 iso_sp[ipISO][nelem].fb[ipHi].SigmaRadEffec,
711 iso_sp[ipISO][nelem].BranchRatio[ipHi][ipLo],
731 if( n ==
iso_sp[ipISO][nelem].numLevels_max -
iso_sp[ipISO][nelem].nCollapsed_max )
741 rate =
exp10( rate );
750 double RecombRelError ,
761 RecombInterp =
iso_RRCoef_Te( ipISO, nelem, temperature, level );
763 RecombRelError = ( RecombInterp - RecombCalc ) /
MAX2( RecombInterp , RecombCalc );
765 return RecombRelError;
777 for(
long ipISO=0; ipISO<
NISO; ipISO++ )
784 for(
long nelem=ipISO; nelem <
LIMELM; ++nelem )
786 long int MaxLevels, maxN;
806 RRCoef[ipISO][nelem] = (
double**)
MALLOC(
sizeof(
double*)*(unsigned)(MaxLevels) );
808 for(
long ipLo=0; ipLo < MaxLevels;++ipLo )
810 RRCoef[ipISO][nelem][ipLo] = (
double*)
MALLOC(
sizeof(
double)*(unsigned)N_ISO_TE_RECOMB );
824 TeRRCoef[N_ISO_TE_RECOMB-1] += 0.01f;
833 for(
long i = 0; i<
NISO; i++ )
844 double RadRecombReturn;
845 long int i, i1, i2, i3, i4, i5;
846 long int ipLo, nelem;
850 const char* chFilename[
NISO] =
851 {
"h_iso_recomb.dat",
"he_iso_recomb.dat" };
873 fprintf(
ioQQQ,
" iso_recomb_setup opening %s:", chFilename[ipISO] );
878 ioDATA =
open_data( chFilename[ipISO],
"r" );
882 fprintf(
ioQQQ,
" Defaulting to on-the-fly computation, ");
883 fprintf(
ioQQQ,
" but the code runs much faster if you compile %s!\n", chFilename[ipISO]);
889 for( nelem = ipISO; nelem <
LIMELM; nelem++ )
910 RRCoef[ipISO][nelem][ipLo][i] = log10(RadRecombReturn);
934 fprintf(
ioQQQ,
" iso_recomb_setup could not read first line of %s.\n", chFilename[ipISO]);
938 i1 = (long)
FFmtRead(chLine,&i,
sizeof(chLine),&lgEOL);
939 i2 = (long)
FFmtRead(chLine,&i,
sizeof(chLine),&lgEOL);
940 i3 = (long)
FFmtRead(chLine,&i,
sizeof(chLine),&lgEOL);
941 i4 = (long)
FFmtRead(chLine,&i,
sizeof(chLine),&lgEOL);
945 " iso_recomb_setup: the version of %s is not the current version.\n", chFilename[ipISO] );
947 " iso_recomb_setup: I expected to find the numbers %i %li %li %i and got %li %li %li %li instead.\n" ,
953 fprintf(
ioQQQ,
"Here is the line image:\n==%s==\n", chLine );
955 " iso_recomb_setup: please recompile the data file with the COMPile RECOmb COEFficient H-LIke [or HE-Like] command.\n" );
961 for( nelem = ipISO; nelem <
LIMELM; nelem++ )
963 for( ipLo=0; ipLo <=
NumLevRecomb[ipISO][nelem]; ipLo++ )
969 fprintf(
ioQQQ,
" iso_recomb_setup could not read line %li of %s.\n", i5,
975 i1 = (long)
FFmtRead(chLine,&i3,
sizeof(chLine),&lgEOL);
976 i2 = (long)
FFmtRead(chLine,&i3,
sizeof(chLine),&lgEOL);
978 if( i1!=nelem || i2!=ipLo )
980 fprintf(
ioQQQ,
" iso_recomb_setup detected insanity in %s.\n", chFilename[ipISO]);
982 " iso_recomb_setup: please recompile the data file with the COMPile RECOmb COEFficient H-LIke [or HE-Like] command.\n" );
989 double ThisCoef =
FFmtRead(chLine,&i3,chLine_LENGTH,&lgEOL);
999 RRCoef[ipISO][nelem][ipLo][i] = ThisCoef;
1004 fprintf(
ioQQQ,
" iso_recomb_setup detected insanity in %s.\n", chFilename[ipISO]);
1006 " iso_recomb_setup: please recompile the data file with the COMPile RECOmb COEFficient H-LIke [or HE-Like] command.\n" );
1029 if(
read_whole_line( chLine , (
int)
sizeof(chLine) , ioDATA ) == NULL )
1031 fprintf(
ioQQQ,
" iso_recomb_setup could not read last line of %s.\n", chFilename[ipISO]);
1035 i1 = (long)
FFmtRead(chLine,&i,
sizeof(chLine),&lgEOL);
1036 i2 = (long)
FFmtRead(chLine,&i,
sizeof(chLine),&lgEOL);
1037 i3 = (long)
FFmtRead(chLine,&i,
sizeof(chLine),&lgEOL);
1038 i4 = (long)
FFmtRead(chLine,&i,
sizeof(chLine),&lgEOL);
1043 " iso_recomb_setup: the version of %s is not the current version.\n", chFilename[ipISO] );
1045 " iso_recomb_setup: I expected to find the numbers %i %li %li %i and got %li %li %li %li instead.\n" ,
1051 fprintf(
ioQQQ,
"Here is the line image:\n==%s==\n", chLine );
1053 " iso_recomb_setup: please recompile the data file with the COMPile RECOmb COEFficient H-LIke [or HE-Like] command.\n" );
1073 ioRECOMB =
open_data( chFilename[ipISO],
"w" );
1074 fprintf(ioRECOMB,
"%i\t%li\t%li\t%i\t%s isoelectronic sequence recomb data, created by COMPile RECOmb COEFficient H-LIke [or HE-Like] command, with %li %s levels, %li ion levels, and %i temperatures.\n",
1085 for( nelem = ipISO; nelem <
LIMELM; nelem++ )
1098 fprintf(ioRECOMB,
"%li\t%li", nelem, ipLo );
1105 RRCoef[ipISO][nelem][ipLo][i] = log10(RadRecombReturn);
1114 fprintf(ioRECOMB,
"%li\t%li", nelem, NumLevRecomb[ipISO][nelem] );
1130 fprintf(ioRECOMB,
"%i\t%li\t%li\t%i\t%s isoelectronic sequence recomb data, created by COMPile RECOmb COEFficient [H-LIke/HE-Like] command, with %li %s levels, %li ion levels, and %i temperatures.\n",
1143 fprintf(
ioQQQ,
"iso_recomb_setup: compilation complete, %s created.\n", chFilename[ipISO] );
1144 fprintf(
ioQQQ,
"The compilation is completed successfully.\n");
1159 1.00000, 1.30103, 1.69897, 2.00000, 2.30103, 2.69897, 3.00000,
1160 3.30103, 3.69897, 4.00000, 4.30103, 4.69897, 5.00000, 5.30103,
1161 5.69897, 6.00000, 6.30103, 6.69897, 7.00000 };
1172 TeDRCoef[i] = Te_over_Z1_Squared[i] + 2. * log10( (
double) nelem );
1179 else if( ipLo<
iso_sp[ipISO][nelem].numLevels_max )
1197 ASSERT( (ipTe >=0) && (ipTe < NUM_DR_TEMPS-1) );
1209 (TeDRCoef[ipTe+1]-TeDRCoef[ipTe]);
1211 rate =
exp10( rate );
1220 ASSERT( rate >= 0. && rate < 1.0e-12 );
1227 STATIC double TempInterp(
double* TempArray,
double* ValueArray,
long NumElements,
double temp )
1229 static long int ipTe=-1;
1235 double alogte = log10(temp);
1240 if( ( alogte < TempArray[0] ) ||
1241 ( alogte > TempArray[NumElements-1] ) )
1243 fprintf(
ioQQQ,
" TempInterp called with te out of bounds \n");
1246 ipTe =
hunt_bisect( TempArray, NumElements, alogte );
1248 else if( alogte < TempArray[ipTe] )
1251 ASSERT( alogte > TempArray[0] );
1253 while( ( alogte < TempArray[ipTe] ) && ipTe > 0)
1256 else if( alogte > TempArray[ipTe+1] )
1259 ASSERT( alogte <= TempArray[NumElements-1] );
1261 while( ( alogte > TempArray[ipTe+1] ) && ipTe < NumElements-1)
1265 ASSERT( (ipTe >=0) && (ipTe < NumElements-1) );
1268 ASSERT( ( alogte >= TempArray[ipTe] )
1269 && ( alogte <= TempArray[ipTe+1] ) && ( ipTe < NumElements-1 ) );
1271 if( ValueArray[ipTe+1] == 0. && ValueArray[ipTe] == 0. )
1278 const int ORDER = 3;
1279 i0 =
max(
min(ipTe-ORDER/2,NumElements-ORDER-1),0);
1280 rate =
lagrange( &TempArray[i0], &ValueArray[i0], ORDER+1, alogte );
double ** DR_Badnell_rate_coef
double RT_recom_effic(long int ip)
void prt_wl(FILE *ioOUT, realnum wl)
FILE * open_data(const char *fname, const char *mode, access_scheme scheme)
double DielecRecombVsTemp[NUM_DR_TEMPS]
NORETURN void TotalInsanity(void)
double iso_recomb_check(long ipISO, long nelem, long level, double temperature)
STATIC double TempInterp(double *TempArray, double *ValueArray, long NumElements, double temp)
bool lgIsoTraceFull[NISO]
bool lgCompileRecomb[NISO]
double iso_RRCoef_Te(long ipISO, long nelem, double temp, long n)
long iso_get_total_num_levels(long ipISO, long nmaxResolved, long numCollapsed)
static double *** TotalRecomb
static long int globalISO
long int ipIsoTrace[NISO]
STATIC double iso_radrecomb_from_cross_section(long ipISO, double temp, long nelem, long ipLo)
void iso_radiative_recomb_effective(long ipISO, long nelem)
void iso_put_error(long ipISO, long nelem, long ipHi, long ipLo, long whichData, realnum errorOpt, realnum errorPess)
double H_cross_section(double EgammaRyd, double EthRyd, long n, long l, long nelem)
static double global_EthRyd
long hunt_bisect(const T x[], long n, T xval)
static long ** NumLevRecomb
t_elementnames elementnames
t_iso_sp iso_sp[NISO][LIMELM]
vector< double > HighestLevelOpacStack
long int n_HighestResolved_local
bool fp_equal(sys_float x, sys_float y, int n=3)
multi_arr< double, 2 > BranchRatio
int dprintf(FILE *fp, const char *format,...)
static double **** RRCoef
static double TeRRCoef[N_ISO_TE_RECOMB]
double H_rad_rec(long int iz, long int n, double t)
void iso_radiative_recomb(long ipISO, long nelem)
STATIC void iso_put_recomb_error(long ipISO, long nelem)
double iso_cross_section(double ERyd, double EthRyd, long n, long l, long S, long globalZ, long globalISO)
#define LIKE_RREC_MAXN(A_)
multi_arr< long, 3 > QuantumNumbers2Index
char chElementSym[LIMELM][CHARS_ELEMENT_SYM]
double lagrange(const double x[], const double y[], long n, double xval)
multi_arr< double, 2 > CascadeProb
STATIC double iso_recomb_integrand(double EE)
double qg32(double, double, double(*)(double))
void iso_recomb_setup(long ipISO)
void iso_recomb_malloc(void)
#define DEBUG_ENTRY(funcname)
double powpq(double x, int p, int q)
static vector< realnum > wavelength
STATIC double cross_section(double EgammaRyd, double EthRyd, long nelem, long n, long l, long s)
multi_arr< double, 2 > DR_Badnell_suppress_fact
int fprintf(const Output &stream, const char *format,...)
char * read_whole_line(char *chLine, int nChar, FILE *ioIN)
double Recomb_Seaton59(long nelem, double temp, long n)
double He_cross_section(double EgammaRyd, double EthRyd, long n, long l, long S, long nelem)
long int nCollapsed_local
const int NHYDRO_MAX_LEVEL
double iso_dielec_recomb_rate(long ipISO, long nelem, long ipLo)
double FFmtRead(const char *chCard, long int *ipnt, long int last, bool *lgEOL)
void iso_recomb_auxiliary_free(void)
bool lgNoRecombInterp[NISO]