double xe_PostSahaH(double nH, double H, double T, HRATEEFF *rate_table, TWO_PHOTON_PARAMS *twog, double zstart, double dlna, double **logfminus_hist, double *logfminus_Ly_hist[], unsigned iz, double z, double *Dxe, int model, double energy_rate){ double s, xeSaha, dxeSaha_dlna, Ddxedlna_Dxe; s = 3.016103031869581e21 *T*sqrt(T) *exp(-EI/T)/nH; /* xe^2/(1-xe) in Saha eq.*/ xeSaha = 2./(1.+sqrt(1.+4./s)); /* Saha equilibrium */ dxeSaha_dlna = -(EI/T - 1.5)/(2.*xeSaha + s)*xeSaha*xeSaha; /* Analytic derivative of above expression */ if (model == 0) { /* Peebles model */ Ddxedlna_Dxe = (rec_HPeebles_dxedlna(xeSaha+0.01*(1.-xeSaha), nH, H, T, T, energy_rate) - rec_HPeebles_dxedlna(xeSaha-0.01*(1.-xeSaha), nH, H, T, T, energy_rate))/0.02/(1.-xeSaha); } else if (model == 1) { /* "Recfast" model */ Ddxedlna_Dxe = (rec_HRecFast_dxedlna(xeSaha+0.01*(1.-xeSaha), nH, H, T, T, energy_rate) - rec_HRecFast_dxedlna(xeSaha-0.01*(1.-xeSaha), nH, H, T, T, energy_rate))/0.02/(1.-xeSaha); } else if (model == 2) { /* EMLA model with 2s and 2p decays only, no radiative transfer */ Ddxedlna_Dxe = (rec_HMLA_dxedlna(xeSaha+0.01*(1.-xeSaha), nH, H, T, T, energy_rate, rate_table) - rec_HMLA_dxedlna(xeSaha-0.01*(1.-xeSaha), nH, H, T, T, energy_rate, rate_table))/0.02/(1.-xeSaha); } else { /* Default mode, with radiative transfer */ Ddxedlna_Dxe = (rec_HMLA_2photon_dxedlna(xeSaha+0.01*(1.-xeSaha),nH, H, T, T, rate_table, twog, zstart, dlna, logfminus_hist, logfminus_Ly_hist, iz, z, energy_rate) - rec_HMLA_2photon_dxedlna(xeSaha-0.01*(1.-xeSaha), nH, H, T, T, rate_table, twog, zstart, dlna, logfminus_hist, logfminus_Ly_hist, iz, z, energy_rate))/0.02/(1.-xeSaha); } *Dxe = dxeSaha_dlna/Ddxedlna_Dxe; /* Compute derivative again just so the fminuses are properly updated */ //dxedlna = rec_HMLA_2photon_dxedlna(xeSaha + *Dxe, nH, H, T, T,rate_table, twog, zstart, dlna, logfminus_hist, logfminus_Ly_hist, iz, z, energy_rate); return xeSaha + *Dxe; }
void rec_get_xe_next2(REC_COSMOPARAMS *param, double z1, double xe_in, double Tm_in, double *xe_out, double *Tm_out, HRATEEFF *rate_table, int func_select, unsigned iz, TWO_PHOTON_PARAMS *twog_params, double **logfminus_hist, double *logfminus_Ly_hist[], double *z_prev, double *dxedlna_prev, double *dTmdlna_prev, double *z_prev2, double *dxedlna_prev2, double *dTmdlna_prev2) { double dxedlna, dTmdlna, Tr, nH, ainv, H; Tr = param->T0 * (ainv=1.+z1); nH = param->nH0 * ainv*ainv*ainv; H = rec_HubbleConstant(param, z1); #if (MODEL == PEEBLES) dxedlna = func_select==FUNC_HEI ? rec_helium_dxedt(xe_in, param->nH0, param->T0, param->fHe, H, z1)/H: rec_HPeebles_dxedlna(xe_in, nH*1e-6, H, Tm_in*kBoltz, Tr*kBoltz, energy_injection_rate(param,z1)); #elif (MODEL == RECFAST) dxedlna = func_select==FUNC_HEI ? rec_helium_dxedt(xe_in, param->nH0, param->T0, param->fHe, H, z1)/H: rec_HRecFast_dxedlna(xe_in, nH*1e-6, H, Tm_in*kBoltz, Tr*kBoltz, energy_injection_rate(param,z1)); #elif (MODEL == EMLA2s2p) dxedlna = func_select==FUNC_HEI ? rec_helium_dxedt(xe_in, param->nH0, param->T0, param->fHe, H, z1)/H: rec_HMLA_dxedlna(xe_in, nH*1e-6, H, Tm_in*kBoltz, Tr*kBoltz, energy_injection_rate(param,z1), rate_table); #else dxedlna = func_select==FUNC_HEI ? rec_helium_dxedt(xe_in, param->nH0, param->T0, param->fHe, H, z1)/H: func_select==FUNC_H2G ? rec_HMLA_2photon_dxedlna(xe_in, nH*1e-6, H, Tm_in*kBoltz, Tr*kBoltz, rate_table, twog_params, param->zstart, param->dlna, logfminus_hist, logfminus_Ly_hist, iz, z1, energy_injection_rate(param,z1)): func_select==FUNC_HMLA ? rec_HMLA_dxedlna(xe_in, nH*1e-6, H, Tm_in*kBoltz, Tr*kBoltz, energy_injection_rate(param,z1), rate_table) :rec_HPeebles_dxedlna(xe_in, nH*1e-6, H, Tm_in*kBoltz, Tr*kBoltz, energy_injection_rate(param,z1)); /* used for z < 20 only */ #endif dTmdlna = rec_dTmdlna(xe_in, Tm_in, Tr, H, param->fHe, nH*1e-6, energy_injection_rate(param,z1)); *xe_out = xe_in + param->dlna * (1.25 * dxedlna - 0.25 * (*dxedlna_prev2)); *Tm_out = Tm_in + param->dlna * (1.25 * dTmdlna - 0.25 * (*dTmdlna_prev2)); *z_prev2 = *z_prev; *dxedlna_prev2 = *dxedlna_prev; *dTmdlna_prev2 = *dTmdlna_prev; *z_prev = z1; *dxedlna_prev = dxedlna; *dTmdlna_prev = dTmdlna; }