Example #1
0
void solve_real_virt(double xr[2], double xv[NVIRT], double Trr[2][2], double *Trv[2], double *Tvr[2], 
                     double *Tvv[3], double sr[2], double sv[NVIRT]){

   double *Tvv_inv_Tvr[2];
   double *Tvv_inv_sv;
   double Trr_new[2][2];
   double sr_new[2];
   unsigned i, j, b;
   double det;   

   unsigned NSUBDIFF;
   NSUBDIFF = NSUBLYA - NDIFF/2;     /* lowest bin of the diffusion region */

   /** Allocate memory **/
   for (i = 0; i < 2; i++) Tvv_inv_Tvr[i] = create_1D_array(NVIRT); 
   Tvv_inv_sv = create_1D_array(NVIRT);    

    
   /*** Computing Tvv^{-1}.Tvr ***/ 
   
   for (i = 0; i < 2; i++) {
      for (b = 0; b < NSUBDIFF; b++)               Tvv_inv_Tvr[i][b] = Tvr[i][b]/Tvv[0][b];
      for (b = NSUBLYA + NDIFF/2; b < NVIRT; b++)  Tvv_inv_Tvr[i][b] = Tvr[i][b]/Tvv[0][b];
      solveTXeqB(Tvv[0]+NSUBDIFF, Tvv[2]+NSUBDIFF, Tvv[1]+NSUBDIFF, Tvv_inv_Tvr[i]+NSUBDIFF, Tvr[i]+NSUBDIFF, NDIFF);
   }

   /*** Trr_new = Trr - Trv.Tvv^{-1}.Tvr ***/ 
   for (i = 0; i < 2; i++) for (j = 0; j < 2; j++) {
          Trr_new[i][j] = Trr[i][j];
          for (b = 0; b < NVIRT; b++) Trr_new[i][j] -= Trv[i][b]*Tvv_inv_Tvr[j][b];
   }
   
   /*** Computing Tvv^{-1}.sv ***/
   for (b = 0; b < NSUBDIFF; b++)               Tvv_inv_sv[b] = sv[b]/Tvv[0][b];
   for (b = NSUBLYA + NDIFF/2; b < NVIRT; b++)  Tvv_inv_sv[b] = sv[b]/Tvv[0][b];
   solveTXeqB(Tvv[0]+NSUBDIFF, Tvv[2]+NSUBDIFF, Tvv[1]+NSUBDIFF, Tvv_inv_sv+NSUBDIFF, sv+NSUBDIFF, NDIFF); 

   /*** sr_new = sr - Trv.Tvv^{-1}sv ***/
   for (i = 0; i < 2; i++) {
      sr_new[i] = sr[i];
      for (b = 0; b < NVIRT; b++) sr_new[i] -= Trv[i][b]*Tvv_inv_sv[b];
   } 

   /*** Solve 2 by 2 system Trr_new.xr = sr_new ***/
   det = Trr_new[0][0] * Trr_new[1][1] - Trr_new[0][1] * Trr_new[1][0];
   xr[0] = (Trr_new[1][1] * sr_new[0] - Trr_new[0][1] * sr_new[1])/det;
   xr[1] = (Trr_new[0][0] * sr_new[1] - Trr_new[1][0] * sr_new[0])/det;

   /*** xv = Tvv^{-1}(sv - Tvr.xr) ***/
   for (b = 0; b < NVIRT; b++) xv[b] = Tvv_inv_sv[b] - Tvv_inv_Tvr[0][b]*xr[0] - Tvv_inv_Tvr[1][b]*xr[1];   
  
   
   /** Free memory **/
   for (i = 0; i < 2; i++) free(Tvv_inv_Tvr[i]); 
   free(Tvv_inv_sv);   
   

}
Example #2
0
void solveTXeqB(double *diag, double *updiag, double *dndiag, 
                double *X, double *B, unsigned N){
     int i;
     double denom;
     double *alpha = create_1D_array(N);
     double *gamma = create_1D_array(N);  /* X[i] = gamma[i] - alpha[i] * X[i+1] */
    
     alpha[0] = updiag[0] / diag[0];
     gamma[0] = B[0] / diag[0];
  
     for (i = 1; i < N; i++) {   
         denom = diag[i] - dndiag[i] * alpha[i-1];
         alpha[i] = updiag[i] / denom;
         gamma[i] = (B[i] - dndiag[i] * gamma[i-1]) / denom;
     }   
    
     X[N-1] = gamma[N-1];
     for (i = N-2; i >= 0; i--) X[i] = gamma[i] - alpha[i] * X[i+1];
    
     free(alpha);
     free(gamma);
}
Example #3
0
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;
}
Example #4
0
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);   
}
Example #5
0
void rec_build_history(REC_COSMOPARAMS *param, HRATEEFF *rate_table, TWO_PHOTON_PARAMS *twog_params,
                       double *xe_output, double *Tm_output) {

  
   long iz;
   double **logfminus_hist; 
   double *logfminus_Ly_hist[3];
   double H, z, z_prev, dxedlna_prev, z_prev2, dxedlna_prev2, dTmdlna_prev, dTmdlna_prev2;
   double Delta_xe;
	
   /* history of photon occupation numbers */
   logfminus_hist = create_2D_array(NVIRT, param->nz);
   logfminus_Ly_hist[0] = create_1D_array(param->nz);   /* Ly-alpha */
   logfminus_Ly_hist[1] = create_1D_array(param->nz);   /* Ly-beta  */ 
   logfminus_Ly_hist[2] = create_1D_array(param->nz);   /* Ly-gamma */ 


   z = param->zstart; 


   /********* He II + III Saha phase *********/
   Delta_xe = 1.;   /* Delta_xe = xHeIII */

   for(iz=0; iz<param->nz && Delta_xe > 1e-9; iz++) {
      z = (1.+param->zstart)*exp(-param->dlna*iz) - 1.;
      xe_output[iz] = rec_sahaHeII(param->nH0,param->T0,param->fHe,z, &Delta_xe);
      Tm_output[iz] = param->T0 * (1.+z); 
   }

   /******* He I + II post-Saha phase *********/
   Delta_xe = 0.;     /* Delta_xe = xe - xe(Saha) */
   
   for (; iz<param->nz && Delta_xe < 5e-4; iz++) {    
      z = (1.+param->zstart)*exp(-param->dlna*iz) - 1.; 
      xe_output[iz] = xe_PostSahaHe(param->nH0,param->T0,param->fHe, rec_HubbleConstant(param,z), z, &Delta_xe);
      Tm_output[iz] = param->T0 * (1.+z);
   }
   
   /****** Segment where we follow the helium recombination evolution, Tm fixed to steady state *******/ 

   z_prev2 = (1.+param->zstart)*exp(-param->dlna*(iz-3)) - 1.; 
   dxedlna_prev2 = (xe_output[iz-2] - xe_output[iz-4])/2./param->dlna;  

   z_prev = (1.+param->zstart)*exp(-param->dlna*(iz-2)) - 1.; 
   dxedlna_prev = (xe_output[iz-1] - xe_output[iz-3])/2./param->dlna;
      
   Delta_xe = 1.;  /* Difference between xe and H-Saha value */
    
   for(; iz<param->nz && (Delta_xe > 1e-4 || z > 1650.); iz++) {
   
      rec_get_xe_next1(param, z, xe_output[iz-1], xe_output+iz, rate_table, FUNC_HEI, iz-1, twog_params,
		     logfminus_hist, logfminus_Ly_hist, &z_prev, &dxedlna_prev, &z_prev2, &dxedlna_prev2); 
      
      z = (1.+param->zstart)*exp(-param->dlna*iz) - 1.; 
      Tm_output[iz] = rec_Tmss(xe_output[iz], param->T0*(1.+z), rec_HubbleConstant(param, z), param->fHe, param->nH0*cube(1.+z), energy_injection_rate(param,z)); 

      /* Starting to populate the photon occupation number with thermal values */
      update_fminus_Saha(logfminus_hist, logfminus_Ly_hist, xe_output[iz], param->T0*(1.+z)*kBoltz, 
                         param->nH0*cube(1.+z)*1e-6, twog_params, param->zstart, param->dlna, iz, z, 0);    
          
      Delta_xe = fabs(xe_output[iz]- rec_saha_xe_H(param->nH0, param->T0, z)); 
    }

 
   /******* Hydrogen post-Saha equilibrium phase *********/
   Delta_xe = 0.;  /*Difference between xe and Saha value */
   
   for(; iz<param->nz && Delta_xe < 5e-5; iz++) {
      z = (1.+param->zstart)*exp(-param->dlna*iz) - 1.; 
      H = rec_HubbleConstant(param,z);
      xe_output[iz] =  xe_PostSahaH(param->nH0*cube(1.+z)*1e-6, H, kBoltz*param->T0*(1.+z), rate_table, twog_params,
				    param->zstart, param->dlna, logfminus_hist, logfminus_Ly_hist, iz, z, &Delta_xe, MODEL, energy_injection_rate(param,z)); 
      Tm_output[iz] = rec_Tmss(xe_output[iz], param->T0*(1.+z), H, param->fHe, param->nH0*cube(1.+z), energy_injection_rate(param,z));
    }   
  
    /******* Segment where we follow the hydrogen recombination evolution with two-photon processes
             Tm fixed to steady state ******/
    
    z_prev2 = (1.+param->zstart)*exp(-param->dlna*(iz-3)) - 1.; 
    dxedlna_prev2 = (xe_output[iz-2] - xe_output[iz-4])/2./param->dlna;  
  
    z_prev = (1.+param->zstart)*exp(-param->dlna*(iz-2)) - 1.; 
    dxedlna_prev = (xe_output[iz-1] - xe_output[iz-3])/2./param->dlna;
        
    for(; iz<param->nz && 1.-Tm_output[iz-1]/param->T0/(1.+z) < 5e-4 && z > 700.; iz++) {  
    
       rec_get_xe_next1(param, z, xe_output[iz-1], xe_output+iz, rate_table, FUNC_H2G, iz-1, twog_params,
               	      logfminus_hist, logfminus_Ly_hist, &z_prev, &dxedlna_prev, &z_prev2, &dxedlna_prev2); 
       z = (1.+param->zstart)*exp(-param->dlna*iz) - 1.; 
       Tm_output[iz] = rec_Tmss(xe_output[iz], param->T0*(1.+z), rec_HubbleConstant(param, z), param->fHe, param->nH0*cube(1.+z)*1e-6, energy_injection_rate(param,z)); 
    }
     
   /******* Segment where we follow the hydrogen recombination evolution with two-photon processes
            AND Tm evolution ******/

    dTmdlna_prev2 = rec_dTmdlna(xe_output[iz-3], Tm_output[iz-3], param->T0*(1.+z_prev2), 
                                rec_HubbleConstant(param, z_prev2), param->fHe, param->nH0*cube(1.+z_prev2), energy_injection_rate(param,z_prev2));
    dTmdlna_prev  = rec_dTmdlna(xe_output[iz-2], Tm_output[iz-2], param->T0*(1.+z_prev), 
                                rec_HubbleConstant(param, z_prev), param->fHe, param->nH0*cube(1.+z_prev), energy_injection_rate(param,z_prev));      

    for(; iz<param->nz && z > 700.; iz++) { 
        
        rec_get_xe_next2(param, z, xe_output[iz-1], Tm_output[iz-1], xe_output+iz, Tm_output+iz, rate_table, FUNC_H2G,  
                        iz-1, twog_params, logfminus_hist, logfminus_Ly_hist, &z_prev, &dxedlna_prev, &dTmdlna_prev, 
                        &z_prev2, &dxedlna_prev2, &dTmdlna_prev2); 
        z = (1.+param->zstart)*exp(-param->dlna*iz) - 1.;
     }

    /***** Segment where we follow Tm as well as xe *****/ 
    /* Radiative transfer effects switched off here */
    for(; iz<param->nz && z>20.; iz++) { 
        
        rec_get_xe_next2(param, z, xe_output[iz-1], Tm_output[iz-1], xe_output+iz, Tm_output+iz, rate_table, FUNC_HMLA,  
                        iz-1, twog_params, logfminus_hist, logfminus_Ly_hist, &z_prev, &dxedlna_prev, &dTmdlna_prev, 
                        &z_prev2, &dxedlna_prev2, &dTmdlna_prev2); 
        z = (1.+param->zstart)*exp(-param->dlna*iz) - 1.;
    }
  
    /*** For z < 20 use Peeble's model. The precise model does not metter much here as 
            1) the free electron fraction is basically zero (~1e-4) in any case and 
            2) the universe is going to be reionized around that epoch 
         Tm is still evolved explicitly ***/
    for(; iz<param->nz; iz++) { 
        
        rec_get_xe_next2(param, z, xe_output[iz-1], Tm_output[iz-1], xe_output+iz, Tm_output+iz, rate_table, FUNC_PEEBLES,  
                        iz-1, twog_params, logfminus_hist, logfminus_Ly_hist, &z_prev, &dxedlna_prev, &dTmdlna_prev, 
                        &z_prev2, &dxedlna_prev2, &dTmdlna_prev2); 
        z = (1.+param->zstart)*exp(-param->dlna*iz) - 1.;
    }

    /* Cleanup */
    free_2D_array(logfminus_hist, NVIRT);
    free(logfminus_Ly_hist[0]); 
    free(logfminus_Ly_hist[1]);
    free(logfminus_Ly_hist[2]);

}