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]