double rec_HMLA_dxedlna(double xe, double nH, double Hubble, double TM, double TR, double energy_rate, HRATEEFF *rate_table){ double Alpha[2]; double Beta[2]; double R2p2s; double matrix[2][2]; double RHS[2]; double det, RLya; double x2[2]; double x1s_db; double C_2p; double chi_ion_H; interpolate_rates(Alpha, Beta, &R2p2s, TR, TM / TR, rate_table); x1s_db = (1.-xe)*exp(-E21/TR); /******** 2s *********/ matrix[0][0] = Beta[0] + 3.*R2p2s + L2s1s; matrix[0][1] = -R2p2s; RHS[0] = xe*xe*nH *Alpha[0] + L2s1s *x1s_db; /******** 2p *********/ RLya = 4.662899067555897e15 *Hubble /nH/(1.-xe); /*8 PI H/(3 nH x1s lambda_Lya^3) */ matrix[1][1] = Beta[1] + R2p2s + RLya; matrix[1][0] = -3.*R2p2s; RHS[1] = xe*xe*nH *Alpha[1] + 3.*RLya *x1s_db; /**** invert the 2 by 2 system matrix_ij * xj = RHSi *****/ det = matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0]; x2[0] = (matrix[1][1] * RHS[0] - matrix[0][1] * RHS[1])/det; x2[1] = (matrix[0][0] * RHS[1] - matrix[1][0] * RHS[0])/det; C_2p=(RLya+R2p2s*L2s1s/matrix[0][0])/(matrix[1][1]-R2p2s*3.*R2p2s/matrix[0][0]); //chi_ion_H = (1.-xe)/3.; // old approximation from Chen and Kamionkowski if (xe < 1.) chi_ion_H = 0.369202*pow(1.-pow(xe,463929),1.70237); // coefficient as revised by Galli et al. 2013 (in fact it is a fit by Vivian Poulin of columns 1 and 4 in Table V of Galli et al. 2013) else chi_ion_H = 0.; return (x1s_db*(L2s1s + 3.*RLya) -x2[0]*L2s1s -x2[1]*RLya)/Hubble +chi_ion_H/nH*energy_rate*(1./EI+(1.-C_2p)/E21)/Hubble; }
double rec_HMLA_dxedlna(double xe, double nH, double Hubble, double TM, double TR, double energy_rate, HRATEEFF *rate_table){ double Alpha[2]; double Beta[2]; double R2p2s; double matrix[2][2]; double RHS[2]; double det, RLya; double x2[2]; double x1s_db; double C_2p; interpolate_rates(Alpha, Beta, &R2p2s, TR, TM / TR, rate_table); x1s_db = (1.-xe)*exp(-E21/TR); /******** 2s *********/ matrix[0][0] = Beta[0] + 3.*R2p2s + L2s1s; matrix[0][1] = -R2p2s; RHS[0] = xe*xe*nH *Alpha[0] + L2s1s *x1s_db; /******** 2p *********/ RLya = 4.662899067555897e15 *Hubble /nH/(1.-xe); /*8 PI H/(3 nH x1s lambda_Lya^3) */ matrix[1][1] = Beta[1] + R2p2s + RLya; matrix[1][0] = -3.*R2p2s; RHS[1] = xe*xe*nH *Alpha[1] + 3.*RLya *x1s_db; /**** invert the 2 by 2 system matrix_ij * xj = RHSi *****/ det = matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0]; x2[0] = (matrix[1][1] * RHS[0] - matrix[0][1] * RHS[1])/det; x2[1] = (matrix[0][0] * RHS[1] - matrix[1][0] * RHS[0])/det; C_2p=(RLya+R2p2s*L2s1s/matrix[0][0])/(matrix[1][1]-R2p2s*3.*R2p2s/matrix[0][0]); return (x1s_db*(L2s1s + 3.*RLya) -x2[0]*L2s1s -x2[1]*RLya)/Hubble +(1.-xe)/(3.*nH)*energy_rate*(1./EI+(1.-C_2p)/E21)/Hubble; }
double rec_HMLA_2photon_dxedlna(double xe, double nH, double H, double TM, double TR, HRATEEFF *rate_table, TWO_PHOTON_PARAMS *twog, double zstart, double dlna, double **logfminus_hist, double *logfminus_Ly_hist[], unsigned iz, double z, double energy_rate){ double xr[2]; double xv[NVIRT]; double xedot, Pib, feq; double fplus[NVIRT], fplus_Ly[3]; unsigned b, i; double Trr[2][2]; double matrix[2][2]; double *Trv[2]; double *Tvr[2]; double *Tvv[3]; double sr[2]; double sv[NVIRT]; double Dtau[NVIRT]; double Alpha[2], Beta[2]; double RLya; double R2p2s; double C_2p; for (i = 0; i < 2; i++) Trv[i] = create_1D_array(NVIRT); for (i = 0; i < 2; i++) Tvr[i] = create_1D_array(NVIRT); for (i = 0; i < 3; i++) Tvv[i] = create_1D_array(NVIRT); /* Redshift photon occupation number from previous times and higher energy bins */ fplus_from_fminus(fplus, fplus_Ly, logfminus_hist, logfminus_Ly_hist, TR, zstart, dlna, iz, z, twog->Eb_tab); /* Compute real-real, real-virtual and virtual-virtual transition rates */ populateTS_2photon(Trr, Trv, Tvr, Tvv, sr, sv, Dtau, xe, TM, TR, nH, H, rate_table, twog, fplus, fplus_Ly, Alpha, Beta, z); /* Solve for the population of the real and virtual states */ solve_real_virt(xr, xv, Trr, Trv, Tvr, Tvv, sr, sv); /*************************************************************/ /* Dark matter annihilation*/ RLya = 4.662899067555897e15 *H /nH/(1.-xe); /*8 PI H/(3 nH x1s lambda_Lya^3) */ interpolate_rates(Alpha, Beta, &R2p2s, TR, TM / TR, rate_table); matrix[0][0] = Beta[0] + 3.*R2p2s + L2s1s; matrix[1][1] = Beta[1] + R2p2s + RLya; C_2p=(RLya+R2p2s*L2s1s/matrix[0][0])/(matrix[1][1]-R2p2s*3.*R2p2s/matrix[0][0]); /*************************************************************/ /* Obtain xe_dot */ xedot = -nH*xe*xe*(Alpha[0]+Alpha[1]) + xr[0]*Beta[0] + xr[1]*Beta[1] +(1.-xe)/(3.*nH)*energy_rate*(1./EI+(1.-C_2p)/E21); /* Update fminuses */ for (b = 0; b < NVIRT; b++) { if (Dtau[b] != 0) { Pib = (1.-exp(-Dtau[b]))/Dtau[b]; feq = -xr[0]*Tvr[0][b] - xr[1]*Tvr[1][b]; feq -= (b == 0 ? xv[1]*Tvv[2][0]: b == NVIRT-1 ? xv[NVIRT-2]*Tvv[1][NVIRT-1]: xv[b+1]*Tvv[2][b] + xv[b-1]*Tvv[1][b]); feq /= (1.-xe)*(1.-Pib)*Tvv[0][b]; logfminus_hist[b][iz] = log(fplus[b] + (feq - fplus[b])*(1.-exp(-Dtau[b]))); } else logfminus_hist[b][iz] = log(fplus[b]); } /* log(xnp/(3 x1s)) , n = 2, 3, 4, assuming 3p and 4p in Boltzmann eq. with 2s */ logfminus_Ly_hist[0][iz] = log(xr[1]/3./(1.-xe)); logfminus_Ly_hist[1][iz] = log(xr[0]/(1.-xe)) - E32/TR; logfminus_Ly_hist[2][iz] = log(xr[0]/(1.-xe)) - E42/TR; for (i = 0; i < 2; i++) free(Trv[i]); for (i = 0; i < 2; i++) free(Tvr[i]); for (i = 0; i < 3; i++) free(Tvv[i]); return xedot/H; }
void populateTS_2photon(double Trr[2][2], double *Trv[2], double *Tvr[2], double *Tvv[3], double sr[2], double sv[NVIRT], double Dtau[NVIRT], double xe, double TM, double TR, double nH, double H, HRATEEFF *rate_table, TWO_PHOTON_PARAMS *twog, double fplus[NVIRT], double fplus_Ly[], double Alpha[2], double Beta[2], double z) { double R2p2s; unsigned b; double RLya, Gammab, Pib, dbfact; double *Aup, *Adn; double A2p_up, A2p_dn; Aup = create_1D_array(NVIRT); Adn = create_1D_array(NVIRT); RLya = 4.662899067555897e15 *H /nH/(1.-xe); /*8 PI H/(3 nH x1s lambda_Lya^3) */ interpolate_rates(Alpha, Beta, &R2p2s, TR, TM / TR, rate_table); /****** 2s row and column ******/ Trr[0][0] = Beta[0] + 3.*R2p2s + 3.* RLya * (1.664786871919931 *exp(-E32/TR) /* Ly-beta escape */ + 1.953125 *exp(-E42/TR)); /* Ly-gamma escape */ Trr[0][1] = -R2p2s; sr[0] = nH * Alpha[0] * xe*xe + 3.* RLya * (1.-xe) * (1.664786871919931 *fplus_Ly[1] + 1.953125 *exp(-E41/TR)); #if (EFFECT_A == 0) /* Standard treatment of 2s-->1s two-photon decays */ Trr[0][0] += L2s1s; sr[0] += L2s1s * (1.-xe) * exp(-E21/TR); #endif /****** 2p row and column ******/ Trr[1][1] = Beta[1] + R2p2s + RLya; Trr[1][0] = -3.*R2p2s; sr[1] = nH * Alpha[1] * xe*xe + 3.*RLya * (1.-xe) * fplus_Ly[0]; /***** Two-photon transitions: populating Trv, Tvr and updating Trr ******/ for (b = 0; b < NVIRT; b++) { dbfact = exp((twog->Eb_tab[b] - E21)/TR); Trr[0][0] -= Tvr[0][b] = -twog->A2s_tab[b]/fabs(exp((twog->Eb_tab[b] - E21)/TR)-1.); Trv[0][b] = Tvr[0][b] *dbfact; Trr[1][1] -= Tvr[1][b] = -exp(-E32/TR)/3. * twog->A3s3d_tab[b]/fabs(exp((twog->Eb_tab[b] - E31)/TR)-1.) -exp(-E42/TR)/3. * twog->A4s4d_tab[b]/fabs(exp((twog->Eb_tab[b] - E41)/TR)-1.); Trv[1][b] = Tvr[1][b] *3.*dbfact; } /****** Tvv and sv. Accounting for DIFFUSION ******/ populate_Diffusion(Aup, Adn, &A2p_up, &A2p_dn, TM, twog->Eb_tab, twog->A1s_tab); /* Updating Tvr, Trv, Trr for diffusion between line center ("2p state") and two neighboring bins */ Trr[1][1] += (A2p_dn + A2p_up); for (b = 0; b < NVIRT; b++) { Gammab = -(Trv[0][b] + Trv[1][b]) + Aup[b] + Adn[b]; /* Inverse lifetime of virtual state b */ /*** Diffusion region ***/ if ( (b >= NSUBLYA - NDIFF/2 && b < NSUBLYA - 1) ||(b > NSUBLYA && b < NSUBLYA + NDIFF/2)) { Tvv[1][b] = -Aup[b-1]; Tvv[2][b] = -Adn[b+1]; } /* Bins neighboring Lyman alpha. */ if (b == NSUBLYA-1) { Tvv[1][b] = -Aup[b-1]; Tvv[2][b] = 0.; Tvr[1][b] -= A2p_dn; Trv[1][b] -= Aup[b]; } if (b == NSUBLYA) { Tvv[1][b] = 0.; Tvv[2][b] = -Adn[b+1]; Tvr[1][b] -= A2p_up; Trv[1][b] -= Adn[b]; } /*********************/ Dtau[b] = Gammab * (1.-xe) * cube(hPc/twog->Eb_tab[b]) * nH /8. /M_PI /H; if (Dtau[b] > 1e-30) { Pib = (1.-exp(-Dtau[b]))/Dtau[b]; Tvv[0][b] = Gammab/(1.-Pib); sv[b] = Tvv[0][b] * (1.-xe) * fplus[b] * Pib; } else { /* Nearly vanishing optical depth: free streaming */ Tvv[0][b] = 1.; Trv[0][b] = Trv[1][b] = Tvr[0][b] = Tvr[1][b] = 0; sv[b] = (1.-xe) * fplus[b]; } } free(Aup); free(Adn); }