43STATIC double TempInterp(
double* TempArray ,
double* ValueArray,
long NumElements );
49 double alpha,RecomIntegral=0.,b,E1,E2,step,OldRecomIntegral,TotChangeLastFive;
50 double change[5] = {0.,0.,0.,0.,0.};
52 DEBUG_ENTRY(
"iso_radrecomb_from_cross_section()" );
94 OldRecomIntegral = RecomIntegral;
99 change[4] = change[3];
100 change[3] = change[2];
101 change[2] = change[1];
102 change[1] = change[0];
103 change[0] = (RecomIntegral - OldRecomIntegral)/RecomIntegral;
104 TotChangeLastFive = change[0] + change[1] + change[2] + change[3] + change[4];
112 alpha = b * RecomIntegral;
154 long ipFirstCollapsed, LastN=0L, ThisN=1L, ipLevel;
155 double topoff, TotMinusExplicitResolved,
156 TotRRThisN=0., TotRRLastN=0., Total_DR_Added=0.;
157 double RecExplictLevels, TotalRadRecomb, RecCollapsed;
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.},
162 {0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,
163 0.,0.,0.,0.,0.,0.,0.,0.,0.,0.,
164 0.,0.,0.,0.,0.,0.,0.,0.,0.,0.}};
174 RecExplictLevels = 0.;
179 ASSERT( ipFirstCollapsed ==
iso_sp[ipISO][nelem].numLevels_local -
iso_sp[ipISO][nelem].nCollapsed_local );
184 for( ipLevel=0; ipLevel<ipFirstCollapsed; ++ipLevel )
209 Total_DR_Added +=
iso_sp[ipISO][nelem].
fb[ipLevel].DielecRecomb;
233 Total_DR_Added +=
iso_sp[ipISO][nelem].
fb[ipLevel].DielecRecomb;
238 iso_sp[ipISO][nelem].
fb[ipLevel].DielecRecomb = 0.;
243 if(
N_(ipLevel) == ThisN )
252 TotRRLastN = TotRRThisN;
258 enum {DEBUG_LOC=
false};
260 static long RUNONCE =
false;
262 if( !RUNONCE && DEBUG_LOC )
264 static long FIRSTTIME =
true;
268 fprintf(
ioQQQ,
"Sum of Radiative Recombination at current iso, nelem, temp = %li %li %.2f\n",
273 fprintf(
ioQQQ,
"%li\t%.2e\n",LastN,TotRRLastN );
284 TotalRadRecomb = RecCollapsed + RecExplictLevels;
297 else if(
iso_sp[ipISO][nelem].lgLevelsLowered )
301 TotalRadRecomb +=
iso_sp[ipISO][nelem].fb[ipLevel].RadRecomb[
ipRecRad];
306 TotalRadRecomb =
iso_RRCoef_Te( ipISO, nelem,
iso_sp[ipISO][nelem].numLevels_max -
iso_sp[ipISO][nelem].nCollapsed_max );
308 if(ipISO==0 && nelem==0 )
311 TeUsed[ipISO][nelem] =
phycon.
te*0.999;
346 if( !
iso_sp[ipISO][nelem].lgLevelsLowered )
351 TotMinusExplicitResolved = TotalRadRecomb - RecExplictLevels;
353 topoff = TotMinusExplicitResolved - RecCollapsed;
359 fabs( topoff/TotalRadRecomb ) > 0.01 )
361 fprintf(
ioQQQ,
" PROBLEM negative RR topoff for %li, rel error was %.2e, temp was %.2f\n",
362 nelem, topoff/TotalRadRecomb,
phycon.
te );
369 topoff =
MAX2( 0., topoff );
371 ASSERT( scale_factor >= 1. );
384 if( Total_DR_Added > TotalRadRecomb/100. )
388 fprintf(
ioQQQ,
" PROBLEM negative DR topoff for %li, tot1, tot2 = %.2e\t%.2e rel error was %.2e, temp was %.2f\n",
440 iso_sp[ipISO][nelem].fb[ipLevel].ConOpacRatio );
464 fprintf(
ioQQQ,
" iso_radiative_recomb trace ipISO=%3ld Z=%3ld\n", ipISO, nelem );
467 fprintf(
ioQQQ,
" iso_radiative_recomb recomb effic" );
472 fprintf(
ioQQQ,
"\n" );
475 fprintf(
ioQQQ,
" iso_radiative_recomb recomb net effic" );
480 fprintf(
ioQQQ,
"\n" );
483 fprintf(
ioQQQ,
" iso_radiative_recomb in optic dep" );
488 fprintf(
ioQQQ,
"\n" );
491 fprintf(
ioQQQ,
" iso_radiative_recomb out op depth" );
496 fprintf(
ioQQQ,
"\n" );
499 fprintf(
ioQQQ,
" iso_radiative_recomb rad rec coef " );
504 fprintf(
ioQQQ,
"\n" );
509 fprintf(
ioQQQ,
" iso_radiative_recomb total rec coef" );
511 fprintf(
ioQQQ,
" case A=" );
514 fprintf(
ioQQQ,
" case B=");
516 fprintf(
ioQQQ,
"\n" );
529 " PROBLEM iso_radiative_recomb non-positive recombination coefficient for ipISO=%3ld Z=%3ld lev n=%3ld rec=%11.2e te=%11.2e\n",
567 0.0009f,0.0037f,0.0003f,0.0003f,0.0003f,0.0018f,
568 0.0009f,0.0050f,0.0007f,0.0003f,0.0001f,0.0007f,
569 0.0045f,0.0071f,0.0005f,0.0005f,0.0004f,0.0005f,0.0004f,0.0009f,
570 0.0045f,0.0071f,0.0005f,0.0005f,0.0004f,0.0005f,0.0004f,0.0005f,0.0004f,0.0009f };
574 0.0100f,0.0060f,0.0080f,0.0080f,0.0080f,0.0200f,
575 0.0200f,0.0200f,0.0200f,0.0600f,0.0600f,0.0080f,
576 0.0200f,0.0200f,0.0070f,0.0100f,0.0100f,0.0020f,0.0030f,0.0070f,
577 0.0300f,0.0300f,0.0100f,0.0200f,0.0200f,0.0200f,0.0200f,0.0010f,0.0004f,0.0090f };
584 if( ipHi >=
iso_sp[ipISO][nelem].numLevels_max -
iso_sp[ipISO][nelem].nCollapsed_max )
609 iso_sp[ipISO][nelem].
fb[ipHi].RadEffec = 0.;
614 ASSERT(
iso_sp[ipISO][nelem].CascadeProb[ipHigher][ipHi] >= 0. );
626 enum {DEBUG_LOC=
false};
632 fprintf(
ioQQQ,
"Effective recombination, ipISO=%li, nelem=%li, Te = %e\n", ipISO, nelem,
phycon.
te );
633 fprintf(
ioQQQ,
"N\tL\tS\tRadEffec\tLifetime\n" );
635 for(
long i=0; i<maxPrt; i++ )
637 fprintf(
ioQQQ,
"%li\t%li\t%li\t%e\t%e\n",
N_(i),
L_(i),
S_(i),
638 iso_sp[ipISO][nelem].fb[i].RadEffec,
639 MAX2( 0.,
iso_sp[ipISO][nelem].st[i].lifetime() ) );
641 fprintf(
ioQQQ,
"\n" );
648 dprintf(
ioQQQ,
"ipHi\tipLo\tWL\tEmiss\tSigmaEmiss\tRadEffec\tSigRadEff\tBrRat\tSigBrRat\n" );
653 iso_sp[ipISO][nelem].
fb[ipHi].SigmaRadEffec = 0.;
659 ASSERT(
iso_sp[ipISO][nelem].
ex[ipHigher][ipHi].SigmaCascadeProb >= 0. );
662 iso_sp[ipISO][nelem].
fb[ipHi].SigmaRadEffec += pow(
iso_sp[ipISO][nelem].
ex[
iso_sp[ipISO][nelem].numLevels_max][ipHigher].Error[
IPRAD] *
663 iso_sp[ipISO][nelem].CascadeProb[ipHigher][ipHi] *
iso_sp[ipISO][nelem].fb[ipHigher].RadRecomb[
ipRecRad], 2.) +
664 pow(
iso_sp[ipISO][nelem].
ex[ipHigher][ipHi].SigmaCascadeProb *
iso_sp[ipISO][nelem].fb[ipHigher].RadRecomb[
ipRecRad], 2.);
667 ASSERT(
iso_sp[ipISO][nelem].fb[ipHi].SigmaRadEffec >= 0. );
668 iso_sp[ipISO][nelem].
fb[ipHi].SigmaRadEffec = sqrt(
iso_sp[ipISO][nelem].fb[ipHi].SigmaRadEffec );
670 for(
long ipLo = 0; ipLo < ipHi; ipLo++ )
672 if( ((
L_(ipLo) ==
L_(ipHi) + 1 ) || (
L_(ipHi) ==
L_(ipLo) + 1 )) )
674 double EnergyInRydbergs =
iso_sp[ipISO][nelem].
fb[ipLo].xIsoLevNIonRyd -
iso_sp[ipISO][nelem].
fb[ipHi].xIsoLevNIonRyd;
677 double sigma_emiss = 0., SigmaBranchRatio = 0.;
679 if( ( emissivity > 2.E-29 ) && (
wavelength < 1.E6 ) && (
N_(ipHi)<=5) )
682 pow( (
double)
iso_sp[ipISO][nelem].
ex[ipHi][ipLo].Error[
IPRAD], 2. ) +
683 pow(
iso_sp[ipISO][nelem].fb[ipHi].SigmaAtot*
iso_sp[ipISO][nelem].st[ipHi].lifetime(), 2.) );
685 sigma_emiss =
EN1RYD * EnergyInRydbergs * sqrt(
686 pow( (
double)
iso_sp[ipISO][nelem].fb[ipHi].SigmaRadEffec *
iso_sp[ipISO][nelem].BranchRatio[ipHi][ipLo], 2.) +
687 pow( SigmaBranchRatio *
iso_sp[ipISO][nelem].fb[ipHi].RadEffec, 2.) );
692 fprintf(
ioQQQ,
"\t%e\t%e\t%e\t%e\t%e\t%e\n",
695 iso_sp[ipISO][nelem].fb[ipHi].RadEffec,
696 iso_sp[ipISO][nelem].fb[ipHi].SigmaRadEffec,
697 iso_sp[ipISO][nelem].BranchRatio[ipHi][ipLo],
717 if( n ==
iso_sp[ipISO][nelem].numLevels_max -
iso_sp[ipISO][nelem].nCollapsed_max )
727 rate = pow( 10. , rate );
736 double RecombRelError ,
759 RecombRelError = ( RecombInterp - RecombCalc ) /
MAX2( RecombInterp , RecombCalc );
761 return RecombRelError;
773 for(
long ipISO=0; ipISO<
NISO; ipISO++ )
780 for(
long nelem=ipISO; nelem <
LIMELM; ++nelem )
782 long int MaxLevels, maxN;
802 RRCoef[ipISO][nelem] = (
double**)
MALLOC(
sizeof(
double*)*(unsigned)(MaxLevels) );
804 for(
long ipLo=0; ipLo < MaxLevels;++ipLo )
829 for(
long i = 0; i<
NISO; i++ )
840 double RadRecombReturn;
841 long int i, i1, i2, i3, i4, i5;
842 long int ipLo, nelem;
847 const char* chFilename[
NISO] =
848 {
"h_iso_recomb.dat",
"he_iso_recomb.dat" };
870 fprintf(
ioQQQ,
" iso_recomb_setup opening %s:", chFilename[ipISO] );
875 ioDATA =
open_data( chFilename[ipISO],
"r" );
879 fprintf(
ioQQQ,
" Defaulting to on-the-fly computation, ");
880 fprintf(
ioQQQ,
" but the code runs much faster if you compile %s!\n", chFilename[ipISO]);
886 for( nelem = ipISO; nelem <
LIMELM; nelem++ )
907 RRCoef[ipISO][nelem][ipLo][i] = log10(RadRecombReturn);
931 fprintf(
ioQQQ,
" iso_recomb_setup could not read first line of %s.\n", chFilename[ipISO]);
935 i1 = (long)
FFmtRead(chLine,&i,
sizeof(chLine),&lgEOL);
936 i2 = (long)
FFmtRead(chLine,&i,
sizeof(chLine),&lgEOL);
937 i3 = (long)
FFmtRead(chLine,&i,
sizeof(chLine),&lgEOL);
938 i4 = (long)
FFmtRead(chLine,&i,
sizeof(chLine),&lgEOL);
942 " iso_recomb_setup: the version of %s is not the current version.\n", chFilename[ipISO] );
944 " iso_recomb_setup: I expected to find the numbers %i %li %li %i and got %li %li %li %li instead.\n" ,
950 fprintf(
ioQQQ,
"Here is the line image:\n==%s==\n", chLine );
952 " iso_recomb_setup: please recompile the data file with the COMPile RECOmb COEFficient H-LIke [or HE-Like] command.\n" );
958 for( nelem = ipISO; nelem <
LIMELM; nelem++ )
960 for( ipLo=0; ipLo <=
NumLevRecomb[ipISO][nelem]; ipLo++ )
966 fprintf(
ioQQQ,
" iso_recomb_setup could not read line %li of %s.\n", i5,
972 i1 = (long)
FFmtRead(chLine,&i3,
sizeof(chLine),&lgEOL);
973 i2 = (long)
FFmtRead(chLine,&i3,
sizeof(chLine),&lgEOL);
975 if( i1!=nelem || i2!=ipLo )
977 fprintf(
ioQQQ,
" iso_recomb_setup detected insanity in %s.\n", chFilename[ipISO]);
979 " iso_recomb_setup: please recompile the data file with the COMPile RECOmb COEFficient H-LIke [or HE-Like] command.\n" );
996 RRCoef[ipISO][nelem][ipLo][i] = ThisCoef;
1001 fprintf(
ioQQQ,
" iso_recomb_setup detected insanity in %s.\n", chFilename[ipISO]);
1003 " iso_recomb_setup: please recompile the data file with the COMPile RECOmb COEFficient H-LIke [or HE-Like] command.\n" );
1026 if(
read_whole_line( chLine , (
int)
sizeof(chLine) , ioDATA ) == NULL )
1028 fprintf(
ioQQQ,
" iso_recomb_setup could not read last line of %s.\n", chFilename[ipISO]);
1032 i1 = (long)
FFmtRead(chLine,&i,
sizeof(chLine),&lgEOL);
1033 i2 = (long)
FFmtRead(chLine,&i,
sizeof(chLine),&lgEOL);
1034 i3 = (long)
FFmtRead(chLine,&i,
sizeof(chLine),&lgEOL);
1035 i4 = (long)
FFmtRead(chLine,&i,
sizeof(chLine),&lgEOL);
1040 " iso_recomb_setup: the version of %s is not the current version.\n", chFilename[ipISO] );
1042 " iso_recomb_setup: I expected to find the numbers %i %li %li %i and got %li %li %li %li instead.\n" ,
1048 fprintf(
ioQQQ,
"Here is the line image:\n==%s==\n", chLine );
1050 " iso_recomb_setup: please recompile the data file with the COMPile RECOmb COEFficient H-LIke [or HE-Like] command.\n" );
1071 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",
1082 for( nelem = ipISO; nelem <
LIMELM; nelem++ )
1095 fprintf(ioRECOMB,
"%li\t%li", nelem, ipLo );
1102 RRCoef[ipISO][nelem][ipLo][i] = log10(RadRecombReturn);
1103 fprintf(ioRECOMB,
"\t%f",
RRCoef[ipISO][nelem][ipLo][i] );
1105 fprintf(ioRECOMB,
"\n" );
1111 fprintf(ioRECOMB,
"%li\t%li", nelem,
NumLevRecomb[ipISO][nelem] );
1122 fprintf(ioRECOMB,
"\t%f", log10(
TotalRecomb[ipISO][nelem][i] ) );
1124 fprintf(ioRECOMB,
"\n" );
1127 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",
1140 fprintf(
ioQQQ,
"iso_recomb_setup: compilation complete, %s created.\n", chFilename[ipISO] );
1141 fprintf(
ioQQQ,
"The compilation is completed successfully.\n");
1156 1.00000, 1.30103, 1.69897, 2.00000, 2.30103, 2.69897, 3.00000,
1157 3.30103, 3.69897, 4.00000, 4.30103, 4.69897, 5.00000, 5.30103,
1158 5.69897, 6.00000, 6.30103, 6.69897, 7.00000 };
1169 TeDRCoef[i] = Te_over_Z1_Squared[i] + 2. * log10( (
double) nelem );
1176 else if( ipLo<
iso_sp[ipISO][nelem].numLevels_max )
1206 (TeDRCoef[ipTe+1]-TeDRCoef[ipTe]);
1208 rate = pow( 10., rate );
1217 ASSERT( rate >= 0. && rate < 1.0e-12 );
1226 static long int ipTe=-1;
1240 fprintf(
ioQQQ,
" TempInterp called with te out of bounds \n");
1250 while( (
phycon.
alogte < TempArray[ipTe] ) && ipTe > 0)
1258 while( (
phycon.
alogte > TempArray[ipTe+1] ) && ipTe < NumElements-1)
1262 ASSERT( (ipTe >=0) && (ipTe < NumElements-1) );
1266 && (
phycon.
alogte <= TempArray[ipTe+1] ) && ( ipTe < NumElements-1 ) );
1268 if( ValueArray[ipTe+1] == 0. && ValueArray[ipTe] == 0. )
1275 const int ORDER = 3;
1276 i0 =
max(
min(ipTe-ORDER/2,NumElements-ORDER-1),0);
const int NHYDRO_MAX_LEVEL
double qg32(double, double, double(*)(double))
int dprintf(FILE *fp, const char *format,...)
double FFmtRead(const char *chCard, long int *ipnt, long int last, bool *lgEOL)
bool fp_equal(sys_float x, sys_float y, int n=3)
char * read_whole_line(char *chLine, int nChar, FILE *ioIN)
NORETURN void TotalInsanity(void)
#define DEBUG_ENTRY(funcname)
double DielecRecombVsTemp[NUM_DR_TEMPS]
double H_rad_rec(long int iz, long int n, double t)
double ** DR_Badnell_rate_coef
multi_arr< double, 2 > BranchRatio
long int n_HighestResolved_local
vector< double > HighestLevelOpacStack
multi_arr< double, 2 > CascadeProb
multi_arr< long, 3 > QuantumNumbers2Index
long int nCollapsed_local
bool lgNoRecombInterp[NISO]
bool lgCompileRecomb[NISO]
FILE * open_data(const char *fname, const char *mode, access_scheme scheme)
t_elementnames elementnames
double He_cross_section(double EgammaRyd, double EthRyd, long n, long l, long S, long nelem)
double Recomb_Seaton59(long nelem, double temp, long n)
STATIC double cross_section(double EgammaRyd, double EthRyd, long nelem, long n, long l, long s)
double H_cross_section(double EgammaRyd, double EthRyd, long n, long l, long nelem)
t_iso_sp iso_sp[NISO][LIMELM]
#define LIKE_RREC_MAXN(A_)
long iso_get_total_num_levels(long ipISO, long nmaxResolved, long numCollapsed)
void iso_put_error(long ipISO, long nelem, long ipHi, long ipLo, long whichData, realnum errorOpt, realnum errorPess)
double iso_radrecomb_from_cross_section(long ipISO, double temp, long nelem, long ipLo)
static long int globalISO
void iso_recomb_malloc(void)
static double TeRRCoef[N_ISO_TE_RECOMB]
STATIC double iso_recomb_integrand(double EE)
void iso_recomb_setup(long ipISO)
static double **** RRCoef
STATIC double TempInterp(double *TempArray, double *ValueArray, long NumElements)
double iso_RRCoef_Te(long ipISO, long nelem, long n)
static double *** TotalRecomb
static long ** NumLevRecomb
double iso_recomb_check(long ipISO, long nelem, long level, double temperature)
double iso_dielec_recomb_rate(long ipISO, long nelem, long ipLo)
STATIC void iso_put_recomb_error(long ipISO, long nelem)
void iso_recomb_auxiliary_free(void)
double iso_cross_section(double EgammaRyd, double EthRyd, long n, long l, long S, long globalZ, long globalISO)
static double global_EthRyd
void iso_radiative_recomb_effective(long ipISO, long nelem)
void iso_radiative_recomb(long ipISO, long nelem)
static realnum * wavelength
UNUSED const double EN1RYD
UNUSED const double MILNE_CONST
UNUSED const double TE1RYD
UNUSED const double RYDLAM
void prt_wl(FILE *ioOUT, realnum wl)
double RT_recom_effic(long int ip)
char chElementSym[LIMELM][CHARS_ELEMENT_SYM]
bool lgIsoTraceFull[NISO]
long int ipIsoTrace[NISO]
void TempChange(double TempNew, bool lgForceUpdate)
double lagrange(const double x[], const double y[], long n, double xval)
long hunt_bisect(const T x[], long n, T xval)