From 44cd0eb71f815906b521f372a38857eca4f80ad3 Mon Sep 17 00:00:00 2001 From: "P.M. Sutter" Date: Mon, 30 Dec 2013 22:48:07 -0600 Subject: [PATCH] beginning to fold in HOD code with jeremy tinker's approval --- c_tools/hod/amoeba.c | 64 + c_tools/hod/amotry.c | 25 + c_tools/hod/aspen_breakout.c | 301 ++++ c_tools/hod/brent.c | 74 + c_tools/hod/buh.c | 2289 ++++++++++++++++++++++++ c_tools/hod/chi2_dist.c | 44 + c_tools/hod/chi2_grid.c | 124 ++ c_tools/hod/cisi.c | 80 + c_tools/hod/cobenorm.c | 168 ++ c_tools/hod/color_samples.c | 488 +++++ c_tools/hod/complex.c | 125 ++ c_tools/hod/complex.h | 26 + c_tools/hod/covar_test.c | 114 ++ c_tools/hod/dFdx.c | 157 ++ c_tools/hod/dark_matter_statistics.c | 161 ++ c_tools/hod/density_dependence.c | 220 +++ c_tools/hod/dump.c | 15 + c_tools/hod/f1dim.c | 18 + c_tools/hod/fit_scale_bias.c | 105 ++ c_tools/hod/ftread.c | 51 + c_tools/hod/ftwrite.c | 38 + c_tools/hod/galaxy_prob_vz.c | 484 +++++ c_tools/hod/gasdev.c | 24 + c_tools/hod/gaussj.c | 59 + c_tools/hod/growthfactor.c | 73 + c_tools/hod/halo_bias.c | 300 ++++ c_tools/hod/halo_bias_error.c | 178 ++ c_tools/hod/halo_concentration.c | 155 ++ c_tools/hod/halo_exclusion.c | 100 ++ c_tools/hod/halo_mass_conversion.c | 86 + c_tools/hod/halo_mass_function.c | 338 ++++ c_tools/hod/halo_mass_function_error.c | 146 ++ c_tools/hod/header.c | 96 + c_tools/hod/header.h | 536 ++++++ c_tools/hod/hod_functions.c | 598 +++++++ c_tools/hod/hod_functions2.c | 403 +++++ c_tools/hod/i3tensor_2.c | 58 + c_tools/hod/input_params.c | 788 ++++++++ c_tools/hod/integrated_bin.c | 32 + c_tools/hod/jacobi.c | 87 + c_tools/hod/jeans.c | 95 + c_tools/hod/jet_pvz_temp.c | 375 ++++ c_tools/hod/kaiser_distortions.c | 432 +++++ c_tools/hod/least_squares.c | 22 + c_tools/hod/linlin_bins.c | 60 + c_tools/hod/linmin.c | 38 + c_tools/hod/m2n_mcmc.c | 1083 +++++++++++ c_tools/hod/m2n_mcmc_new.c | 1047 +++++++++++ c_tools/hod/m2n_mcmc_using_PMN.c | 1036 +++++++++++ c_tools/hod/main.c | 109 ++ c_tools/hod/mass2number.c | 69 + c_tools/hod/mcmc.c | 469 +++++ c_tools/hod/mcmc_color.c | 539 ++++++ c_tools/hod/mcmc_exp.c | 632 +++++++ c_tools/hod/mcmc_with_errors.c | 425 +++++ c_tools/hod/meshlink2.c | 91 + c_tools/hod/midinf.c | 29 + c_tools/hod/midpnt.c | 28 + c_tools/hod/mnbrak.c | 64 + c_tools/hod/mstar.c | 39 + c_tools/hod/nbody_xi.c | 432 +++++ c_tools/hod/nbrsfind2.c | 139 ++ c_tools/hod/nfw_transform.c | 36 + c_tools/hod/nonlinear_power_spectrum.c | 204 +++ c_tools/hod/nrutil.c | 293 +++ c_tools/hod/nrutil.h | 77 + c_tools/hod/old.c | 376 ++++ c_tools/hod/one_halo_rspace.c | 231 +++ c_tools/hod/output_params.c | 349 ++++ c_tools/hod/pair_density.c | 175 ++ c_tools/hod/polint.c | 39 + c_tools/hod/populate_simulation.c | 702 ++++++++ c_tools/hod/powell.c | 58 + c_tools/hod/powspec.c | 214 +++ c_tools/hod/qromo.c | 34 + c_tools/hod/qtrap.c | 20 + c_tools/hod/ran1.c | 47 + c_tools/hod/ran2.c | 63 + c_tools/hod/sigmac.c | 173 ++ c_tools/hod/sort2.c | 81 + c_tools/hod/splie2.c | 13 + c_tools/hod/splin2.c | 23 + c_tools/hod/spline.c | 38 + c_tools/hod/splint.c | 36 + c_tools/hod/tasks.c | 170 ++ c_tools/hod/test.c | 5 + c_tools/hod/tf_eisenstein_hu.c | 140 ++ c_tools/hod/transfnc.c | 70 + c_tools/hod/transfunc_file.c | 59 + c_tools/hod/trapzd.c | 89 + c_tools/hod/two_halo_rspace.c | 511 ++++++ c_tools/hod/utility.c | 142 ++ c_tools/hod/wp_minimization.c | 745 ++++++++ c_tools/hod/xi_matter.c | 180 ++ c_tools/hod/zbrent.c | 76 + 95 files changed, 21950 insertions(+) create mode 100644 c_tools/hod/amoeba.c create mode 100644 c_tools/hod/amotry.c create mode 100644 c_tools/hod/aspen_breakout.c create mode 100644 c_tools/hod/brent.c create mode 100644 c_tools/hod/buh.c create mode 100644 c_tools/hod/chi2_dist.c create mode 100644 c_tools/hod/chi2_grid.c create mode 100644 c_tools/hod/cisi.c create mode 100644 c_tools/hod/cobenorm.c create mode 100644 c_tools/hod/color_samples.c create mode 100644 c_tools/hod/complex.c create mode 100644 c_tools/hod/complex.h create mode 100644 c_tools/hod/covar_test.c create mode 100644 c_tools/hod/dFdx.c create mode 100644 c_tools/hod/dark_matter_statistics.c create mode 100644 c_tools/hod/density_dependence.c create mode 100644 c_tools/hod/dump.c create mode 100644 c_tools/hod/f1dim.c create mode 100644 c_tools/hod/fit_scale_bias.c create mode 100644 c_tools/hod/ftread.c create mode 100644 c_tools/hod/ftwrite.c create mode 100644 c_tools/hod/galaxy_prob_vz.c create mode 100644 c_tools/hod/gasdev.c create mode 100644 c_tools/hod/gaussj.c create mode 100644 c_tools/hod/growthfactor.c create mode 100644 c_tools/hod/halo_bias.c create mode 100644 c_tools/hod/halo_bias_error.c create mode 100644 c_tools/hod/halo_concentration.c create mode 100644 c_tools/hod/halo_exclusion.c create mode 100644 c_tools/hod/halo_mass_conversion.c create mode 100644 c_tools/hod/halo_mass_function.c create mode 100644 c_tools/hod/halo_mass_function_error.c create mode 100644 c_tools/hod/header.c create mode 100644 c_tools/hod/header.h create mode 100644 c_tools/hod/hod_functions.c create mode 100644 c_tools/hod/hod_functions2.c create mode 100644 c_tools/hod/i3tensor_2.c create mode 100644 c_tools/hod/input_params.c create mode 100644 c_tools/hod/integrated_bin.c create mode 100644 c_tools/hod/jacobi.c create mode 100644 c_tools/hod/jeans.c create mode 100644 c_tools/hod/jet_pvz_temp.c create mode 100644 c_tools/hod/kaiser_distortions.c create mode 100644 c_tools/hod/least_squares.c create mode 100644 c_tools/hod/linlin_bins.c create mode 100644 c_tools/hod/linmin.c create mode 100644 c_tools/hod/m2n_mcmc.c create mode 100644 c_tools/hod/m2n_mcmc_new.c create mode 100644 c_tools/hod/m2n_mcmc_using_PMN.c create mode 100644 c_tools/hod/main.c create mode 100644 c_tools/hod/mass2number.c create mode 100644 c_tools/hod/mcmc.c create mode 100644 c_tools/hod/mcmc_color.c create mode 100644 c_tools/hod/mcmc_exp.c create mode 100644 c_tools/hod/mcmc_with_errors.c create mode 100644 c_tools/hod/meshlink2.c create mode 100644 c_tools/hod/midinf.c create mode 100644 c_tools/hod/midpnt.c create mode 100644 c_tools/hod/mnbrak.c create mode 100644 c_tools/hod/mstar.c create mode 100644 c_tools/hod/nbody_xi.c create mode 100644 c_tools/hod/nbrsfind2.c create mode 100644 c_tools/hod/nfw_transform.c create mode 100644 c_tools/hod/nonlinear_power_spectrum.c create mode 100644 c_tools/hod/nrutil.c create mode 100644 c_tools/hod/nrutil.h create mode 100644 c_tools/hod/old.c create mode 100644 c_tools/hod/one_halo_rspace.c create mode 100644 c_tools/hod/output_params.c create mode 100644 c_tools/hod/pair_density.c create mode 100644 c_tools/hod/polint.c create mode 100644 c_tools/hod/populate_simulation.c create mode 100644 c_tools/hod/powell.c create mode 100644 c_tools/hod/powspec.c create mode 100644 c_tools/hod/qromo.c create mode 100644 c_tools/hod/qtrap.c create mode 100644 c_tools/hod/ran1.c create mode 100644 c_tools/hod/ran2.c create mode 100644 c_tools/hod/sigmac.c create mode 100644 c_tools/hod/sort2.c create mode 100644 c_tools/hod/splie2.c create mode 100644 c_tools/hod/splin2.c create mode 100644 c_tools/hod/spline.c create mode 100644 c_tools/hod/splint.c create mode 100644 c_tools/hod/tasks.c create mode 100644 c_tools/hod/test.c create mode 100644 c_tools/hod/tf_eisenstein_hu.c create mode 100644 c_tools/hod/transfnc.c create mode 100644 c_tools/hod/transfunc_file.c create mode 100644 c_tools/hod/trapzd.c create mode 100644 c_tools/hod/two_halo_rspace.c create mode 100644 c_tools/hod/utility.c create mode 100644 c_tools/hod/wp_minimization.c create mode 100644 c_tools/hod/xi_matter.c create mode 100644 c_tools/hod/zbrent.c diff --git a/c_tools/hod/amoeba.c b/c_tools/hod/amoeba.c new file mode 100644 index 0000000..a856e9e --- /dev/null +++ b/c_tools/hod/amoeba.c @@ -0,0 +1,64 @@ +#include +#define NRANSI +#include "nrutil.h" +#define NMAX 5000 +#define GET_PSUM \ + for (j=1;j<=ndim;j++) {\ + for (sum=0.0,i=1;i<=mpts;i++) sum += p[i][j];\ + psum[j]=sum;} +#define SWAP(a,b) {swap=(a);(a)=(b);(b)=swap;} + +void amoeba(double **p, double y[], int ndim, double ftol, + double (*funk)(double []), int *nfunk) +{ + double amotry(double **p, double y[], double psum[], int ndim, + double (*funk)(double []), int ihi, double fac); + int i,ihi,ilo,inhi,j,mpts=ndim+1; + double rtol,sum,swap,ysave,ytry,*psum; + + psum=dvector(1,ndim); + *nfunk=0; + GET_PSUM + for (;;) { + ilo=1; + ihi = y[1]>y[2] ? (inhi=2,1) : (inhi=1,2); + for (i=1;i<=mpts;i++) { + if (y[i] <= y[ilo]) ilo=i; + if (y[i] > y[ihi]) { + inhi=ihi; + ihi=i; + } else if (y[i] > y[inhi] && i != ihi) inhi=i; + } + rtol=2.0*fabs(y[ihi]-y[ilo])/(fabs(y[ihi])+fabs(y[ilo])); + if (rtol < ftol) { + SWAP(y[1],y[ilo]) + for (i=1;i<=ndim;i++) SWAP(p[1][i],p[ilo][i]) + break; + } + if (*nfunk >= NMAX) nrerror("NMAX exceeded"); + *nfunk += 2; + ytry=amotry(p,y,psum,ndim,funk,ihi,-1.0); + if (ytry <= y[ilo]) + ytry=amotry(p,y,psum,ndim,funk,ihi,2.0); + else if (ytry >= y[inhi]) { + ysave=y[ihi]; + ytry=amotry(p,y,psum,ndim,funk,ihi,0.5); + if (ytry >= ysave) { + for (i=1;i<=mpts;i++) { + if (i != ilo) { + for (j=1;j<=ndim;j++) + p[i][j]=psum[j]=0.5*(p[i][j]+p[ilo][j]); + y[i]=(*funk)(psum); + } + } + *nfunk += ndim; + GET_PSUM + } + } else --(*nfunk); + } + free_dvector(psum,1,ndim); +} +#undef SWAP +#undef GET_PSUM +#undef NMAX +#undef NRANSI diff --git a/c_tools/hod/amotry.c b/c_tools/hod/amotry.c new file mode 100644 index 0000000..d13ecb6 --- /dev/null +++ b/c_tools/hod/amotry.c @@ -0,0 +1,25 @@ +#define NRANSI +#include "nrutil.h" + +double amotry(double **p, double y[], double psum[], int ndim, + double (*funk)(double []), int ihi, double fac) +{ + int j; + double fac1,fac2,ytry,*ptry; + + ptry=dvector(1,ndim); + fac1=(1.0-fac)/ndim; + fac2=fac1-fac; + for (j=1;j<=ndim;j++) ptry[j]=psum[j]*fac1-p[ihi][j]*fac2; + ytry=(*funk)(ptry); + if (ytry < y[ihi]) { + y[ihi]=ytry; + for (j=1;j<=ndim;j++) { + psum[j] += ptry[j]-p[ihi][j]; + p[ihi][j]=ptry[j]; + } + } + free_dvector(ptry,1,ndim); + return ytry; +} +#undef NRANSI diff --git a/c_tools/hod/aspen_breakout.c b/c_tools/hod/aspen_breakout.c new file mode 100644 index 0000000..7022879 --- /dev/null +++ b/c_tools/hod/aspen_breakout.c @@ -0,0 +1,301 @@ +#include +#include +#include +#include + +#ifdef PARALLEL +#include +#endif + +#include "header.h" + +void output_hod(char fname[]); +void output_wp(char fname[]); +double func_find_mone(double m); +double func_find_mone2(double m); +double func_find_alpha(double a); +double fsat_g1; + +void aspen_breakout() +{ + int i,j,k,i1; + double x1,x2,x3,x4,x5,x6,r,dr,fsat,m1,mcut,mmin,dlogm; + char fname[100]; + FILE *fp; + + //goto loop_m1; + // goto loop_cvir; + //goto loop_alpha; + //goto loop_mcut2; + + /* Vary M_min, find M1 such that fsat is fixed. + */ + OUTPUT=3; + HOD.alpha = 1.0; + for(i=1;i<=5;++i) + { + muh(0); + RESET_FLAG_1H++; + RESET_FLAG_2H++; + RESET_KAISER++; + + sprintf(Task.root_filename,"fsat.%d",i); + + HOD.M_min = pow(10.0,i+9.0); + HOD.M_cut = 4*HOD.M_min; + if(i==1) { + HOD.M1 = 30*HOD.M_min; + set_HOD_params(); + fsat = fsat_g1 = qromo(func_satfrac,log(HOD.M_min),log(HOD.M_max),midpnt)/GALAXY_DENSITY; + fprintf(stderr,"%e %e %e %f %f\n",HOD.M_min,HOD.M1,GALAXY_DENSITY,fsat,HOD.M1/HOD.M_min); + muh(2); + } + set_HOD_params(); + HOD.M1 = exp(zbrent(func_find_mone2,log(HOD.M_low/10),log(HOD.M_max),1.0E-4)); + fsat = qromo(func_satfrac,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY; + + fprintf(stdout,"MUH %e %e %e %f %f\n",HOD.M_min,HOD.M1,GALAXY_DENSITY,fsat,HOD.M1/HOD.M_min); + + sprintf(fname,"fsat_1h.%d",i); + output_wp(fname); + sprintf(fname,"fsat_wp.%d",i); + output_wp(fname); + sprintf(fname,"fsat_hod.%d",i); + output_hod(fname); + + } + exit(0); + + /* Vary sigma8 at fixed HOD/ngal (so change mmin) + */ + for(i=0;i<=3;++i) + { + SIGMA_8 = 0.9*growthfactor((double)i); + fprintf(stderr,"z=%d, sigma8= %f\n",i,SIGMA_8); + RESET_COSMOLOGY++; + RESET_FLAG_1H++; + RESET_FLAG_2H++; + RESET_KAISER++; + //HOD.M_min = 0; + set_HOD_params(); + + sprintf(fname,"SIGMA8a.%d",i); + output_wp(fname); + } + exit(0); + SIGMA_8=0.9; + RESET_COSMOLOGY++; + + loop_m1: + + /* Vary fsat by varying M1 + */ + + m1 = HOD.M1; + i1 = 0; + for(i=-2;i<=2;++i) + { + HOD.M1 = m1*pow(10.0,i/10.0); + RESET_FLAG_1H++; + RESET_FLAG_2H++; + RESET_KAISER++; + HOD.M_min = HOD.M_low = 0; + set_HOD_params(); + + fsat = qromo(func_satfrac,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY; + fprintf(stderr,"M1= %e fsat=%f\n",HOD.M1,fsat); + + sprintf(fname,"M1_wp.%d",++i1); + output_wp(fname); + sprintf(fname,"M1_hod.%d",i1); + output_hod(fname); + } + HOD.M1 = m1; + exit(0); + + loop_mcut1: + + /* Vary M_cut, fix M1 and fsat + */ + mcut = HOD.M_cut; + HOD.M_min = 0; + set_HOD_params(); + + dlogm = (log(HOD.M1) - log(HOD.M_min))/4; + mmin = log(HOD.M_min); + + fsat_g1 = qromo(func_satfrac,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY; + i1 = 0; + for(i=0;i<5;++i) + { + HOD.M_cut = exp(dlogm*i+mmin); + HOD.M1 = exp(zbrent(func_find_mone,log(HOD.M_min),log(HOD.M_max),1.0E-4)); + + RESET_FLAG_1H++; + RESET_FLAG_2H++; + RESET_KAISER++; + HOD.M_min = HOD.M_low = 0; + set_HOD_params(); + + fprintf(stderr,"M_cut= %e M1= %e %f\n",HOD.M_cut,HOD.M1,HOD.M1/HOD.M_cut); + + sprintf(fname,"Mcut1_wp.%d",++i1); + output_wp(fname); + sprintf(fname,"Mcut1_hod.%d",i1); + output_hod(fname); + } + + loop_mcut2: + + /* Vary M_cut/fsat, keep M_cut/M1 = 1 + */ + mcut = 3.0e13; + m1 = 3.0e13; + + i1 = 0; + dlogm = (log(3.0e13) - log(10.0e12))/4; + for(i=0;i<5;++i) + { + HOD.M_cut = HOD.M1 = exp(dlogm*i)*10.0e12; + + RESET_FLAG_1H++; + RESET_FLAG_2H++; + RESET_KAISER++; + HOD.M_min = HOD.M_low = 0; + set_HOD_params(); + + fsat = qromo(func_satfrac,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY; + fprintf(stderr,"M_min= %e M1= %e fsat=%f\n",HOD.M_min,HOD.M1,fsat); + + + sprintf(fname,"Mcut2_wp.%d",++i1); + output_wp(fname); + sprintf(fname,"Mcut2_hod.%d",i1); + output_hod(fname); + } + + loop_alpha: + + /* Vary Mcut as above, but fix f_sat by varying alpha + */ + mcut = 3.0e13; + m1 = 3.0e13; + + i1 = 0; + mmin = log(6.0e12); + dlogm = (log(3.0e13) - mmin)/4; + HOD.M_cut = HOD.M1 = exp(mmin); + + HOD.alpha = 0.1; + HOD.M_min = HOD.M_low = 0; + set_HOD_params(); + + fsat = qromo(func_satfrac,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY; + fprintf(stderr,"fsat = %f %e\n",fsat,HOD.M_min); + for(i=0;i<5;++i) + { + HOD.M_cut = HOD.M1 = exp(dlogm*i + mmin); + + RESET_FLAG_1H++; + RESET_FLAG_2H++; + RESET_KAISER++; + + HOD.alpha = zbrent(func_find_alpha,0.05,2.0,1.0E-4); + fprintf(stderr,"M_cut= %e alpha = %f\n",HOD.M_cut,HOD.alpha); + + + sprintf(fname,"alpha_wp.%d",++i1); + output_wp(fname); + sprintf(fname,"alpha_hod.%d",i1); + output_hod(fname); + } + + loop_cvir: + + /* Vary cvir with central one above + */ + HOD.M_cut = HOD.M1 = exp(dlogm*2 + mmin); + + HOD.alpha = zbrent(func_find_alpha,0.05,2.0,1.0E-4); + fprintf(stderr,"M_cut= %e alpha = %f\n",HOD.M_cut,HOD.alpha); + + i1 = 0; + for(i=0;i<5;++i) + { + CVIR_FAC = pow(3.0,i-2); + RESET_FLAG_1H++; + RESET_FLAG_2H++; + RESET_KAISER++; + + sprintf(fname,"cvir_wp.%d",++i1); + output_wp(fname); + sprintf(fname,"cvir_hod.%d",i1); + output_hod(fname); + } + + exit(0); +} + +double func_find_alpha(double a) +{ + HOD.alpha = a; + return qromo(func_galaxy_density,log(HOD.M_low),log(HOD.M_max),midpnt) - GALAXY_DENSITY; +} + +double func_find_mone(double m) +{ + double fsat; + HOD.M1=exp(m); + HOD.M_min = 0; + set_HOD_params(); + fsat = qromo(func_satfrac,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY; + return fsat-fsat_g1; +} +double func_find_mone2(double m) +{ + double fsat; + HOD.M1=exp(m); + set_HOD_params(); + fsat = qromo(func_satfrac,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY; + return fsat-fsat_g1; +} + +void output_hod(char fname[]) +{ + FILE *fp; + double dlogm,sig,m; + int i; + + fp=fopen(fname,"w"); + dlogm=(log(HOD.M_max)-log(HOD.M_low))/99; + for(i=1;i<=100;++i) + { + m=exp((i-1)*dlogm)*HOD.M_low; + sig = N_sat(m)*N_sat(m) + N_cen(m)*(1-N_cen(m)); + fprintf(fp,"%e %e %e %e %e %e\n", + m,N_cen(m),N_sat(m),N_avg(m),sig,sig/(N_avg(m)*N_avg(m))); + } + fclose(fp); +} + +void output_wp(char fname[]) +{ + FILE *fp; + double r,dr,x1,x2,x3,x4,x5; + int j; + + fp=fopen(fname,"w"); + dr=(log(70.0)-log(0.05))/49.0; + for(j=0;j<50;++j) + { + r=exp(j*dr+log(0.05)); + x1=one_halo_real_space(r); + x2=two_halo_real_space(r); + x3=projected_xi(r); + //x4 = projected_xi1h(r); + //x5 = projected_xi2h(r); + fprintf(fp,"%f %e %e %e %e\n",r,x1,x2,x1+x2,x3); + fflush(fp); + } + fclose(fp); +} diff --git a/c_tools/hod/brent.c b/c_tools/hod/brent.c new file mode 100644 index 0000000..ce843b6 --- /dev/null +++ b/c_tools/hod/brent.c @@ -0,0 +1,74 @@ +#include +#define NRANSI +#include "nrutil.h" +#define ITMAX 100 +#define CGOLD 0.3819660 +#define ZEPS 1.0e-10 +#define SHFT(a,b,c,d) (a)=(b);(b)=(c);(c)=(d); + +double brent(double ax, double bx, double cx, double (*f)(double), double tol, + double *xmin) +{ + int iter; + double a,b,d,etemp,fu,fv,fw,fx,p,q,r,tol1,tol2,u,v,w,x,xm; + double e=0.0; + + a=(ax < cx ? ax : cx); + b=(ax > cx ? ax : cx); + x=w=v=bx; + fw=fv=fx=(*f)(x); + for (iter=1;iter<=ITMAX;iter++) { + xm=0.5*(a+b); + tol2=2.0*(tol1=tol*fabs(x)+ZEPS); + if (fabs(x-xm) <= (tol2-0.5*(b-a))) { + *xmin=x; + return fx; + } + if (fabs(e) > tol1) { + r=(x-w)*(fx-fv); + q=(x-v)*(fx-fw); + p=(x-v)*q-(x-w)*r; + q=2.0*(q-r); + if (q > 0.0) p = -p; + q=fabs(q); + etemp=e; + e=d; + if (fabs(p) >= fabs(0.5*q*etemp) || p <= q*(a-x) || p >= q*(b-x)) + d=CGOLD*(e=(x >= xm ? a-x : b-x)); + else { + d=p/q; + u=x+d; + if (u-a < tol2 || b-u < tol2) + d=SIGN(tol1,xm-x); + } + } else { + d=CGOLD*(e=(x >= xm ? a-x : b-x)); + } + u=(fabs(d) >= tol1 ? x+d : x+SIGN(tol1,d)); + fu=(*f)(u); + if (fu <= fx) { + if (u >= x) a=x; else b=x; + SHFT(v,w,x,u) + SHFT(fv,fw,fx,fu) + } else { + if (u < x) a=u; else b=u; + if (fu <= fw || w == x) { + v=w; + w=u; + fv=fw; + fw=fu; + } else if (fu <= fv || v == x || v == w) { + v=u; + fv=fu; + } + } + } + nrerror("Too many iterations in brent"); + *xmin=x; + return fx; +} +#undef ITMAX +#undef CGOLD +#undef ZEPS +#undef SHFT +#undef NRANSI diff --git a/c_tools/hod/buh.c b/c_tools/hod/buh.c new file mode 100644 index 0000000..4cbb50b --- /dev/null +++ b/c_tools/hod/buh.c @@ -0,0 +1,2289 @@ +#include +#include +#include +#include +#include + +#ifdef PARALLEL +#include +#endif + +#include "header.h" + +#define MAGSOL 5.33 + +/* Data structures to hold multiple correlation functions + * and their corresponding covariance matrices. + */ + +struct WP_ARRAY { + double *x; + double *r; + double *e; + double *eigen; + double **covar; + + double mag1; + double mag2; + double mean_mag; + double ngal; + int np; + + double M_min; + double sigma_logM; + double M1; + double M_low; + double M_cut; + double mmin_hi; + +} wp_array[15]; + +struct gao_parameters { + double f0; + double s0; +} GAO; + +double **covar_array[15]; + +/* Local globals for qromo + */ +double *mass_g9, + *lum_g9, + *sig_g9, + *y_lum_g9, + *y_sig_g9, + curlum_g9, + OMEGA_TEMP; +int n_g9, + VARY_GAMMA=0, + VARY_CVIR=0, + VARY_ALPHA=0; + + +/* External function for density dependence. + */ +void dd_hod_functions(float *hmass, float *hdensity, int nhalo); + + +/* Local functions. + */ +void ml_input_data(int); +void switch_wp_data(int n); +double schechter(double mag, double mstar, double phi0,double alpha); +double func_integrate_schechter(double m); +double func_integrate_lum_schechter(double m); +double ml_initialize(int nwp, int nhod, double *a, double **cov1, double *avg1, double *start_dev); + +double chi2_ml_function(int count); +void mass2light_functions(int n_wp, double *a); +double total_halo_light(double mass, int n_wp, double *a, double *ss); +double func_ml_lum(double m); +double func_ml_norm(double m); +double chi2_CNOC_data(int count); + +double chi2_ml_wrapper(double *a); + +void ml_function_test(int n_wp, double *a); +void ml_function_test_monte_carlo(int n_wp, double *a); +int poisson_deviate(double nave); +double poisson_prob(int n, double nave); +void dispersion_test(int n_wp, double *a, double mass); +double random_luminosity(double m1, double m2); +void calc_multiplicity_function(int n_wp, int n_start); +double chi2_multiplicity_function(int count); +void analyze_chain(void); + +void output_wp_fits(int n_wp, double *a); + +/* Local Functions for simulation population. + */ +double NFW_density(double r, double rs, double ps); +double NFW_velocity(double mass, double v[]); +void NFW_position(double mass, double x[]); +void ml_mock_catalog(int n_wp, double *a); +double random_2df_magnitude_error(void); +void ml_mock_catalog_gao(int n_wp, double *a); +double N_cen_gao(double m, int ii, double *mmin); +double N_cen_hiden(double m); + +/* External functions. + */ +double chi2_wp_wrapper(double *a); + +void ml_minimization() +{ + int i,j,k,n_wp=9,n_hod=0,n1,n2,n3; + + double stepfac=1; + double error=1,tolerance=0,**cov1,**tmp,*a,*a1,*avg1,chi2,chi2prev,*start_dev, + **evect,*eval,*aprev,*atemp,**tmp1,*opar,x1,fsat,chi2array[15],**chain,x,x2,x3; + int n,nrot,niter=0,count=0,imax_chain=30000,NSTEP = 50; + long IDUM=-555; + + int *pcheck,pcnt,ptot=10,nancheck,astart[10]; + + + + fprintf(stderr,"\n\nCHI2 MINIMIZATION OF M/L DATA..........\n"); + fprintf(stderr, "--------------------------------------------\n\n"); + + ml_input_data(n_wp); + + Work.imodel=2; + Work.chi2=1; + HOD.pdfc = 9; + + /* In Zehavi et al, this is 40 Mpc/h, + * but Norberg et al use 50. + */ + wp.pi_max=50.0; + + srand48(32498793); + + astart[0] = 1; + for(i=1;i<=5;++i) + astart[i] = astart[i-1] + 2; + for(i=6;i<=8;++i) + astart[i] = astart[i-1] + 3; + + n = astart[8]+2; + if(HOD.free[3]) { + VARY_ALPHA=1; + HOD.free[3] = 0; + n++; + } + if(HOD.free[6]) { + VARY_CVIR=1; + HOD.free[6] = 0; + n++; + } + if(HOD.free[10]==2) { + VARY_GAMMA=1; + HOD.free[10]=0; + } + + for(i=8;i<100;++i) + if(HOD.free[i]) { n++; MCMC++; } + OMEGA_TEMP = 1.651693e-01; + + printf("mcmc_min> %d free parameters\n",n); + + pcheck=calloc(ptot,sizeof(int)); + + a=dvector(1,n); + start_dev=dvector(1,n); + a1=dvector(1,n_hod); + aprev=dvector(1,n); + atemp=dvector(1,n); + cov1=dmatrix(1,n,1,n); + avg1=dvector(1,n); + + tmp=dmatrix(1,n,1,n); + tmp1=dmatrix(1,n,1,1); + evect=dmatrix(1,n,1,n); + eval=dvector(1,n); + + chain=dmatrix(1,imax_chain,1,n); + + chi2prev=ml_initialize(n_wp,n_hod,a,cov1,avg1,start_dev); + + + if(IDUM_MCMC==-1) + mass2light_functions(n_wp,a); + if(IDUM_MCMC==-2) + ml_mock_catalog(n_wp,a); + if(IDUM_MCMC==-3) + { + calc_multiplicity_function(n_wp,2); + calc_multiplicity_function(n_wp,5); + exit(0); + } + if(IDUM_MCMC==-4) + { + output_wp_fits(n_wp,a); + exit(0); + } + if(IDUM_MCMC==-5) + ml_mock_catalog_gao(n_wp,a); + if(IDUM_MCMC==-6) + ml_function_test(n_wp,a); + if(IDUM_MCMC==-7) + ml_function_test_monte_carlo(n_wp,a); + if(IDUM_MCMC==-8) + analyze_chain(); + + niter++; + for(i=1;i<=n;++i) + aprev[i] = a[i]; + + for(i=1;i<=n;++i) + chain[niter][i]=a[i]; + + IDUM=IDUM_MCMC; + + pcnt=0; + pcheck[pcnt]=1; + + stepfac=1; + while(niter1) + { + RESET_COSMOLOGY++; + i = 7; + j = astart[8]+2+VARY_ALPHA+VARY_CVIR; + if(HOD.free[++i])OMEGA_TEMP = a[++j]; + if(HOD.free[++i])SIGMA_8 = a[++j]; + if(HOD.free[++i])GAMMA = a[++j]; + if(HOD.free[++i])VBIAS = a[++j]; + if(HOD.free[++i])VBIAS_C = a[++j]; + if(HOD.free[++i])SIGV = a[++j]; + if(HOD.free[++i])SPECTRAL_INDX = a[++j]; + + if(VARY_GAMMA) + GAMMA = gasdev(&IDUM)*0.02 + 0.15; + printf("COSMO %d %f %f %f %d\n",count+1,OMEGA_TEMP,SIGMA_8,GAMMA,j); + } + + chi2=0; + + /* Restrict CVIR_FAC + */ + i = astart[8]+3+VARY_ALPHA; + if(VARY_CVIR) + if(a[i]<0.3 || a[i]>1.2)continue; + if(HOD.free[10]) + if(GAMMA<0.11 && GAMMA>0.19)continue; + + ++count; + for(i=n_wp-1;i>=0;--i) + { + n_hod = 3; + HOD.free[5] = 1; + if(i<6){ n_hod = 2; HOD.free[5] = 0; HOD.sigma_logM = 0.2; } + for(k=0,j=astart[i];j<=astart[i]+n_hod-1;++j) + { + a1[++k] = a[j]; + } + if(VARY_ALPHA) + HOD.alpha = a[astart[8]+3]; + if(VARY_CVIR) + CVIR_FAC = a[astart[8]+4]; + wp.ncf = n_hod; + + switch_wp_data(i); + chi2+=chi2array[i]=chi2_wp_wrapper(a1); + + wp_array[i].M_min = HOD.M_min; + wp_array[i].sigma_logM = HOD.sigma_logM; + wp_array[i].M1 = HOD.M1; + wp_array[i].M_low = HOD.M_low; + wp_array[i].M_cut = HOD.M_cut; + + if(!ThisTask) + { + printf("TRY%d %d ",i,count); + for(j=1;j<=n_hod;++j) + printf("%.4e ",a1[j]); + printf("%e\n",chi2array[i]); + fflush(stdout); + } + } + chi2+=chi2_ml_function(count); + chi2+=chi2_multiplicity_function(count); + + if(!ThisTask) + { + printf("TRY_ALL %d %e %e\n",count,chi2,chi2prev); + fflush(stdout); + } + + pcheck[pcnt]=0; + if(!(chi21) + { + RESET_COSMOLOGY++; + i=7; + j = astart[8]+2+VARY_ALPHA+VARY_CVIR; + if(HOD.free[++i])OMEGA_TEMP = a[++j]; + if(HOD.free[++i])SIGMA_8 = a[++j]; + if(HOD.free[++i])GAMMA = a[++j]; + if(HOD.free[++i])VBIAS = a[++j]; + if(HOD.free[++i])VBIAS_C = a[++j]; + if(HOD.free[++i])SIGV = a[++j]; + + if(VARY_GAMMA) + GAMMA = gasdev(&IDUM)*0.02 + 0.15; + printf("COSMO %f %f %f\n",OMEGA_TEMP,SIGMA_8,GAMMA); + } + + chi2=0; + + /* Restrict CVIR_FAC and GAMMA + */ + i = astart[8]+3+VARY_ALPHA; + if(VARY_CVIR) + if(a[i]<0.3 || a[i]>1.2)continue; + if(HOD.free[10]) + if(GAMMA<0.11 && GAMMA>0.19)continue; + + ++count; + for(i=n_wp-1;i>=0;--i) + { + n_hod = 3; + HOD.free[5] = 1; + if(i<6){ n_hod = 2; HOD.free[5] = 0; HOD.sigma_logM = 0.2; } + for(k=0,j=astart[i];j<=astart[i]+n_hod-1;++j) + { + a1[++k] = a[j]; + } + if(VARY_ALPHA) + HOD.alpha = a[astart[8]+3]; + if(VARY_CVIR) + CVIR_FAC = a[astart[8]+4]; + wp.ncf = n_hod; + + switch_wp_data(i); + chi2+=chi2array[i]=chi2_wp_wrapper(a1); + + wp_array[i].M_min = HOD.M_min; + wp_array[i].sigma_logM = HOD.sigma_logM; + wp_array[i].M1 = HOD.M1; + wp_array[i].M_low = HOD.M_low; + wp_array[i].M_cut = HOD.M_cut; + + if(!ThisTask) + { + printf("TRY%d %d ",i,count); + for(j=1;j<=n_hod;++j) + printf("%.4e ",a1[j]); + printf("%e\n",chi2array[i]); + fflush(stdout); + } + } + chi2+=chi2_ml_function(count); + chi2+=chi2_multiplicity_function(count); + + if(!ThisTask) + { + printf("TRY_ALL %d %e %e\n",count,chi2,chi2prev); + fflush(stdout); + } + + pcheck[pcnt]=0; + if(!(chi2 no PCA, plus with innermost data point + * + sprintf(wp.fname_wp,"/gal/sr2/tinker/ml_ratio/data/xi_june04.%.02f.%.02f.keML.txt", + wp_array[i].mag2,wp_array[i].mag1); + */ + + sprintf(wp.fname_wp,"/gal/sr2/tinker/voids/data/half_mag_samples/cov.10001.%.02f.%.02f.keML.com.xi2.2.log2", + wp_array[i].mag2,wp_array[i].mag1); + if(i==n_wp-1) + sprintf(wp.fname_wp,"/gal/sr2/tinker/voids/data/threshold_samples/cov.10001.-22.00.-21.00.keML.com.xi2.2.log2"); + + + sprintf(wp.fname_covar,"xi_covar.%d",i); + wp_input(); + + wp_array[i].x=dvector(1,wp.np); + wp_array[i].r=dvector(1,wp.np); + wp_array[i].e=dvector(1,wp.np); + wp_array[i].eigen=dvector(1,wp.np); + wp_array[i].covar=dmatrix(1,wp.np,1,wp.np); + + for(j=1;j<=wp.np;++j) + { + wp_array[i].x[j]=wp.x[j]; + wp_array[i].r[j]=wp.r[j]; + wp_array[i].e[j]=wp.e[j]; + wp_array[i].eigen[j]=wp.eigen[j]; + for(k=1;k<=wp.np;++k) + wp_array[i].covar[j][k] = wp.covar[j][k]; + } + wp_array[i].np=wp.np; + + free_dvector(wp.x,1,wp.np); + free_dvector(wp.r,1,wp.np); + free_dvector(wp.e,1,wp.np); + + /* This is TEMP as well. + */ + if(i==8)wp_array[i].mag2 = -23; + wp_array[i].ngal = qromo(func_integrate_schechter, + wp_array[i].mag2,wp_array[i].mag1,midpnt); + if(i==8)wp_array[i].ngal = 1.25e-4; + fprintf(stderr,"%f %e\n",wp_array[i].mean_mag,wp_array[i].ngal); + /*fscanf(fp,"%lf",&wp_array[i].ngal);*/ + } + /*fclose(fp);*/ + + wp.x=dvector(1,wp.np); + wp.r=dvector(1,wp.np); + wp.e=dvector(1,wp.np); + +} + +/* This is just the value of the Schechter Function fit to + * 2F at magnitude m--> for getting total number density of galaxies. + */ +double func_integrate_schechter(double m) +{ + double mstar=-19.66,phi0=0.0161,alpha=-1.21; + return(schechter(m,mstar,phi0,alpha)); +} + +/* This is the luminosity-weighted Schechter function value + * at magnitdue m--> to get the total amount of light. + */ +double func_integrate_lum_schechter(double m) +{ + double mstar=-19.66,phi0=0.0161,alpha=-1.21,lum; + lum = pow(10.0,-0.4*(m-MAGSOL)); + return(schechter(m,mstar,phi0,alpha)*lum); +} + +/* Function to return the value of the Schechter function + * given the parameters. + */ +double schechter(double mag, double mstar, double phi0,double alpha) +{ + return(0.4*log(10.0)*phi0*pow(10.0,-0.4*(mag-mstar)*(alpha+1))* + exp(-pow(10.0,-0.4*(mag-mstar)))); +} + + +/* Routine to switch the global wp data variables with + * the current dataset in the chi^2 loop. + */ +void switch_wp_data(int n) +{ + int i,j; + + i=n; + for(j=1;j<=wp_array[i].np;++j) + { + wp.x[j]=wp_array[i].x[j]; + wp.r[j]=wp_array[i].r[j]; + wp.e[j]=wp_array[i].e[j]; + } + wp.np=wp_array[i].np; + GALAXY_DENSITY=wp_array[i].ngal; + + HOD.i_wp = n; +} + + + +double ml_initialize(int nwp, int nhod, double *a, double **cov1, double *avg1, double *start_dev) +{ + int i,j=0,k,astart[10],np; + double x1,x2,m1[50],alpha[50],mcut[50],sig[50],*a1,chi2,chi2array[15]; + long IDUM = -556; + FILE *fp; + + astart[0] = 1; + for(i=1;i<=5;++i) + astart[i] = astart[i-1] + 2; + for(i=6;i<=8;++i) + astart[i] = astart[i-1] + 3; + + a1=dvector(1,nhod); + + fp=openfile("initial_values.dat"); + for(i=1;i<=nwp;++i) + fscanf(fp,"%lf %lf %lf %lf",&m1[i],&alpha[i],&mcut[i],&sig[i]); + fclose(fp); + + + j=0; + for(k=1;k<=nwp;++k) + { + i=0; + if(HOD.free[++i]) + { + /* + * This one will eventually be set set to one. + * + */ + } + + if(HOD.free[++i]) + { + a[++j]=log10(m1[k]); + start_dev[j]=0.001; + } + + /* + * Reserve alpha to get the same for all wp + */ + if(HOD.free[++i]) + { + /* + a[++j]=alpha[k]; + start_dev[j]=0.01; + */ + } + + if(HOD.free[++i]) + { + a[++j]=log10(mcut[k]); + start_dev[j]=0.001; + } + + /* Only leave sigma_logM free for i_wp>=6 + */ + if(HOD.free[++i] && k>5) + { + a[++j]=log10(sig[k]); + start_dev[j]=0.01; + } + } + + if(VARY_ALPHA) + { + a[++j]=HOD.alpha; + start_dev[j]=0.01; + } + + if(VARY_CVIR) + { + a[++j]=CVIR_FAC; + start_dev[j]=0.01; + } + + np = j; + + /* If using Powell's method or amoeba, then stop here + */ + for(i=0;i1) + { + i=7; + j=np; + if(HOD.free[++i]){ a[++j]=OMEGA_TEMP; start_dev[j]=0.005; np++; } + if(HOD.free[++i]){ a[++j]=SIGMA_8; start_dev[j]=0.01; np++; } + if(HOD.free[++i]){ a[++j]=GAMMA; start_dev[j]=0.01; np++; } + if(HOD.free[++i]){ a[++j]=VBIAS; start_dev[j]=0.01; np++; } + if(HOD.free[++i]){ a[++j]=VBIAS_C; start_dev[j]=0.01; np++; } + if(HOD.free[++i]){ a[++j]=SIGV; start_dev[j]=0.01; np++; } + } + + + for(i=1;i<=np;++i) + { + avg1[i]=a[i]; + printf("BEGIN %d %f\n",i,a[i]); + for(j=1;j<=nhod*nwp;++j) + cov1[i][j]=a[i]*a[j]; + } + + chi2=0; + for(i=nwp-1;i>=0;--i) + { + nhod = 3; + HOD.free[5] = 1; + if(i<6){ nhod = 2; HOD.free[5] = 0; HOD.sigma_logM = 0.2; } + wp.ncf=nhod; + for(k=0,j=astart[i];j<=astart[i]+nhod-1;++j) + { + a1[++k] = a[j]; + } + if(VARY_ALPHA) + HOD.alpha = a[astart[8]+3]; + if(VARY_CVIR) + CVIR_FAC = a[astart[8]+4]; + printf("ALPHA = %f CVIR = %f\n",HOD.alpha,CVIR_FAC); + + switch_wp_data(i); + + chi2+=chi2array[i]=chi2_wp_wrapper(a1); + printf("CHI %d %e\n",i,chi2array[i]); + + wp_array[i].M_min = HOD.M_min; + wp_array[i].sigma_logM = HOD.sigma_logM; + wp_array[i].M1 = HOD.M1; + wp_array[i].M_low = HOD.M_low; + wp_array[i].M_cut = HOD.M_cut; + } + + chi2+=chi2_ml_function(0) + chi2_multiplicity_function(0); + printf("INITIAL CHI2 %e\n",chi2); + return(chi2); +} + +/* This function takes the 2PIGG multiplicity function and returns a chi^2 value + * based on the multplicity function implies by the current point in the chain. + */ +double chi2_multiplicity_function(int count) +{ + int i,j,k,nmass=200,nmulti=145,n_start,n_wp=9; + double dlogm,mass,mlo,mhi,dndM,nsat,ncen,chi2a=0,chi2b=0,x,nlo,nhi; + static double *multi,*dy,*ngal; + FILE *fp; + + static int flag=0,NP; + static float *N_2PIGG,*M1_2PIGG,*E1_2PIGG,*M2_2PIGG,*E2_2PIGG; + + if(!flag) + { + flag = 1; + fp = openfile("/gal/sr2/tinker/ml_ratio/2PIGG_MULTI.dat"); + NP = filesize(fp); + + N_2PIGG = vector(1,NP); + E1_2PIGG = vector(1,NP); + M1_2PIGG = vector(1,NP); + E2_2PIGG = vector(1,NP); + M2_2PIGG = vector(1,NP); + + for(i=1;i<=NP;++i) + { + fscanf(fp,"%f %f %f %f %f",&N_2PIGG[i],&M2_2PIGG[i],&E2_2PIGG[i],&M1_2PIGG[i],&E1_2PIGG[i]); + if(M1_2PIGG[i]>-99) { + M1_2PIGG[i] = pow(10.0,M1_2PIGG[i]); + E1_2PIGG[i] = log(10.0)*M1_2PIGG[i]*E1_2PIGG[i]; + } + if(M2_2PIGG[i]>-99) { + M2_2PIGG[i] = pow(10.0,M2_2PIGG[i]); + E2_2PIGG[i] = log(10.0)*M2_2PIGG[i]*E2_2PIGG[i]; + } + } + fclose(fp); + + multi = dvector(1,nmulti); + dy = dvector(1,nmulti); + ngal = dvector(1,nmulti); + for(i=1;i<=nmulti;++i) + ngal[i] = i; + + } + + /* First do the multiplicity function for galaxies M_b<-18 + */ + n_start = 2; + + for(i=1;i<=nmulti;++i) + multi[i] = 0; + + + mlo = log(wp_array[n_start].M_low); + mhi = log(HOD.M_max); + dlogm = (mhi - mlo)/(nmass-1); + + for(j=1;j<=nmass;++j) + { + mass = exp((j-1)*dlogm + mlo); + dndM = dndM_interp(mass); + nsat = ncen = 0; + for(i=n_start;i0 && j>=nlo && j0 && j>=nlo && j_M and sig_L(M) curves + */ + for(i=1;i<=n;++i) + { + curlum_g9=1; + if(i==1)curlum_g9=-1; + mass_g9[i] = exp((i-1)*dlogm+mlo); + lum_g9[i] = total_halo_light(mass_g9[i],n_wp,a,&sig_g9[i]); + if(mass_g9[i]ML_2PIGG[i]) + chi2 += (ml-ML_2PIGG[i])*(ml-ML_2PIGG[i])/E1_2PIGG[i]/E1_2PIGG[i]; + else + chi2 += (ml-ML_2PIGG[i])*(ml-ML_2PIGG[i])/E2_2PIGG[i]/E2_2PIGG[i]; + printf("MLC %d %e %e %e\n",count,curlum_g9,ML_2PIGG[i],ml); + } + for(i=1;i<=N_LENSING;++i) + { + curlum_g9 = L_LENSING[i]; + ml = qromo(func_ml_lum,mlo,mhi,midpnt)/qromo(func_ml_norm,mlo,mhi,midpnt); + ml = ml*OMEGA_TEMP/OMEGA_M; + chi2 += (ml-ML_LENSING[i])*(ml-ML_LENSING[i])/E_LENSING[i]/E_LENSING[i]; + printf("MLC %d %e %e %e\n",count,curlum_g9,ML_LENSING[i],ml); + } + + printf("ML_CHI2 %d %e\n",count,chi2); + chi2+=chi2_CNOC_data(count); + return(chi2); +} + +double chi2_CNOC_data(int count) +{ + static int flag=0,n; + static float *mass,x1,x2,lum_avg=0; + double chi2,dx1,*ax1,lum,ml_ave=0; + FILE *fp; + int i; + + if(!flag) + { + flag = 1; + fp = openfile("/gal/sr2/tinker/ml_ratio/CNOC_ML.dat"); + n = filesize(fp); + mass = vector(1,n); + + for(i=1;i<=n;++i) + { + fscanf(fp,"%f %f %f",&mass[i],&x1,&x2); + lum_avg += mass[i]/x1; + mass[i] /= (OMEGA_TEMP/OMEGA_M); + } + lum_avg=lum_avg/n/1.07*0.887; + fclose(fp); + } + + for(i=1;i<=n;++i) + { + lum = total_halo_light(mass[i],9,ax1,&dx1); + ml_ave += mass[i]/lum/(OMEGA_M/OMEGA_TEMP); + } + ml_ave/=n; + chi2 = (ml_ave - 382)*(ml_ave - 382)/34./34.; + printf("MLC %d %e %e %e %f\n",count,lum_avg,ml_ave,382.0,OMEGA_TEMP/OMEGA_M); + return(chi2); +} + + +/* This function converts the (M/L)_M curve to the (M/L)_L curve. + * It assumes that the dispersion about at fixed M is a Gaussian + * with variance as the sum of the individual variances for each mag bin. + * + * NB- Each sat function is Poisson, and each cen function is Bernoulli, + * but with nine of each we're reaching the central limit theorem. Works great + * for M>10^14 M_sol, but more of an approximation for 10^13 M_sol. + */ + +void mass2light_functions(int n_wp, double *a) +{ + int i,j,k,n=100; + double *lum,*sig,mlo,mhi,dlogm,*mass,*ml_lum,*y_lum, *y_sig; + double t0,t1; + + n_g9=n; + + mlo=log(1.0e11); + mhi=log(5.0e15); + dlogm=(mhi-mlo)/(n-1); + + mass_g9=dvector(1,n); + lum_g9=dvector(1,n); + sig_g9=dvector(1,n); + ml_lum=dvector(1,n); + + y_lum_g9=dvector(1,n); + y_sig_g9=dvector(1,n); + + t0 = clock(); + + /* Tabulate _M and sig_L(M) curves + */ + for(i=1;i<=n;++i) + { + mass_g9[i] = exp((i-1)*dlogm+mlo); + lum_g9[i] = total_halo_light(mass_g9[i],n_wp,a,&sig_g9[i]); + if(mass_g9[i]=0;--j) + { + HOD.i_wp=j; + HOD.M1 = wp_array[j].M1; + HOD.M_cut = wp_array[j].M_cut; + HOD.M_min = wp_array[j].M_min; + HOD.sigma_logM = wp_array[j].sigma_logM; + HOD.M_low = wp_array[j].M_low; + + ncen = N_cen(mass); + nsat = N_sat(mass); + + /* Sum up probability of no satellite galaxies in this halos. + */ + p*=exp(-nsat); + mean_cen+=ncen*pow(10.0,-0.4*(wp_array[j].mean_mag-MAGSOL)); + + /* Sum the squares of the errors + */ + err+=(nsat+ncen*(1-ncen))*pow(10.0,-0.8*(wp_array[j].mean_mag-MAGSOL)); + mean+=(ncen+nsat)*pow(10.0,-0.4*(wp_array[j].mean_mag-MAGSOL)); + + if(OUTPUT==2) + printf("%e %e ",ncen,nsat); + } + norm = nsat/func_integrate_schechter(-17.25); + + if(OUTPUT==2){ + printf("\n"); + fflush(stdout); + } + *ss = sqrt(err); + + /* Use the value of N_sat at -17>M_b>-17.5 to normalize the schechter function + * for extrapolating to lower luminosities. + */ + norm = nsat/func_integrate_schechter(-17.25); + corr_mean = mean + qromo(func_integrate_lum_schechter,-17.0,-13.0,midpnt)*norm; + mean = corr_mean; + return(mean); + + /* Now remove systems with no satellite galaxies from the means. + */ + if(p==1)p=0; + corr_mean = (mean - mean_cen*p)/(1-p); + mean = corr_mean; + fflush(stdout); + + return(mean); +} + +/******************************************************************************** + * Code for getting the central occupation funciton based on the magnitude + * bin in question, and the next highest magnitude bin. (The lower limit of the + * brighter mag bin will define the upper limit of the fainter bin.) + * + * The general form of each will be pdfc==2. + * + * The routine assumes that the values in the global HOD structure + * represent the HOD parameters to be used for the ii node in the array + * (which is relevent since M_min must be set after the other params are chosen). + * + * If ii==8, then we are at the largest luminosity bin, which we'll treat + * currently as a threshold sample. + */ +double N_cen_i(double m, int ii) +{ + int i; + double n1,n2,n,logm,n2max=0; + + logm=log10(m); + n1=0.5*(1+erf((logm - log10(HOD.M_min))/HOD.sigma_logM)); + if(ii==8)return(n1); + + for(n2=0,i=ii+1;i<9;++i) + if(m>wp_array[i].M_low) + { + n2=0.5*(1+erf((logm - log10(wp_array[i].M_min))/wp_array[i].sigma_logM)); + if(n2>n2max)n2max=n2; + } + n = n1-n2max; + /* + if(n2>1)n2=1; + if(n1+n2>1) n = 1-n2; + else n = n1; + if(ii==6 && (logm<13.01 && logm>12.99)) + { + printf("NCEN %e %e %e %e %e %e\n",n1,n2,HOD.M_min, + HOD.sigma_logM,wp_array[ii+1].M_min,wp_array[ii+1].sigma_logM); + } + */ + if(n<0)return(0); + return(n); +} + +/*********************************************************************************/ +/********************************************************************************* + * + * The following functions are to calculate the multiplicity function + * for a given magnitude threshold. + */ +/*********************************************************************************/ +/*********************************************************************************/ + +void calc_multiplicity_function(int n_wp, int n_start) +{ + int i,j,k,nmass=2000,nmulti=200; + double dlogm,mass,*multi,mlo,mhi,dndM,nsat,*ncumu,ncen; + + multi = dvector(1,nmulti); + ncumu = dvector(1,nmulti); + for(i=1;i<=nmulti;++i) + multi[i] = 0; + + mlo = log(wp_array[n_start].M_low); + mhi = log(HOD.M_max); + dlogm = (mhi - mlo)/(nmass-1); + + for(j=1;j<=nmass;++j) + { + mass = exp((j-1)*dlogm + mlo); + dndM = dndM_interp(mass); + nsat = ncen = 0; + for(i=n_start;i0;--i) + ncumu[i] = ncumu[i+1]+multi[i]; + for(i=1;i<=nmulti;++i) + printf("MULTI%d %d %e %e\n",n_start,i,multi[i],ncumu[i]); + +} + + +/*********************************************************************************/ +/********************************************************************************* + * + * The following functions are for using powell/amoeba to minimze the set of + * correlation functions. + * + */ +/*********************************************************************************/ +/*********************************************************************************/ + +void ml_powell() +{ + int n,niter,i,j,n_wp=9,n_hod,n_mag,k,astart[10]; + double *a,**pp,*yy,FTOL=1.0E-3,chi2min,s1,dlogm,m,d[100],*avg1,**cov1,*start_dev,*a1; + FILE *fp; + char aa[1000]; + + fprintf(stderr,"\n\nCHI2 MINIMIZATION OF BINNED W_P(R_P) DATA..........\n"); + fprintf(stderr, "---------------------------------------------------\n\n"); + + if(POWELL) + FTOL=1.0E-3; + else + FTOL=1.0E-4; + + /* In Zehavi et al, this is 40 Mpc/h, + * but Norberg et al use 50. + */ + wp.pi_max=50.0; + + ml_input_data(n_wp); + + Work.imodel=2; + Work.chi2=1; + HOD.pdfc = 9; + MCMC=0; + + srand48(32498793); + + /* Find the number of free parameters in the minimization + * for the real-space correlation function. + */ + n_hod=0; + for(n=0,i=1;i<100;++i) + { + if(i<=7) + n+=HOD.free[i]*n_wp; + else + n+=HOD.free[i]; + if(i<=7) + n_hod+=HOD.free[i]; + + if(OUTPUT) + printf("mcmc_min> free[%i] = %d\n",i,HOD.free[i]); + } + wp.ncf=n_hod; + wp.ncf_tot=n; + a=dvector(1,n); + start_dev=dvector(1,n); + + ml_initialize(n_wp,n_hod,a,cov1,avg1,start_dev); + + astart[0] = 1; + for(i=1;i<=5;++i) + astart[i] = astart[i-1] + 2; + for(i=6;i<=8;++i) + astart[i] = astart[i-1] + 3; + + for(i=1;i<=n;++i) + a[i]=pow(10.0,a[i]); + + for(i=1;i<=n;++i) + printf("a[%d] = %e\n",i,a[i]); + + n_mag=n_wp-1; + + + + /* Loop through all magnitudes. + */ + MAGNITUDE_LOOP: + + n = n_hod = 3; + HOD.free[5] = 1; + if(n_mag<6){ n = n_hod = 2; HOD.free[5] = 0; HOD.sigma_logM = 0.2;} + + n = n_hod; + a1=dvector(1,n); + if(POWELL) + pp=dmatrix(1,n,1,n); + else + pp=dmatrix(1,n+1,1,n); + yy=dvector(1,n+1); + + for(k=0,j=astart[n_mag];j<=astart[n_mag]+n_hod-1;++j) + a1[++k] = a[j]; + + switch_wp_data(n_mag); + + /* Make the starting stepsize 10% of the initial values. + */ + for(i=1;i<=n;++i) + d[i]=a1[i]*0.1; + + if(POWELL) + { + for(i=1;i<=n;++i) + { + for(j=1;j<=n;++j) + { + pp[i][j]=0; + if(i==j)pp[i][j]+=d[j]; + } + } + } + else + { + for(j=1;j<=n;++j) + pp[1][j]=a1[j]; + yy[1]=chi2_ml_wrapper(a1); + + for(i=1;i<=n;++i) + { + a1[i]+=d[i]; + if(i>1)a1[i-1]-=d[i-1]; + yy[i+1]=chi2_ml_wrapper(a1); + for(j=1;j<=n;++j) + pp[i+1][j]=a1[j]; + } + a1[wp.ncf_tot]-=d[wp.ncf_tot]; + } + + if(POWELL) + { + if(OUTPUT)printf("wp_min> starting powell.\n"); + powell(a1,pp,n,FTOL,&niter,&chi2min,chi2_wp); + chi2min = chi2_wp(a1); + } + else + { + if(OUTPUT)printf("wp_min> starting amoeba.\n"); + amoeba(pp,yy,n,FTOL,chi2_wp,&niter); + for(i=1;i<=n;++i)a1[i]=pp[1][i]; + chi2min = chi2_wp(a1); + } + printf("POWELL%d %e %e ",n_mag,chi2min,HOD.M_min); + for(i=1;i<=n;++i) + printf("%e ",a1[i]); + printf("%e\n",GALAXY_BIAS); + + wp_array[n_mag].M_min = HOD.M_min; + wp_array[n_mag].M_low = HOD.M_low; + wp_array[n_mag].M_cut = HOD.M_cut; + wp_array[n_mag].M1 = HOD.M1; + wp_array[n_mag].sigma_logM = HOD.sigma_logM; + n_mag--; + + if(n_mag<0) + exit(0); + + free_dvector(a1,1,n); + free_dvector(yy,1,n+1); + if(POWELL) + free_dmatrix(pp,1,n,1,n); + else + free_dmatrix(pp,1,n+1,1,n); + + goto MAGNITUDE_LOOP; + +} + + +/* This routine loops through all 9 magnitude bins + * to get the total chi^2 for a set of parameters. + */ +double chi2_ml_wrapper(double *a) +{ + static double *a1; + static int flag=1,niter=0; + double chi2,chi2i,t0,t1; + int i,j,nwp,nhod; + + t0=clock(); + + nwp=9; + nhod=wp.ncf; + if(flag) + { + flag=0; + a1=dvector(1,nhod); + } + + chi2=0; + ++niter; + + for(i=nwp-1;i>=0;--i) + { + for(j=1;j<=nhod;++j) + a1[j] = a[i+(j-1)*nwp+1]; + + switch_wp_data(i); + chi2+=chi2i=chi2_wp(a1); + + printf("TRY%d %d ",i,niter); + for(j=1;j<=nhod;++j) + printf("%.4e ",a1[j]); + printf("%e\n",chi2i); + fflush(stdout); + + wp_array[i].M_min = HOD.M_min; + wp_array[i].sigma_logM = HOD.sigma_logM; + } + t1=clock(); + printf("ITERALL %d %e %.2f\n",niter,chi2,difftime(t1,t0)/CLOCKS_PER_SEC); + return(chi2); +} + +/********************************************************************************* + * + * This is for Monte Carlo testing of some of the routines. + * + */ +/*********************************************************************************/ +/*********************************************************************************/ +/*********************************************************************************/ + + +void ml_function_test(int n_wp, double *a) +{ + FILE *fp; + int i,j,n,imass; + double mass; + char aa[1000]; + + /* fp=openfile("/gal/sr2/tinker/voids/LANL/halo.LANL.400"); */ + fp=openfile("/gal/sr2/tinker/voids/LANL/halo.400_z.5.dat"); + + while(!feof(fp)) + { + fscanf(fp,"%d %d",&i,&imass); + fgets(aa,1000,fp); + mass=imass*RHO_CRIT*OMEGA_M*pow(0.3125,3.0); + dispersion_test(n_wp,a,mass); + if(feof(fp))break; + } + exit(0); +} + +/* does the same as the above function, but instead of using a mass + * function for a simulation, it uses a mass funcation created by + * monte carlo sampling of the analytic function. + */ +void ml_function_test_monte_carlo(int n_wp, double *a) +{ + FILE *fp; + int i,j,n,imass; + double mass,pmax,p; + char aa[1000]; + long IDUMx=-442123; + + n=1E6; + + i=0; + pmax = dndM_interp(1.0E11); + while(ip)continue; + i++; + dispersion_test(n_wp,a,mass); + } + +} + +void ml_mock_catalog(int n_wp, double *a) +{ + FILE *fp,*fpa[9],*fp2,*fpb[9]; + int i,j,k,n,imass,n1,j_start=0,i1,galcnt[9][1000],halocnt[1000],imag; + double mass,xg[3],vg[3],nsat,nc[10],ncen,mlo,mag,err1,err2; + char aa[1000]; + float x1,xh[3],vh[3]; + long IDUM3 = -445; + + fp=openfile("/gal/sr2/tinker/voids/LANL/halo.LANL.400"); + for(i=j_start;ij_start) + nc[j] = nc[j-1]+N_cen(mass); + else + nc[j] = N_cen(mass); + + n1 = poisson_deviate(nsat); + for(i=1;i<=n1;++i) + { + NFW_position(mass,xg); + NFW_velocity(mass,vg); + for(k=0;k<3;++k) + { + xg[k]+=xh[k]; + if(xg[k]<0)xg[k]+=BOX_SIZE; + if(xg[k]>BOX_SIZE)xg[k]-=BOX_SIZE; + vg[k]+=vh[k]; + } + fprintf(fpa[j],"%e %e %e %e %e %e\n",xg[0],xg[1],xg[2],vg[0],vg[1],vg[2]); + mag = random_luminosity(wp_array[j].mag1,wp_array[j].mag2); + fprintf(fpb[j],"%f\n",mag); + /* random_2df_magnitude_error(); */ + imag = (-mag-17)*2; + if(imag>=n_wp)imag = n_wp; + + /* Bin up the galaxies by halo mass to check the HOD + */ + galcnt[imag][i1]++; + } + } + ncen=drand48(); + for(j=j_start;j=n_wp)imag = n_wp; + galcnt[imag][i1]++; + } + halocnt[i1]++; + + if(feof(fp))break; + } + + /* output the binned HOD + */ + for(j=0;j0) + fprintf(fp2,"%d %f %f %d %d\n", + i,(i+0.5)*0.1,(float)galcnt[j][i]/halocnt[i],galcnt[j][i],halocnt[i]); + fclose(fp2); + } + + exit(0); +} + +double random_2df_magnitude_error() +{ + double p,m; + p=0; + while(3*drand48()>p) + { + m = drand48()*2-1; + p = 1/RT2PI/.14*exp(-m*m/2/.14/.14)*0.7 + + 1/RT2PI/.235*exp(-pow(log(1+m),2.0)/2/.235/.235)/(1+m)*0.3; + /* + printf("BUH %f %f %f %f\n",m,p, + 1/RT2PI/.14*exp(-m*m/2/.14/14),1/RT2PI/.235*exp(-pow(log(1+m),2.0)/2/.235/.235)/(1+m)*0.3 ); + */ + } + return(m); +} + +void NFW_position(double mass, double x[]) +{ + double r,pr,max_p,costheta,sintheta,phi1,signs,rvir,rs,cvir; + + cvir=halo_concentration(mass)*CVIR_FAC; + rvir=pow(3*mass/(4*DELTA_HALO*PI*RHO_CRIT*OMEGA_M),1.0/3.0); + rs=rvir/cvir; + max_p=NFW_density(rs,rs,1.0)*rs*rs*4.0*PI; + + for(;;) { + r=drand48()*rvir; + pr=NFW_density(r,rs,1.0)*r*r*4.0*PI/max_p; + + if(drand48()<=pr) + { + costheta=2.*(drand48()-.5); + sintheta=sqrt(1.-costheta*costheta); + signs=2.*(drand48()-.5); + costheta=signs*costheta/fabs(signs); + phi1=2.0*PI*drand48(); + + x[0]=r*sintheta*cos(phi1); + x[1]=r*sintheta*sin(phi1); + x[2]=r*costheta; + return; + } + } +} + +/* This is the NFW density profile + */ +double NFW_density(double r, double rs, double ps) +{ + return(ps*rs/(r*(1+r/rs)*(1+r/rs))); +} + +/* This sets the velocity to be isotropic Gaussian. + */ +double NFW_velocity(double mass, double v[]) +{ + static long IDUM2=-455; + static double fac = -1; + double sigv; + int i; + + if(fac<0) + fac=sqrt(4.499E-48)*pow(4*DELTA_HALO*PI*OMEGA_M*RHO_CRIT/3,1.0/6.0)*3.09E19; + sigv=fac*pow(mass,1.0/3.0)/sqrt(2.0); + for(i=0;i<3;++i) + v[i]=gasdev(&IDUM2)*sigv*VBIAS; +} + + +void dispersion_test(int n_wp, double *a, double mass) +{ + int i,j,k,n=1,n1,n1t; + double ml_ratio,x1,nsat,ncen,err=0,mean=0,nc[10],mag; + + for(i=1;i<=n;++i) + { + n1t =mean=err=x1=0; + for(j=0;j0) + { + if(mass>HOD.M_low) + nc[j] = nc[j-1]+N_cen(mass); + else + nc[j] = nc[j-1]+0; + } + else + { + if(mass>HOD.M_low) + nc[j] = N_cen(mass); + else + nc[j] = 0; + } + + n1t += n1 = poisson_deviate(nsat); + mag = random_luminosity(wp_array[j].mag1,wp_array[j].mag2); + x1 += (n1)*pow(10.0,-0.4*(mag-MAGSOL)); + + } + ncen=drand48(); + for(j=0;j=n_wp)j=n_wp-1; + mag = random_luminosity(wp_array[j].mag1,wp_array[j].mag2); + x1+=pow(10.0,-0.4*(mag-MAGSOL)); + if(x1>0) { + HOD.i_wp = j; + printf("LUM %f %f %f %d %f %e %d %e\n", + log10(x1),log10(mass),mass/x1,n1t,ncen,nc[j],j,N_cen(mass)); + fflush(stdout); + } + } + +} + +double random_luminosity(double m1, double m2) +{ + double p1,p2,pn,m; + + pn = func_integrate_schechter(m1); + for(;;) + { + m = drand48()*(m2-m1)+m1; + p1 = func_integrate_schechter(m)/pn; + p2 = drand48(); + if(p20) + for(i=1;i<=n;++i) + fac*=nave/i; + + return((float)(fac*exp(-nave))); +} + +/*********************************************************************************/ +/*********************************************************************************/ +/* + * For outputting the fits and the data all in one file. + * + */ +/*********************************************************************************/ +/*********************************************************************************/ + +void output_wp_fits(int n_wp, double *a) +{ + int i,j,nr=50; + double *x[10],rlo=0.1,rhi=50,dlogr,r; + FILE *fp; + char fname[100]; + + dlogr = (log(rhi)-log(rlo))/(nr-1); + + for(i=0;i=j_start;--j) + { + HOD.i_wp=j; + HOD.M_min=wp_array[j].M_min; + HOD.M1 = pow(10.0,a[j+0*n_wp+1]); + HOD.M_cut = pow(10.0,a[j+1*n_wp+1]); + HOD.sigma_logM = pow(10.0,a[j+2*n_wp+1]); + + GALAXY_DENSITY = wp_array[j].ngal; + dd_hod_functions(hmass,hden,nh); + mmin_lo[j] = HOD.M_min_loden; + mmin_hi[j] = HOD.M_min_loden*(1+GAO.f0*exp(-j*j/2.0/GAO.s0/GAO.s0)); + wp_array[j].M_min = HOD.M_min_loden; + wp_array[j].M_low = HOD.M_low; + + fprintf(stdout,"MMIN %d %e %e %e\n",j,mmin_lo[j],mmin_hi[j],HOD.M_low); + } + fflush(stdout); + + for(ih=1;ih<=nh;++ih) + { + fscanf(fp,"%d %d %e %e %e %e %e %e %e", + &i,&imass,&xh[0],&xh[1],&xh[2],&x1,&vh[0],&vh[1],&vh[2]); + mass=imass*RHO_CRIT*OMEGA_M*pow(0.3125,3.0); + if(massDENSITY_THRESHOLD) + { + if(j>j_start) + nc[j] = nc[j-1]+N_cen_hiden(mass); + else + nc[j] = N_cen_hiden(mass); + /* printf("NCEN %d %d %e %e\n",i,ih,N_cen_hiden(mass),nc[j]);*/ + } + else + { + if(j>j_start) + nc[j] = nc[j-1]+N_cen(mass); + else + nc[j] = N_cen(mass); + /* printf("NCEN %d %d %e %e\n",i,ih,N_cen_hiden(mass),nc[j]);*/ + } + + nsat = N_sat(mass); + n1 = poisson_deviate(nsat); + for(i=1;i<=n1;++i) + { + NFW_position(mass,xg); + NFW_velocity(mass,vg); + for(k=0;k<3;++k) + { + xg[k]+=xh[k]; + if(xg[k]<0)xg[k]+=BOX_SIZE; + if(xg[k]>BOX_SIZE)xg[k]-=BOX_SIZE; + vg[k]+=vh[k]; + } + fprintf(fpa[j],"%e %e %e %e %e %e\n",xg[0],xg[1],xg[2],vg[0],vg[1],vg[2]); + mag = random_luminosity(wp_array[j].mag1,wp_array[j].mag2); + fprintf(fpb[j],"%f\n",mag); + imag = (-mag-17)*2; + if(imag>=n_wp)imag = n_wp; + + /* Bin up the galaxies by halo mass to check the HOD + */ + galcnt[imag][i1]++; + } + } + density_flag=0; + + ncen=drand48(); + for(j=j_start;j=n_wp)imag = n_wp; + galcnt[imag][i1]++; + } + halocnt[i1]++; + + if(feof(fp))break; + } + + /* output the binned HOD + */ + for(j=0;j0) + fprintf(fp2,"%d %f %f %d %d\n", + i,(i+0.5)*0.1,(float)galcnt[j][i]/halocnt[i],galcnt[j][i],halocnt[i]); + fclose(fp2); + } + + exit(0); +} + + +double N_cen_gao(double m, int ii, double *mmin) +{ + int i; + double n1,n2,n,logm,n2max=0; + + logm=log10(m); + n1=0.5*(1+erf((logm - log10(HOD.M_min))/HOD.sigma_logM)); + if(ii==8)return(n1); + + for(n2=0,i=ii+1;i<9;++i) + if(m>wp_array[i].M_low) + { + n2=0.5*(1+erf((logm - log10(mmin[i]))/wp_array[i].sigma_logM)); + if(n2>n2max)n2max=n2; + } + n = n1-n2max; + if(n<0)return(0); + return(n); +} + +double N_cen_hiden(double m) +{ + int i,ii; + double n1,n2,n,logm,n2max=0,f; + + if(mwp_array[i].M_low) + { + f=1 + GAO.f0*exp(-i*i/2.0/GAO.s0/GAO.s0); + n2=0.5*(1+erf((logm - log10(wp_array[i].M_min*f))/wp_array[i].sigma_logM)); + if(n2>n2max)n2max=n2; + } + n = n1-n2max; + if(n<0)return(0); + return(n); +} + +/*************************************************************************************88 + * This is to read in a chain and do some other calculations with it. + */ + +void analyze_chain() +{ + int i,j,k,n,n_wp=9,i1,i2; + FILE *fp,*fpa[9]; + char aa[1000]; + float x1,x2,x3,x4,x5,x6,x7; + + /* + for(i=0;i acc.%d",i,i); + fprintf(stderr,"%s\n",aa); + system(aa); + } + */ + for(i=0;i=0;--j) + { + if(j==n_wp-1)RESET_COSMOLOGY++; + + if(j>=6) + { + fscanf(fpa[j],"%4s %d %d %e %e %e %e %e %e %e",aa,&i1,&i2,&x1,&x2,&x3,&x4,&x5,&x6,&x7); + } + else + { + fscanf(fpa[j],"%4s %d %d %e %e %e %e %e %e",aa,&i1,&i2,&x1,&x2,&x4,&x5,&x6,&x7); + x3 = log10(0.2); + } + printf("%d %f %f %f %f %f %f %f\n",i,x1,x2,x3,x4,x5,x6,x7); + + fgets(aa,1000,fpa[j]); + HOD.M1 = pow(10.0,x1); + HOD.M_cut = pow(10.0,x2); + HOD.sigma_logM = pow(10.0,x3); + HOD.alpha = x4; + CVIR_FAC = x5; + OMEGA_TEMP = x6; + SIGMA_8 = x7; + + set_HOD_params(); + + wp_array[j].M_min = HOD.M_min; + wp_array[j].sigma_logM = HOD.sigma_logM; + wp_array[j].M1 = HOD.M1; + wp_array[j].M_low = HOD.M_low; + wp_array[j].M_cut = HOD.M_cut; + } + printf("SIGMA %f %f %f\n",SIGMA_8,OMEGA_TEMP,OMEGA_M); + fflush(stdout); + + chi2_multiplicity_function(i); + printf("CHI2_CNOC %e\n",chi2_CNOC_data(i)); + } + + exit(0); +} diff --git a/c_tools/hod/chi2_dist.c b/c_tools/hod/chi2_dist.c new file mode 100644 index 0000000..935b2dd --- /dev/null +++ b/c_tools/hod/chi2_dist.c @@ -0,0 +1,44 @@ +#include +#include +#include + +#define pi 3.14159265358979323846 + +double nu; +double func(double); +double func_gam(double); +double func_gauss(double); + +int main(int argc, char **argv) +{ + int i,n; + double x,f,qromo(),midinf(),fgam,midpnt(),fgauss; + + nu=2; + if(argc>1) + nu=atof(argv[1]); + + fgam = qromo(func_gam,0.0,0.1,midpnt) + qromo(func_gam,0.1,1.0E+30,midinf); + + for(i=1;i<=200;++i) + { + x=i/10.0; + f=qromo(func,x,1.0E+30,midinf); + fgauss = 2*qromo(func_gauss,0.0,x,midpnt); + f*=1/(pow(2.0,nu/2.0)*fgam); + printf("%f %e %e\n",x,1-f,fgauss); + } +} + +double func(double x) +{ + return(pow(x,nu/2-1)*exp(-x/2)); +} +double func_gam(double x) +{ + return(pow(x,nu/2-1)*exp(-x)); +} +double func_gauss(double x) +{ + return(exp(-x*x/2)/sqrt(2*pi)); +} diff --git a/c_tools/hod/chi2_grid.c b/c_tools/hod/chi2_grid.c new file mode 100644 index 0000000..49f36e6 --- /dev/null +++ b/c_tools/hod/chi2_grid.c @@ -0,0 +1,124 @@ +#include +#include +#include +#include + +#ifdef PARALLEL +#include +#endif + +#include "header.h" + +void wp_input(void); + +void chi2_grid(int argc, char**argv) +{ + int i1,i2,i3,i4,n,nhod = 3,i,j; + double alo[4],ahi[5],*a; + float avector[100][3],chi2,bias,mmin; + FILE *fp; + char fname[100]; + + /* + * OMEGA_M + * SIGMA_8 + * VBIAS + * VBIAS_C + */ + + n = 10; + + alo[0] = 0.18; + ahi[0] = 0.26; + alo[1] = 0.84; + ahi[1] = 0.94; + alo[2] = 0.5; + ahi[2] = 1.0; + alo[3] = 0.0; + ahi[3] = 0.5; + + a = dvector(1,nhod); + + wp_input(); + + if(!ThisTask) + { + sprintf(fname,"%s.grid",Task.root_filename); + fp = fopen(fname,"w"); + } + MCMC=1; + + for(i3=1;i3<=n;++i3) + { + VBIAS = (i3-1)*(ahi[2] - alo[2])/(n-1) + alo[2]; + for(i4=1;i4<=n;++i4) + { + VBIAS_C = (i4-1)*(ahi[3] - alo[3])/(n-1) + alo[3]; + RESET_COSMOLOGY++; + one_halo_real_space(1); + two_halo_real_space(1); + + a[1] = VBIAS; + a[2] = VBIAS_C; + + chi2 = chi2_zspace(a); + if(!ThisTask) + { + printf("GRID %d %d %f %f %e\n",i3,i4,VBIAS,VBIAS_C,chi2); + fprintf(fp,"%d %d %f %f %e\n",i3,i4,VBIAS,VBIAS_C,chi2); + } + } + } + exit(0); + + for(i=66;i<=98;++i) + { + sprintf(fname,"xi_%d.fit",i); + fp = openfile(fname); + fscanf(fp,"%e %e %e %e %e %e",&chi2,&mmin,&avector[i][0],&avector[i][1],&avector[i][2],&bias); + fclose(fp); + } + wp.ncf = 3; + + for(i1=1;i1<=n;++i1) + { + OMEGA_M = (i1-1)*(ahi[0] - alo[0])/(n-1) + alo[0]; + for(i2=1;i2<=n;++i2) + { + SIGMA_8= (i2-1)*(ahi[1] - alo[1])/(n-1) + alo[1]; + for(i3=1;i3<=n;++i3) + { + VBIAS = (i3-1)*(ahi[2] - alo[2])/(n-1) + alo[2]; + for(i4=1;i4<=n;++i4) + { + VBIAS_C = (i4-1)*(ahi[3] - alo[3])/(n-1) + alo[3]; + RESET_COSMOLOGY++; + + j = 100.001*SIGMA_8; + a[1] = avector[j][0]*OMEGA_M/0.25; + a[2] = avector[j][1]; + a[3] = avector[j][2]*OMEGA_M/0.25; + + if(!ThisTask) + { + printf("GOO %f %d %e %e %e\n",SIGMA_8,j,a[1],a[2],a[3]); + fflush(stdout); + } + + chi2 = chi2_wp(a); + chi2 += chi2_zspace(a); + if(!ThisTask) + { + printf("GRID %d %d %d %d %f %f %f %f %e\n",i1,i2,i3,i4,OMEGA_M,SIGMA_8,VBIAS,VBIAS_C,chi2); + fprintf(fp,"%d %d %d %d %f %f %f %f %e\n",i1,i2,i3,i4,OMEGA_M,SIGMA_8,VBIAS,VBIAS_C,chi2); + } + } + } + } + } + if(!ThisTask) + fclose(fp); + exit(0); + + +} diff --git a/c_tools/hod/cisi.c b/c_tools/hod/cisi.c new file mode 100644 index 0000000..070aae7 --- /dev/null +++ b/c_tools/hod/cisi.c @@ -0,0 +1,80 @@ +#include +#include "complex.h" +#define EPS 6.0e-8 +#define EULER 0.57721566 +#define MAXIT 100 +#define PIBY2 1.5707963 +#define FPMIN 1.0e-30 +#define TMIN 2.0 +#define TRUE 1 +#define ONE Complex(1.0,0.0) + +void cisi(double x, double *ci, double *si) +{ + void endrun(char *error_text); + int i,k,odd; + float a,err,fact,sign,sum,sumc,sums,t,term; + fcomplex h,b,c,d,del; + + t=fabs(x); + if (t == 0.0) { + *si=0.0; + *ci = -1.0/FPMIN; + return; + } + if (t > TMIN) { + b=Complex(1.0,t); + c=Complex(1.0/FPMIN,0.0); + d=h=Cdiv(ONE,b); + for (i=2;i<=MAXIT;i++) { + a = -(i-1)*(i-1); + b=Cadd(b,Complex(2.0,0.0)); + d=Cdiv(ONE,Cadd(RCmul(a,d),b)); + c=Cadd(b,Cdiv(Complex(a,0.0),c)); + del=Cmul(c,d); + h=Cmul(h,del); + if (fabs(del.r-1.0)+fabs(del.i) < EPS) break; + } + if (i > MAXIT) endrun("cf failed in cisi"); + h=Cmul(Complex(cos(t),-sin(t)),h); + *ci = -h.r; + *si=PIBY2+h.i; + } else { + if (t < sqrt(FPMIN)) { + sumc=0.0; + sums=t; + } else { + sum=sums=sumc=0.0; + sign=fact=1.0; + odd=TRUE; + for (k=1;k<=MAXIT;k++) { + fact *= t/k; + term=fact/k; + sum += sign*term; + err=term/fabs(sum); + if (odd) { + sign = -sign; + sums=sum; + sum=sumc; + } else { + sumc=sum; + sum=sums; + } + if (err < EPS) break; + odd=!odd; + } + if (k > MAXIT) endrun("maxits exceeded in cisi"); + } + *si=sums; + *ci=sumc+log(t)+EULER; + } + if (x < 0.0) *si = -(*si); +} +#undef EPS +#undef EULER +#undef MAXIT +#undef PIBY2 +#undef FPMIN +#undef TMIN +#undef TRUE +#undef ONE diff --git a/c_tools/hod/cobenorm.c b/c_tools/hod/cobenorm.c new file mode 100644 index 0000000..ec12b81 --- /dev/null +++ b/c_tools/hod/cobenorm.c @@ -0,0 +1,168 @@ +#include +#include +#include +#include +#include + +#ifdef PARALLEL +#include +#endif + +#include "header.h" + + +/* This is the one that Andrew Zentner gave me: + * taken from Bunn, Liddle & White (and appears to + * give different answers from the Bunn & White functions. + */ +double cobenorm(double Om) +{ + double Ol, n, f, pwr, g, r=0, d0, + cobe_norm; + + n = SPECTRAL_INDX; + + Ol = 1 - Om; + + f= 0.750 - 0.130*(Ol*Ol); + + pwr = -0.8 - 0.05*log(Om); + + g = 1.0-0.180*(1.0-n)*Ol - 0.03*r*Ol; + + d0 = 1.91e-5*(pow(7.0,((n-1.0)/2.0))); + + cobe_norm = d0*(exp(1.010*(1.0-n))/ + sqrt(1.0+r*f))*(pow(Om,pwr))*g; + + return cobe_norm; +} + +/* + + Ol = 1.d0-Om + + f=0.75d0-0.13d0*(Ol**2.d0) + + pwr = -0.8d0 - 0.05d0*log(Om) + + g = 1.d0-0.18d0*(1.d0-n)*Ol - 0.03d0*r*Ol + + d0 = 1.91d-5*(7.d0**((n-1.d0)/2.d0)) + + cobe_norm = d0*(exp(1.01d0*(1.d0-n))/ + & dsqrt(1.d0+r*f))*(Om**pwr)*g + +*/ + +/* The function below was supplied by Risa Wechsler; + * I set it up to always assume flat universe. + */ +double cobenorm_risa(double omega_m) +/* Return the Bunn & White (1997) fit for delta_H */ +/* Given lambda, omega_m, qtensors, and tilt */ +/* Open model with tensors is from Hu & White */ +{ + // cout< +#include +#include +#include +#include + +#ifdef PARALLEL +#include +#endif + +#include "header.h" + +/* This file contains routines to fit a red/blue color-selected sample. + * It does a simultaneous fit to the red, blue, and all samples. It basically + * acts as a wrapper around the normal wp_minimization routines. + */ +void initial_color_values(double *a, double **pp, double *yy); +void wp_input(void); +void wp_color_input(void); +double chi2_wp_color(double *a); +double dd_func_red_fraction(double x); + +/* external functions + */ +void mcmc_color_minimization(void); + +void fit_color_samples() +{ + int n,niter,i,j; + double *a,**pp,*yy,FTOL=1.0E-3,chi2min,s1,dlogm,m; + FILE *fp; + char aa[1000]; + + mcmc_color_minimization(); + + fprintf(stderr,"\n\nCHI2 MINIMIZATION OF W_P(R_P) COLOR DATA..........\n"); + fprintf(stderr, "--------------------------------------------\n\n"); + + HOD.blue_fraction = 0.5857; /* <- Millenium fraction (sloan);; SDSS fraction -> 0.565; */ + HOD.blue_fraction = 0.6555; /* <- Millenium fraction (B-V>0.8) */ + HOD.blue_fraction = 0.565; /* SDSS -19,-20 */ + HOD.blue_fraction = 0.492; /* SDSS -20,-21 */ + HOD.blue_fraction = 0.379; /* SDSS -21 */ + + wp_color.ON = 1; + + if(POWELL) + FTOL=1.0E-3; + else + FTOL=1.0E-5; + + for(n=0,i=1;i<=7;++i) + { + n+=HOD.free[i]; + if(!OUTPUT)continue; + printf("wp_min> free[%i] = %d\n",i,HOD.free[i]); + } + /* The parameters that govern the blue fraction aren't + * listed in the HOD.free array, so add them in. + * NB: There are four parameters for these two functions, + * one of which is fit by the number densities. + */ + n+=3; + + if(OUTPUT)printf("wp_min> Number of free parameters: %d\n",n); + + wp_color_input(); + + wp.ncf=n; + a=dvector(1,n); + if(POWELL) + pp=dmatrix(1,n,1,n); + else + pp=dmatrix(1,n+1,1,n); + yy=dvector(1,n+1); + + initial_color_values(a,pp,yy); + + if(POWELL) + { + if(OUTPUT)printf("wp_min> starting powell.\n"); + powell(a,pp,n,FTOL,&niter,&chi2min,chi2_wp_color); + chi2min = chi2_wp_color(a); + } + else + { + if(OUTPUT)printf("wp_min> starting amoeba.\n"); + amoeba(pp,yy,n,FTOL,chi2_wp_color,&niter); + for(i=1;i<=n;++i)a[i]=pp[1][i]; + chi2min = chi2_wp_color(a); + } + + s1=qromo(func_galaxy_bias,log(HOD.M_low),log(HOD.M_max),midpnt); + GALAXY_BIAS=s1/GALAXY_DENSITY; + + printf("POWELL %e %e %e ",chi2min,HOD.M_min,HOD.fblue0_cen); + if(HOD.pdfc==7) + printf("%e ",HOD.M_cen_max); + for(i=1;i<=n;++i)printf("%e ",a[i]); + printf(" %f\n",GALAXY_BIAS); + + /* Output the fit and the HOD curve. + */ + sprintf(aa,"%s.fit",Task.root_filename); + fp=fopen(aa,"w"); + fprintf(fp,"%e %e %e ",chi2min,HOD.M_min,HOD.fblue0_cen); + if(HOD.pdfc==7) + fprintf(fp,"%e ",HOD.M_cen_max); + for(i=1;i<=n;++i)fprintf(fp,"%e ",a[i]); + fprintf(fp," %f\n",GALAXY_BIAS); + fclose(fp); + + sprintf(aa,"%s.HOD",Task.root_filename); + fp=fopen(aa,"w"); + dlogm=(log(HOD.M_max)-log(HOD.M_low))/99; + for(i=1;i<=100;++i) + { + m=exp((i-1)*dlogm)*HOD.M_low; + fprintf(fp,"%e %e %e %e\n",m,N_cen(m),N_sat(m),N_avg(m)); + } + fclose(fp); + +} + +double chi2_wp_color(double *a) +{ + double chi2,nsat_blue,ncen_blue,dlogm,m,func_blue_fraction(),temp1,temp2,fsat_blue,fsat_red,fsat_all; + int i,j; + static int iter=0; + + COVAR = 0; + + HOD.color = 0; + GALAXY_DENSITY2 = GALAXY_DENSITY = wp_color.ngal_full; + wp.np = wp_color.n_full; + + for(i=wp.ncf-2;i<=wp.ncf;++i) + if(a[i]<0)return(1.0e+7); + + for(i=1;i<=wp.np;++i) + { + wp.r[i] = wp_color.r_full[i]; + wp.x[i] = wp_color.x_full[i]; + wp.e[i] = wp_color.e_full[i]; + for(j=1;j<=wp.np;++j) + wp.covar[i][j] = wp_color.covar_full[i][j]; + } + + chi2 = chi2_wp(a); + + HOD.M_low0 = set_low_mass(); + + fsat_all = qromo(func_satfrac,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY; + + /* + dlogm=(log(HOD.M_max)-log(HOD.M_low))/99; + for(i=1;i<=100;++i) + { + m=exp((i-1)*dlogm)*HOD.M_low; + printf("HODFULL %e %f %f %f\n",m,N_cen(m)+N_sat(m),N_cen(m),N_sat(m)); + } + printf("GALDEN FULL %e\n",qromo(func_galaxy_density,log(HOD.M_low),log(HOD.M_max),midpnt)); + sprintf(Task.root_filename,"gal_full"); + populate_simulation(); + */ + + + if(!iter) + for(i=1;i<=wp.np;++i) + for(j=1;j<=wp.np;++j) + wp_color.covar_full[i][j] = wp.covar[i][j]; + + HOD.fblue0_sat = a[wp.ncf - 2]; + HOD.sigma_fblue_sat = a[wp.ncf - 1]; + HOD.sigma_fblue_cen = a[wp.ncf - 0]; + HOD.fblue0_cen = 1.0; + + HOD.color = 1; + HOD.fblue0_cen = pow(10.0,zbrent(func_blue_fraction,-5.0,1.0,1.0E-5)); + + if(OUTPUT) + fprintf(stdout,"old fblue0_cen= %e %e\n",HOD.fblue0_cen,HOD.M_min); + + if(DENSITY_DEPENDENCE) + { + HOD.color = 2; + temp1 = HOD.M_min; + temp2 = HOD.M_low; + populate_simulation(); + HOD.M_min = temp1; + HOD.M_low = temp2; + HOD.fblue0_cen = pow(10.0,zbrent(dd_func_red_fraction,-5.0,1.0,1.0E-5)); + HOD.color = 1; + if(OUTPUT) + fprintf(stdout,"new fblue0_cen= %e %e\n",HOD.fblue0_cen, + (1. - HOD.M_min_fac*(1.0 - HOD.fblue0_cen))); + // populate_simulation(); + //exit(0); + } + else + HOD.fblue0_cen = pow(10.0,zbrent(func_blue_fraction,-5.0,1.0,1.0E-5)); + + if(ERROR_FLAG) + { + ERROR_FLAG=0; + return(1.0e7); + } + + + /* This is only if you have square functions for the central occupation + */ + /* + nsat_blue = qromo(func_satellite_density,log(HOD.M_low),log(HOD.M_max),midpnt); + ncen_blue = qromo(func_central_density,log(HOD.M_low),log(HOD.M_cen_max),midpnt); + HOD.fblue0_cen = (wp_color.ngal_blue - nsat_blue)/ncen_blue; + */ + + GALAXY_DENSITY2 = GALAXY_DENSITY = wp_color.ngal_blue; + wp.np = wp_color.n_blue; + + for(i=1;i<=wp.np;++i) + { + wp.r[i] = wp_color.r_blue[i]; + wp.x[i] = wp_color.x_blue[i]; + wp.e[i] = wp_color.e_blue[i]; + for(j=1;j<=wp.np;++j) + wp.covar[i][j] = wp_color.covar_blue[i][j]; + } + + chi2 += chi2_wp(a); + fsat_blue = qromo(func_satfrac,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY; + + /* + dlogm=(log(HOD.M_max)-log(HOD.M_low))/99; + for(i=1;i<=100;++i) + { + m=exp((i-1)*dlogm)*HOD.M_low; + printf("HODBLUE %e %f %f %f\n",m,N_cen(m)+N_sat(m),N_cen(m),N_sat(m)); + } + printf("GALDEN BLUE %e\n",qromo(func_galaxy_density,log(HOD.M_low),log(HOD.M_max),midpnt)); + + sprintf(Task.root_filename,"gal_blue"); + populate_simulation(); + */ + + if(!iter) + for(i=1;i<=wp.np;++i) + for(j=1;j<=wp.np;++j) + wp_color.covar_blue[i][j] = wp.covar[i][j]; + + HOD.color = 2; + GALAXY_DENSITY2 = GALAXY_DENSITY = wp_color.ngal_red; + wp.np = wp_color.n_red; + + for(i=1;i<=wp.np;++i) + { + wp.r[i] = wp_color.r_red[i]; + wp.x[i] = wp_color.x_red[i]; + wp.e[i] = wp_color.e_red[i]; + for(j=1;j<=wp.np;++j) + wp.covar[i][j] = wp_color.covar_red[i][j]; + } + + chi2 += chi2_wp(a); + fsat_red = qromo(func_satfrac,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY; + + /* + dlogm=(log(HOD.M_max)-log(HOD.M_low))/99; + for(i=1;i<=100;++i) + { + m=exp((i-1)*dlogm)*HOD.M_low; + printf("HODRED %e %f %f %f\n",m,N_cen(m)+N_sat(m),N_cen(m),N_sat(m)); + } + printf("GALDEN RED %e\n",qromo(func_galaxy_density,log(HOD.M_low),log(HOD.M_max),midpnt)); + + sprintf(Task.root_filename,"gal_red"); + populate_simulation(); + + exit(0); + */ + if(!iter) + for(i=1;i<=wp.np;++i) + for(j=1;j<=wp.np;++j) + wp_color.covar_red[i][j] = wp.covar[i][j]; + + iter++; + + wp.fsat_all = fsat_all; + wp.fsat_red = fsat_red; + wp.fsat_blue = fsat_blue; + + printf("COLOR_PARAMS %d %e %e %e %e %e %e %e %e\n",iter,chi2,HOD.M_min,HOD.M1,HOD.alpha,HOD.fblue0_cen,HOD.fblue0_sat,HOD.sigma_fblue_cen,HOD.sigma_fblue_sat); + printf("COLOR_ITER %d %e %e %f %f %f\n",iter,chi2,HOD.fblue0_cen,fsat_all,fsat_blue,fsat_red); + fflush(stdout); + return(chi2); + +} + +double func_blue_fraction(double x) +{ + double n; + HOD.fblue0_cen=pow(10.0,x); + n = qtrap(func_galaxy_density,log(HOD.M_low),log(HOD.M_max),1.0E-4); + //printf("%f %e %e %e %e\n",HOD.fblue0_cen,n,wp_color.ngal_blue,central_blue_fraction(HOD.M_min),HOD.M_low); + return n - wp_color.ngal_blue; +} + +void initial_color_values(double *a, double **pp, double *yy) +{ + static int flag=0; + int i,j; + double d[100]; + + COVAR=0; + + if(!flag) { + i=0;j=0; + if(HOD.free[++i])a[++j]=HOD.M_min; + if(HOD.free[++i])a[++j]=HOD.M1; + if(HOD.free[++i])a[++j]=HOD.alpha; + if(HOD.free[++i])a[++j]=HOD.M_cut; + if(HOD.free[++i])a[++j]=HOD.sigma_logM; + if(HOD.free[++i])a[++j]=CVIR_FAC; + if(HOD.pdfc>=7){ + if(HOD.free[++i])a[++j]=HOD.M_cen_max; } + else { + if(HOD.free[++i])a[++j]=HOD.MaxCen; } + + a[++j] = HOD.fblue0_sat; + a[++j] = HOD.sigma_fblue_sat; + a[++j] = HOD.sigma_fblue_cen; + + printf("INITIAL VALUES: "); + for(i=1;i<=wp.ncf;++i)printf("%e ",a[i]); + printf("\n"); + } + flag++; + + /* Make the starting stepsize 10% of the initial values. + */ + for(i=1;i<=wp.ncf;++i) + d[i]=a[i]*0.25/flag; + + + if(POWELL) + { + for(i=1;i<=wp.ncf;++i) + { + for(j=1;j<=wp.ncf;++j) + { + pp[i][j]=0; + if(i==j)pp[i][j]+=d[j]; + } + } + } + else + { + for(j=1;j<=wp.ncf;++j) + pp[1][j]=a[j]; + yy[1]=chi2_wp_color(a); + + for(i=1;i<=wp.ncf;++i) + { + a[i]+=d[i]; + if(i>1)a[i-1]-=d[i-1]; + for(j=1;j<=wp.ncf;++j) + yy[i+1]=chi2_wp_color(a); + pp[i+1][j]=a[j]; + } + a[wp.ncf]-=d[wp.ncf]; + } +} + +void wp_color_input() +{ + float x1,x2,x3; + FILE *fp; + int i,j,n=11; + char a[1000],b[1000]; + + + /* The first call to wp_input() will be the standard full sample. + */ + wp_input(); + + /* Put the data into the wp_color arrays + */ + wp_color.r_full = dvector(1,wp.np); + wp_color.x_full = dvector(1,wp.np); + wp_color.e_full = dvector(1,wp.np); + wp_color.covar_full = dmatrix(1,wp.np,1,wp.np); + wp_color.n_full = wp.np; + if(wp.np>n)wp_color.n_full = n; + wp_color.ngal_full = GALAXY_DENSITY; + + for(i=1;i<=wp.np;++i) + { + wp_color.r_full[i] = wp.r[i]; + wp_color.x_full[i] = wp.x[i]; + wp_color.e_full[i] = wp.e[i]; + for(j=1;j<=wp.np;++j) + wp_color.covar_full[i][j] = wp.covar[i][j]; + } + free_dvector(wp.r,1,wp.np); + free_dvector(wp.x,1,wp.np); + free_dvector(wp.e,1,wp.np); + free_dmatrix(wp.covar,1,wp.np,1,wp.np); + + /* The second call is the blue sample. + */ + sprintf(a,"%s",wp.fname_wp); + sprintf(b,"%s",wp.fname_covar); + + sprintf(wp.fname_wp,"%s_blue",a); + sprintf(wp.fname_covar,"%s_blue",b); + wp_input(); + + wp_color.r_blue = dvector(1,wp.np); + wp_color.x_blue = dvector(1,wp.np); + wp_color.e_blue = dvector(1,wp.np); + wp_color.covar_blue = dmatrix(1,wp.np,1,wp.np); + wp_color.n_blue = wp.np; + if(wp.np>n)wp_color.n_blue = n; + wp_color.ngal_blue = GALAXY_DENSITY*HOD.blue_fraction; + + for(i=1;i<=wp.np;++i) + { + wp_color.r_blue[i] = wp.r[i]; + wp_color.x_blue[i] = wp.x[i]; + wp_color.e_blue[i] = wp.e[i]; + for(j=1;j<=wp.np;++j) + wp_color.covar_blue[i][j] = wp.covar[i][j]; + } + free_dvector(wp.r,1,wp.np); + free_dvector(wp.x,1,wp.np); + free_dvector(wp.e,1,wp.np); + free_dmatrix(wp.covar,1,wp.np,1,wp.np); + + /* The third call is the red sample. + */ + sprintf(wp.fname_wp,"%s_red",a); + sprintf(wp.fname_covar,"%s_red",b); + wp_input(); + + wp_color.r_red = dvector(1,wp.np); + wp_color.x_red = dvector(1,wp.np); + wp_color.e_red = dvector(1,wp.np); + wp_color.covar_red = dmatrix(1,wp.np,1,wp.np); + wp_color.n_red = wp.np; + if(wp.np>n)wp_color.n_red = n; + wp_color.ngal_red = GALAXY_DENSITY*(1-HOD.blue_fraction); + + for(i=1;i<=wp.np;++i) + { + wp_color.r_red[i] = wp.r[i]; + wp_color.x_red[i] = wp.x[i]; + wp_color.e_red[i] = wp.e[i]; + for(j=1;j<=wp.np;++j) + wp_color.covar_red[i][j] = wp.covar[i][j]; + } + free_dvector(wp.r,1,wp.np); + free_dvector(wp.x,1,wp.np); + free_dvector(wp.e,1,wp.np); + free_dmatrix(wp.covar,1,wp.np,1,wp.np); + + /* Open permanent arrays that are larger than any individual array in + * the color sequence. + */ + wp.r = dvector(1,15); + wp.x = dvector(1,15); + wp.e = dvector(1,15); + wp.covar = dmatrix(1,15,1,15); +} + +/* +double N_cen_blue(double m) +{ + if(m + +typedef struct FCOMPLEX {float r,i;} fcomplex; + +fcomplex Cadd(fcomplex a, fcomplex b) +{ + fcomplex c; + c.r=a.r+b.r; + c.i=a.i+b.i; + return c; +} + +fcomplex Csub(fcomplex a, fcomplex b) +{ + fcomplex c; + c.r=a.r-b.r; + c.i=a.i-b.i; + return c; +} + + +fcomplex Cmul(fcomplex a, fcomplex b) +{ + fcomplex c; + c.r=a.r*b.r-a.i*b.i; + c.i=a.i*b.r+a.r*b.i; + return c; +} + +fcomplex Complex(float re, float im) +{ + fcomplex c; + c.r=re; + c.i=im; + return c; +} + +fcomplex Conjg(fcomplex z) +{ + fcomplex c; + c.r=z.r; + c.i = -z.i; + return c; +} + +fcomplex Cdiv(fcomplex a, fcomplex b) +{ + fcomplex c; + float r,den; + if (fabs(b.r) >= fabs(b.i)) { + r=b.i/b.r; + den=b.r+r*b.i; + c.r=(a.r+r*a.i)/den; + c.i=(a.i-r*a.r)/den; + } else { + r=b.r/b.i; + den=b.i+r*b.r; + c.r=(a.r*r+a.i)/den; + c.i=(a.i*r-a.r)/den; + } + return c; +} + +float Cabs(fcomplex z) +{ + float x,y,ans,temp; + x=fabs(z.r); + y=fabs(z.i); + if (x == 0.0) + ans=y; + else if (y == 0.0) + ans=x; + else if (x > y) { + temp=y/x; + ans=x*sqrt(1.0+temp*temp); + } else { + temp=x/y; + ans=y*sqrt(1.0+temp*temp); + } + return ans; +} + +fcomplex Csqrt(fcomplex z) +{ + fcomplex c; + float x,y,w,r; + if ((z.r == 0.0) && (z.i == 0.0)) { + c.r=0.0; + c.i=0.0; + return c; + } else { + x=fabs(z.r); + y=fabs(z.i); + if (x >= y) { + r=y/x; + w=sqrt(x)*sqrt(0.5*(1.0+sqrt(1.0+r*r))); + } else { + r=x/y; + w=sqrt(y)*sqrt(0.5*(r+sqrt(1.0+r*r))); + } + if (z.r >= 0.0) { + c.r=w; + c.i=z.i/(2.0*w); + } else { + c.i=(z.i >= 0) ? w : -w; + c.r=z.i/(2.0*c.i); + } + return c; + } +} + +fcomplex RCmul(float x, fcomplex a) +{ + fcomplex c; + c.r=x*a.r; + c.i=x*a.i; + return c; +} diff --git a/c_tools/hod/complex.h b/c_tools/hod/complex.h new file mode 100644 index 0000000..99e065d --- /dev/null +++ b/c_tools/hod/complex.h @@ -0,0 +1,26 @@ +/* CAUTION: This is the ANSI C (only) version of the Numerical Recipes + utility file complex.h. Do not confuse this file with the same-named + file complex.h that is supplied in the 'misc' subdirectory. + *That* file is the one from the book, and contains both ANSI and + traditional K&R versions, along with #ifdef macros to select the + correct version. *This* file contains only ANSI C. */ + +#ifndef _NR_COMPLEX_H_ +#define _NR_COMPLEX_H_ + +#ifndef _FCOMPLEX_DECLARE_T_ +typedef struct FCOMPLEX {float r,i;} fcomplex; +#define _FCOMPLEX_DECLARE_T_ +#endif /* _FCOMPLEX_DECLARE_T_ */ + +fcomplex Cadd(fcomplex a, fcomplex b); +fcomplex Csub(fcomplex a, fcomplex b); +fcomplex Cmul(fcomplex a, fcomplex b); +fcomplex Complex(float re, float im); +fcomplex Conjg(fcomplex z); +fcomplex Cdiv(fcomplex a, fcomplex b); +float Cabs(fcomplex z); +fcomplex Csqrt(fcomplex z); +fcomplex RCmul(float x, fcomplex a); + +#endif /* _NR_COMPLEX_H_ */ diff --git a/c_tools/hod/covar_test.c b/c_tools/hod/covar_test.c new file mode 100644 index 0000000..ad817dc --- /dev/null +++ b/c_tools/hod/covar_test.c @@ -0,0 +1,114 @@ +#include +#include +#include +#include +#include + +#ifdef PARALLEL +#include +#endif + +#include "header.h" + +void covar_test() +{ + int i,j,k,n,nd=2,nrot; + float x[5],x1,x2,x3,x4,x0; + double **cov,**tmp,*avg,**tmp1,*eval,**evect,*a,*atemp; + FILE *fp; + + fp = openfile("acc.out"); + n = filesize(fp); + + a = dvector(1,nd); + atemp = dvector(1,nd); + + cov = dmatrix(1,nd,1,nd); + evect = dmatrix(1,nd,1,nd); + avg = dvector(1,nd); + eval = dvector(1,nd); + tmp = dmatrix(1,nd,1,nd); + tmp1 = dmatrix(1,nd,1,1); + + for(j=1;j<=nd;++j) + { + avg[j] = 0; + tmp1[j][1] = 0; + for(k=1;k<=nd;++k) + cov[j][k] = 0; + } + + for(i=1;i<=n;++i) + { + fscanf(fp,"%f %d %f %f %f %f",&x0,&j,&x[1],&x[2],&x[3],&x[4]); + x[1] = log(x[1]); + x[3] = log(x[3]); + x[4] = log(x[4]); + for(j=1;j<=nd;++j) + { + avg[j] += x[j]; + for(k=1;k<=nd;++k) + cov[j][k] += x[j]*x[k]; + } + } + + for(j=1;j<=nd;++j) + for(k=1;k<=nd;++k) + cov[j][k] = cov[j][k]/n - avg[j]*avg[k]/(n*n); + + for(j=1;j<=nd;++j) + { + printf("cov %d> ",j); + for(k=1;k<=nd;++k) + printf("%f ",cov[j][k]); + printf("\n"); + } + printf("\n"); + + n = nd; + + jacobi(cov,n,eval,evect,&nrot); + + for(j=1;j<=nd;++j) + { + printf("jac %d> ",j); + for(k=1;k<=nd;++k) + printf("%f ",evect[j][k]); + printf("\n"); + } + printf("\n"); + + for(k=1;k<=nd;++k) + printf("%f ",eval[k]); + printf(" %d \n",nrot); + printf("\n"); + + + gaussj(evect,n,tmp1,1); + + for(j=1;j<=nd;++j) + { + printf("gj %d> ",j); + for(k=1;k<=nd;++k) + printf("%f ",evect[j][k]); + printf("\n"); + } + printf("\n"); + + + for(i=1;i<=n;++i) + atemp[i] = sqrt(eval[i]); + + for(i=1;i<=n;++i) + for(a[i]=0,j=1;j<=n;++j) + a[i] += atemp[j]*evect[j][i]; + + + for(k=1;k<=nd;++k) + printf("%f ",a[k]); + printf("\n\n"); + + + exit(0); +} + diff --git a/c_tools/hod/dFdx.c b/c_tools/hod/dFdx.c new file mode 100644 index 0000000..642166d --- /dev/null +++ b/c_tools/hod/dFdx.c @@ -0,0 +1,157 @@ +#include +#include +#include +#include "header.h" + +/** halo pair separation profile for halo with concentration c_NFW + [satellite-satellite] + x=r/(2*R_vir) 0<=x<=1 + analytic solution of Sheth et al (2001) MNRAS 325, 1288 (eq.A25) + dF/dx \propto \lambda(r)*r^2 + normalized so that \int_0^1 dF/dx dx =1 + The normalization factor in this subroutine is obtained from my + fitting formula, which has a fractional error less than 0.2% for + c_NFW in the range ~1 to ~100. The formula is basically a double + powerlaw with a smooth transition and the residuals are further + reduced with a (1+sine) function. + **/ + +double dFdx_ss(double x, double c_NFW) +{ + double f,y,a,Anorm; + double A0=4.915,alpha=-3.099,beta=0.617,cNFWc=1.651,mu=4.706; + double B0=0.0336,omega=2.684,phi=0.4079; + /** above are parameters in fitting formula of the normalization **/ + double t; + double t1,t2,t3,ta; + + if(x<=0.0 || x>=1.0) return 0.0; + + a=1.0/c_NFW; + y=2.0*c_NFW*x; + + + if(x<0.5) + { + f=(-4.0*(1.0+a)+2.0*a*y*(1.0+2.0*a)+a*a*y*y)/(2.0*(1.0+a)*(1.0+a)*(2.0+y)); + f=f+log(fabs((1.0+a-a*y)*(1.0+y))/(1.0+a))/y+y*log(1.0+y)/(2.0+y)/(2.0+y); + } + else + { + f=y*log((1.0+a)/fabs(a*y+a-1))/(2.0+y)/(2.0+y); + f=f+0.5*y*(a*a*y-2.0*a)/(1.0+a)/(1.0+a)/(2.0+y); + } + + /** get the normalization factor from a fitting formula **/ + t=pow(c_NFW/cNFWc,(beta-alpha)/mu); + Anorm=A0*pow(c_NFW,alpha)*pow(1.0+t,mu)*(1.0+B0*sin(omega*(log10(c_NFW)-phi))); + + return Anorm*f; +} + +/** [central-satellite] i.e. the NFW profile rho(r)*r^2 + x=r/(2*R_vir) + **/ + +double dFdx_cs(double x, double c_NFW) +{ + double f,A,y; + + if(x>0.5) return 0.0; + else { + y=1.0+2.0*c_NFW*x; + f=x/(y*y); + A=(log(1.0+c_NFW)-c_NFW/(1.0+c_NFW))/(4.0*c_NFW*c_NFW); + return f/A; + } +} + +/* The redshift-space one-halo term spends the majority of its time + * calculating NFW pair densities for sat-sat pairs. To speed up + * the calculation, this tabulates the values of dFdx_ss on a grid + * for bilinear interpolation. + * + * In tests, accuracy is usually about 1E-5, and at worst 1E-3. + */ +double dFdx_ss_interp(double r, double c) +{ + static int flag=0,reset=0; + static double **x; + static double clo,dlogc,chi; + int nx=2000, nc=100, i,j,ir,ic; + double c_nfw,x1,x2,x3,c_fac=2; + + if(!flag) + { + x=dmatrix(0,nc,1,nx); + flag=1; + if(OUTPUT) + fprintf(stdout,"dFdx_ss_interp> Tabulating dFdx_ss...\n"); + clo = 0.1; + chi = 1000.0; + dlogc = (log(chi)-log(clo))/(nc-1); + for(j=1;j<=nx;++j) + x[0][j]=0; + for(i=1;i<=nc;++i) + { + c_nfw=exp((i-1)*dlogc)*clo; + for(j=1;j<=nx;++j) { + x[i][j]=dFdx_ss((double)j/nx,c_nfw); } + } + if(OUTPUT) + fprintf(stdout,"dFdx_ss_interp> ...Finished.\n"); + } + r*=nx; + c_fac = log(c/clo)/dlogc+1; + ir=(int)r; + ic=(int)c_fac; + if(ic==0)ic++; + if(ic==nc)ic--; + if(ic==0 || ic>=nc) { + printf("%f %f %f %d\n",r/nx,c,c_fac,ic); + endrun("dFdx error"); } + + x1=(x[ic][ir+1]-x[ic][ir])*(r-ir)+x[ic][ir]; + x2=(x[ic+1][ir+1]-x[ic+1][ir])*(r-ir)+x[ic+1][ir]; + return((x2-x1)*(c_fac-ic)+x1); +} + + +/* Well, it looks like it really doesn't help much of anything to tabulate + * the central-satellite function (which isn't too surprising since the number + * of computations isn't very large). But the above one seems to do very well. + */ + +double dFdx_cs_interp(double r, double c) +{ + static int flag=0; + static double **x; + int nx=1000, nc=19, i,j,ir,ic; + double c_nfw,x1,x2,x3; + + if(r>0.5)return(0); + + if(!flag++) + { + fprintf(stderr,"Tabulating dFdx_cs...\n"); + x=dmatrix(0,nc,1,nx); + for(i=1;i<=nc;++i) + { + c_nfw=i; + x[0][j]=0; + for(j=1;j<=nx;++j) + x[i][j]=dFdx_cs((double)j/nx,c_nfw); + fprintf(stderr,"%d\n",i); + } + fprintf(stderr,"Finished.\n"); + } + r*=nx; + ir=(int)r; + ic=(int)c; + if(ic==0 || ic>=nc) + endrun("dFdx error"); + + x1=(x[ic][ir+1]-x[ic][ir])*(r-ir)+x[ic][ir]; + x2=(x[ic+1][ir+1]-x[ic+1][ir])*(r-ir)+x[ic+1][ir]; + return((x2-x1)*(c-ic)+x1); +} diff --git a/c_tools/hod/dark_matter_statistics.c b/c_tools/hod/dark_matter_statistics.c new file mode 100644 index 0000000..e3ed8b5 --- /dev/null +++ b/c_tools/hod/dark_matter_statistics.c @@ -0,0 +1,161 @@ +#include +#include +#include +#include +#include "header.h" + +void output_matter_power_spectrum() +{ + int k; + double dlogk,xk,plin,pnl; + FILE *fp; + char aa[100]; + + fprintf(stderr,"\n\nCALCULATING MATTER POWER SPECTRA.\n"); + fprintf(stderr, "---------------------------------\n\n"); + + sprintf(aa,"%s.matter_pk",Task.root_filename); + fp = fopen(aa,"w"); + + for(k=-300;k<=100;++k) + { + xk=pow(10.0,k/100.0); + plin = linear_power_spectrum(xk)/(xk*xk*xk)*TWOPI*PI; + pnl = nonlinear_power_spectrum(xk)/(xk*xk*xk)*TWOPI*PI; + fprintf(fp,"%e %e %e\n",xk,plin,pnl); + } + fclose(fp); + +} + +void output_matter_correlation_function() +{ + int k,nr=50; + double dlogr,r,xlin,xnl,rmin = 0.05,rmax = 80.0; + FILE *fp; + char aa[100]; + + fprintf(stderr,"\n\nCALCULATING MATTER CORRELATION FUNCTIONIONS.\n"); + fprintf(stderr, "--------------------------------------------\n\n"); + + sprintf(aa,"%s.matter_xi",Task.root_filename); + fp = fopen(aa,"w"); + + dlogr = (log(rmax) - log(rmin))/(nr-1); + + for(k=0;k +#include +#include + +#include "header.h" + +#define NBINLOOKUP2 10000000 +double *xm1,*xf1,*dx1,*mfunc1,*mfy1,*xm2; +int inx; + +double N_cen_hiden(double m); +double func_ng6(double m); + +void dd_hod_functions(float *hmass, float *hdensity, int nhalo) +{ + static int flag=0; + + int i,j,k,nh,i1,i2,ibin,*nbin,*fbin; + float *den,*mbin,mass,density,ng1,ng2; + FILE *fp,*fp2; + char a[1000]; + + double func_ng3(),func_ng4(); + + /* Variables for the log bins. + */ + float dlogm,dmax=5.0e16,dmin=1.0e9,*dupp,binfac; + int idmax=1000,kbin,*binlookup; + + if(flag)goto SKIP1; + flag=1; + + /*********************** + *initializing the logarithmic bins + */ + idmax = 100; + + dlogm=log(dmax/dmin)/(float)(idmax-1) ; + dupp=malloc(idmax*sizeof(float)); + binlookup=(int *)calloc(NBINLOOKUP2+2,sizeof(int)) ; + ibin=0 ; + for (i=0;i<=NBINLOOKUP2;i++) { + mass=dmax*i/NBINLOOKUP2 ; + if (mass>0) { + kbin=(int)floor(log(mass/dmin)/dlogm+1.0) ; + } + else { + kbin=0 ; + } + if (kbin<0) kbin=0 ; + if (kbin>ibin) { + dupp[ibin]=mass ; + ibin=kbin ; + } + binlookup[i]=kbin ; + } + binlookup[NBINLOOKUP2+1]=idmax ; + binfac=NBINLOOKUP2/dmax ; + dupp[idmax-1]=dmax; + + nbin=calloc(idmax,sizeof(int)); + mbin=calloc(idmax,sizeof(double)); + fbin=calloc(idmax,sizeof(int)); + + for(i=1;i<=nhalo;++i) + { + mass=hmass[i]; + j=binlookup[(int)(mass*binfac)]; + mbin[j]+=mass; + nbin[j]++; + if(GAO_EFFECT) { + if(hdensity[i]>DENSITY_THRESHOLD) + fbin[j]++; + } else { + if(hdensity[i]1)x=1; + if(x<0)x=0; + // x=x*dn*(N_sat(m) + N_cen_hiden(m))*m; <-- this is for GAO EFFECT + x=x*dn*N_avg(m)*m; + return(x); +} + +double func_ng5(double m) +{ + double x,dn; + splint(xm2,mfunc1,mfy1,inx,m,&dn); + dn=exp(dn); + m=exp(m); + // dn = dndM_interp(m); + splint(xm1,xf1,dx1,inx,m,&x); + if(x>1)x=1; + if(x<0)x=0; + x=(1-x)*dn*N_avg(m)*m; + return(x); +} + +double func_ng4(double m) +{ + double mlo,x1,x2,func_ng5(),func_mlow(); + + HOD.M_min=exp(m); + if(SOFT_CENTRAL_CUTOFF) + mlo = (zbrent(func_mlow,log(HOD.M_min*1.0E-4),log(HOD.M_min),1.0E-5)); + else + mlo = m; + HOD.M_low=exp(mlo); + x1 = qromo(func_ng5,mlo,log(HOD.M_max),midpnt); + HOD.M_min=HOD.M_min*HOD.M_min_fac; + x2 = qromo(func_ng3,mlo,log(HOD.M_max),midpnt); + // printf("%e %e %e\n",x1,x2,GALAXY_DENSITY); + return((x1+x2)-GALAXY_DENSITY); +} + + +double density_fraction(double m) +{ + double x; + splint(xm1,xf1,dx1,inx,m,&x); + return(x); +} + +double func_ng_hiden(double m) +{ + return(0); +} +double func_ng_loden(double m) +{ + return(0); +} + +/* Color-dependent models. + */ +double dd_func_red_fraction(double x) +{ + double n; + HOD.fblue0_cen=pow(10.0,x); + //HOD.fblue0_cen = 0.67; + n = qtrap(func_ng6,log(HOD.M_low),log(HOD.M_max),1.0E-5); + printf("%f %e %e %e %e %e\n",HOD.fblue0_cen,n,wp_color.ngal_red,N_avg(8.0e11),HOD.M_min,HOD.M_low); + // exit(0); + return n - wp_color.ngal_red; +} + +double func_ng6(double m) +{ + double x,x1,dn,xt; + splint(xm2,mfunc1,mfy1,inx,m,&dn); + dn=exp(dn); + m=exp(m); + //dn = dndM_interp(m); + splint(xm1,xf1,dx1,inx,m,&x); + if(x>1)x=1; + if(x<0)x=0; + // printf("%e %e\n",m,x); + x1=(1-x)*dn*N_avg(m)*m; // 1-x is fraction above critical density. + xt = HOD.fblue0_cen; + HOD.fblue0_cen = (1. - HOD.M_min_fac*(1.0 - HOD.fblue0_cen)); + x1+=x*dn*N_avg(m)*m; + HOD.fblue0_cen = xt; + return(x1); +} diff --git a/c_tools/hod/dump.c b/c_tools/hod/dump.c new file mode 100644 index 0000000..e7550ae --- /dev/null +++ b/c_tools/hod/dump.c @@ -0,0 +1,15 @@ + if(Work.iquad && Work.iquad_covar) + { + calc_rquad(Work.r_quad,rquad,Work.n_quad); + for(i=0;i +#include +#include +#include + +#ifdef PARALLEL +#include +#endif + +#include "header.h" + +void initial_scale_bias_parameters(double **pp, double *yy); +double chi2_scale_bias(double *a); +char *BIAS_FILENAME; +double LARGE_SCALE_BIAS; + +void fit_scale_bias(int argc, char **argv) +{ + FILE *fp; + int n,i,j,k,niter; + + double FTOL = 1.e-3; + double **pp,*yy; + + BIAS_FILENAME = argv[3]; + LARGE_SCALE_BIAS = atof(argv[4]); + + wp.ncf = 4; + + pp=dmatrix(1,wp.ncf+1,1,wp.ncf); + yy=dvector(1,wp.ncf+1); + initial_scale_bias_parameters(pp,yy); + amoeba(pp,yy,wp.ncf,FTOL,chi2_scale_bias,&niter); + +} + +void initial_scale_bias_parameters(double **pp, double *yy) +{ + int i,j; + double d[100],a[100]; + + a[1] = 1.17; + a[2] = 1.79; + a[3] = 1.01; + a[4] = 2.03; + + for(i=1;i<=wp.ncf;++i) + d[i]=a[i]*0.2; + + for(j=1;j<=wp.ncf;++j) + pp[1][j]=a[j]; + yy[1]=chi2_scale_bias(a); + + for(i=1;i<=wp.ncf;++i) + { + a[i]+=d[i]; + if(i>1)a[i-1]-=d[i-1]; + yy[i+1]=chi2_scale_bias(a); + + for(j=1;j<=wp.ncf;++j) + pp[i+1][j]=a[j]; + } + a[wp.ncf]-=d[wp.ncf]; + +} + + +double chi2_scale_bias(double *a) +{ + static FILE *fp; + static int n, flag = 1; + static float *r,*x,*e; + + int i; + double xi,chi2=0,b; + char aa[1000]; + + if(flag) + { + fp = openfile(BIAS_FILENAME); + n = filesize(fp); + + r = vector(1,n); + x = vector(1,n); + e = vector(1,n); + + for(i=1;i<=n;++i) { + fscanf(fp,"%f %f %f",&r[i],&x[i],&e[i]); + x[i] = x[i]/LARGE_SCALE_BIAS; //bias_interp(7.70e10,-1); + e[i] = 0.05*x[i]; + fgets(aa,1000,fp); } + flag = 0; + } + + for(i=1;i<=n;++i) + { + if(r[i]>20)continue; + xi = xi_interp(r[i]); + b = pow(1+a[1]*xi,a[2])/pow(1+a[3]*xi,a[4]); + chi2 += (b - x[i])*(b - x[i])/e[i]/e[i]; + } + if(isnan(chi2))chi2 = 1.0E7; + printf("ITER %e %f %f %f %f\n",chi2,a[1],a[2],a[3],a[4]); + return(chi2); +} diff --git a/c_tools/hod/ftread.c b/c_tools/hod/ftread.c new file mode 100644 index 0000000..4a6b504 --- /dev/null +++ b/c_tools/hod/ftread.c @@ -0,0 +1,51 @@ +/* ftread reads unformatted data that has been written by fortran + or in fortran convention -- i.e. an integer with the number of + bytes in the record, the record data, and another integer with + the number of bytes in the record. ftread does various error + checks, writing a message to stderr and returning a negative + value if an error or warning occurs. The call is identical to + the standard i/o library routine fread. +*/ + +#include + +int ftread(ptr,size,nitems,stream) +char *ptr ; +unsigned size, nitems ; +FILE *stream ; + +{ + int nbyte1, nbyte2, nitem1 ; + int errno ; + + errno = 0 ; + if ( fread(&nbyte1,sizeof(int),1,stream) != 1 ) { + errno = -10 ; + fprintf(stderr,"read error, file empty ? \n") ; + } + nitem1 = fread(ptr,size,nitems,stream) ; + if ( nitem1 != nitems ) { + errno = -20 ; + fprintf(stderr,"read error, %d items expected, %d items read. \n", + nitems,nitem1) ; + } + if ( fread(&nbyte2,sizeof(int),1,stream) != 1 ) { + errno = -30 ; + fprintf(stderr,"read error, file too short ? \n") ; + } + if ( nbyte1 != nbyte2 ) { + errno = errno - 1 ; + fprintf(stderr, + "read warning, byte #s do not match, nbyte1 = %d, nbyte2 = %d \n", + nbyte1,nbyte2) ; + } + if ( nbyte1 != size*nitems) { + errno = errno - 2 ; + fprintf(stderr, + "read warning, byte # does not match item #, nbyte1 = %d, nitems = %d \n", + nbyte1,nitems) ; + } + + return(errno) ; + +} diff --git a/c_tools/hod/ftwrite.c b/c_tools/hod/ftwrite.c new file mode 100644 index 0000000..3952a84 --- /dev/null +++ b/c_tools/hod/ftwrite.c @@ -0,0 +1,38 @@ +/* ftwrite writes data unformatted using fortran convention -- + i.e. an integer specifying the number of bytes in the record, + the data record, and another integer specifying the number of + bytes in the record. The call is identical to the standard + i/o library routine fwrite. +*/ + +#include + +int ftwrite(ptr,size,nitems,stream) +char *ptr ; +unsigned size, nitems ; +FILE *stream ; + +{ + int nbytes, nitem1 ; + int errno ; + + errno = 0 ; + nbytes = size*nitems ; + if ( fwrite(&nbytes,sizeof(int),1,stream) != 1 ) { + errno = -10 ; + fprintf(stderr,"write error, is the file open ? \n") ; + } + nitem1 = fwrite(ptr,size,nitems,stream) ; + if ( nitem1 != nitems ) { + errno = -20 ; + fprintf(stderr,"write error, %d items requested, %d items written. \n", + nitems,nitem1) ; + } + if ( fwrite(&nbytes,sizeof(int),1,stream) != 1 ) { + errno = -30 ; + fprintf(stderr,"write error on second byte label \n") ; + } + + return(errno) ; + +} diff --git a/c_tools/hod/galaxy_prob_vz.c b/c_tools/hod/galaxy_prob_vz.c new file mode 100644 index 0000000..4b2eab2 --- /dev/null +++ b/c_tools/hod/galaxy_prob_vz.c @@ -0,0 +1,484 @@ +#include +#include +#include +#include + +#ifdef PARALLEL +#include +#endif + +#include "header.h" + + +/* These are the parameters for creating the pdf table. + */ +int nv1,nr1,nphi1; +void create_pdf_table(); +double ***ppp,*vvv,*rbin,*phibin,***yy2,FIRSTFLAG=1; +double BINSIZE; + +double galaxy_prob_vz(double vel, double rad, double theta) +{ + static int flag=0,prev_cosmo=0; + static double *y,*ya,*yb,*y2b,*xb,rv[21],rmin,rmax,dlogr; + + int i,j,k,irad,iphi; + double vprob,m1,m2; + + if(!flag || RESET_PVZ || RESET_COSMOLOGY!=prev_cosmo) + { + rmin=1.7*pow(3*HOD.M_low/(4*DELTA_HALO*PI*OMEGA_M*RHO_CRIT),1.0/3.0); + rmax=XI_MAX_RADIUS; + dlogr=log(rmax/rmin)/(nr1-1); + + if((RESET_PVZ || RESET_COSMOLOGY!=prev_cosmo) && !ThisTask) + { + printf("RESET: creating new table for:\n"); + printf(" > OMEGA_M = %f\n",OMEGA_M); + printf(" > SIGMA_8 = %f\n",SIGMA_8); + printf(" > VBIAS = %f\n",VBIAS); + printf(" > VBIAS_C = %f\n",VBIAS_C); + fflush(stdout); + } + RESET_PVZ=0; + prev_cosmo=RESET_COSMOLOGY; + + create_pdf_table(); + + if(!flag) + { + y=dvector(1,nphi1); + ya=dvector(1,nphi1); + yb=dvector(1,4); + y2b=dvector(1,4); + xb=dvector(1,4); + } + + flag=1; + + for(i=1;i<=nr1;++i) + for(j=1;j<=nphi1;++j) + spline(vvv,ppp[i][j],nv1,1.0E+30,1.0E+30,yy2[i][j]); + + } + if(fabs(vel)>MAXVEL)return(0); + + if(theta<0)theta*=-1; + + for(i=1;i<=nr1;++i) + if(radnr1-1)i=nr1-1; + irad=i; + while(rbin[irad-2]==0)irad++; + if(irad>nr1-1) + { + printf("ERROR CANNOT ITERPOLATE FOR r=%f\n",rad); + exit(0); + } + + for(j=1,i=irad-2;i<=irad+1;++i,++j) + { + for(k=1;k<=nphi1;++k) + { + splint(vvv,ppp[i][k],yy2[i][k],nv1,vel,&y[k]); + } + spline(phibin,y,nphi1,1.0E+30,1.0E+30,ya); + splint(phibin,y,ya,nphi1,theta,&yb[j]); + xb[j]=rbin[i]; + } + spline(xb,yb,4,1.0E30,1.0E30,y2b); + splint(xb,yb,y2b,4,rad,&vprob); + + if(vprob<0)vprob=0; + return(vprob); + + + + irad=i; + if(irad<2)irad=2; + if(irad>nr1)irad=nr1; + iphi = (int)theta/(PI/18.0)+1; + if(iphi==nphi1)iphi=nphi1-1; + + + for(j=1,i=irad-1;i<=irad;++i) + { + for(k=iphi;k<=iphi+1;++k) + { + splint(vvv,ppp[i][k],yy2[i][k],nv1,vel,&y[j++]); + } + } + m1 = (y[1]-y[2])/(phibin[iphi]-phibin[iphi+1])*(theta-phibin[iphi])+y[1]; + m2 = (y[3]-y[4])/(phibin[iphi]-phibin[iphi+1])*(theta-phibin[iphi])+y[3]; + vprob = (m2-m1)/(rbin[irad]-rbin[irad-1])*(rad-rbin[irad-1])+m1; + if(vprob<0)vprob=0; + return(vprob); + +} + +/* For consistency, the MAXVEL and BINSIZE variables will be scaled by + * OMEGA_M^0.6. + * + */ +void create_pdf_table() +{ +#define NZMASS 19 + + int TEST=1; + + FILE *fp; + double dlogr,vbias1,vbias2; + static int CNT=0; + + double sgal[NZMASS][NZMASS],sgal_cs[NZMASS][NZMASS],sgal_cc[NZMASS][NZMASS], + *cf,fdat[10],s2gal[4],wgal[3],**mtemp, + ***ptemp,*vtemp,*temp,*p1temp,*p2temp,*precv,*rvir,*ngal,**ngal2,**ngal2x,*mbin; + double binsize,ptot,vprob,p0,p1,p2,p3,s1,s2,s3,s4,v1,v, + mass,mlo,mhi,qromo(),midpnt(),sgal1[NZMASS][NZMASS],hmass[NZMASS], + sgal2[NZMASS][NZMASS],w1[NZMASS][NZMASS],w2[NZMASS][NZMASS],mass1,mass2,wsum,fac, + w3[NZMASS][NZMASS],t0,tsum=0,t1,tdiff,frac1,frac2,frac3,frac4,x1,x2,deltar, + haloweight,immax,mmax,rmax,rmin,exfac,xx1=0,weightsum; + int i,j,k,n,nzmass,imass=0,irad,im1,im2,istep=1,istart=1,jstart=1,jstep=1, + idat[10],nitems; + float f1; + + CNT++; + +#ifdef PARALLEL + istep = 1; + istart = 1; + jstart = ThisTask + 1; + jstep = NTask; +#endif + + BINSIZE=20*pow(OMEGA_M/0.3,0.6); + + rmin=R_MIN_2HALO; + rmin=1.1*pow(3*HOD.M_low/(4*DELTA_HALO*PI*OMEGA_M*RHO_CRIT),1.0/3.0); + rmax=XI_MAX_RADIUS; + nr1=30; + nv1=301; + nphi1=9; + MAXVEL=BINSIZE*floor(nv1/2); + + + /* This assumes that even if the cosmology is changed, that + * the dimensions of these arrays won't change. + */ + if(FIRSTFLAG) + { + vvv=dvector(1,nv1); + rbin=dvector(1,nr1); + phibin=dvector(1,nphi1); + yy2=d3tensor(1,nr1,1,nphi1,1,nv1); + ppp=d3tensor(1,nr1,1,nphi1,1,nv1); + FIRSTFLAG=0; + } + + if(TEST) + { + HOD.pdfs=0; + HOD.M_min = HOD.M_low = 4.4e11; + rmin=1.1*pow(3*HOD.M_low/(4*DELTA_HALO*PI*OMEGA_M*RHO_CRIT),1.0/3.0); + } + + dlogr=log(rmax/rmin)/(nr1-1); + for(i=1;i<=nr1;++i) + rbin[i]=rmin*exp((i-1)*dlogr); + for(i=1;i<=nphi1;++i) + phibin[i]=(i-0.5)/nphi1*PI/2; + for(i=1;i<=nv1;++i) + vvv[i]=-MAXVEL+(i-1)*BINSIZE; + + nzmass=NUM_POW2MASS_BINS-1; + + ptemp=d3tensor(0,nzmass-1,0,nzmass-1,1,nv1); + vtemp=dvector(1,nv1); + temp=dvector(1,nv1); + p1temp=dvector(1,nv1); + p2temp=dvector(1,nv1); + precv=dvector(1,nv1); + rvir=dvector(0,nzmass); + mbin=dvector(0,nzmass); + + + for(i=1;i<=nr1;++i) + for(j=1;j<=nphi1;++j) + for(k=1;k<=nv1;++k) + ppp[i][j][k]=0; + + binsize=BINSIZE; + + fac=sqrt(4.499E-48/2.0)*pow(4*DELTA_HALO*PI*OMEGA_M*RHO_CRIT/3,1.0/6.0)*3.09E19; + fac=fac*fac; + + /* w1 -> number of i_sat + j_cen pairs + * w2 -> number of j_sat + i_cen pairs + * w3 -> number of i_sat + j_sat pairs + * + * Okay, I know that all you have to do is switch the indices on + * w1 to get w2, but just to keep things really clear, I'll have three + * different matrices. + */ + + for(i=0;i mass threshold + */ + /* + vbias1=1; + if(mass1 mass threshold + */ + /* + vbias2=1; + if(mass2nphi1) { i++; j=j-nphi1; } + if(i>nr1)break; + jstart=j; + for(j=jstart;j<=nphi1;j+=jstep) + { + t1=second(); + tdiff=timediff(t0,t1); + tsum+=tdiff; + t0=second(); + if(NTask==1 && OUTPUT) + { + fprintf(stdout,"P(v_z) r[%d]= %5.2f phi[%d]=%4.1f [dt= %.2f T=%7.2f] (task= %d)\n", + i,rbin[i],j,phibin[j]*180/PI,tdiff,tsum,ThisTask); + fflush(stdout); + } + for(im1=0;im1rvir[im2]*0.75) + { + ppp[i][j][k]+=ptemp[im1][im2][k]*ngal2[im1][im2]* + (bias_interp(hmass[im1],-1)*bias_interp(hmass[im2],-1)); + if(k==1)weightsum+=ngal2[im1][im2]* + (bias_interp(hmass[im1],-1)*bias_interp(hmass[im2],-1)); + } + continue; + + if(rbin[i]/(rvir[im1]+rvir[im2])>0.5) + { + exfac=1; + if(rbin[i]/(rvir[im1]+rvir[im2])<1.5) + exfac=ellipsoidal_exclusion_probability(rvir[im2]/rvir[im1], + rbin[i]/(rvir[im1]+rvir[im2])); + /* + if(rbin[i]<(rvir[im1]+rvir[im2])) + exfac = 0; + if(rvir[im2]/rvir[im1]>pow(100.0,.333) && rbin[i]>(rvir[im1]+rvir[im2])*0.5) + exfac = 1; + */ + ppp[i][j][k]+=ptemp[im1][im2][k]*ngal2[im1][im2]*exfac*1* + sqrt(bias_interp(hmass[im1],-1)*bias_interp(hmass[im2],-1)); + if(k==1)weightsum+=ngal2[im1][im2]*exfac*1* + sqrt(bias_interp(hmass[im1],-1)*bias_interp(hmass[im2],-1)); + } + } + //printf("WEIGHTSUM %d %d %e %.0f\n", + // i,j,weightsum,weightsum*BOX_SIZE*BOX_SIZE*BOX_SIZE); + if(weightsum>0) + { + for(k=1;k<=nv1;++k) + ppp[i][j][k]/=weightsum; + // for(k=1;k<=nv1;++k) + //printf("yTEST %d %d %f %e\n",i,j,vvv[k],ppp[i][j][k]); + for(ptot=0,k=1;k<=nv1;++k) + ptot+=ppp[i][j][k]*binsize; + } + else + for(k=1;k<=nv1;++k) + ppp[i][j][k]=0; + + } + } + +#ifdef PARALLEL + for(i=1;i<=nr1;++i) + for(j=1;j<=nphi1;++j) + { + for(k=1;k<=nv1;++k) + temp[k]=ppp[i][j][k]; + MPI_Allreduce(&temp[1],&precv[1],nv1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD); + for(k=1;k<=nv1;++k) + ppp[i][j][k]=precv[k]; + } +#endif + + free_d3tensor(ptemp,0,nzmass-1,0,nzmass-1,1,nv1); + free_dvector(vtemp,1,nv1); + free_dvector(temp,1,nv1); + free_dvector(p1temp,1,nv1); + free_dvector(p2temp,1,nv1); + free_dvector(precv,1,nv1); + free_dvector(rvir,0,nzmass); + free_dvector(mbin,0,nzmass); + free_dvector(ngal,0,nzmass-1); + free_dmatrix(ngal2,0,nzmass-1,0,nzmass-1); + +} + + diff --git a/c_tools/hod/gasdev.c b/c_tools/hod/gasdev.c new file mode 100644 index 0000000..b823590 --- /dev/null +++ b/c_tools/hod/gasdev.c @@ -0,0 +1,24 @@ +#include + +float gasdev(long *idum) +{ + float ran1(long *idum); + static int iset=0; + static float gset; + float fac,rsq,v1,v2; + + if (iset == 0) { + do { + v1=2.0*ran1(idum)-1.0; + v2=2.0*ran1(idum)-1.0; + rsq=v1*v1+v2*v2; + } while (rsq >= 1.0 || rsq == 0.0); + fac=sqrt(-2.0*log(rsq)/rsq); + gset=v1*fac; + iset=1; + return v2*fac; + } else { + iset=0; + return gset; + } +} diff --git a/c_tools/hod/gaussj.c b/c_tools/hod/gaussj.c new file mode 100644 index 0000000..c938ae0 --- /dev/null +++ b/c_tools/hod/gaussj.c @@ -0,0 +1,59 @@ +#include +#define NRANSI +#include "nrutil.h" +#define SWAP(a,b) {temp=(a);(a)=(b);(b)=temp;} + +void gaussj(double **a, int n, double **b, int m) +{ + int *indxc,*indxr,*ipiv; + int i,icol,irow,j,k,l,ll; + double big,dum,pivinv,temp; + + indxc=ivector(1,n); + indxr=ivector(1,n); + ipiv=ivector(1,n); + for (j=1;j<=n;j++) ipiv[j]=0; + for (i=1;i<=n;i++) { + big=0.0; + for (j=1;j<=n;j++) + if (ipiv[j] != 1) + for (k=1;k<=n;k++) { + if (ipiv[k] == 0) { + if (fabs(a[j][k]) >= big) { + big=fabs(a[j][k]); + irow=j; + icol=k; + } + } else if (ipiv[k] > 1) nrerror("gaussj: Singular Matrix-1"); + } + ++(ipiv[icol]); + if (irow != icol) { + for (l=1;l<=n;l++) SWAP(a[irow][l],a[icol][l]) + for (l=1;l<=m;l++) SWAP(b[irow][l],b[icol][l]) + } + indxr[i]=irow; + indxc[i]=icol; + if (a[icol][icol] == 0.0) nrerror("gaussj: Singular Matrix-2"); + pivinv=1.0/a[icol][icol]; + a[icol][icol]=1.0; + for (l=1;l<=n;l++) a[icol][l] *= pivinv; + for (l=1;l<=m;l++) b[icol][l] *= pivinv; + for (ll=1;ll<=n;ll++) + if (ll != icol) { + dum=a[ll][icol]; + a[ll][icol]=0.0; + for (l=1;l<=n;l++) a[ll][l] -= a[icol][l]*dum; + for (l=1;l<=m;l++) b[ll][l] -= b[icol][l]*dum; + } + } + for (l=n;l>=1;l--) { + if (indxr[l] != indxc[l]) + for (k=1;k<=n;k++) + SWAP(a[k][indxr[l]],a[k][indxc[l]]); + } + free_ivector(ipiv,1,n); + free_ivector(indxr,1,n); + free_ivector(indxc,1,n); +} +#undef SWAP +#undef NRANSI diff --git a/c_tools/hod/growthfactor.c b/c_tools/hod/growthfactor.c new file mode 100644 index 0000000..2c09945 --- /dev/null +++ b/c_tools/hod/growthfactor.c @@ -0,0 +1,73 @@ +#include +#include +#include +#include "header.h" + +/* This calculates the linear growthfactor at redshift z. + * Currently, the default is a flat LCDM universe, but can easily + * be changed. + */ +double x03_g1, + xi3_g1; +double func_D0(double); +double func_Di(double); + +double growthfactor(double z) +{ + int i; + double zp1,x03,xi3,bi,b0,yy,sqx,sqx1,dbdx,x0,xi,lambda_i,htemp,omega_L,omega_i,hubble_i, + astart,fac,redshift; + + redshift=z; + astart=1.0/(z+1); + zp1=redshift+1; + omega_L=1-OMEGA_M; + + hubble_i = sqrt(OMEGA_M/(astart*astart*astart) + + (1.0-OMEGA_M-omega_L)/(astart*astart) +omega_L); + + if(omega_L>0) + { + lambda_i=omega_L/(omega_L+(1.0-OMEGA_M-omega_L)*zp1*zp1+OMEGA_M*pow(zp1,3.0)); + omega_i=OMEGA_M*pow(zp1,3.0)*lambda_i/omega_L; + } + else + { + lambda_i=0; + omega_i=OMEGA_M*zp1/(1.0+OMEGA_M*redshift); + } + + fac=astart; + + if((OMEGA_M < 0.99) && (omega_L > 0.001)) + { + x03_g1=x03=1.0/OMEGA_M-1.0; + xi3_g1=xi3=1.0/omega_i-1.0; + b0 = qromo(func_D0,0.0,1.0,midpnt); + bi = qromo(func_Di,0.0,1.0,midpnt); + b0=b0*sqrt(x03+1.0); + bi=bi*sqrt(xi3+1.0)*astart; + fac=bi/b0; + } + + + if((OMEGA_M < 0.99) && (omega_L == 0)) + { + x0=1.0/OMEGA_M-1.0; + xi=x0*astart; + b0 = 1.+3./x0+3.*sqrt(1+x0)*log(sqrt(1.+x0)-sqrt(x0))/pow(x0,1.5); + bi = 1.+3./xi+3.*sqrt(1+xi)*log(sqrt(1.+xi)-sqrt(xi))/pow(xi,1.5); + fac = bi/b0; + } + return(fac); +} + +double func_Di(double y) +{ + return(pow(1.0+xi3_g1*pow(y,1.2),-1.5)); +} + +double func_D0(double y) +{ + return(pow(1.0+x03_g1*pow(y,1.2),-1.5)); +} diff --git a/c_tools/hod/halo_bias.c b/c_tools/hod/halo_bias.c new file mode 100644 index 0000000..10d2ace --- /dev/null +++ b/c_tools/hod/halo_bias.c @@ -0,0 +1,300 @@ +#include +#include +#include + +#include "header.h" + + +/* This is the bias factor for halos. Mass (in h^{-1} M_sol) is the input. + * This is not the scale-dependent bias factor, which can be calculated later. + * + * There are many variants of the bias in this function. + * The one it is set up to use is from the Tinker etal (in prep, currently) + * bias paper calibrated from the SO halo catalogs from the Tinker et al mass functino + * paper. The parameters of the bias functions are calibrated such that they will + * work with any chosen halo overdensity. + * + * Other variants: + * + * The parameterization of b(M) is taken from Sheth Mo & Tormen (2001 MNRAS 232 1) + * but the actual parameters have been replaced by the values of Appendix A in + * Tinker, Weinberg, Zheng, & Zehavi. 2005 Apj (M/L paper) + * + * See also Seljak & Warren (2004). + * See also Sheth & Tormen (1999) + * See also Mo & White (1996) + */ + +double bias_from_file(double m, double r); + +double bias(double mass) +{ + double rm,sig,k,neff,b,logk,khi,klo,phi,plo,nu,psp,x; + static int flag=0; + static double pnorm, prev_delta=-1; + + // variables for the SO(DELTA) bias functions + static double bias_A, bias_a, bias_B, bias_b; + + /* Original SMT parameters */ + double a=0.707,bb=0.5,c=0.6; + + pnorm=SIGMA_8/sigmac(8.0); + rm=pow(3.0*mass/(4.0*PI*OMEGA_M*RHO_CRIT),1.0/3.0); + sig=pnorm*sigmac(rm); + + /* Tinker et al parameters */ + a=0.707; + bb=0.35; + c=0.8; + + /* Fitting to Mike Warren's simulations. */ + bb=0.28; + + /* Use the globel parameters. */ + a=BIAS_A; bb=BIAS_B; c=BIAS_C; + + /* First normalize the power spectrum + */ + pnorm=SIGMA_8/sigmac(8.0); + rm=pow(3.0*mass/(4.0*PI*OMEGA_M*RHO_CRIT),1.0/3.0); + sig=pnorm*sigmac(rm); + + + + /* This is from Tinker etal in prep for SO halos + */ + if(DELTA_HALO != prev_delta) + { + bias_A = pow(fabs(log10(DELTA_HALO)-2.69),2)*0.16 + 0.785; + bias_a = (log10(DELTA_HALO) - 2.28)*0.45; + bias_B = 0.4*(log10(DELTA_HALO)-2.3)+0.7*log10(DELTA_HALO)*exp(-pow(4/log10(DELTA_HALO),4.0))+1.23; + bias_b = 2.4; + fprintf(stderr,"BIAS PARAMS: %f %f %f %f\n",bias_A, bias_a, bias_B, bias_b); + prev_delta = DELTA_HALO; + } + + a = pow(sig,-bias_a); + b = 1 - bias_A*a/(a+1) + bias_B*pow(sig,-bias_b); + + return(b); + + /* This is the Seljak & Warren (2004) bias. + * There's an alpha_s in the correction term, which here I set to zero. (RUNNING.) + * See App. A of Tinker et al (M/L) for a comparison of this bias with above bias. + */ + x=mass/MSTAR; + b=(0.53+0.39*pow(x,0.45)+0.13/(40*x+1) + 5.0e-4*pow(x,1.5)); + b=b+log10(x)*(0.4*(OMEGA_M-0.3+SPECTRAL_INDX-1)+0.3*(SIGMA_8-0.9+HUBBLE-0.7)+0.8*0.0); + return(b); + + /* This is the Sheth Mo Tormen bias. + * (possible that parameter values have been changed to better fit simulations, + * ie from Tinker etal 2005 ML paper). + */ + nu=DELTA_CRIT/sig; + b=1+1.0/(sqrt(a)*DELTA_CRIT)*(sqrt(a)*a*nu*nu + sqrt(a)*bb*pow(a*nu*nu,1-c) - + (pow(a*nu*nu,c)/(pow(a*nu*nu,c)+bb*(1-c)*(1-c/2.)))); + return(b); + + + + /* This is Sheth & Tormen + */ + nu = DELTA_CRIT/sig; + nu = nu*nu; + return(1 + (0.707*nu - 1)/DELTA_CRIT + 2*0.3/DELTA_CRIT/(1+pow(0.707*nu,0.3))); + + /* This is the old Mo & White (1996) formula + */ + return(1+DELTA_CRIT/sig/sig-1/DELTA_CRIT); + + +} + +/* Just like the halo mass function, we'll set this up such that + * you just need to interpolate. + * + * Now this has been changed to calculate the spatial-scale dependence + * of the bias factor. If you don't want the scale dep. b, then just + * input r<0. + * + * If the global flag LINEAR_PSP==0, uses the scale dependence calculated for + * for halo bias relative to the non-linear matter \xi_m(r): + * + * f^2(r) = (1.0+xi*1.17)^1.49/(1.0+xi*0.69)^2.09 --> b(r) = b0*f(r) + * + * For LINEAR_PSP==1, use scale dependence determined for the linear P(k): + * + * f(r) = 1 + exp[-(r/A)^0.7] --> where A is a parameter that we're gonna have to + * determine in more detail, but now A \approx 1 + */ +double bias_interp(double m, double r) +{ + static int flag=0,prev_cosmo=0; + static double *x,*y,*y2, pnorm; + int i,n=100; + double dm,max=16.3,min=9,a,b,m1,m2,dm1,xi,power,rm,sig,b1,b2,mass,rvir,a1; + + if(!flag || RESET_COSMOLOGY!=prev_cosmo) + { + if(!ThisTask && OUTPUT) + fprintf(stdout,"RESET: resetting bias for %f %f\n",OMEGA_M,SIGMA_8); + if(!flag) + { + x=dvector(1,n); + y=dvector(1,n); + y2=dvector(1,n); + } + flag=1; + dm=(double)(max-min)/n; + for(i=1;i<=n;++i) + { + x[i]=pow(10.0,min+i*dm); + y[i]=log(bias(x[i])); + x[i] = log(x[i]); + //printf("BIAS %f %f\n",x[i]/2.302, y[i]/2.302); + continue; + + // no longer need to do this part, since we're taking into account + // halo overdensity in the bias formula. + if(DELTA_HALO!=200) + { + x[i]=log(halo_mass_conversion2(x[i],halo_c200(x[i]),200.0,DELTA_HALO)); + } + else + { + x[i]=log(x[i]); + } + } + spline(x,y,n,2.0E+30,2.0E+30,y2); + prev_cosmo=RESET_COSMOLOGY; + pnorm=SIGMA_8/sigmac(8.0); + + } + + + m=log(m); + splint(x,y,y2,n,m,&a); + a = exp(a); + + // if we're using systematic errors in an MCMC, adjust parameter a1 (amplitude) + if(USE_ERRORS) + a *= M2N.bias_amp; + + // if no scale-dependence required, return the large-scale value + if(r<0) return a; + + + /* + * SCALE DEPENDENT BIAS!!! + *---------------------------------------------------------------------- + */ + + /* first, calculate the standard Zheng-like, mass-independent scale bias + * based on the non-linear correlation function + * (re-calibrated using the SO catalogs) + */ + xi = xi_interp(r); + b = pow(1.0+xi*0.92,2.08)*pow(1.0+xi*0.74,-2.37); + if(b<0.6)b=0.6; + + /* Now the mass-dependent term. + * Where the mass-dependence comes in the form of the large-scale bias itself + */ + /* + sig = sigmac_radius_interp(r); + if(a<0) + b *= pow(1 + 0.028*pow(a,1.53)*pow(sig,1.57),2.59)/ + pow(1 + 0.253*pow(a,1.24)*pow(sig,1.71),0.397); + */ + + // if we're using systematic errors in an MCMC, adjust parameter a1 (amplitude) + if(USE_ERRORS) { + b = (b-1)*M2N.scalebias_amp + 1; + if(b<0)b=0; + } + return b*a; + +} + + +/* This is the integrand which qromo or qtrap would call + * to calculate the large-scale galaxy bias. + * The integral is a number-weighted average of the halo + * bias function, integrated over the halo mass function. + */ +double func_galaxy_bias(double m) +{ + m=exp(m); + return(dndM_interp(m)*N_avg(m)*bias_interp(m,-1.)*m); +} + +/* + * This is to get the bias from a series of files. + * + */ +double bias_from_file(double m, double r) +{ + FILE *fp; + static int nfiles=10, *n, flag =1; + static double *mass, **rad, **bias; + float x1,x2,x3; + char fname[1000]; + int i,j,i1,i2; + double b; + + if(flag) + { + n = ivector(0,nfiles-1); + mass = dvector(0,nfiles-1); + rad = dmatrix(0,nfiles-1,1,30); + bias = dmatrix(0,nfiles-1,1,30); + + fp = openfile("/home/tinker/cosmo/SDSS/zspace_analysis/SO_calibration/halofiles/sigma.dat"); + + for(i=0;imass[nfiles-1])return -1; + + for(i=1;i=m)break; + i2 = i; + i1 = i-1; + + + for(j=2;j<=n[i1];++j) + if(rad[i1][j]>r)break; + x1 = (bias[i1][j] - bias[i1][j-1])/(rad[i1][j] - rad[i1][j-1])*(r-rad[i1][j-1]) + bias[i1][j-1]; + + for(j=2;j<=n[i2];++j) + if(rad[i2][j]>r)break; + x2 = (bias[i2][j] - bias[i2][j-1])/(rad[i2][j] - rad[i2][j-1])*(r-rad[i2][j-1]) + bias[i2][j-1]; + + b = (x2 - x1)/(mass[i2] - mass[i1])*(m - mass[i1]) + x1; + + // if(r>log(4)) + // printf("%e %e %f %f %f %f %f\n",m,r,b,x2,x1,mass[i2],mass[i1]); + return b; + +} diff --git a/c_tools/hod/halo_bias_error.c b/c_tools/hod/halo_bias_error.c new file mode 100644 index 0000000..e28b419 --- /dev/null +++ b/c_tools/hod/halo_bias_error.c @@ -0,0 +1,178 @@ +#include +#include +#include + +#include "header.h" + + +/* This is the bias factor for halos. Mass (in h^{-1} M_sol) is the input. + * This is not the scale-dependent bias factor, which can be calculated later. + * + * The parameterization of b(M) is taken from Sheth Mo & Tormen (2001 MNRAS 232 1) + * but the actual parameters have been replaced by the values of Appendix A in + * Tinker, Weinberg, Zheng, & Zehavi. 2005 Apj (submitted) + */ + +double bias(double mass) +{ + static int prev_cosmo=-1; + static long IDUM=-3333; + double rm,sig,k,neff,b,logk,khi,klo,phi,plo,nu,psp,x,fac,fac1,fac2; + static int flag=0,na=4; + static double pnorm,*xa,*ya,*za; + int i; + + /* Original SMT parameters */ + double a=0.707,bb=0.5,c=0.6; + + /* Tinker et al parameters */ + a=0.707; + bb=0.35; + c=0.8; + + /* Fitting to Mike Warren's simulations. */ + bb=0.28; + + /* Use the globel parameters. */ + a=BIAS_A; bb=BIAS_B; c=BIAS_C; + + if(!flag) + { + xa=dvector(1,na); + ya=dvector(1,na); + za=dvector(1,na); + flag=1; + xa[1] = log(1/2.51); + xa[2] = log(1/1.49); + xa[3] = log(1/0.905); + xa[4] = log(1/0.501); + } + + if(prev_cosmo != RESET_COSMOLOGY) + { + prev_cosmo=RESET_COSMOLOGY; + for(i=1;i<=4;++i) + ya[i] = gasdev(&IDUM); + spline(xa,ya,na,1.0E+30,1.0E+30,za); + } + + + /* First normalize the power spectrum + */ + pnorm=SIGMA_8/sigmac(8.0); + rm=pow(3.0*mass/(4.0*PI*OMEGA_M*RHO_CRIT),1.0/3.0); + sig=pnorm*sigmac(rm); + + nu=DELTA_CRIT/sig; + b=1+1.0/(sqrt(a)*DELTA_CRIT)*(sqrt(a)*a*nu*nu + sqrt(a)*bb*pow(a*nu*nu,1-c) - + (pow(a*nu*nu,c)/(pow(a*nu*nu,c)+bb*(1-c)*(1-c/2.)))); + + splint(xa,ya,za,na,log(1/sig),&fac1); + fac2 = 0.0158*pow(sig,-2.7) + 0.00251*pow(sig,2.2); + fac = 1 + fac1*fac2; + if(fac<0.01)fac=0.01; + b*=fac; + + return(b); + + + /* This is the Seljak & Warren (2004) bias. + * There's an alpha_s in the correction term, which here I set to zero. (RUNNING.) + * See App. A of Tinker et al for a comparison of this bias with above bias. + */ + x=mass/MSTAR; + b=(0.53+0.39*pow(x,0.45)+0.13/(40*x+1) + 5.0e-4*pow(x,1.5)); + b=b+log10(x)*(0.4*(OMEGA_M-0.3+SPECTRAL_INDX-1)+0.3*(SIGMA_8-0.9+HUBBLE-0.7)+0.8*0.0); + return(b); + + /* This is the old Mo & White (1996) formula + */ + return(1+DELTA_CRIT/sig/sig-1/DELTA_CRIT); + + +} + +/* Just like the halo mass function, we'll set this up such that + * you just need to interpolate. + * + * Now this has been changed to calculate the spatial-scale dependence + * of the bias factor. If you don't want the scale dep. b, then just + * input r<0. + * + * If the global flag LINEAR_PSP==0, uses the scale dependence calculated for + * for halo bias relative to the non-linear matter \xi_m(r): + * + * f^2(r) = (1.0+xi*1.17)^1.49/(1.0+xi*0.69)^2.09 --> b(r) = b0*f(r) + * + * For LINEAR_PSP==1, use scale dependence determined for the linear P(k): + * + * f(r) = 1 + exp[-(r/A)^0.7] --> where A is a parameter that we're gonna have to + * determine in more detail, but now A \approx 1 + */ +double bias_interp(double m, double r) +{ + static int flag=0,prev_cosmo=0; + static double *x,*y,*y2; + int i,n=100; + double dm,max=16.3,min=9,a,b,m1,m2,dm1,xi; + + if(!flag || RESET_COSMOLOGY!=prev_cosmo) + { + if(!ThisTask && OUTPUT) + fprintf(stdout,"RESET: resetting bias for %f %f\n",OMEGA_M,SIGMA_8); + if(!flag) + { + x=dvector(1,n); + y=dvector(1,n); + y2=dvector(1,n); + } + flag=1; + dm=(double)(max-min)/n; + for(i=1;i<=n;++i) + { + x[i]=pow(10.0,min+i*dm); + y[i]=log(bias(x[i])); + if(DELTA_HALO!=200) + { + m1 = halo_mass_conversion2(x[i]*1.001,halo_c200(x[i]*1.001),DELTA_HALO,200.0); + m2 = halo_mass_conversion2(x[i]*0.999,halo_c200(x[i]*0.999),DELTA_HALO,200.0); + dm1 = (x[i]*1.001 - x[i]*0.999)/(m1-m2); + y[i] = y[i] + log(dm1); + x[i]=log(halo_mass_conversion2(x[i],halo_c200(x[i]),DELTA_HALO,200.0)); + } + else + x[i]=log(x[i]); + } + spline(x,y,n,2.0E+30,2.0E+30,y2); + prev_cosmo=RESET_COSMOLOGY; + + } + + m=log(m); + splint(x,y,y2,n,m,&a); + if(r<0 || r>10)return(exp(a)); + + if(LINEAR_PSP) + { + b=exp(-pow(r,0.7)) + 1; + } + else + { + xi=xi_interp(r); + b=pow(1.0+xi*1.17,1.49*0.5)*pow(1.0+xi*0.69,-2.09*0.5); + } + a=exp(a)*b; + return(a); + +} + + +/* This is the integrand which qromo or qtrap would call + * to calculate the large-scale galaxy bias. + * The integral is a number-weighted average of the halo + * bias function, integrated over the halo mass function. + */ +double func_galaxy_bias(double m) +{ + return(dndM_interp(m)*N_avg(m)*bias_interp(m,-1.)); +} diff --git a/c_tools/hod/halo_concentration.c b/c_tools/hod/halo_concentration.c new file mode 100644 index 0000000..71f0f9b --- /dev/null +++ b/c_tools/hod/halo_concentration.c @@ -0,0 +1,155 @@ +#include +#include +#include + +#include "header.h" + +double collapse_redshift(double z); +double cvir_pnorm_g1, + cvir_sigma_g1; + +/* This calculates and tabulates the halo concentrations + * as a function of halo mass. Uses the "Bullock model", + * described in a little more detail below. + */ + +double halo_concentration(double m) +{ + static int flag=1,n,prev_cosmo=0; + static double *x,*y,*y2; + int i; + float x1,x2,cfac; + double a,dm,x3,x4; + FILE *fp; + char fname[1000]; + + if(flag || RESET_COSMOLOGY!=prev_cosmo) + { + MSTAR = mstar(); + if(OUTPUT) + fprintf(stdout,"Calc cvir with DELTA_HALO= %f\n",DELTA_HALO); + prev_cosmo=RESET_COSMOLOGY; + n=50; + if(flag) + { + x=dvector(1,n); + y=dvector(1,n); + y2=dvector(1,n); + } + cvir_pnorm_g1=SIGMA_8/sigmac(8.0); + + flag=0; + + dm=(log(HOD.M_max)-log(1.0E8))/(n-1); + for(i=1;i<=n;++i) + { + x[i]=exp((i-1)*dm+log(1.0E8)); + y[i]=cvir_model(x[i]); + x[i]=log(halo_mass_conversion(x[i],&y[i],DELTA_HALO)); + y[i]=log(y[i]); + //y[i] = log(10); + } + spline(x,y,n,1.0E+30,1.0E+30,y2); + } + cfac = 0.13*log10(m/1.0e12) + 0.125; + cfac = 1; + if(m>80*MSTAR) m=80*MSTAR; + m=log(m); + splint(x,y,y2,n,m,&a); + return(exp(a)*cfac); + +} + + +/* This is the cvir model, which should reproduce the results + * of cvir3.f, which can be obtained off James Bullock's web site. + * + * Basic idea; For a halo of mass M, find the collapse redshift + * of that halo be finding the redshift at which rms mass variance + * sigma(Mf) = DELTA_CRIT (using linear growth factor), where Mf is some + * fraction of the redshift zero halo mass. + * + * cvir = k*(1+z_coll(M*f)) + * + * Model params: + * - k = 3.12 - fitting parameter (taken from cvir3.f) + * - f = 0.001 - fraction of halo mass that collapsed at z_coll + */ + +double cvir_model(double mass) +{ + double cvir,z_coll,zbrent(),rad; + double k=3.12; + double f=0.001; + + rad=pow(3.0*f*mass/(4.0*PI*OMEGA_M*RHO_CRIT),1.0/3.0); + cvir_sigma_g1=cvir_pnorm_g1*sigmac(rad); + + if(collapse_redshift(0.0)<0)return(k); + z_coll=zbrent(collapse_redshift,0.0,200.0,1.0E-3); + cvir=k*(1+z_coll); + return(cvir); +} + +/* This is the input function to find where sig(M)*D(z)-DELTA_CRIT = 0 + * which is the redshift at which a halo of mass M collapsed. + */ +double collapse_redshift(double z) +{ + double D; + D=growthfactor(z); + return(cvir_sigma_g1*D-DELTA_CRIT); +} + +/* Some quantities are specific to an overdensity of 200 (i.e., the Jenkins mass + * function and the halo bias relation of Tinker et al. ) + * Specfically, these are actually for FOF 0.2 halos, for which 200 is the + * current best approximation. (Although Warren et al quotes 250, which is the most recent + * value.) + * + * Therefore, the halo concentrations for Delta=200 halos need to be easily + * accessible for halo mass conversion of these quantities. The values are + * tabulates here, as opposed to the above routine which tabulates the + * concentrations for a user-specified overdensity. + */ + +double halo_c200(double m) +{ + static int flag=1,n,prev_cosmo=0; + static double *x,*y,*y2; + int i; + float x1,x2; + double a,dm,x3,x4; + FILE *fp; + char fname[1000]; + + if(flag || RESET_COSMOLOGY!=prev_cosmo) + { + if(OUTPUT) + fprintf(stdout,"Calc cvir with DELTA_HALO= %f\n",200.0); + prev_cosmo=RESET_COSMOLOGY; + n=50; + if(flag) + { + x=dvector(1,n); + y=dvector(1,n); + y2=dvector(1,n); + } + cvir_pnorm_g1=SIGMA_8/sigmac(8.0); + + flag=0; + + dm=(log(HOD.M_max)-log(1.0E8))/(n-1); + for(i=1;i<=n;++i) + { + x[i]=exp((i-1)*dm+log(1.0E8)); + y[i]=cvir_model(x[i]); + x[i]=log(halo_mass_conversion(x[i],&y[i],200.0)); + y[i]=log(y[i]); + } + } + m=log(m); + splint(x,y,y2,n,m,&a); + return(exp(a)); + +} diff --git a/c_tools/hod/halo_exclusion.c b/c_tools/hod/halo_exclusion.c new file mode 100644 index 0000000..b29d6b8 --- /dev/null +++ b/c_tools/hod/halo_exclusion.c @@ -0,0 +1,100 @@ +#include +#include +#include +#include "header.h" + +double m_g3,r_g3; + +double func_ng(double m); + +/* The restr + */ + +double restricted_number_density(double r) +{ + static int flag=1; + static double *x,*y; + int i,n=50,j; + double mlimit,dlogm,logm,mmin,sum=0,t0,t1,s1,r1,r2,ng2; + + r_g3=r; + ng2=GALAXY_DENSITY*GALAXY_DENSITY; + + /* Calculate the maximum allowable halo mass. + */ + mlimit=log(4./3.*DELTA_HALO*RHO_CRIT*PI*r_g3*r_g3*r_g3*OMEGA_M); + mmin=log(HOD.M_low); + r1=pow(3*HOD.M_low/(4*PI*DELTA_HALO*RHO_CRIT*OMEGA_M),1.0/3.0); + + /* Calculate the double integral at specified masses. + */ + dlogm=(mlimit-mmin)/(n-1); + for(i=1;i<=n;++i) + { + logm=(i-0.5)*dlogm+mmin; + m_g3=exp(logm); + r2 = pow(3*m_g3/(4*PI*DELTA_HALO*RHO_CRIT*OMEGA_M),1.0/3.0); + if(EXCLUSION==3) { + if(ellipsoidal_exclusion_probability(r1/r2,r_g3/(r1+r2))==0)break; } + else { + if(r1+r2>r_g3)break; } + s1=qtrap(func_ng,mmin,mlimit,1.0E-4); + sum+=s1*m_g3*dlogm; + if(s1==0)break; + if(sum>=ng2)break; + } + return sqrt(sum); +} + + +double func_ng(double m) +{ + static double fac2=-1; + double s1,rv1,rv2,exfac=1,n,N; + + m=exp(m); + if(fac2<0) + fac2=pow(3.0/(4*DELTA_HALO*PI*RHO_CRIT*OMEGA_M),1.0/3.0); + rv1=pow(m_g3,1.0/3.0)*fac2; + rv2=pow(m,1.0/3.0)*fac2; + + if(EXCLUSION==3) + { + if(0.5*(rv1+rv2)>r_g3)return(0); + if(1.5*(rv1+rv2)>r_g3)exfac=ellipsoidal_exclusion_probability(rv2/rv1,r_g3/(rv2+rv1)); + } + else + { + if(rv1+rv2>r_g3)return(0); + } + + n=dndM_interp(m)*dndM_interp(m_g3); + N=N_avg(m)*N_avg(m_g3); + return(exfac*n*N*m); +} + +/* This is the probability that two halos do not overlap, given their + * radii and separation. Of course, for spherical halos P(x) is a step function + * at x = (r1+r2)/r_sep = 1, but for ellipsoidal halos there is a chance + * that they could be closer. In detail, P(x) changes depending on the mass + * ratio of the halos, but using tabulated values does not appear to make + * significant difference in the results for xi_2h(r). The function below is + * a fit to Monte Carlo results for a halos with a distribution of axis ratios + * which is lognormal in e_b = (1-b/a) and e_c = (1-c/a) with dispersions of 0.2 + * mean =0.9 and =0.8 (pretty reasonable values). + */ +double ellipsoidal_exclusion_probability(double rv, double r) +{ + static int flag=0,nr=101,nratio=31; + static double **xprob,*rad,*ratio,rhi,rlo,mhi,mlo,dr,dm; + float x1,x2,x3; + int i,j,im,ir; + FILE *fp; + + if(rv<1)rv=1.0/rv; + + r=(r-0.8)/0.29; + if(r>1)return(1.0); + if(r<0)return(0.0); + return(3*r*r-2*r*r*r); +} diff --git a/c_tools/hod/halo_mass_conversion.c b/c_tools/hod/halo_mass_conversion.c new file mode 100644 index 0000000..34cce65 --- /dev/null +++ b/c_tools/hod/halo_mass_conversion.c @@ -0,0 +1,86 @@ +#include +#include +#include +#include "header.h" + + +/* This is a routine which takes a virial mass (as defined by the virial + * overdensity relation (see fitting formula of Bryan & Normax) + * and converts if to a mass of some given overdensity. This is all + * taken from the appendix of Hu & Kravtsov. 2003ApJ...584..702H + */ + +/* Constants from conversion formula in Hu & Kravtsov (2003) + */ +#define a1 0.5116 +#define a2 -0.4283 +#define a3 -3.13E-3 +#define a4 -3.52E-5 + +double HK_func(double x); + +double halo_mass_conversion(double mvir, double *cvir1, double delta_halo) +{ + double x,y,z,vx,vy,vz,x1,x2,x3,x4,omega_m,delta=180,mstar,delta_vir,delta_fof,p,f, + mp,v,mass,lambda,error,tol=1.0E-3,cprev,m_delta,delta_fac,cvir,rdelta,rvir; + + cvir=*cvir1; + omega_m=OMEGA_M; + lambda=1-OMEGA_M; + mstar=MSTAR; + delta=delta_halo; + + x=omega_m-1; + delta_vir=(18*PI*PI+82*x-39*x*x)/(1+x); + + /* Now convert from virial mass to m_delta. + */ + f=delta/delta_vir*HK_func(1.0/cvir); + p=a2+a3*log(f)+a4*log(f)*log(f); + x1=1.0/sqrt(a1*pow(f,2*p)+0.5625)+2*f; + m_delta=mvir*(delta/delta_vir*pow(1.0/(x1*cvir),3.0)); + + /* Now convert the cvir to c_delta. + */ + rvir=pow(3*mvir/(4*delta_vir*PI*RHO_CRIT*OMEGA_M),1.0/3.0); + rdelta=pow(3*m_delta/(4*delta*PI*RHO_CRIT*OMEGA_M),1.0/3.0); + *cvir1=cvir*rdelta/rvir; + + return(m_delta); +} + +/* This is a slight modification to the above routine-- instead of converting from + * the virial mass, it converts from a specified Delta to the other Delta. + * (so here the "_vir" quantities are any arbitrary input overdensity.) + */ + +double halo_mass_conversion2(double mvir, double cvir1, double delta_vir, double delta_halo) +{ + double x,y,z,vx,vy,vz,x1,x2,x3,x4,omega_m,delta=180,mstar,delta_fof,p,f, + mp,v,mass,lambda,error,tol=1.0E-3,cprev,m_delta,delta_fac,cvir,rdelta,rvir; + + cvir=cvir1; + omega_m=OMEGA_M; + lambda=1-OMEGA_M; + mstar=MSTAR; + delta=delta_halo; + + /* Now convert from virial mass to m_delta. + */ + f=delta/delta_vir*HK_func(1.0/cvir); + p=a2+a3*log(f)+a4*log(f)*log(f); + x1=1.0/sqrt(a1*pow(f,2*p)+0.5625)+2*f; + m_delta=mvir*(delta/delta_vir*pow(1.0/(x1*cvir),3.0)); + + /* Now convert the cvir to c_delta. + */ + rvir=pow(3*mvir/(4*delta_vir*PI*RHO_CRIT*OMEGA_M),1.0/3.0); + rdelta=pow(3*m_delta/(4*delta*PI*RHO_CRIT*OMEGA_M),1.0/3.0); + + return(m_delta); +} + +double HK_func(double x) +{ + return(x*x*x*(log(1+1.0/x)-1.0/(1+x))); +} diff --git a/c_tools/hod/halo_mass_function.c b/c_tools/hod/halo_mass_function.c new file mode 100644 index 0000000..139bc9b --- /dev/null +++ b/c_tools/hod/halo_mass_function.c @@ -0,0 +1,338 @@ +#include +#include +#include + +#include "header.h" + +/* This is a calculation of the differential halo mass function of + * Jenkins et al 2001 (MNRAS 321, 372). + * + * Also included is the mass function from my own analysis, which is + * a variant of the Sheth-Tormen mass function (leaving all 3 parameters + * as free parameters), with a 2-parameter high-mass cutoff of the form + * suggested by Reed et al. + * + */ +void initialize_mass_function(double *a1, double *a2, double *a3, double *a4); + +double halo_mass_function(double mass) +{ + double sig,logm,a,slo,shi,rm,rlo,rhi,mlo,mhi,dsdM,n,nuprime,nufnu,p,A; + static int flag=0,SO180=0,SO324=0,WARREN=0,ST=0,JENKINS=0; + static double pnorm, prev_delta; + double btemp = -1; + + static double + a1 = 0.325277, + a2 = 0.492785, + a3 = 0.310289, + a4 = 1.317104, + a5 = 2.425681; + + /* Jenkins et al. SO 180 best-fit + */ + if(SO180) + { + JENKINS_A = 0.301; + JENKINS_B = 0.64; + JENKINS_C = 3.82; + } + if(SO324) + { + JENKINS_A = 0.316; + JENKINS_B = 0.67; + JENKINS_C = 3.82; + } + if(JENKINS) //their .2 fof function + { + JENKINS_A = 0.315; + JENKINS_B = 0.61; + JENKINS_C = 3.8; + } + + + /* First normalize the power spectrum + */ + pnorm=SIGMA_8/sigmac(8.0); + rm=pow(3.0*mass/(4.0*PI*OMEGA_M*RHO_CRIT),1.0/3.0); + sig=pnorm*sigmac(rm); + logm=log10(mass); + + mlo=0.99*mass; + mhi=1.01*mass; + rlo=pow(3.0*mlo/(4.0*PI*OMEGA_M*RHO_CRIT),1.0/3.0); + rhi=pow(3.0*mhi/(4.0*PI*OMEGA_M*RHO_CRIT),1.0/3.0); + + slo=pnorm*sigmac(rlo); + shi=pnorm*sigmac(rhi); + dsdM=(shi-slo)/(mhi-mlo); + + if(SO324)goto JENKINS_FUNCTION; + if(SO180)goto JENKINS_FUNCTION; + if(WARREN)goto WARREN_FUNCTION; + if(ST)goto ST_FUNCTION; + if(JENKINS)goto JENKINS_FUNCTION; + + /* Tinker et al. (in prep) for SO 200 + */ + if(DELTA_HALO != prev_delta) + { + initialize_mass_function(&a1,&a2,&a3,&a4); + prev_delta = DELTA_HALO; + + // if we're using systematic errors in an MCMC, adjust parameter a1 (amplitude) + if(USE_ERRORS) + a1 *= M2N.mf_amp; + + fprintf(stderr,"MF PARAMS for DELTA=%f %f %f %f %f\n",DELTA_HALO,a1,a2,a3,a4); + } + + n = -a1*(pow(sig/a3,-a2)+1)*exp(-a4/sig/sig)*OMEGA_M*RHO_CRIT/mass/sig*dsdM; + return(n); + + /* Jenkins et al. FOF .2 best-fit (unless SO180==1) + */ + JENKINS_FUNCTION: + a=-JENKINS_A*OMEGA_M*RHO_CRIT/mass/sig; + n=a*dsdM*exp(-pow(fabs(JENKINS_B-log(sig)),JENKINS_C)); + return(n); + + /* Warren et al. (calibrated only on concordance cosmology, FOF.2) + */ + WARREN_FUNCTION: + n = -0.7234*(pow(sig,-1.625)+0.2538)*exp(-1.198/sig/sig)*OMEGA_M*RHO_CRIT/mass/sig*dsdM; + return(n); + + + + /* Need to find the derivative dlog(sig)/dlog(M) + */ + mlo=0.99*logm; + mhi=1.01*logm; + rlo=pow(3.0*pow(10.0,mlo)/(4.0*PI*OMEGA_M*RHO_CRIT),1.0/3.0); + rhi=pow(3.0*pow(10.0,mhi)/(4.0*PI*OMEGA_M*RHO_CRIT),1.0/3.0); + slo=log10(pnorm*sigmac(rlo)); + shi=log10(pnorm*sigmac(rhi)); + dsdM=(shi-slo)/(mhi-mlo); + + ST_FUNCTION: + + /* This is a bunch of Sheth-Tormen stuff. + * NB! because I'm skipping the above derivative (dlogs/dlogM), i'm using the lower + */ + nuprime=0.841*DELTA_CRIT/sig; + nufnu=0.644*(1+1.0/pow(nuprime,0.6))*(sqrt(nuprime*nuprime/2/PI))*exp(-nuprime*nuprime/2); + //n=RHO_CRIT*OMEGA_M/mass*mass*nufnu*fabs(dsdM); + n=RHO_CRIT*OMEGA_M/mass*nufnu*fabs(dsdM)/sig; + return(n); + + + + +} + + +/* It may be a bit costly to run the above function every time you need + * dn/dM, so here we put the values into an array and then interpolate. + * + * The currentrange of masses calculated is 10^9 to 10^16.7. The tabulation is + * done in log(M), so the spline interpolation will perform a power-law fit + * to masses outside this range. + */ +double dndM_interp(double m) +{ + static int flag=0,prev_cosmo=0; + static double *x,*y,*y2; + int i,n=2000; + double dm,max=16.7,min=8,a,m1,m2,dm1; + + if(!flag || RESET_COSMOLOGY!=prev_cosmo) + { + if(!ThisTask && OUTPUT) + fprintf(stdout,"RESET: resetting mass function for %f %f\n",OMEGA_M,SIGMA_8); + fflush(stdout); + + if(!flag) + { + x=dvector(1,n); + y=dvector(1,n); + y2=dvector(1,n); + } + flag=1; + dm=(double)(max-min)/n; + for(i=1;i<=n;++i) + { + x[i]=pow(10.0,min+i*dm); + y[i]=log(halo_mass_function(x[i])); + x[i]=log(x[i]); + continue; + + /* + m1 = halo_mass_conversion2(x[i]*1.001,halo_concentration(x[i]*1.001),DELTA_HALO,200); + m2 = halo_mass_conversion2(x[i]*0.999,halo_concentration(x[i]*0.999),DELTA_HALO,200.0); + dm1 = (x[i]*1.001 - x[i]*0.999)/(m1-m2); + y[i] = y[i] + log(dm1); + x[i]=log(halo_mass_conversion2(x[i],halo_concentration(x[i]),DELTA_HALO,200.0)); + printf("%e %e %e %e\n",exp(x[i]),exp(y[i]),0.1*exp(y[i]),0.1); + continue; + */ + if(DELTA_HALO!=200) + { + m1 = halo_mass_conversion2(x[i]*1.001,halo_c200(x[i]*1.001),200.0,DELTA_HALO); + m2 = halo_mass_conversion2(x[i]*0.999,halo_c200(x[i]*0.999),200.0,DELTA_HALO); + dm1 = (x[i]*1.001 - x[i]*0.999)/(m1-m2); + y[i] = y[i] + log(dm1); + x[i]=log(halo_mass_conversion2(x[i],halo_c200(x[i]),200.0,DELTA_HALO)); + } + else + x[i]=log(x[i]); + + } + spline(x,y,n,2.0E+30,2.0E+30,y2); + prev_cosmo=RESET_COSMOLOGY; + } + //exit(0); + m=log(m); + splint(x,y,y2,n,m,&a); + return(exp(a)); + +} + + +/* Reads mass function in from a file and spline interpolates. + */ +double nbody_massfunction(double m) +{ + static int flag=0,n; + static double *x,*y,*y2,log10_2,normhi,normlo; + float x1,x2,x3; + int i; + double a,dx; + char aa[1000]; + FILE *fp; + + if(!flag) + { + log10_2=log10(2.0); + flag++; + if(!(fp=fopen(Files.MassFuncFile,"r"))) + endrun("ERROR opening MassFuncFile"); + i=0; + n = filesize(fp); + fprintf(stderr,"Read %d lines from [%s]\n",n,Files.MassFuncFile); + x=dvector(1,n); + y=dvector(1,n); + y2=dvector(1,n); + for(i=1;i<=n;++i) + { + fscanf(fp,"%f %f",&x1,&x2); + x[i]=log(x1); + y[i]=log(x2); + fgets(aa,1000,fp); + } + spline(x,y,n,2.0E+30,2.0E+30,y2); + fclose(fp); + fprintf(stderr,"Minimum halo mass in N-body dndM= %e\n",exp(x[1])); + + normhi = exp(y[n])/halo_mass_function(exp(x[n])); + normlo = exp(y[1])/halo_mass_function(exp(x[1])); + } + + m=log(m); + // if(m>x[n])return(0); + /*if(mx[n]) + return(halo_mass_function(exp(m))*normhi); + if(m=1600) *a1 = 0.26; + + //second parameter + y[1] = 1.466904e+00 ; + y[2] = 1.521782e+00 ; + y[3] = 1.559186e+00 ; + y[4] = 1.614585e+00 ; + y[5] = 1.869936e+00 ; + y[6] = 2.128056e+00 ; + y[7] = 2.301275e+00 ; + y[8] = 2.529241e+00 ; + y[9] = 2.661983e+00 ; + + spline(x,y,n,1.0E+30,1.0E+30,z); + splint(x,y,z,n,log(DELTA_HALO),a2); + + //third parameter + y[1] = 2.571104e+00 ; + y[2] = 2.254217e+00 ; + y[3] = 2.048674e+00 ; + y[4] = 1.869559e+00 ; + y[5] = 1.588649e+00 ; + y[6] = 1.507134e+00 ; + y[7] = 1.464374e+00 ; + y[8] = 1.436827e+00 ; + y[9] = 1.405210e+00 ; + + spline(x,y,n,1.0E+30,1.0E+30,z); + splint(x,y,z,n,log(DELTA_HALO),a3); + + + //fourth parameter + y[1] = 1.193958e+00; + y[2] = 1.270316e+00; + y[3] = 1.335191e+00; + y[4] = 1.446266e+00; + y[5] = 1.581345e+00; + y[6] = 1.795050e+00; + y[7] = 1.965613e+00; + y[8] = 2.237466e+00; + y[9] = 2.439729e+00; + + spline(x,y,n,1.0E+30,1.0E+30,z); + splint(x,y,z,n,log(DELTA_HALO),a4); + + // now adjust for redshift + if(!(REDSHIFT>0))return; + + ztemp = REDSHIFT; + if(REDSHIFT>3) ztemp = 3.0; + *a1 *= pow(1+ztemp,-0.14); + *a2 *= pow(1+ztemp,-0.14); + at = -pow(0.75/log10(DELTA_HALO/75),1.2); + at = pow(10.0,at); + *a3 *= pow(1+ztemp,-at); + +} diff --git a/c_tools/hod/halo_mass_function_error.c b/c_tools/hod/halo_mass_function_error.c new file mode 100644 index 0000000..d4cddf5 --- /dev/null +++ b/c_tools/hod/halo_mass_function_error.c @@ -0,0 +1,146 @@ +#include +#include +#include + +#include "header.h" + +/* This is a calculation of the differential halo mass function of + * Jenkins et al 2001 (MNRAS 321, 372). + * + * Also included is the mass function from my own analysis, which is + * a variant of the Sheth-Tormen mass function (leaving all 3 parameters + * as free parameters, with a 2-parameter high-mass cutoff of the form + * suggested by Reed et al. + * + */ + +double halo_mass_function(double mass) +{ + double sig,logm,a,slo,shi,rm,rlo,rhi,mlo,mhi,dsdM,n,nuprime,nufnu,p,A; + static int flag=0, prev_cosmo=-1,na=4; + static double pnorm,*xa,*ya,*za; + + double fac1,fac2,fac; + static long IDUM=-555; + int i; + static double + a1 = 0.325277, + a2 = 0.492785, + a3 = 0.310289, + a4 = 1.317104, + a5 = 2.425681; + + if(!flag) + { + xa=dvector(1,na); + ya=dvector(1,na); + za=dvector(1,na); + flag=1; + xa[1] = log(1/2.51); + xa[2] = log(1/1.49); + xa[3] = log(1/0.905); + xa[4] = log(1/0.501); + } + + if(prev_cosmo != RESET_COSMOLOGY) + { + prev_cosmo=RESET_COSMOLOGY; + for(i=1;i<=4;++i) + ya[i] = gasdev(&IDUM); + spline(xa,ya,na,1.0E+30,1.0E+30,za); + } + + + /* First normalize the power spectrum + */ + pnorm=SIGMA_8/sigmac(8.0); + + rm=pow(3.0*mass/(4.0*PI*OMEGA_M*RHO_CRIT),1.0/3.0); + sig=pnorm*sigmac(rm); + logm=log10(mass); + + mlo=0.99*mass; + mhi=1.01*mass; + rlo=pow(3.0*mlo/(4.0*PI*OMEGA_M*RHO_CRIT),1.0/3.0); + rhi=pow(3.0*mhi/(4.0*PI*OMEGA_M*RHO_CRIT),1.0/3.0); + slo=pnorm*sigmac(rlo); + shi=pnorm*sigmac(rhi); + dsdM=(shi-slo)/(mhi-mlo); + + if(BEST_FIT) + { + n = a1*sqrt(2*a2/PI)*(1+pow(sig*sig/(a2*DELTA_CRIT*DELTA_CRIT),a3)) + *DELTA_CRIT/sig*exp(-a2*DELTA_CRIT*DELTA_CRIT/(2*sig*sig)) + *exp(-a4/sig/pow(fabs(cosh(2*sig)),a5)); + + splint(xa,ya,za,na,log(1/sig),&fac1); + fac2 = 0.00562*pow(sig,-2.9) + 0.00158*pow(sig,2.2); + fac = 1 + fac1*fac2; + if(fac<0.01)fac=0.01; + n = n*fac; + /* printf("%e %e %e %e\n",sig,n,n/fac,fac); */ + n = -n*OMEGA_M*RHO_CRIT/mass/sig*dsdM; + return(n); + } + + /* Jenkins et al. + */ + a=-JENKINS_A*OMEGA_M*RHO_CRIT/mass/sig; + n=a*dsdM*exp(-pow(fabs(JENKINS_B-log(sig)),JENKINS_C)); + return(n); + +} + + +/* It may be a bit costly to run the above function every time you need + * dn/dM, so here we put the values into an array and then interpolate. + */ +double dndM_interp(double m) +{ + static int flag=0,prev_cosmo=0; + static double *x,*y,*y2; + int i,n=1000; + double dm,max=16.7,min=9,a,m1,m2,dm1; + + if(!flag || RESET_COSMOLOGY!=prev_cosmo) + { + if(!ThisTask && OUTPUT) + fprintf(stdout,"RESET: resetting mass function for %f %f\n",OMEGA_M,SIGMA_8); + fflush(stdout); + + if(!flag) + { + x=dvector(1,n); + y=dvector(1,n); + y2=dvector(1,n); + } + flag=1; + dm=(double)(max-min)/n; + for(i=1;i<=n;++i) + { + x[i]=pow(10.0,min+i*dm); + y[i]=log(halo_mass_function(x[i])); + if(DELTA_HALO!=200) + { + m1 = halo_mass_conversion2(x[i]*1.001,halo_c200(x[i]*1.001),DELTA_HALO,200.0); + m2 = halo_mass_conversion2(x[i]*0.999,halo_c200(x[i]*0.999),DELTA_HALO,200.0); + dm1 = (x[i]*1.001 - x[i]*0.999)/(m1-m2); + y[i] = y[i] + log10(dm1); + x[i]=log10(halo_mass_conversion2(x[i],halo_c200(x[i]),DELTA_HALO,200.0)); + } + else + x[i]=log(x[i]); + } + spline(x,y,n,2.0E+30,2.0E+30,y2); + prev_cosmo=RESET_COSMOLOGY; + } + + m=log(m); + splint(x,y,y2,n,m,&a); + return(exp(a)); + +} + + + + diff --git a/c_tools/hod/header.c b/c_tools/hod/header.c new file mode 100644 index 0000000..c911069 --- /dev/null +++ b/c_tools/hod/header.c @@ -0,0 +1,96 @@ +#include +#include "header.h" + + +/* These are the globale variables. When needed, each is set to the + * default value. Those without defualt values are either calculated + * or set in the batfile. + */ + + +double GAMMA=0.2, /* Shape parameter of EBW power spectrum */ + HUBBLE=0.7, /* Hubble in 100 km/s/Mpc (not realy used in code). */ + SIGMA_8=0.95, /* Normalization of power spectrum */ + RHO_CRIT=2.775e11, /* Critial mass density in h^2 M_sun/Mpc^3 */ + SPECTRAL_INDX=1.0, /* n_s -> P(k) = k^n_s */ + OMEGA_M=0.1, /* Matter density */ + OMEGA_TEMP=0.3, /* For M/L minimization */ + OMEGA_B=0.0, /* Baryon density */ + DELTA_CRIT=1.686, /* Critical overdensity for linear collapse */ + MSTAR, /* Mass scale at which sigm(M) = DELTA_CRIT */ + GALAXY_DENSITY, /* Number density of galaxies (Mpc/h)^-3 */ + GALAXY_DENSITY2, /* Number density of SECOND SET of galaxies (Mpc/h)^-3 (for x-corr)*/ + GRAVITY, /* Newton's constant in internal units. */ + BOX_SIZE, /* Size of box, if comparing to simulations. */ + RESOLUTION, /* Simulations: BOX_SIZE/np^(1/3) */ + R_MIN_2HALO=-1.0, /* Minimum scale of two-halo pairs, set by halo exclusion */ + MASS_PER_PARTICLE, /* Simulations: mass in M_sol/h */ + GALAXY_BIAS, /* Large scale bias of galaxies w.r.t linear matter distribution */ + DELTA_HALO=200, /* Overdensity which defines the edge of a halo. */ + VBIAS=1.0, /* Velocity bias of satellite galaxies. */ + VBIAS_SLOPE=0.00, /* Slope of velocity bias relation with halo mass. */ + VBIAS_MASS_THRESHOLD=0, /* Threshold mass above which there is no velocity bias. */ + VBIAS_C=0.00, /* Velocity bias of central galaxies. */ + CVIR_FAC=1.0, /* Ratio between galaxy and dark matter concentrations */ + BIAS_A=0.707, /* parameter for halo bias function (Tinker et all 2005 App. A) */ + BIAS_B=0.35, /* parameter for halo bias function (adapted from Sheth Mo Tormen) */ + BIAS_C=0.8, /* parameter for halo bias function */ + JENKINS_A=0.315, /* Jenkins mass function--> normalization */ + JENKINS_B=0.61, /* Jenkins mass function--> constant in exponential */ + JENKINS_C=3.8, /* Jenkins mass function--> exponent in exponential */ + DNDM_PARAMS[10], /* Holds parameters for 5-param dndM fit */ + MAXVEL=4000, /* maximum velocity in the P(vz) lookup table (set later) */ + SIGV=500, /* Free parameter for Kaiser model */ + BETA, /* Redshift-space distortion parameter. */ + XI_MAX_RADIUS=0, /* Maximum radial value of 2-halo term */ + LOCAL_DENSITY=0, /* for Hubble Bubble calculations--> change the mass function */ + MASS_THRESHOLD=0, /* Mass at which you turn on change in HOD */ + REDSHIFT=0, /* redshift */ + DENSITY_THRESHOLD=0; /* Density at which you turn on change in HOD. */ + +int ITRANS=4, /* Type of transfer function to be used */ + RESET_KAISER=0, /* Flag to reset tabulated Kaiser distortion quantities */ + RESET_COSMOLOGY=0, /* Flag to recalculate tabulated quantities (e.g. b(M), dn/dM...) */ + SOFT_CENTRAL_CUTOFF=0, /* Whether N_cen is a step function or not */ + NUM_POW2MASS_BINS, /* Number of mass bins for velocity PDF calculation */ + RESET_PVZ=0, /* Flag to recalculate velocity PDF table */ + COVAR=1, /* Flag to use covariance matrix for wp chi^2 */ + PCA=0, /* Flag to use principle component analysis for chi^2 calc */ + COVARZ=0, /* Flag to use covariance matrix for xi(s,p) chi^2*/ + EXCLUSION=2, /* Type of two-halo exclusion ("spherical" is default) */ + FIX_PARAM=1, /* Which parameter to leave free for fixing ng (1=M_min)*/ + DEPROJECTED=0, /* Fit 3-space data rather than wp(rp) */ + OUTPUT=1, /* Flag to output diagnostic information */ + POWELL=1, /* minimization technique 1=POWELL, 0=AMOEBA */ + MCMC=0, /* Flag for doing Markov Chain analysis */ + LINEAR_PSP=0, /* Flag for using linear P(k) for two-halo term. (Instead of Smith)*/ + KAISER=0, /* Flag for using Kaiser linear+exponential model */ + ERROR_FLAG=0, /* Global notification of problem with qromo/zbrent/etc */ + BEST_FIT=0, /* Use best-fit mass function, bias from Tinker et al's analysis */ + RESET_FLAG_2H=0, /* Flag to recalculate 2-halo term */ + RESET_FLAG_1H=0, /* Flag to recalculate 1-halo term */ + IVFLAG=0, + WP_ONLY=0, /* =1 use only wp, =0 use n(N) and M/L (+others in ml_min.c) */ + GAO_EFFECT=0, /* =1 means that HOD changes in high density, =0 means lo den change.*/ + N_HOD_PARAMS=9, /* number of possible parameters for HOD. for use w/ MCMC */ + XCORR=0, /* flag for cross-correlation */ + RESTART = 0, /* For restarting an MCMC chain (ml only) */ + USE_ERRORS = 0, /* Flag for using systematic errors on massfunc, bias, etc in MCMC */ + DENSITY_DEPENDENCE = 0; /* Flag for den-dep HOD. */ + +char RESTART_FILE[100]; /* previous output file from which to restart chain */ + +long IDUM_MCMC=-555; /* Random seed to start Markov Chain. */ + +/* These are for the parallel implementation, an ID for each + * processor and the total number of processors. + */ +int ThisTask=0, + NTask=1; + +struct hod_parameters HOD,HOD2,HODt; +struct file_parameters Files; +struct perform_tasks Task; +struct workspace Work; +struct COLOR_DATA wp_color; +struct m2n_workspace M2N; diff --git a/c_tools/hod/header.h b/c_tools/hod/header.h new file mode 100644 index 0000000..e73f9ed --- /dev/null +++ b/c_tools/hod/header.h @@ -0,0 +1,536 @@ +#include "nrutil.h" +#include "stdlib.h" +#include "stdio.h" + +/* Function prototypes--> utility files + */ +double second(void); +double timediff(double t0,double t1); +void endrun(char *instring); +FILE *openfile(char *ff); +int filesize(FILE *fp); +void least_squares(double *x, double *y, int n, double *a, double *b); +void check_for_smoothness(double *x, double *y, int n, double r); +void read_parameter_file(char *fname); +void output_parameter_file(char *fname); +double ***d3tensor(long nrl, long nrh, long ncl, long nch, long ndl, long ndh); +void free_d3tensor(double ***t, long nrl, long nrh, long ncl, long nch, + long ndl, long ndh); + +/* Function prototypes--> general control of tasks + */ +void tasks(int argc, char **argv); + +/* Function prototypes--> numerical recipes + */ +double qromo(double (*func)(double), double a, double b, + double (*choose)(double(*)(double), double, double, int)); +void polint(double xa[], double ya[], int n, double x, double *y, double *dy); +double midpnt(double (*func)(double), double a, double b, int n); +double midinf(double (*funk)(double), double aa, double bb, int n); +void splint(double xa[], double ya[], double y2a[], int n, double x, double *y); +void spline(double x[], double y[], int n, double yp1, double ypn, double y2[]); +double zbrent(double (*func)(double), double x1,double x2, double tol); +double qtrap(double (*func)(double), double a, double b, double EPS); +void powell(double p[], double **xi, int n, double ftol, int *iter, double *fret, + double (*func)(double [])); +void amoeba(double **p, double y[], int ndim, double ftol, + double (*funk)(double []), int *nfunk); +void gaussj(double **a, int n, double **b, int m); +float gasdev(long *idum); +void jacobi(double **a, int n, double d[], double **v, int *nrot); +float ran1(long *idum); +double ran2(long *idum); +double trapzd(double (*func)(double), double a, double b, int n); +void sort2(unsigned long n, float arr[], int id[]); + + +/* Function prototypes--> power spectrum routines. + */ +double transfnc(double xk); +double sigmac(double rad); +double nonlinear_sigmac(double rad); +double transfunc_file(double xk); +double nonlinear_power_spectrum(double xk); +double linear_power_spectrum(double xk); +double mstar(void); +double tf_eisenstein_hu(double k); +double cobenorm(double omega_m); +double cobe_prior(double omega_m); +double sigmac_interp(double m); +double sigmac_radius_interp(double m); + +/* Function prototypes--> matter correlation function routines. + */ +double xi_interp(double r); +double xi_linear_interp(double r); +double projected_xi_matter(double r); + +/* Function protoypes--> outputting matter stats + */ +void output_matter_power_spectrum(void); +void output_matter_correlation_function(void); +void output_matter_variance(void); +void output_halo_concentrations(void); +void output_halo_mass_function(void); +void output_halo_correlation_function(double mass); + +/* Function prototypes--> HOD functions (+related); + */ +double N_avg(double m); +double N_cen(double m); +double N_sat(double m); +double moment_ss(double m); +double func_galaxy_density(double m); +double func_satfrac(double m); +void set_HOD_params(void); +double set_low_mass(void); +double set_high_central_mass(void); +double N_cen_i(double m, int ii); +double satellite_blue_fraction(double m); +double central_blue_fraction(double m); + +double func_central_density(double m); +double func_satellite_density(double m); + +double number_weighted_central_mass(void); +double number_weighted_halo_mass(void); + +/* Density-dependent HOD functions + */ +void dd_hod_functions(float *hmass, float *hdensity, int nhalo); +int internal_populate_simulation(float *x, float *y, float *z, float reduction_factor, int ivel, + float *vx, float *vy, float *vz); + + +/* Function prototypes--> HOD functions for second HOD (+related); + */ +double N_avg2(double m); +double N_cen2(double m); +double N_sat2(double m); +double moment_ss2(double m); +double func_galaxy_density2(double m); +double func_satfrac2(double m); +void set_HOD2_params(void); +double set_low_mass2(void); +double set_high_central_mass2(void); + +/* Function prototypes--> halo mass function. + */ +double halo_mass_function(double mass); +double dndM_interp(double m); + +/* Function prototypes--> halo bias. + */ +double bias_interp(double m, double r); +double bias(double m); +double func_galaxy_bias(double m); + +/* Function prototypes--> halo profile: pair density + */ +double dFdx_ss(double x, double c_NFW); +double dFdx_cs(double x, double c_NFW); +double dFdx_ss_interp(double r, double c); +double dFdx_cs_interp(double r, double c); +double nfw_transform(double xk, double m); + +/* Function prototypes--> real-space galaxy correlation function. + */ +double one_halo_real_space(double r); +double two_halo_real_space(double r); +double ellipsoidal_exclusion_probability(double rv, double r); +double restricted_number_density(double r); +double projected_xi(double r); +double projected_xi_rspace(double r); +double nbody_xi(double r); +double integrated_wp_bin(double r); + + +/* Function prototypes--> redshift-space galaxy correlation function. + */ +double one_halo(double rs, double rp); +double two_halo(double rs, double rp); +void xi_multipoles(void); +double small_scale_measure(double rs); +void calc_rhalf(double r[], double rhalf[], int nr); +double integrated_bin(double xlo, double ylo, double dx1, double dy1, int n); +void linlin_bins(void); +double xi2d_interp(double rs1, double rp1, double rs2, double rp2); +double xi2d_interp_polar(double rs1, double rs2, double phi1, double phi2); + + +/* Function prototypes--> halo pairwise velocity model + */ +double spherical_collapse_model(double delta); +double galaxy_prob_vz(double vel, double rad, double theta); +void vdelta_v4(double m0, double m1, double rad, double theta, double binsize, + double v0, int nv, double *a, double *pv, double *pt, double *pz, + double wgal[3], double sgal[4]); +void pairwise_velocity_dispersion(void); +void output_velocity_moments(int imass); +double jeans_dispersion(double mass, double rx, double v[]); + + +/* Function prototypes--> halo concentrations. + */ +double growthfactor(double z); +double halo_concentration(double m); +double cvir_model(double mass); +double halo_mass_conversion(double mvir, double *cvir1, double delta_halo); +double halo_mass_conversion2(double mvir, double cvir1, double delta_vir, double delta_halo); +double halo_c200(double m); +double HK_func(double x); + +/* Function prototypes--> HOD fitting of correlation functions. + */ +void wp_minimization(char *fname); +void mcmc_minimization(void); +void zspace_minimization(char *fname); +double chi2_wp(double *a); +double chi2_zspace(double *a); +void fit_color_samples(void); + +/* Function prototypes--> Linear+exponential model. + */ +double kaiser_distortion(double rs, double rp); +void fit_dispersion_model(void); +double linear_kaiser_distortion(double rs, double rp); + +/* Function prototypes--> Jean's solution to velocity dispersions. + */ +double satellite_dispersion(double r, double rs, double rvir); +double velocity_dispersion_profile(double sig, double cvir, double rvir, double r); + +/* Function prototypes--> random position/velocities of sat gals (simulation population) + */ +void populate_simulation(void); +void populate_sampled_simulation(void); +double NFW_density(double r, double rs, double ps); +double NFW_velocity(double mass, double v[], double mag); +double NFW_position(double mass, double x[]); +int poisson_deviate(double nave); +double poisson_prob(int n, double nave); + +/* Definitions + */ +#define PI 3.14159265358979323846 +#define TWOPI (2*PI) +#define THIRD (1.0/3.0) +#define ROOT2 1.41421356237309504880 +#define RT2PI 2.50662827463100050241 +#define LN_2 0.6931471805599452 +#define ROOT8 2.82842712475 +#define WORKBUF 1000 +#define LOGE_10 2.30258509 +#define c_on_H0 3000 + +#define mabs(A) ((A) < 0.0 ? -(A) : (A)) +#define cnint(x) ((x-floor(x)) < 0.5 ? floor(x) : ceil(x)) +#define muh(x) fprintf(stdout,"%d\n",x);fflush(stdout) +#define fmuh(x) fprintf(stderr,"%e\n",x) +#define square(x) (x*x) + +/* Global variables + */ +extern double + GAMMA, + HUBBLE, + SIGMA_8, + RHO_CRIT, + SPECTRAL_INDX, + OMEGA_M, + OMEGA_B, + OMEGA_TEMP, + DELTA_CRIT, + MSTAR, + GALAXY_DENSITY, + GALAXY_DENSITY2, + NG_ONE_HALO, + GRAVITY, + VZ_LIMIT, + BOX_SIZE, + RESOLUTION, + R_MIN_2HALO, + MASS_PER_PARTICLE, + GALAXY_BIAS, + DELTA_HALO, + VBIAS, + VBIAS_SLOPE, + VBIAS_C, + VBIAS_MASS_THRESHOLD, + CVIR_FAC, + MAXVEL, + BIAS_A, + BIAS_B, + BIAS_C, + JENKINS_A, + JENKINS_B, + JENKINS_C, + DNDM_PARAMS[10], + SIGV, + BETA, + XI_MAX_RADIUS, + MASS_THRESHOLD, + DENSITY_THRESHOLD, + REDSHIFT, + LOCAL_DENSITY; + +extern int RESET_COSMOLOGY, + RESET_KAISER, + ITRANS, + COVAR, + PCA, + COVARZ, + EXCLUSION, + SOFT_CENTRAL_CUTOFF, + NUM_POW2MASS_BINS, + FIX_PARAM, + DEPROJECTED, + OUTPUT, + POWELL, + MCMC, + BEST_FIT, + LINEAR_PSP, + KAISER, + RESET_PVZ, + ERROR_FLAG, + RESET_FLAG_2H, + RESET_FLAG_1H, + GAO_EFFECT, + IVFLAG, + WP_ONLY, + N_HOD_PARAMS, + XCORR, + RESTART, + USE_ERRORS, + DENSITY_DEPENDENCE; + +extern char RESTART_FILE[100]; + +extern long IDUM_MCMC; + +/* These are variables for the parallel implementation. + */ +extern int ThisTask,NTask; + + +/* HOD parameters. For definitions, look at the comments in + * hod_functions.c + */ +extern struct hod_parameters { + double M_min; + double M_max; + double M1; + double M_cut; + double M_low,M_low0; + double M_hi; + double sigma_logM; + double alpha; + double MaxCen; + double M_cen_max; + + double fblue0_cen; + double sigma_fblue_cen; + double fblue0_sat; + double sigma_fblue_sat; + double blue_fraction; + + int color; + int pdfc; + int pdfs; + int free[100]; + int i_wp; + + double M_sat_break; + double alpha1; + + double M_min_loden; + double M_min_hiden; + double M_min_fac; +} HOD, HOD2, HODt; + + +/* Structure to keep information/data about fitting + * color-defined samples. + */ +struct COLOR_DATA { + int ON; + double ngal_red; + double ngal_blue; + double ngal_full; + int n_red; + int n_blue; + int n_full; + double *r_red,*r_blue,*r_full; + double *e_red,*e_blue,*e_full; + double *x_red,*x_blue,*x_full; + double **covar_red, **covar_blue, **covar_full; +} wp_color; + + +/* This is to put the work done in xi_multipoles into + * a global space. + */ +extern struct workspace { + int nrad; + int n_mono; + int n_quad; + int n_half; + int n_z; + int SDSS_bins; + double rad[WORKBUF]; + double r_mono[WORKBUF]; + double r_quad[WORKBUF]; + double r_half[WORKBUF]; + double rsigma[WORKBUF][WORKBUF]; + double rpi[WORKBUF][WORKBUF]; + double xi_mono[WORKBUF]; + double xi_quad[WORKBUF]; + double xi_half[WORKBUF]; + double xi_z[WORKBUF][WORKBUF]; + double data_m[WORKBUF]; + double covar_m[WORKBUF][WORKBUF]; + double data_q[WORKBUF]; + double covar_q[WORKBUF][WORKBUF]; + double data_h[WORKBUF]; + double covar_h[WORKBUF][WORKBUF]; + double data_z[WORKBUF][WORKBUF]; + double err_m[WORKBUF]; + double err_q[WORKBUF]; + double err_h[WORKBUF]; + double err_z[WORKBUF][WORKBUF]; + + double **covarz; + int n_ze; + char covarz_file[WORKBUF]; + + double rmlo,rmhi; + double rqlo,rqhi; + double rhlo,rhhi; + double zlo,zhi; + + int ncf; + double cf[WORKBUF]; + int chi2; + int imono; + int imono_covar; + int iquad; + int iquad_covar; + int ihalf; + int ihalf_covar; + int izspace; + int imodel; + int i_quad2mono; + int i_monopole; + char monofile[WORKBUF]; + char monocovarfile[WORKBUF]; + char quadfile[WORKBUF]; + char quadcovarfile[WORKBUF]; + char halffile[WORKBUF]; + char halfcovarfile[WORKBUF]; + char esysfile[WORKBUF]; + char zfile[WORKBUF]; + double absolute_error; + double percentage_error; + double eq_abs; + double em_abs; + double em_per; + double eh_per; + int use_asymptotic_values; + int iout; + int SysErrFlag; + + double *psp[6]; + double r_2h[6][100]; + double xi_2h[6][100]; + int n_2h[6]; + +} Work; + +extern struct m2n_workspace { + int ndata; + float *mass, *m2n, *err, *radius; + int *Ngals_lo, *Ngals_hi, current_Ngals, current_bin; + char m2n_filename[100]; + double *model_m2n, *model_mass; + + int counts_nbins, *counts_N200; + double *ndens_N200; + + // systematic errors in the modeling + // to modify things like bias, scale-bias, mass function + double bias_err, bias_amp; + double mf_err, mf_amp; + double scalebias_err, scalebias_amp; + long IDUM; + +} M2N; + +/* Various input files and flags on whether or not to use them. + */ +extern struct file_parameters { + char HaloFile[1000]; + char HaloDensityFile[1000]; + char TF_file[100]; + char TwoHaloFile[100]; + int i_TwoHalo; + char MassFuncFile[100]; + int i_MassFunc; + char PDFTable[100]; + int i_PDFTable; + char PSPFile[100]; + int i_Cvir; + char CvirFile[100]; + + char HaloFileFormat[100]; +} Files; + +/* Various tasks the the program will perform + */ + +extern struct perform_tasks { + int All; + int real_space_xi; + int z_space_xi; + int kaiser_xi; + int multipoles; + int r_half; + int wp_minimize; + int zspace_minimize; + int MCMC; + int HOD; + int PVD; + int populate_sim; + int matter_xi; + int matter_pk; + int sigma_r; + int cvir; + int dndM; + char root_filename[100]; +} Task; + + +/* Workspace for w_p minimzation. + */ +struct WP { + double **covar; + int np; + int ncf; + int ncf_tot; + double pi_max; + double *r; + double *x; + double *e; + char fname_covar[100]; + char fname_wp[100]; + int format; + int iter; + double esys; + double *eigen; + int npca; + double ngal; + double ngal_err; + int n_wp; + + double fsat_all, fsat_red, fsat_blue; +} wp; diff --git a/c_tools/hod/hod_functions.c b/c_tools/hod/hod_functions.c new file mode 100644 index 0000000..e7003d5 --- /dev/null +++ b/c_tools/hod/hod_functions.c @@ -0,0 +1,598 @@ +#include +#include +#include + +#include "header.h" + +/* This file holds several useful functions for the HOD, such as the number of + * central and satellite halos, their second moment. + * + * This also intializes the HOD parameters. + */ + +/* internal routines. + */ +double fixfunc1(double m); +double fixfunc2(double m); +double func_mlow(double m); +double func_mhi(double m); +double one_halo_from_file(double m); + +/***************** + * DIFFERENT HOD PARAMETERIZATIONS: (1) Central galaxies + * + * This integer HOD.pdfc controls the parameterization of the central occupation. + * (I realize 'pdf' is not the right acronym, but it's a holdover from old code.) + * + * For soft central cutoffs, the PDF is the nearest integer distribution, AKA + * Bernoulli distribution. + * + * 0 = No galaxies, just halos. (always returns 1) + * 1 = Hard cutoff at M_min. Unity above M_min. (DEFAULT) + * 2 = Soft cutoff of the form 0.5*(1+erf((log10(m) - log10(HOD.M_min))/HOD.sigma_logM) + * 3 = Soft cutoff of the form N_cen = exp(-HOD.M_min/m) + * 4 = Hard cutoff, but N_cen -> 0 for M>M_min (i.e., blue galaxies) + * MaxCen*exp(-(lgM-lgM_min)**2/2/(sigma_logM)**2) + * NB! -> The value of N_cen(M_min) can be < 1. (It will== MaxCen) + * 5 = Hard Cutoff, Step function, but N_cen != 1, but some number < 1. + * 6 = Same as 4, but symmetric Gaussian around M_min (This is for mag bins.) + * 7 = A sqaure function. N_cen=1 for M_min <= m <= M_cen_max (for mag bin data) + * 8 = A sqaure function (like case 7) but with Gaussian cutoffs on either edge + * instead of sharp cutoffs. + * + * 9 = Magnitude bin model, but the upper mass cutoff is defined by the lower + * mass cutoff of the next-highest bin. (see function in ml_minimization.c) + * + * M_low is a parameter created to keep the integrals from having to go to M=0 for + * soft central cutoffs. N_cen(mlow) = 1.0E-3; + * If the value of sigma_logM gets above 1 or so, then M_low can be rediculously + * small, so I have placed a lower limit on M_low of 1.0E+7 Msol/h + */ +double N_cen(double m) +{ + double x,f=1; + + //return(one_halo_from_file(m)); + + if(HOD.color) + f=central_blue_fraction(m); + + switch(HOD.pdfc) { + case -1: + return 0; + case 0: + return 1; + case 1: + if(m=HOD.M_min && m<=HOD.M_cen_max)return(f); + return(0); + case 8: + if(m>=HOD.M_min && m<=HOD.M_cen_max)return(f); + if(mnc)return(nc); + } + return(n); + case 9: + if(mnc)return(nc); + } + return n; + } + m1 = (pow(HOD.M_sat_break/HOD.M1,HOD.alpha)*exp(-HOD.M_cut/HOD.M_sat_break)); + n = m1*pow(m/HOD.M_sat_break,HOD.alpha1); + return n; + break; + + case 10: + if(m1)x=1; + if(HOD.color==2) + return(1-x); + return(x); +} + +/* If the sample is split up by color, this function + * returns the blue fraction at a given mass for central galaxies. + * This function is parameterized as a log-normal. + * See equation (11) in Zehavi et al Apj 2005, 360, 1 + * + * if HOD.color == 1, returns blue fraction + * if HOD.color == 2, returns red fraction + */ +double central_blue_fraction(double m) +{ + double x; + x = log10(m) - log10(HOD.M_low0); + x=(HOD.fblue0_cen*exp(-x*x/(2*HOD.sigma_fblue_cen*HOD.sigma_fblue_cen))); + if(x>1)x=1; + if(HOD.color==2) + return(1-x); + return(x); +} + +/* If what is needed is the total number of galaxies in a halo. + */ +double N_avg(double m) +{ + return(N_cen(m)+N_sat(m)); +} + + +/* This is the <(N_sat-1)(N_sat)> moment, which is + * for the number of pairs of satellite galaxies. + * For a Poisson distribution, = N^2 + */ +double moment_ss(double m) +{ + double n,x; + n=N_sat(m); + return(n*n); + + // sub-poisson model from millennium run + // doesn't seem to effect -20.5 stats much + x = 0.6 + 0.4*exp(-0.1/pow(n,1.5)); + return(n*n*x*x); + +} + +/* This is a function to set the HOD parameters until + * I get some input code or batch file set up. + * + */ +void set_HOD_params() +{ + int i,j=1; + double m,error=1.0,tol=1.0E-4,prev,s1,mlo; + + /* If the mass function at M_max is undefined, reset M_max + */ + //LOCAL_DENSITY = -0.2; + if(LOCAL_DENSITY!=0) + { + HOD.M_max = 1.0E16; + while(dndM_interp(HOD.M_max)<=0) + { + HOD.M_max*=0.9; + } + fprintf(stderr,"NEW M_max= %e\n",HOD.M_max); + } + + if(HOD.pdfc == 2 || HOD.pdfc == 3 || HOD.pdfc == 6 || HOD.pdfc == 8 || HOD.pdfc == 9) + SOFT_CENTRAL_CUTOFF=1; + + /* Error trap both the galaxy density and M_min both left unspecified. + */ + if(HOD.M_min<=0 && GALAXY_DENSITY<=0 && HOD.free[0]==0) + endrun("ERROR: Must specify either M_min or GALAXY_DENSITY"); + + /* If the user has specified M_min and M1, calculate the galaxy density. + */ + if(HOD.M_min>0 && HOD.M1>0) + { + HOD.M_low = -1; + if(SOFT_CENTRAL_CUTOFF) + HOD.M_low0 = HOD.M_low = exp(zbrent(func_mlow,log(HOD.M_min*1.0E-6),log(HOD.M_min*1.1),1.0E-5)); + else + HOD.M_low0 = HOD.M_low = HOD.M_min; + GALAXY_DENSITY=qromo(func_galaxy_density,log(HOD.M_low),log(HOD.M_max),midpnt); + if(OUTPUT) { + fprintf(stdout,"M_low= %e\n",HOD.M_low); + fprintf(stdout,"ng= %e\n",GALAXY_DENSITY); } + } + + /* If M_min<=0 then use the specified galaxy density to calculate M_min + */ + if(HOD.M_min<=0) + { + if(HOD.pdfc==7 && HOD.pdfc==8) + HOD.M_min=pow(10.0,zbrent(fixfunc1,8.0,log10(HOD.M_cen_max*0.99),1.0E-5)); + else + HOD.M_min=pow(10.0,zbrent(fixfunc1,7.0,14.8,1.0E-5)); + + HOD.M_low = -1; + if(SOFT_CENTRAL_CUTOFF) + HOD.M_low = exp(zbrent(func_mlow,log(HOD.M_min)-5*HOD.sigma_logM*2.3, + log(HOD.M_min),1.0E-5)); + else + HOD.M_low = HOD.M_min; + if(HOD.M_low<1.0E7)HOD.M_low=1.0E+7; + if(OUTPUT) { + fprintf(stdout,"M_min %e [ng= %e]\n",HOD.M_min,GALAXY_DENSITY); + fprintf(stdout,"M_low= %e\n",HOD.M_low); } + } + + /* If M1<=0 then use the specified galaxy density to calculate M1 + */ + if(HOD.M1<=0) + { + HOD.M_low = -1; + if(SOFT_CENTRAL_CUTOFF) + HOD.M_low = exp(zbrent(func_mlow,log(HOD.M_min)-5*HOD.sigma_logM*2.3, + log(HOD.M_min*1.1),1.0E-5)); + else + HOD.M_low = HOD.M_min; + if(HOD.M_low<1.0E7)HOD.M_low=1.0E+7; + HOD.M1=pow(10.0,zbrent(fixfunc2,log10(HOD.M_low),15.8,1.0E-5)); + if(OUTPUT) { + fprintf(stdout,"M1 %e [ng= %e]\n",HOD.M1,GALAXY_DENSITY); + fprintf(stdout,"M_min = %e M_low= %e\n",HOD.M_min,HOD.M_low); } + } + + /* Set the number of halo mass bins we've got. + */ + NUM_POW2MASS_BINS=log(HOD.M_max/HOD.M_low)/LN_2+1; + + if(HOD.pdfc==6) + HOD.M_hi = set_high_central_mass(); + HOD.M_low0 = set_low_mass(); + return; + +} + +/* If soft central cutoff, then put a lower limit on mass integrals + * that begins at the mass where N_cen=0.001. + */ +double func_mlow(double m) +{ + /* Have a check in case the passed mass is equal to M_min, but the value of + * N_cen is < 0.001 (which might be the case for very small sigma_logM) + */ + if(fabs(exp(m)-HOD.M_min)<0.001*HOD.M_min) + if(N_cen(exp(m))<0.001)return(0); + // fprintf(stderr,"MLO %e %e %e %e %e\n",exp(m),N_cen(exp(m)),HOD.M_min,HOD.M_cen_max,HOD.M_low); + return(N_cen(exp(m))-0.001); +} + +/* It is straightforward to calculate what M_low + * should be given the other parameters on N_cen. + */ +double set_low_mass() +{ + double m; + + if(!SOFT_CENTRAL_CUTOFF)return(HOD.M_min); + switch(HOD.pdfc){ + case 8: + case 6: + m = log10(HOD.M_min) - sqrt(-2*HOD.sigma_logM*HOD.sigma_logM*log(0.001)); + m = pow(10.0,m); + return(m); + case 9: + m = exp(zbrent(func_mlow,log(HOD.M_min)-5*HOD.sigma_logM*2.3, + log(HOD.M_min),1.0E-5)); + return(m); + default: + m = exp(zbrent(func_mlow,log(HOD.M_min*1.0E-6), + log(HOD.M_min),1.0E-5)); + + return(m); + } + return(0); +} + +/* If modeling magnitude bin samples, then there will be a high mass + * scale for central galaxies as well as a low mass scale. This finds + * the mass at which N_cen(m)=0.001, where m>M_min. + */ +double set_high_central_mass() +{ + double m,n; + + if(HOD.pdfc==7) + return(HOD.M_cen_max); + if(!(HOD.pdfc==6 || HOD.pdfc==8 || HOD.pdfc==9)) + return(HOD.M_max); + + m = HOD.M_min; + n = N_cen(m); + + while(n>0.001) + { + m*=2; + n = N_cen(m); + if(m>HOD.M_max)return(HOD.M_max); + } + m = exp(zbrent(func_mhi,log(m/2),log(m),1.0E-5)); + return(m); +} + +double func_mhi(double m) +{ + m=exp(m); + return(N_cen(m)-0.001); +} + +/* This is a copy of the above function that can be called from any routine. + * (But this one integrates over dlogm). + */ +double func_halo_density(double m) +{ + double n1; + + m=exp(m); + n1=dndM_interp(m); + return(n1*m); +} + + +/* This is a copy of the above function that can be called from any routine. + * (But this one integrates over dlogm + */ +double func_galaxy_density(double m) +{ + double n1,n2,m0; + + m=exp(m); + n1=dndM_interp(m); + n2=N_avg(m); + return(n1*n2*m); +} + +double func_mean_halo_mass(double m) +{ + double n1,n2,m0; + + m=exp(m); + n1=dndM_interp(m); + n2=N_avg(m); + return(n1*n2*m*m); +} + +/* This is the equation for zbrent to solve. What value + * of M_min gives the correct galaxy density? + * For HODs that have sharp central cutoffs, use M_min as the lower + * limit of the integration. For soft cutoffs, first find M_low. + */ +double fixfunc1(double m) +{ + double n,mlo; + + HOD.M_min=m=pow(10.0,m); + HOD.M_low=0; + if(SOFT_CENTRAL_CUTOFF) + mlo = (zbrent(func_mlow,log(HOD.M_min)-5*HOD.sigma_logM*2.3,log(HOD.M_min),1.0E-5)); + else + mlo = log(HOD.M_min); + if(exp(mlo)<1.0E7)mlo=log(1.0E+7); + + n=qromo(func_galaxy_density,mlo,log(HOD.M_max),midpnt); + // fprintf(stderr,"MMIN %e %e %e %e %e %e\n",m,exp(mlo),n,GALAXY_DENSITY,N_sat(2*m),N_cen(m)); + return(GALAXY_DENSITY-n); +} + +/* This function is sent to zbrent to determine what M1 is based + * on the number density. Both M_min and M_low have already been specified. + */ +double fixfunc2(double m) +{ + double n; + HOD.M1=m=pow(10.0,m); + n=qromo(func_galaxy_density,log(HOD.M_low),log(HOD.M_max),midpnt); + return(GALAXY_DENSITY-n); +} + + +/* This function is to be passed to qromo to integrate the number density + * of satellite galaxies. + */ +double func_satfrac(double m) +{ + m=exp(m); + return(N_sat(m)*dndM_interp(m)*m); +} + +/* This function is to be passed to qromo to integrate the number density + * of satellite galaxies. + */ +double func_satellite_density(double m) +{ + m=exp(m); + return(N_sat(m)*dndM_interp(m)*m); +} + +/* This function is to be passed to qromo to integrate the number density + * of satellite galaxies. + */ +double func_central_density(double m) +{ + m=exp(m); + return(N_cen(m)*dndM_interp(m)*m); +} + +/* Calculates the average mass of a halo in the HOD. + */ +double number_weighted_halo_mass() +{ + double funcxx1(); + return(qromo(funcxx1,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY); +} +double funcxx1(double m) +{ + m=exp(m); + return(m*N_avg(m)*dndM_interp(m)*m); +} + +/* Calculates the average mass of a halo in the HOD + * (weighted by central galaxies). + */ +double number_weighted_central_mass() +{ + double funcxx2(); + return(qromo(funcxx2,log(HOD.M_low),log(HOD.M_max),midpnt)/ + qromo(func_central_density,log(HOD.M_low),log(HOD.M_max),midpnt)); +} +double funcxx2(double m) +{ + m=exp(m); + return(m*N_cen(m)*dndM_interp(m)*m); +} + +double one_halo_from_file(double m) +{ + static double *x, *y, *z; + static int n, flag = 1; + FILE *fp; + int i; + double a; + + if(flag) + { + muh(0); + fp = openfile("ncen.dat"); + muh(0); + n = filesize(fp); + x = dvector(1,n); + y = dvector(1,n); + z = dvector(1,n); + for(i=1;i<=n;++i) + fscanf(fp,"%lf %lf",&x[i],&y[i]); + spline(x,y,n,1.0E+30,1.0E+30,z); + flag = 0; + muh(0); + } + if(log10(m)0) return 1; + return pow(10.0,a); + +} diff --git a/c_tools/hod/hod_functions2.c b/c_tools/hod/hod_functions2.c new file mode 100644 index 0000000..75598ef --- /dev/null +++ b/c_tools/hod/hod_functions2.c @@ -0,0 +1,403 @@ +#include +#include +#include + +#include "header.h" + +/* It is not elegant to do things in this manner, but the code was + * written with auto-correlation functions in mind first, and so copy+edit for + * a second HOD was the most efficient method of modifying the code for the + * cross-correlation function. + * + * NB-- No blue/red galaxies for the second HOD. + */ + +/* This file holds several useful functions for the HOD, such as the number of + * central and satellite halos, their second moment. + * + * This also intializes the HOD parameters. + */ + +/* internal routines. + */ +double fixfunc1_2(double m); +double fixfunc2_2(double m); +double func_mlow2(double m); +double func_mhi2(double m); + +/***************** + * DIFFERENT HOD PARAMETERIZATIONS: (1) Central galaxies + * + * This integer HOD.pdfc controls the parameterization of the central occupation. + * (I realize 'pdf' is not the right acronym, but it's a holdover from old code.) + * + * For soft central cutoffs, the PDF is the nearest integer distribution, AKA + * Bernoulli distribution. + * + * 0 = No galaxies, just halos. (always returns 1) + * 1 = Hard cutoff at M_min. Unity above M_min. (DEFAULT) + * 2 = Soft cutoff of the form 0.5*(1+erf((log10(m) - log10(HOD.M_min))/HOD.sigma_logM) + * 3 = Soft cutoff of the form N_cen = exp(-HOD.M_min/m) + * 4 = Hard cutoff, but N_cen -> 0 for M>M_min (i.e., blue galaxies) + * MaxCen*exp(-(lgM-lgM_min)**2/2/(sigma_logM)**2) + * NB! -> The value of N_cen(M_min) can be < 1. (It will== MaxCen) + * 5 = Hard Cutoff, Step function, but N_cen != 1, but some number < 1. + * 6 = Same as 4, but symmetric Gaussian around M_min (This is for mag bins.) + * 7 = A sqaure function. N_cen=1 for M_min <= m <= M_cen_max (for mag bin data) + * 8 = A sqaure function (like case 7) but with Gaussian cutoffs on either edge + * instead of sharp cutoffs. + * + * 9 = Magnitude bin model, but the upper mass cutoff is defined by the lower + * mass cutoff of the next-highest bin. (see function in ml_minimization.c) + * + * M_low is a parameter created to keep the integrals from having to go to M=0 for + * soft central cutoffs. N_cen(mlow) = 1.0E-3; + * If the value of sigma_logM gets above 1 or so, then M_low can be rediculously + * small, so I have placed a lower limit on M_low of 1.0E+7 Msol/h + */ +double N_cen2(double m) +{ + double x,f=1; + + switch(HOD2.pdfc) { + case 0: + return 1; + case 1: + if(m=HOD2.M_min && m<=HOD2.M_cen_max)return(f); + return(0); + case 8: + if(m>=HOD2.M_min && m<=HOD2.M_cen_max)return(f); + if(m moment, which is + * for the number of pairs of satellite galaxies. + * For a Poisson distribution, = N^2 + */ +double moment_ss2(double m) +{ + double n; + n=N_sat2(m); + return(n*n); +} + +/* This is a function to set the HOD parameters until + * I get some input code or batch file set up. + * + */ +void set_HOD2_params() +{ + int i,j=1; + double m,error=1.0,tol=1.0E-4,prev,s1,mlo; + + + if(HOD2.pdfc == 2 || HOD2.pdfc == 3 || HOD2.pdfc == 6 || HOD2.pdfc == 8 || HOD2.pdfc == 9) + SOFT_CENTRAL_CUTOFF=1; + + /* Error trap both the galaxy density and M_min both left unspecified. + */ + if(HOD2.M_min<=0 && GALAXY_DENSITY2<=0 && HOD2.free[0]==0) + endrun("ERROR: Must specify either M_min or GALAXY_DENSITY2"); + + /* If the user has specified M_min and M1, calculate the galaxy density. + */ + if(HOD2.M_min>0 && HOD2.M1>0) + { + HOD2.M_low = -1; + if(SOFT_CENTRAL_CUTOFF) + HOD2.M_low = exp(zbrent(func_mlow2,log(HOD2.M_min*1.0E-6),log(HOD2.M_min*1.1),1.0E-5)); + else + HOD2.M_low = HOD2.M_min; + GALAXY_DENSITY2=qromo(func_galaxy_density2,log(HOD2.M_low),log(HOD2.M_max),midpnt); + if(OUTPUT) { + fprintf(stdout,"M_low= %e\n",HOD2.M_low); + fprintf(stdout,"ng= %e\n",GALAXY_DENSITY2); } + } + + /* If M_min<=0 then use the specified galaxy density to calculate M_min + */ + if(HOD2.M_min<=0) + { + if(HOD2.pdfc==7 && HOD2.pdfc==8) + HOD2.M_min=pow(10.0,zbrent(fixfunc1_2,8.0,log10(HOD2.M_cen_max*0.99),1.0E-5)); + else + HOD2.M_min=pow(10.0,zbrent(fixfunc1_2,8.0,14.8,1.0E-5)); + + HOD2.M_low = -1; + if(SOFT_CENTRAL_CUTOFF) + HOD2.M_low = exp(zbrent(func_mlow2,log(HOD2.M_min)-5*HOD2.sigma_logM*2.3, + log(HOD2.M_min),1.0E-5)); + else + HOD2.M_low = HOD2.M_min; + if(HOD2.M_low<1.0E7)HOD2.M_low=1.0E+7; + if(OUTPUT) { + fprintf(stdout,"M_min %e [ng= %e]\n",HOD2.M_min,GALAXY_DENSITY2); + fprintf(stdout,"M_low= %e\n",HOD2.M_low); } + } + + /* If M1<=0 then use the specified galaxy density to calculate M1 + */ + if(HOD2.M1<=0) + { + HOD2.M_low = -1; + if(SOFT_CENTRAL_CUTOFF) + HOD2.M_low = exp(zbrent(func_mlow2,log(HOD2.M_min)-5*HOD2.sigma_logM*2.3, + log(HOD2.M_min*1.1),1.0E-5)); + else + HOD2.M_low = HOD2.M_min; + if(HOD2.M_low<1.0E7)HOD2.M_low=1.0E+7; + HOD2.M1=pow(10.0,zbrent(fixfunc2_2,log10(HOD2.M_low),15.8,1.0E-5)); + if(OUTPUT) { + fprintf(stdout,"M1 %e [ng= %e]\n",HOD2.M1,GALAXY_DENSITY2); + fprintf(stdout,"M_min = %e M_low= %e\n",HOD2.M_min,HOD2.M_low); } + } + + HOD2.M_hi = set_high_central_mass2(); + return; + +} + +/* If soft central cutoff, then put a lower limit on mass integrals + * that begins at the mass where N_cen=0.001. + */ +double func_mlow2(double m) +{ + /* Have a check in case the passed mass is equal to M_min, but the value of + * N_cen is < 0.001 (which might be the case for very small sigma_logM) + */ + if(fabs(exp(m)-HOD2.M_min)<0.001*HOD2.M_min) + if(N_cen2(exp(m))<0.001)return(0); + /* fprintf(stderr,"MLO %e %e %e %e %e\n",exp(m),N_cen(exp(m)),HOD2.M_min,HOD2.M_cen_max,HOD2.M_low); */ + return(N_cen2(exp(m))-0.001); +} + +/* It is straightforward to calculate what M_low + * should be given the other parameters on N_cen. + */ +double set_low_mass2() +{ + double m; + + if(!SOFT_CENTRAL_CUTOFF)return(HOD2.M_min); + switch(HOD2.pdfc){ + case 8: + case 6: + m = log10(HOD2.M_min) - sqrt(-2*HOD2.sigma_logM*HOD2.sigma_logM*log(0.001)); + m = pow(10.0,m); + return(m); + default: + m = exp(zbrent(func_mlow2,log(HOD2.M_min)-5*HOD2.sigma_logM*2.3, + log(HOD2.M_min),1.0E-5)); + return(m); + } + return(0); +} + +/* If modeling magnitude bin samples, then there will be a high mass + * scale for central galaxies as well as a low mass scale. This finds + * the mass at which N_cen(m)=0.001, where m>M_min. + */ +double set_high_central_mass2() +{ + double m,n; + + if(HOD2.pdfc==7) + return(HOD2.M_cen_max); + if(!(HOD2.pdfc==6 || HOD2.pdfc==8 || HOD2.pdfc==9)) + return(HOD2.M_max); + + m = HOD2.M_min; + n = N_cen(m); + + while(n>0.001) + { + m*=2; + n = N_cen(m); + if(m>HOD2.M_max)return(HOD2.M_max); + } + m = exp(zbrent(func_mhi2,log(m/2),log(m),1.0E-5)); + return(m); +} + +double func_mhi2(double m) +{ + m=exp(m); + return(N_cen2(m)-0.001); +} + + +/* This is a copy of the above function that can be called from any routine. + * (But this one integrates over dlogm + */ +double func_galaxy_density2(double m) +{ + double n1,n2,m0; + + m=exp(m); + n1=dndM_interp(m); + n2=N_avg2(m); + return(n1*n2*m); +} + +/* This is the equation for zbrent to solve. What value + * of M_min gives the correct galaxy density? + * For HODs that have sharp central cutoffs, use M_min as the lower + * limit of the integration. For soft cutoffs, first find M_low. + */ +double fixfunc1_2(double m) +{ + double n,mlo; + + HOD2.M_min=m=pow(10.0,m); + HOD2.M_low=0; + if(SOFT_CENTRAL_CUTOFF) + mlo = (zbrent(func_mlow2,log(HOD2.M_min)-5*HOD2.sigma_logM*2.3,log(HOD2.M_min),1.0E-5)); + else + mlo = log(HOD2.M_min); + if(exp(mlo)<1.0E7)mlo=log(1.0E+7); + n=qromo(func_galaxy_density,mlo,log(HOD2.M_max),midpnt); + /* fprintf(stderr,"MMIN %e %e %e %e\n",m,exp(mlo),n,GALAXY_DENSITY2); */ + return(GALAXY_DENSITY2-n); +} + +/* This function is sent to zbrent to determine what M1 is based + * on the number density. Both M_min and M_low have already been specified. + */ +double fixfunc2_2(double m) +{ + double n; + HOD2.M1=m=pow(10.0,m); + n=qromo(func_galaxy_density,log(HOD2.M_low),log(HOD2.M_max),midpnt); + return(GALAXY_DENSITY2-n); +} + + +/* This function is to be passed to qromo to integrate the number density + * of satellite galaxies. + */ +double func_satfrac2(double m) +{ + m=exp(m); + return(N_sat2(m)*dndM_interp(m)*m); +} + +/* This function is to be passed to qromo to integrate the number density + * of satellite galaxies. + */ +double func_satellite_density2(double m) +{ + m=exp(m); + return(N_sat2(m)*dndM_interp(m)*m); +} + +/* This function is to be passed to qromo to integrate the number density + * of satellite galaxies. + */ +double func_central_density2(double m) +{ + m=exp(m); + return(N_cen2(m)*dndM_interp(m)*m); +} diff --git a/c_tools/hod/i3tensor_2.c b/c_tools/hod/i3tensor_2.c new file mode 100644 index 0000000..d2ff8f1 --- /dev/null +++ b/c_tools/hod/i3tensor_2.c @@ -0,0 +1,58 @@ +#include +#include +#include +#define NR_END 1 +#define FREE_ARG char* + + +int ***i3tensor_2(long nrl, long nrh, long ncl, long nch, long ndl, long ndh) +/* allocate a float 3tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */ +{ + long i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1; + int ***t; + + /* allocate pointers to pointers to rows */ + t=(int ***) malloc((size_t)((nrow+NR_END)*sizeof(int**))); + if (!t)exit(0); + t += NR_END; + t -= nrl; + + /* allocate pointers to rows and set pointers to them */ + t[nrl]=(int **) malloc((size_t)((nrow*ncol+NR_END)*sizeof(int*))); + if (!t[nrl])exit(0); + t[nrl] += NR_END; + t[nrl] -= ncl; + + /* allocate rows and set pointers to them */ + t[nrl][ncl]=(int *) malloc((size_t)((nrow*ncol*ndep+NR_END)*sizeof(int))); + if (!t[nrl][ncl])exit(0); + t[nrl][ncl] += NR_END; + t[nrl][ncl] -= ndl; + + for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep; + for(i=nrl+1;i<=nrh;i++) { + t[i]=t[i-1]+ncol; + t[i][ncl]=t[i-1][ncl]+ncol*ndep; + for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep; + } + + /* return pointer to array of pointers to rows */ + return t; +} + + + +void free_i3tensor(int ***t, long nrl, long nrh, long ncl, long nch, + long ndl, long ndh) +/* free a int i3tensor allocated by f3tensor() */ +{ + free((FREE_ARG) (t[nrl][ncl]+ndl-NR_END)); + free((FREE_ARG) (t[nrl]+ncl-NR_END)); + free((FREE_ARG) (t+nrl-NR_END)); +} + + + + +#undef NR_END +#undef FREE_ARG diff --git a/c_tools/hod/input_params.c b/c_tools/hod/input_params.c new file mode 100644 index 0000000..63a7980 --- /dev/null +++ b/c_tools/hod/input_params.c @@ -0,0 +1,788 @@ +#include +#include +#include +#include + +#include "header.h" + +/* This function is taken from Volker Springel's GADGET code and + * modified for the parameters used for the HOD.x code. + */ + +/* + * This function parses the parameterfile in a simple way. + * Each paramater is defined by a keyword (`tag'), and can be + * either of type douple, int, or character string. + * The routine makes sure that each parameter appears + * exactly once in the parameterfile. + */ +void read_parameter_file(char *fname) +{ +#define DOUBLE 1 +#define STRING 2 +#define INT 3 +#define CHAR 4 +#define LONG 4 +#define MAXTAGS 300 + + FILE *fd,*fdout; + + char buf[200],buf1[200],buf2[200],buf3[200],tempchar; + int i,j,nt,ii,nn,ctemp; + int id[MAXTAGS]; + void *addr[MAXTAGS]; + char tag[MAXTAGS][200]; + int errorFlag=0; + int IDUM_MCMC_TEMP=-555; + + nt=0; + + strcpy(tag[nt],"RESTART"); + addr[nt]=&RESTART; + id[nt++]=INT; + + strcpy(tag[nt],"RESTART_FILE"); + addr[nt]=&RESTART_FILE; + id[nt++]=STRING; + + strcpy(tag[nt],"GAMMA"); + addr[nt]=&GAMMA; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"OMEGA_M"); + addr[nt]=&OMEGA_M; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"REDSHIFT"); + addr[nt]=&REDSHIFT; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"OMEGA_TEMP"); + addr[nt]=&OMEGA_TEMP; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"OMEGA_B"); + addr[nt]=&OMEGA_B; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"SIGMA_8"); + addr[nt]=&SIGMA_8; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"HUBBLE"); + addr[nt]=&HUBBLE; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"ITRANS"); + addr[nt]=&ITRANS; + id[nt++]=INT; + + strcpy(tag[nt],"LINEAR_PSP"); + addr[nt]=&LINEAR_PSP; + id[nt++]=INT; + + strcpy(tag[nt],"KAISER"); + addr[nt]=&KAISER; + id[nt++]=INT; + + strcpy(tag[nt],"BETA"); + addr[nt]=&BETA; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"SIGV"); + addr[nt]=&SIGV; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"IDUM_MCMC"); + addr[nt]=&IDUM_MCMC_TEMP; + id[nt++]=INT; + + strcpy(tag[nt],"SPECTRAL_INDX"); + addr[nt]=&SPECTRAL_INDX; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"DELTA_HALO"); + addr[nt]=&DELTA_HALO; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"BOX_SIZE"); + addr[nt]=&BOX_SIZE; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"RESOLUTION"); + addr[nt]=&RESOLUTION; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"VBIAS"); + addr[nt]=&VBIAS; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"VBIAS_C"); + addr[nt]=&VBIAS_C; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"TF_file"); + addr[nt]=Files.TF_file; + id[nt++]=STRING; + + strcpy(tag[nt],"M1"); + addr[nt]=&HOD.M1; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"M_min"); + addr[nt]=&HOD.M_min; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"M_cen_max"); + addr[nt]=&HOD.M_cen_max; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"M_cut"); + addr[nt]=&HOD.M_cut; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"M_max"); + addr[nt]=&HOD.M_max; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"sigma_logM"); + addr[nt]=&HOD.sigma_logM; + id[nt++]=DOUBLE; + + HOD.MaxCen=1; + strcpy(tag[nt],"MaxCen"); + addr[nt]=&HOD.MaxCen; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"alpha"); + addr[nt]=&HOD.alpha; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"alpha1"); + addr[nt]=&HOD.alpha1; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"M_sat_break"); + addr[nt]=&HOD.M_sat_break; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"pdfc"); + addr[nt]=&HOD.pdfc; + id[nt++]=INT; + + strcpy(tag[nt],"pdf"); + addr[nt]=&tempchar; + id[nt++]=CHAR; + + strcpy(tag[nt],"pdfs"); + addr[nt]=&HOD.pdfs; + id[nt++]=INT; + + strcpy(tag[nt],"M_min_fac"); + addr[nt]=&HOD.M_min_fac; + id[nt++]=DOUBLE; + + /* Paramaters for the second HOD function + * (for x-corr) + */ + strcpy(tag[nt],"XCORR"); + addr[nt]=&XCORR; + id[nt++]=INT; + XCORR=0; + + strcpy(tag[nt],"GALAXY_DENSITY2"); + addr[nt]=&GALAXY_DENSITY2; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"HOD2.M1"); + addr[nt]=&HOD2.M1; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"HOD2.M_min"); + addr[nt]=&HOD2.M_min; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"HOD2.M_cen_max"); + addr[nt]=&HOD2.M_cen_max; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"HOD2.M_cut"); + addr[nt]=&HOD2.M_cut; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"HOD2.M_max"); + addr[nt]=&HOD2.M_max; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"HOD2.sigma_logM"); + addr[nt]=&HOD2.sigma_logM; + id[nt++]=DOUBLE; + + HOD2.MaxCen=1; + strcpy(tag[nt],"HOD2.MaxCen"); + addr[nt]=&HOD2.MaxCen; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"HOD2.alpha"); + addr[nt]=&HOD2.alpha; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"HOD2.alpha1"); + addr[nt]=&HOD2.alpha1; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"HOD2.M_sat_break"); + addr[nt]=&HOD2.M_sat_break; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"HOD2.pdfc"); + addr[nt]=&HOD2.pdfc; + id[nt++]=INT; + HOD2.pdfc=-1; + + strcpy(tag[nt],"HOD2.pdfs"); + addr[nt]=&HOD2.pdfs; + id[nt++]=INT; + HOD2.pdfs=-1; + + /* Finished with HOD2 params + */ + + strcpy(tag[nt],"color"); + addr[nt]=&HOD.color; + id[nt++]=INT; + HOD.color=0; + + strcpy(tag[nt],"fblue0_cen"); + addr[nt]=&HOD.fblue0_cen; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"sigma_fblue_cen"); + addr[nt]=&HOD.sigma_fblue_cen; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"fblue0_sat"); + addr[nt]=&HOD.fblue0_sat; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"sigma_fblue_sat"); + addr[nt]=&HOD.sigma_fblue_sat; + id[nt++]=DOUBLE; + + + strcpy(tag[nt],"GALAXY_DENSITY"); + addr[nt]=&GALAXY_DENSITY; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"EXCLUSION"); + addr[nt]=&EXCLUSION; + id[nt++]=INT; + + strcpy(tag[nt],"FIX_PARAM"); + addr[nt]=&FIX_PARAM; + id[nt++]=INT; + + strcpy(tag[nt],"POWELL"); + addr[nt]=&POWELL; + id[nt++]=INT; + + strcpy(tag[nt],"OUTPUT"); + addr[nt]=&OUTPUT; + id[nt++]=INT; + + for(i=0;i<=16;++i) + { + sprintf(tag[nt],"free[%d]",i); + addr[nt]=&HOD.free[i]; + id[nt++]=INT; + } + + strcpy(tag[nt],"All"); + addr[nt]=&Task.All; + id[nt++]=INT; + + strcpy(tag[nt],"real_space_xi"); + addr[nt]=&Task.real_space_xi; + id[nt++]=INT; + + strcpy(tag[nt],"z_space_xi"); + addr[nt]=&Task.z_space_xi; + id[nt++]=INT; + + strcpy(tag[nt],"kaiser_xi"); + addr[nt]=&Task.kaiser_xi; + id[nt++]=INT; + + strcpy(tag[nt],"multipoles"); + addr[nt]=&Task.multipoles; + id[nt++]=INT; + + strcpy(tag[nt],"r_half"); + addr[nt]=&Task.r_half; + id[nt++]=INT; + + strcpy(tag[nt],"PVD"); + addr[nt]=&Task.PVD; + id[nt++]=INT; + Task.PVD = 0; + + strcpy(tag[nt],"cvir"); + addr[nt]=&Task.cvir; + id[nt++]=INT; + Task.cvir = 0; + + strcpy(tag[nt],"matter_xi"); + addr[nt]=&Task.matter_xi; + id[nt++]=INT; + Task.matter_xi = 0; + + strcpy(tag[nt],"matter_pk"); + addr[nt]=&Task.matter_pk; + id[nt++]=INT; + Task.matter_pk = 0; + + strcpy(tag[nt],"massfunc"); + addr[nt]=&Task.dndM; + id[nt++]=INT; + Task.matter_pk = 0; + + strcpy(tag[nt],"sigma_r"); + addr[nt]=&Task.sigma_r; + id[nt++]=INT; + Task.sigma_r = 0; + + strcpy(tag[nt],"wp_minimize"); + addr[nt]=&Task.wp_minimize; + id[nt++]=INT; + Task.wp_minimize=0; + + strcpy(tag[nt],"zspace_minimize"); + addr[nt]=&Task.zspace_minimize; + id[nt++]=INT; + Task.zspace_minimize=0; + + strcpy(tag[nt],"MCMC"); + addr[nt]=&Task.MCMC; + id[nt++]=INT; + Task.MCMC=0; + + strcpy(tag[nt],"populate_sim"); + addr[nt]=&Task.populate_sim; + id[nt++]=INT; + Task.populate_sim=0; + + strcpy(tag[nt],"HaloFile"); + addr[nt]=&Files.HaloFile; + id[nt++]=STRING; + + strcpy(tag[nt],"HaloFileFormat"); + addr[nt]=&Files.HaloFileFormat; + id[nt++]=STRING; + + strcpy(tag[nt],"HaloDensityFile"); + addr[nt]=&Files.HaloDensityFile; + id[nt++]=STRING; + + strcpy(tag[nt],"DENSITY_DEPENDENCE"); + addr[nt]=&DENSITY_DEPENDENCE; + id[nt++]=INT; + + strcpy(tag[nt],"DENSITY_THRESHOLD"); + addr[nt]=&DENSITY_THRESHOLD; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"WP_ONLY"); + addr[nt]=&WP_ONLY; + id[nt++]=INT; + + strcpy(tag[nt],"HOD"); + addr[nt]=&Task.HOD; + id[nt++]=INT; + Task.HOD=0; + + strcpy(tag[nt],"COVAR"); + addr[nt]=&COVAR; + id[nt++]=INT; + COVAR=1; + + strcpy(tag[nt],"PCA"); + addr[nt]=&PCA; + id[nt++]=INT; + PCA=0; + + strcpy(tag[nt],"wp_npca"); + addr[nt]=&wp.npca; + id[nt++]=INT; + wp.npca=0; + + strcpy(tag[nt],"DEPROJECTED"); + addr[nt]=&DEPROJECTED; + id[nt++]=INT; + + strcpy(tag[nt],"fname_covar"); + addr[nt]=&wp.fname_covar; + id[nt++]=STRING; + + wp.pi_max=40; + strcpy(tag[nt],"pi_max"); + addr[nt]=&wp.pi_max; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"esys"); + addr[nt]=&wp.esys; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"fname_wp"); + addr[nt]=&wp.fname_wp; + id[nt++]=STRING; + + wp.format=1; + strcpy(tag[nt],"wp_format"); + addr[nt]=&wp.format; + id[nt++]=INT; + + wp.n_wp=9; + strcpy(tag[nt],"n_wp"); + addr[nt]=&wp.n_wp; + id[nt++]=INT; + + strcpy(tag[nt],"root_filename"); + addr[nt]=&Task.root_filename; + id[nt++]=STRING; + + strcpy(tag[nt],"CVIR_FAC"); + addr[nt]=&CVIR_FAC; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"JENKINS_A"); + addr[nt]=&JENKINS_A; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"JENKINS_C"); + addr[nt]=&JENKINS_C; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"JENKINS_B"); + addr[nt]=&JENKINS_B; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"BEST_FIT"); + addr[nt]=&BEST_FIT; + id[nt++]=INT; + + + + if((fd=fopen(fname,"r"))) + { + nn=filesize(fd); + sprintf(buf,"%s","hod-usedvalues"); + if(!(fdout=fopen(buf,"w"))) + { + fprintf(stdout,"error opening file '%s' \n",buf); + errorFlag=1; + } + else + { + /*while(!feof(fd))*/ + for(ii=1;ii<=nn;++ii) + { + fgets(buf,200,fd); + if(sscanf(buf,"%s%s%s",buf1,buf2,buf3)<2) + continue; + + if(buf1[0]=='%') + continue; + + for(i=0,j=-1;i=0) + { + switch(id[j]) + { + case DOUBLE: + *((double*)addr[j])=atof(buf2); + fprintf(fdout,"%-35s%g\n",buf1,*((double*)addr[j])); + break; + case STRING: + strcpy(addr[j],buf2); + fprintf(fdout,"%-35s%s\n",buf1,buf2); + break; + case INT: + *((int*)addr[j])=atoi(buf2); + fprintf(fdout,"%-35s%d\n",buf1,*((int*)addr[j])); + break; + case CHAR: + *((char*)addr[j])=buf2[0]; + fprintf(fdout,"%-35s%c\n",buf1,*((int*)addr[j])); + break; + } + } + else + { + fprintf(stderr,"Error in file %s: Tag '%s' not allowed or multiple defined.\n", + fname,buf1); + errorFlag=1; + } + } + } + fclose(fd); + fclose(fdout); + + } + else + { + fprintf(stderr,"Parameter file %s not found.\n", fname); + exit(1); + } + + + /* Check the params for some basic interpretation + */ + MASS_PER_PARTICLE=pow(RESOLUTION,3.0)*RHO_CRIT*OMEGA_M; + + /* If minimizing data, make sure to set M_min to 0 + */ + if(MCMC || Task.wp_minimize) + HOD.M_min = 0; + + for(i=0;i=4 && HOD.pdfc<=6))continue; + if(!strcmp(tag[i],"HOD2.M_cut") && HOD2.pdfs<2)continue; + if(!strcmp(tag[i],"HOD2.M1") && !XCORR)continue; + if(!strcmp(tag[i],"HOD2.M_cen_max") && HOD2.pdfc!=7)continue; + if(!strcmp(tag[i],"HOD2.sigma_logM") && (!XCORR || (HOD2.pdfc==1 || HOD2.pdfc==7)))continue; + if(!strcmp(tag[i],"HOD2.pdfs") && !XCORR)continue; + if(!strcmp(tag[i],"HOD2.pdfc") && !XCORR)continue; + if(!strcmp(tag[i],"HOD2.alpha") && !XCORR)continue; + if(!strcmp(tag[i],"HOD2.alpha1") && HOD2.pdfs!=4 && HOD2.pdfs!=5)continue; + if(!strcmp(tag[i],"HOD2.M_sat_break") && HOD2.pdfs!=4 && HOD2.pdfs!=5)continue; + if(!strcmp(tag[i],"GALAXY_DENSITY2") && !XCORR)continue; + if(!strcmp(tag[i],"XCORR"))continue; + + if(!strcmp(tag[i],"alpha1"))continue; + if(!strcmp(tag[i],"M_sat_break"))continue; + + if(!strcmp(tag[i],"OMEGA_TEMP")) + { + OMEGA_TEMP = OMEGA_M; + continue; + } + + if(!strcmp(tag[i],"GAMMA") && ITRANS==4) + { + fprintf(stderr,"No value of GAMMA specified for ITRANS=4\n"); + errorFlag=1; + } + if(!strcmp(tag[i],"HUBBLE") && ITRANS==5) + { + fprintf(stderr,"No value of HUBBLE specified for ITRANS=5\n"); + errorFlag=1; + } + if(!strcmp(tag[i],"OMEGA_B") && ITRANS==5) + { + fprintf(stderr,"No value of OMEGA_B specified for ITRANS=5\n"); + errorFlag=1; + } + + if(!strcmp(tag[i],"GAMMA"))continue; + if(!strcmp(tag[i],"pdf"))continue; + if(!strcmp(tag[i],"WP_ONLY"))continue; + if(!strcmp(tag[i],"RESTART"))continue; + if(!strcmp(tag[i],"RESTART_FILE"))continue; + if(!strcmp(tag[i],"DEPROJECTED"))continue; + if(!strcmp(tag[i],"POWELL"))continue; + if(!strcmp(tag[i],"LINEAR_PSP"))continue; + if(!strcmp(tag[i],"BOX_SIZE"))continue; + if(!strcmp(tag[i],"RESOLUTION"))continue; + if(!strcmp(tag[i],"DELTA_HALO"))continue; + if(!strcmp(tag[i],"VBIAS"))continue; + if(!strcmp(tag[i],"COVAR"))continue; + if(!strcmp(tag[i],"VBIAS_C"))continue; + if(!strcmp(tag[i],"CVIR_FAC"))continue; + if(!strcmp(tag[i],"ITRANS"))continue; + if(!strcmp(tag[i],"IDUM_MCMC"))continue; + if(!strcmp(tag[i],"FIX_PARAM"))continue; + if(!strcmp(tag[i],"DEPROJECTED"))continue; + if(!strcmp(tag[i],"OUTPUT"))continue; + if(!strcmp(tag[i],"JENKINS_A"))continue; + if(!strcmp(tag[i],"JENKINS_B"))continue; + if(!strcmp(tag[i],"JENKINS_C"))continue; + if(!strcmp(tag[i],"BEST_FIT"))continue; + if(!strcmp(tag[i],"KAISER"))continue; + if(!strcmp(tag[i],"SIGV"))continue; + if(!strcmp(tag[i],"BETA"))continue; + + + if(!strcmp(tag[i],"MCMC"))continue; + if(!strcmp(tag[i],"wp_minimize"))continue; + if(!strcmp(tag[i],"wp_format"))continue; + if(!strcmp(tag[i],"n_wp"))continue; + if(!strcmp(tag[i],"wp_npca"))continue; + if(!strcmp(tag[i],"z_space_xi"))continue; + if(!strcmp(tag[i],"multipoles"))continue; + if(!strcmp(tag[i],"r_half"))continue; + if(!strcmp(tag[i],"zspace_minimize"))continue; + if(!strcmp(tag[i],"pi_max"))continue; + if(!strcmp(tag[i],"esys"))continue; + + if(HOD.color) + { + if(!strcmp(tag[i],"fblue0_cen") || + !strcmp(tag[i],"sigma_fblue_cen") || + !strcmp(tag[i],"fblue0_sat") || + !strcmp(tag[i],"sigma_fblue_sat")) + { + fprintf(stderr,"Parameters for color HOD not specified.\n"); + exit(0); + } + continue; + } + + if(!strcmp(tag[i],"color"))continue; + if(!strcmp(tag[i],"fblue0_cen"))continue; + if(!strcmp(tag[i],"sigma_fblue_cen"))continue; + if(!strcmp(tag[i],"fblue0_sat"))continue; + if(!strcmp(tag[i],"sigma_fblue_sat"))continue; + + + if(!strcmp(tag[i],"free[0]"))continue; + if(!strcmp(tag[i],"free[1]"))continue; + if(!strcmp(tag[i],"free[2]"))continue; + if(!strcmp(tag[i],"free[3]"))continue; + if(!strcmp(tag[i],"free[4]"))continue; + if(!strcmp(tag[i],"free[5]"))continue; + if(!strcmp(tag[i],"free[6]"))continue; + if(!strcmp(tag[i],"free[7]"))continue; + if(!strcmp(tag[i],"free[8]"))continue; + if(!strcmp(tag[i],"free[9]"))continue; + if(!strcmp(tag[i],"free[10]"))continue; + if(!strcmp(tag[i],"free[11]"))continue; + if(!strcmp(tag[i],"free[12]"))continue; + if(!strcmp(tag[i],"free[13]"))continue; + if(!strcmp(tag[i],"free[14]"))continue; + if(!strcmp(tag[i],"free[15]"))continue; + if(!strcmp(tag[i],"free[16]"))continue; + + if(!strcmp(tag[i],"All"))continue; + if(!strcmp(tag[i],"massfunc"))continue; + if(!strcmp(tag[i],"populate_sim"))continue; + if(!strcmp(tag[i],"HaloFile"))continue; + if(!strcmp(tag[i],"HaloFileFormat"))continue; + if(!strcmp(tag[i],"HOD"))continue; + if(!strcmp(tag[i],"PCA"))continue; + if(!strcmp(tag[i],"PVD"))continue; + if(!strcmp(tag[i],"matter_xi"))continue; + if(!strcmp(tag[i],"matter_pk"))continue; + if(!strcmp(tag[i],"sigma_r"))continue; + if(!strcmp(tag[i],"kaiser_xi"))continue; + if(!strcmp(tag[i],"cvir"))continue; + + if(!strcmp(tag[i],"TF_file")) + { + if(ITRANS==11) { + sprintf(Files.TF_file,"CMBFAST_trans.dat"); + fprintf(stderr,"No transfer function file, using [%s]\n",Files.TF_file); + } + continue; + } + + if(!strcmp(tag[i],"fname_covar")) + { + if(Task.wp_minimize) { + fprintf(stderr,"No filename specified for covariance matrix.\n"); + errorFlag=1; + } + continue; + } + if(!strcmp(tag[i],"fname_wp")) + { + if(Task.wp_minimize) { + fprintf(stderr,"No filename specified for wp data.\n"); + errorFlag=1; + } + continue; + } + if(!strcmp(tag[i],"M_cut")) + { + if(HOD.pdfs==2 || HOD.pdfs==3){ + fprintf(stderr,"No value for M_cut given for pdfs= 2/3\n"); + errorFlag=1; + } + continue; + } + if(!strcmp(tag[i],"M_cen_max")) + { + if(HOD.pdfc==7) { + fprintf(stderr,"No value for M_cen_max given for pdfc= 7\n"); + errorFlag=1; + } + continue; + } + if(!strcmp(tag[i],"sigma_logM")) + { + if(HOD.pdfc==2){ + fprintf(stderr,"No value for sigma_logM given for pdfc=2\n"); + errorFlag=1; + } + continue; + } + if(!strcmp(tag[i],"MaxCen")) + { + if(HOD.pdfc==5){ + fprintf(stderr,"No value for MaxCen given for pdfc=5\n"); + errorFlag=1; + } + continue; + } + if(*tag[i]) + { + fprintf(stderr,"Error. I miss a value for tag '%s' in parameter file '%s'.\n", + tag[i],fname); + errorFlag=1; + } + } + + if(PCA==1 && COVAR==1) + { + fprintf(stderr,"EEROR: you have both PCA and COVAR set to 1.\n"); + errorFlag=1; + } + + IDUM_MCMC=IDUM_MCMC_TEMP; + MCMC = Task.MCMC; + + if(errorFlag) + endrun("error in input_params "); + + /* Other initialization stuff. + */ + MSTAR=mstar(); + + ctemp = HOD.color; + if(Task.wp_minimize) + HOD.color = 0; + set_HOD_params(); + HOD.color = ctemp; + //if(XCORR)set_HOD2_params(); + +#undef DOUBLE +#undef STRING +#undef INT +#undef MAXTAGS +} + + diff --git a/c_tools/hod/integrated_bin.c b/c_tools/hod/integrated_bin.c new file mode 100644 index 0000000..f083f6c --- /dev/null +++ b/c_tools/hod/integrated_bin.c @@ -0,0 +1,32 @@ +#include +#include +#include + +#ifdef PARALLEL +#include +#endif +#include "header.h" + +double integrated_bin(double xlo, double ylo, double dx1, double dy1, int n) +{ + int i,j; + double dx,dy,xsum=0,vol=0,x1,x2,rs,rp; + + dx=dx1/n; + dy=dy1/n; + + for(i=1;i<=n;++i) + for(j=1;j<=n;++j) + { + rs=xlo+(i-0.5)*dx; + rp=ylo+(j-0.5)*dy; + x2=two_halo(rs,rp); + x1=one_halo(rs,rp); + xsum+=2*dy*rs*dx*(x1+x2); + } + dx=xlo+dx1; + dy=ylo+dy1; + xsum/=((dx*dx-xlo*xlo)*dy1); + return(xsum); + +} diff --git a/c_tools/hod/jacobi.c b/c_tools/hod/jacobi.c new file mode 100644 index 0000000..090f85c --- /dev/null +++ b/c_tools/hod/jacobi.c @@ -0,0 +1,87 @@ +#include +#define NRANSI +#include "nrutil.h" +#define ROTATE(a,i,j,k,l) g=a[i][j];h=a[k][l];a[i][j]=g-s*(h+g*tau);\ + a[k][l]=h+s*(g-h*tau); + +void jacobi(double **a, int n, double d[], double **v, int *nrot) +{ + int j,iq,ip,i; + double tresh,theta,tau,t,sm,s,h,g,c,*b,*z; + + b=dvector(1,n); + z=dvector(1,n); + for (ip=1;ip<=n;ip++) { + for (iq=1;iq<=n;iq++) v[ip][iq]=0.0; + v[ip][ip]=1.0; + } + for (ip=1;ip<=n;ip++) { + b[ip]=d[ip]=a[ip][ip]; + z[ip]=0.0; + } + *nrot=0; + for (i=1;i<=50;i++) { + sm=0.0; + for (ip=1;ip<=n-1;ip++) { + for (iq=ip+1;iq<=n;iq++) + sm += fabs(a[ip][iq]); + } + if (sm == 0.0) { + free_dvector(z,1,n); + free_dvector(b,1,n); + return; + } + if (i < 4) + tresh=0.2*sm/(n*n); + else + tresh=0.0; + for (ip=1;ip<=n-1;ip++) { + for (iq=ip+1;iq<=n;iq++) { + g=100.0*fabs(a[ip][iq]); + if (i > 4 && (double)(fabs(d[ip])+g) == (double)fabs(d[ip]) + && (double)(fabs(d[iq])+g) == (double)fabs(d[iq])) + a[ip][iq]=0.0; + else if (fabs(a[ip][iq]) > tresh) { + h=d[iq]-d[ip]; + if ((double)(fabs(h)+g) == (double)fabs(h)) + t=(a[ip][iq])/h; + else { + theta=0.5*h/(a[ip][iq]); + t=1.0/(fabs(theta)+sqrt(1.0+theta*theta)); + if (theta < 0.0) t = -t; + } + c=1.0/sqrt(1+t*t); + s=t*c; + tau=s/(1.0+c); + h=t*a[ip][iq]; + z[ip] -= h; + z[iq] += h; + d[ip] -= h; + d[iq] += h; + a[ip][iq]=0.0; + for (j=1;j<=ip-1;j++) { + ROTATE(a,j,ip,j,iq) + } + for (j=ip+1;j<=iq-1;j++) { + ROTATE(a,ip,j,j,iq) + } + for (j=iq+1;j<=n;j++) { + ROTATE(a,ip,j,iq,j) + } + for (j=1;j<=n;j++) { + ROTATE(v,j,ip,j,iq) + } + ++(*nrot); + } + } + } + for (ip=1;ip<=n;ip++) { + b[ip] += z[ip]; + d[ip]=b[ip]; + z[ip]=0.0; + } + } + nrerror("Too many iterations in routine jacobi"); +} +#undef ROTATE +#undef NRANSI diff --git a/c_tools/hod/jeans.c b/c_tools/hod/jeans.c new file mode 100644 index 0000000..1f4831b --- /dev/null +++ b/c_tools/hod/jeans.c @@ -0,0 +1,95 @@ +#include +#include +#include +#include +#include + +#include "header.h" + +double *mu_x,*mu_y,*mu_z; +int mu_n; + +/* Equation (10) of vdB et al, assuming alpha = 1 (standard NFW) + */ +double func_jeans1(double x) +{ + return(x/(1+x)/(1+x)); +} + +/* Equation (11) of vdB et al. + */ +double func_jeans2(double x) +{ + double y; + splint(mu_x,mu_y,mu_z,mu_n,x,&y); + return(y/(x*x*x*(1+x)*(1+x))); +} +double jeans_dispersion(double mass, double rx, double v[]) +{ + int i,j,k,n,nc,nr; + double rmin,rmax,dlogr; + static double cmin,cmax,dlogc; + double rvir,rs,s1,sig,mu1,vcirc,cvir; + + static long IDUM2 = -4555; + + static double fac=-1; + static int prev_cosmo=-1; + + if(fac<0) + { + mu_n = nc = 1000; + cmin = 0.1; + cmax = 100.0; + dlogc = (log(cmax) - log(cmin))/(nc-1); + + mu_x = dvector(1,nc); + mu_y = dvector(1,nc); + mu_z = dvector(1,nc); + + for(i=1;i<=nc;++i) + { + mu_x[i] = exp((i-1)*dlogc)*cmin; + mu_y[i] = qromo(func_jeans1,0,mu_x[i],midpnt); + } + spline(mu_x,mu_y,nc,1.0E+30,1.0E+30,mu_z); + fac=sqrt(4.499E-48)*3.09E19; + } + + cvir = halo_concentration(mass); + rvir = pow(3*mass/(4*PI*DELTA_HALO*OMEGA_M*RHO_CRIT),THIRD); + rs = rvir/cvir; + rx = rx/rs; + vcirc = fac*fac*mass/rvir; + splint(mu_x,mu_y,mu_z,mu_n,cvir,&mu1); + + s1 = qromo(func_jeans2,rx,cmax,midpnt); + sig = sqrt(cvir*vcirc/mu1*rx*(1+rx)*(1+rx)*s1); + + if(isnan(sig)) + sig = sqrt(vcirc/2); + + for(i=0;i<3;++i) + v[i]=gasdev(&IDUM2)*sig*VBIAS; + + return sig; + + nr = 100; + rmin = rvir*0.01; + rmax = rvir*0.99; + dlogr = (log(rmax) - log(rmin))/(nr-1); + rs = rvir/cvir; + + vcirc = fac*fac*mass/rvir; + splint(mu_x,mu_y,mu_z,mu_n,cvir,&mu1); + + for(i=0;i +#include +#include +#include "header.h" + +double delta_pdf(double delta, double r); + +void vdelta_v4(double m0, double m1, double rad, double theta, double binsize, + double v0, int nv, double *a, double *pv, double *pt, double *pz, + double wgal[3], double sgal[4]) +{ + static double pnorm=-1,flag=0; + static double *rho,*mu,*pdelta; + static int prev_cosmo=0; + + int i,j,k,nrho=75,halo_pair_only=0,use_file_coeff=0; + double dlogrho,sintheta,costheta,tan2theta,rho_min,rho_max,w,b0, + collapse_factor,rho200,ptot,v,sigv,rho0,x1,x2,x3,rvir0,rho200t,sigvt,alpha,alphat, + rvir1,rvirmax,rvir2,vfac,sr1,sr2,sr3,sr4,st1,st2,st3,st4,sz1,sz2,sz3,sz4, + gnorm1,gnorm2,gnorm3,gnorm4,vv,pmax,rcrit,sig20,sig10,sig5; + + int direction,iend; + double sigz1[76],sigz2[76],sigz3[76],sigz4[76], + g1[76],g2[76],g3[76],g4[76],minp,xfit[3],yfit[3],afit,bfit; + + double t0,t1,tt1,tt2; + int ii=0; + + double vfac0 = 0.97; /* factor om rho200[t,r]. was 0.97 */ + + for(i=1;i<=nv;++i) + /* pt[i]=pv[i]=*/ pz[i]=0; + + rvir0=(pow(3*m0/(4*DELTA_HALO*PI*RHO_CRIT*OMEGA_M),1.0/3.0) + + pow(3*m1/(4*DELTA_HALO*PI*RHO_CRIT*OMEGA_M),1.0/3.0)); + rvir1=pow(3*m1/(4*DELTA_HALO*PI*RHO_CRIT*OMEGA_M),1.0/3.0); + rvir2=pow(3*m0/(4*DELTA_HALO*PI*RHO_CRIT*OMEGA_M),1.0/3.0); + b0=(bias_interp(m0,-1)+bias_interp(m1,-1)); + + /* 0.5 comes from ellipsoidal halo exclusion. + */ + if(radpmax){ pmax=pdelta[i]; j=i; } + } + + pmax*=1.0E-4; + for(i=1;i=pmax)break; + rho_min=rho[i]; + for(i=j+1;i<50;++i) + if(pdelta[i]<=pmax)break; + rho_max=rho[i]; + + /* Tabulate the spherical collapse model, density, and p(delta). + */ + dlogrho=log(rho_max/rho_min)/(nrho-1); + ptot=0; + + for(i=1;i<=nrho;++i) + { + rho[i]=rho_min*exp((i-1)*dlogrho); + pdelta[i]=exp(-rho0/rho[i])*delta_pdf(rho[i]-1,rad)*rho[i]; + ptot+=pdelta[i]*dlogrho; + if(pdelta[i]>pdelta[j])j=i; + + x1=-(100*rad)*pow(OMEGA_M,0.6)*(rho[i]-1)/3; + + /* If underdense region, use linear theory. + */ + if(rho[i]<=1) + { + mu[i]=x1; + continue; + } + + x2=(rad)*spherical_collapse_model(rho[i]-1)*exp(-(4.5/rad/rho[i])*(4.5/rad/rho[i])); + if(x2>0)x2=0; + + /* If small separation, use spherical collapse model only. + */ + if(rad<=4) + { + mu[i]=x2; + continue; + } + + /* If intermediate separation, use linear combination of v_sph & v_lin. + */ + if(rad<=20) + { + w=-0.62*log(rad)+1.86; + mu[i]=w*x2 + (1-w)*x1; + continue; + } + + /* In linear regime. Use linear theory. + */ + mu[i]=x1; + } + + if(rad<=rcrit) + for(i=1;i<=nrho;++i) + mu[i]=mu[j]; + + for(i=1;i<=nrho;++i) + pdelta[i]/=ptot; + + vfac=pow(OMEGA_M/0.3,0.6)*(SIGMA_8/0.8)*vfac0; + + /* If Halos only, then set all the galaxy velocity dispersions + * and weights to be zero. + */ + if(!HOD.pdfs) + { + sgal[0]=sgal[1]=sgal[2]=0; + wgal[0]=wgal[1]=wgal[2]=0; + } + + + for(i=1;i<=nrho;++i) + { + sigv=200*pow(rho[i]/rho200,alpha)*vfac; + sigvt=200*pow(rho[i]/rho200t,alphat)*vfac; + + + sr1=sigv*sigv + sgal[0]; + sr2=sigv*sigv + sgal[1]; + sr3=sigv*sigv + sgal[2]; + sr4=sigv*sigv + sgal[3]; + + st1=sigvt*sigvt + sgal[0]; + st2=sigvt*sigvt + sgal[1]; + st3=sigvt*sigvt + sgal[2]; + st4=sigvt*sigvt + sgal[3]; + + sz1=2*(st1+tan2theta*sr1)*costheta*costheta; + sz2=2*(st2+tan2theta*sr2)*costheta*costheta; + sz3=2*(st3+tan2theta*sr3)*costheta*costheta; + sz4=2*(st4+tan2theta*sr4)*costheta*costheta; + + sigz1[i]=sz1; + sigz2[i]=sz2; + sigz3[i]=sz3; + sigz4[i]=sz4; + + gnorm1=wgal[0]/(RT2PI*sqrt(st1*sr1)*sqrt(1.0/(sr1) + tan2theta/(st1))); + gnorm2=wgal[1]/(RT2PI*sqrt(st2*sr2)*sqrt(1.0/(sr2) + tan2theta/(st2))); + gnorm3=wgal[2]/(RT2PI*sqrt(st3*sr3)*sqrt(1.0/(sr3) + tan2theta/(st3))); + gnorm4=(1-wgal[0]-wgal[1]-wgal[2])/ + (RT2PI*sqrt(st4*sr4)*sqrt(1.0/(sr4) + tan2theta/(st4))); + + g1[i]=gnorm1; + g2[i]=gnorm2; + g3[i]=gnorm3; + g4[i]=gnorm4; + } + + /* Find the mode of the distribution. Start at vz=0 and work either way. + */ + for(k=1,j=nv/2;j<=nv;++j,++k) + { + for(i=1;i<=nrho;++i) + { + v=v0+(j-1)*binsize; + vv=(v-sintheta*mu[i])*(v-sintheta*mu[i]); + pz[j]+=pdelta[i]*dlogrho/costheta* + (g1[i]*exp(-vv/(sigz1[i])) + g2[i]*exp(-vv/(sigz2[i])) + + g3[i]*exp(-vv/(sigz3[i])) + g4[i]*exp(-vv/(sigz4[i]))); + } + if(k==2){ + if(pz[j-1]>pz[j])direction=-1; + else direction=1; + break; + } + } + + direction=1; + if(direction==1)iend=nv; + else iend=1; + + for(k=1,j=nv/2-direction;j!=iend;j+=direction,++k) + { + if(pz[j]>0)goto SKIP1; + for(i=1;i<=nrho;++i) + { + v=v0+(j-1)*binsize; + vv=(v-sintheta*mu[i])*(v-sintheta*mu[i]); + pz[j]+=pdelta[i]*dlogrho/costheta* + (g1[i]*exp(-vv/(sigz1[i])) + g2[i]*exp(-vv/(sigz2[i])) + + g3[i]*exp(-vv/(sigz3[i])) + g4[i]*exp(-vv/(sigz4[i]))); + } + SKIP1: + if(k<3)continue; + if(direction>0) { + /*printf("%d %e %e %e\n",j,pz[j],pz[j-1],pz[j-2]);*/ + if(pz[j-1]>pz[j] && pz[j-1]>pz[j-2]) { + minp = pz[j-1]*0.001; break; } + } else { + /*printf("%d %e %e %e\n",j,pz[j],pz[j+1],pz[j+2]);*/ + if(pz[j+1]>pz[j] && pz[j+1]>pz[j+2]) { + minp = pz[j+1]*0.001; break; } + } + } + + for(j=nv/2;j<=nv;++j) + { + if(pz[j]>0)continue; + for(i=1;i<=nrho;++i) + { + v=v0+(j-1)*binsize; + vv=(v-sintheta*mu[i])*(v-sintheta*mu[i]); + pz[j]+=pdelta[i]*dlogrho/costheta* + (g1[i]*exp(-vv/(sigz1[i])) + g2[i]*exp(-vv/(sigz2[i])) + + g3[i]*exp(-vv/(sigz3[i])) + g4[i]*exp(-vv/(sigz4[i]))); + } + if(pz[j]<=minp && nv-j>=3)break; + } + + + /* Now extrapolate the rest of the PVD from the last three points. + */ + for(k=0,i=j-2;i<=j;++i,++k) + { + yfit[k]=log(pz[i]); + xfit[k]=v0+(i-1)*binsize; + } + least_squares(xfit,yfit,3,&afit,&bfit); + + + for(i=j+1;i<=nv;++i) + pz[i] = exp(afit + bfit*(v0+(i-1)*binsize)); + + /* Now go from the mode to i=0 + */ + for(j=nv/2-1;j>=1;--j) + { + if(pz[j]>0)continue; + for(i=1;i<=nrho;++i) + { + v=v0+(j-1)*binsize; + vv=(v-sintheta*mu[i])*(v-sintheta*mu[i]); + pz[j]+=pdelta[i]*dlogrho/costheta* + (g1[i]*exp(-vv/(sigz1[i])) + g2[i]*exp(-vv/(sigz2[i])) + + g3[i]*exp(-vv/(sigz3[i])) + g4[i]*exp(-vv/(sigz4[i]))); + } + if(pz[j]<=minp && j>=3)break; + } + + + /* Now extrapolate the rest of the PVD from the last three points. + */ + for(k=2,i=j+2;i>=j;--i,--k) + { + yfit[k]=log(pz[i]); + xfit[k]=v0+(i-1)*binsize; + } + least_squares(xfit,yfit,3,&afit,&bfit); + + for(i=j-1;i>0;--i) + pz[i] = exp(afit + bfit*(v0+(i-1)*binsize)); + + + /* Do this just to get rid of any numerical roundoff errors and such. + * (It whould already be one by construction if I didn't have the + * linear extrapolation at the end of each side, but the correction + * shouldn't be much.) + */ + for(ptot=0,i=1;i<=nv;++i) + ptot+=pz[i]*binsize; + + for(i=1;i<=nv;++i) + pz[i]/=ptot; + + + if(isnan(ptot)) + { + printf("NAN ptot %f %f %f %f %f %f\n",rho200,rho200t,alpha,rho0,sr4,st4); + fflush(stdout); + for(i=1;i<=nv;++i) + pt[i]=pz[i]=pv[i]=0; + return; + } + + + return; + +} + +/* This is the standard log-normal 1-pt distribution of dark + * matter densities (non-linear) at top-hat smoothing scale r. + */ +double delta_pdf(double delta, double r) +{ + static int model_prev=0; + static double pnorm=-1,rprev=0,sig0,sig1sqr; + double pnorm1; + + if(pnorm<0 || RESET_COSMOLOGY!=model_prev) + { + pnorm1=SIGMA_8/sigmac(8.0); + /*printf("NORM %e %e %e\n",pnorm1,sigmac(8.0),nonlinear_sigmac(8.0));*/ + pnorm=pnorm1*sigmac(80.0)/nonlinear_sigmac(80.0); + rprev=0; + /*printf("NORM %e %e %e %e %f\n",pnorm,sigmac(8.0),sigmac(80.0),nonlinear_sigmac(80.0),SIGMA_8);*/ + } + if(r!=rprev) + { + sig0=pnorm*nonlinear_sigmac(r); + sig1sqr=log(1+sig0*sig0); + /*printf("NORM %f %f %e %e %e\n",r,sig0,pnorm,nonlinear_sigmac(8.0),sigmac(8.0));*/ + } + rprev=r; + model_prev=RESET_COSMOLOGY; + return(1.0/(RT2PI*sqrt(sig1sqr))*exp(-pow(log((1+delta))+sig1sqr*0.5,2.0)/ + (2*sig1sqr))/(1+delta)); + +} diff --git a/c_tools/hod/kaiser_distortions.c b/c_tools/hod/kaiser_distortions.c new file mode 100644 index 0000000..6030a9a --- /dev/null +++ b/c_tools/hod/kaiser_distortions.c @@ -0,0 +1,432 @@ +#include +#include +#include +#include "header.h" + +/* Local variables for the coordinate in redshift space. + */ +double rs_g8,rp_g8; + +/* Internal functions. + */ +double func_kaiser(double z); +double xi_bar(double r); +double f_xibar(double r); +double xi_prime(double r, double mu); +double xi_t(double r); +double Lpoly(double x, int i); +double f_xi2bar(double r); +double xi_harmonic(double r, int i); +double scale_dependent_dispersion(double r); +double scale_dependent_skewness(double r); + +void initial_dispersion_model_values(double *a, double **pp, double *yy); +void dispersion_model_input(void); +double chi2_dispersion_model(double *a); + +/* Internal variables. + */ +struct DISPERION_MODEL_STRUCT { + int n; + double **rs,**rp; + double **x,**e; +} XX; + +double *rr_g8, *aa_g8; +int nparams_g8, niter_g8=0; + +void fit_dispersion_model() +{ + int n,niter,i,j; + double *a,**pp,*yy,FTOL=1.0E-3,chi2min,s1,dlogm,m; + FILE *fp; + char aa[1000]; + + fprintf(stderr,"\n\nCHI2 MINIMIZATION OF xi(SIGMA,PI) WITH DISPERSION MODEL.\n"); + fprintf(stderr, "--------------------------------------------------------\n\n"); + + if(POWELL) + FTOL=1.0E-4; + else + FTOL=1.0E-4; + + nparams_g8 = n = 8; + + dispersion_model_input(); + + wp.ncf=n; + a=dvector(1,n); + rr_g8 = dvector(1,n); + aa_g8 = dvector(1,n); + + for(i=1;i<=n;++i) + rr_g8[i] = (log(10)-log(0.1))/(n-1.)*(i-1) + log(0.1); + + BETA = 0.5; + + if(POWELL) + pp=dmatrix(1,n,1,n); + else + pp=dmatrix(1,n+1,1,n); + yy=dvector(1,n+1); + + initial_dispersion_model_values(a,pp,yy); + + if(POWELL) + { + if(OUTPUT)printf("dispersion_model> starting powell.\n"); + powell(a,pp,n,FTOL,&niter,&chi2min,chi2_dispersion_model); + chi2min = chi2_dispersion_model(a); + } + else + { + if(OUTPUT)printf("dispersion_model> starting amoeba.\n"); + amoeba(pp,yy,n,FTOL,chi2_dispersion_model,&niter); + for(i=1;i<=n;++i)a[i]=pp[1][i]; + chi2min = chi2_dispersion_model(a); + } +} + + +void initial_dispersion_model_values(double *a, double **pp, double *yy) +{ + static int flag=0; + int i,j; + double d[100]; + + + if(!flag) { + for(i=1;i<=nparams_g8;++i) + a[i] = 500; + + printf("INITIAL VALUES: "); + for(i=1;i<=wp.ncf;++i)printf("%e ",a[i]); + printf("\n"); + } + flag++; + + /* Make the starting stepsize 10% of the initial values. + */ + for(i=1;i<=wp.ncf;++i) + d[i]=a[i]*0.1/flag; + + + if(POWELL) + { + for(i=1;i<=wp.ncf;++i) + { + for(j=1;j<=wp.ncf;++j) + { + pp[i][j]=0; + if(i==j)pp[i][j]+=d[j]; + } + } + } + else + { + for(j=1;j<=wp.ncf;++j) + pp[1][j]=a[j]; + yy[1]=chi2_dispersion_model(a); + + for(i=1;i<=wp.ncf;++i) + { + a[i]+=d[i]; + if(i>1)a[i-1]-=d[i-1]; + yy[i+1]=chi2_dispersion_model(a); + for(j=1;j<=wp.ncf;++j) + pp[i+1][j]=a[j]; + } + a[wp.ncf]-=d[wp.ncf]; + } +} + +void dispersion_model_input() +{ + FILE *fp; + int i,j; + + fp = openfile("xi2d.data"); + XX.n = (int)sqrt(filesize(fp)*0.99)+1; + + XX.rs = dmatrix(1,XX.n,1,XX.n); + XX.rp = dmatrix(1,XX.n,1,XX.n); + XX.x = dmatrix(1,XX.n,1,XX.n); + XX.e = dmatrix(1,XX.n,1,XX.n); + + for(i=1;i<=XX.n;++i) + for(j=1;j<=XX.n;++j) + fscanf(fp,"%lf %lf %lf %lf",&XX.rs[i][j],&XX.rp[i][j],&XX.x[i][j],&XX.e[i][j]); + + fclose(fp); + +} + +double chi2_dispersion_model(double *a) +{ + int i,j; + double xx,r,chi2=0; + + for(i=1;i<=nparams_g8;++i) + { + aa_g8[i] = a[i]; + if(a[i]<=0)return(1.0E7); + } + + for(i=2;i<=XX.n;++i) + for(j=2;j<=XX.n;++j) + { + xx = kaiser_distortion(XX.rs[i][j],XX.rp[i][j]); + /* printf("%f %f %f %f %f\n",XX.rs[i][j],XX.rp[i][j],XX.x[i][j],xx,xx); */ + chi2 += (xx-XX.x[i][j])*(xx-XX.x[i][j])/(XX.e[i][j]*XX.e[i][j]); + } + niter_g8++; + printf("ITER %d %e ",niter_g8,chi2); + for(i=1;i<=nparams_g8;++i) + printf("%e ",a[i]); + printf("\n"); + fflush(stdout); + + if(niter_g8%100==0) + { + for(i=1;i<=100;++i) + { + r = exp((log(40)-log(0.1))/(100-1.)*(i-1) + log(0.1)); + xx = scale_dependent_dispersion(r); + printf("PVD %d %f %f\n",niter_g8,r,xx); + } + fflush(stdout); + } + + return(chi2); +} + +double kaiser_distortion(double rs, double rp) +{ + double s1,rlim=60,rr; + static int prev=-1; + + if(prev==-1 || prev!=RESET_COSMOLOGY) + { + prev=RESET_COSMOLOGY; + /* + BETA = pow(OMEGA_M,0.6)/qromo(func_galaxy_bias,HOD.M_low,HOD.M_max,midpnt)* + GALAXY_DENSITY; + */ + printf("kaiser> BETA= %f SIGV= %f\n",BETA,SIGV); + } + + rs_g8=rs; + rp_g8=rp; + rr=sqrt(rs*rs+rp*rp); + /* if(rr*1.5>10)rlim=rr*5.5; */ + /* s1=qromo(func_kaiser,-rlim,rlim,midpnt); */ + s1=qtrap(func_kaiser,-rlim,rlim,1.0E-3); + return(s1-1); +} + +double linear_kaiser_distortion(double r, double z) +{ + double mu; + + mu= sqrt(1 - z/r*z/r); + mu = z/r; + return xi_prime(r,mu); +} + +double func_kaiser(double z) +{ + double r,mu,v,x,sigv; + + r=sqrt(z*z+rs_g8*rs_g8); + mu=z/r; + v=(rp_g8-z)*100.0; + + sigv = scale_dependent_dispersion(r); + /* + if(v*z<0) + sigv*=scale_dependent_skewness(r); + */ + /* + x=(1+one_halo_real_space(r)+two_halo_real_space(r))* + exp(-ROOT2*fabs(v)/sigv)/ROOT2/sigv*100.0; + */ + x=(1+xi_prime(r,mu)+one_halo_real_space(r))*exp(-ROOT2*fabs(v)/sigv)/ROOT2/sigv*100.0; + return(x); +} +double scale_dependent_skewness(double r) +{ + return 1.5; +} + +double scale_dependent_dispersion(double r) +{ + static int niter=-1,flag=0; + static double *z,*x,*y; + double a; + int i; + + if(niter!=niter_g8) + { + niter = niter_g8; + if(!flag) + { + flag++; + x=dvector(1,nparams_g8+1); + y=dvector(1,nparams_g8+1); + z=dvector(1,nparams_g8+1); + y[1] = 0; + x[1] = log(0.01); + for(i=2;i<=nparams_g8+1;++i) + x[i] = rr_g8[i-1]; + } + for(i=2;i<=nparams_g8+1;++i) + y[i] = aa_g8[i-1]; + spline(x,y,nparams_g8+1,1.0E+30,1.0E+30,z); + } + r=log(r); + if(r>rr_g8[nparams_g8])return(aa_g8[nparams_g8]); + splint(x,y,z,nparams_g8+1,r,&a); + return(a); +} + +/* This function tabulates the spherically averaged correlation function. + * Equation (A7) in Madgwick et al. + */ +double xi_bar(double r) +{ + static int flag=0,prev=-1; + static double *x,*y,*y2; + int n=100,i; + static double rmin,rmax,lgr,a; + + if(!flag || prev!=RESET_KAISER) + { + if(OUTPUT>1) + printf("Tabulating xi_bar...\n"); + prev=RESET_KAISER; + if(!flag) + { + x=malloc(n*sizeof(double)); + x--; + y=malloc(n*sizeof(double)); + y--; + y2=malloc(n*sizeof(double)); + y2--; + } + flag=1; + rmin=-1.9; + rmin=log10(R_MIN_2HALO); + rmax=log10(80.0); + for(i=1;i<=n;++i) + { + lgr=(rmax-rmin)*(i-1.0)/(n-1.0)+rmin; + x[i]=pow(10.0,lgr); + y[i]=qtrap(f_xibar,0.0,x[i],1.0E-4)*3/(x[i]*x[i]*x[i]); + //printf("XIBAR %f %e\n",x[i],y[i]); + } + spline(x,y,n,1.0E30,1.0E30,y2); + } + + if(r1) + printf("Tabulating xi_2bar...\n"); + prev=RESET_KAISER; + if(!flag) + { + x=malloc(n*sizeof(double)); + x--; + y=malloc(n*sizeof(double)); + y--; + y2=malloc(n*sizeof(double)); + y2--; + } + flag=1; + rmin=-1.9; + rmin = log10(R_MIN_2HALO); + rmax=log10(80.0); + for(i=1;i<=n;++i) + { + lgr=(rmax-rmin)*(i-1.0)/(n-1.0)+rmin; + x[i]=pow(10.0,lgr); + y[i]=qtrap(f_xi2bar,0.0,x[i],1.0E-4)*5/(x[i]*x[i]*x[i]*x[i]*x[i]); + //printf("XI2BAR %f %e\n",x[i],y[i]); + } + spline(x,y,n,1.0E30,1.0E30,y2); + } + + if(r +#include +#include +#ifdef PARALLEL +#include +#endif +#include "header.h" + +void linlin_bins() +{ + FILE *fp,*fp2; + char fname[100]; + int nsize_rpi,nsize_rsig,i,j; + double rp,rs,r,dx1,dx2,dx3,dx4,dx5,rslo,rshi,drs,binsize_rpi=2; + float x1; + + + nsize_rpi=15; + nsize_rsig=15; + binsize_rpi=2.0; + + sprintf(fname,"%s.linlin",Task.root_filename); + fp=fopen(fname,"w"); + + rshi=0; + for(i=1;i<=nsize_rsig;++i) + { + rslo=rshi; + rshi=rslo+binsize_rpi; + drs=rshi-rslo; + rs=0.5*(rshi+rslo); + + for(j=1;j<=nsize_rpi;++j) + { + rp=(j-0.5)*binsize_rpi; + r=sqrt(rs*rs+rp*rp); + if(!KAISER) + { + dx4=two_halo(rs,rp); + dx1=one_halo(rs,rp); + } + else + { + dx1=0; + dx4=0; + } + /* + dx5=integrated_bin(rslo,(j-1)*binsize_rpi,drs,binsize_rpi,10); + */ + dx5=xi2d_interp(rslo,(j-1)*binsize_rpi,rslo+drs,j*binsize_rpi); + fprintf(fp,"%e %e %e %e %e\n",rs,rp,dx5,dx1,dx4); + fprintf(stdout,"%e %e %e %e %e\n",rs,rp,dx5,dx1,dx4); + fflush(stdout); + fflush(fp); + } + } + fclose(fp); + + +} diff --git a/c_tools/hod/linmin.c b/c_tools/hod/linmin.c new file mode 100644 index 0000000..7323a06 --- /dev/null +++ b/c_tools/hod/linmin.c @@ -0,0 +1,38 @@ +#define NRANSI +#include "nrutil.h" +#define TOL 2.0e-4 + +int ncom; +double *pcom,*xicom,(*nrfunc)(double []); + +void linmin(double p[], double xi[], int n, double *fret, double (*func)(double [])) +{ + double brent(double ax, double bx, double cx, + double (*f)(double), double tol, double *xmin); + double f1dim(double x); + void mnbrak(double *ax, double *bx, double *cx, double *fa, double *fb, + double *fc, double (*func)(double)); + int j; + double xx,xmin,fx,fb,fa,bx,ax; + + ncom=n; + pcom=dvector(1,n); + xicom=dvector(1,n); + nrfunc=func; + for (j=1;j<=n;j++) { + pcom[j]=p[j]; + xicom[j]=xi[j]; + } + ax=0.0; + xx=1.0; + mnbrak(&ax,&xx,&bx,&fa,&fx,&fb,f1dim); + *fret=brent(ax,xx,bx,f1dim,TOL,&xmin); + for (j=1;j<=n;j++) { + xi[j] *= xmin; + p[j] += xi[j]; + } + free_dvector(xicom,1,n); + free_dvector(pcom,1,n); +} +#undef TOL +#undef NRANSI diff --git a/c_tools/hod/m2n_mcmc.c b/c_tools/hod/m2n_mcmc.c new file mode 100644 index 0000000..0e6902f --- /dev/null +++ b/c_tools/hod/m2n_mcmc.c @@ -0,0 +1,1083 @@ +#include +#include +#include +#include + +#ifdef PARALLEL +#include +#endif + +#include "header.h" + +// parameters of Eduardo's P(M|N200) +#define B_rozo -0.12596 +#define alpha_rozo 1.149 + + +/* External functions from wp_minimization.c + */ +void wp_input(void); +double poisson_prob(int n, double nave); + +/* Internal functions. + */ +double m2n_chi2_wp_wrapper(double *a); +double m2n_initialize(double *a, double **cov1, double *avg1, double *start_dev); +void m2n_input(void); +double chi2_m2n(void); +double chi2_number_profiles(void); +int parameter_out_of_range(double *a); + +double prob_ngals_ntrue(double m, int ngals, int ntrue); +double prob_ntrue_mass(double m, double ntrue); +double m2n_func1(double m); +double m2n_func1a(double m); +double m2n_func2(double m); +double m2n_func3(double m); + +double comoving_volume(double zlo, double zhi); +double efunc1(double z); +void input_maxbcg_counts(void); + +void test_pdf(void); + +/* Variables. + */ +int USE_IWEIGHT; + +/****************************************************************** + * + * HOD.free[] also controls which variables will be held constant/vary + * during MCMC minimization. Since this routine will also so z-space + * minimization if requested, indices>6 are cosmological. + * + * i variable + * --- -------- + * [1] -> M_min + * [2] -> M1 + * [3] -> alpha + * [4] -> M_cut + * [5] -> sigmaM + * [6] -> CVIR_FAC + * [7] -> MaxCen (or M_cen_max) + * [8] -> M_sat_break + * [9] -> alpha1 + * + * [10]-> OMEGA_M + * [11]-> SIGMA_8 + * [12]-> VBIAS + * [13]-> VBIAS_C + * [14]-> GAMMA + * [15]-> SPECTRAL_INDX + * [16]-> HUBBLE PARAMETER [used for P(k)] + * + * [0] -> The galaxy_density will be considered data with errors on it, + * and therefore no variable will be fixed by the galaxy density. + * + */ +void m2n_mcmc() +{ + double stepfac=1; + double error=1,tolerance=0,**cov1,**tmp,*a,*avg1,chi2,chi2prev, + **evect,*eval,*aprev,*atemp,**tmp1,*opar,x1,fsat,**chain,*start_dev,*eval_prev; + int n,i,j,k,nrot,niter=0,count=0,imax_chain=100000,NSTEP=50,NSTEP_MAX=10000,convergence=0; + long IDUM=-555; + + int *pcheck,pcnt,ptot=20,firstflag=1,*iweight,total_weight; + double t0,tprev,temp,chi2a,chi2b; + + double delta_halo_rhoc = 200; + + int icvir; + + //test_pdf(); + + // initialize use of SYSTEMATIC ERROR + USE_ERRORS = 1; + M2N.IDUM = -5555; + + opar=dvector(1,100); + + MCMC=Task.MCMC; + + pcheck=calloc(ptot,sizeof(int)); + + /* read in the wp data for a single luminosity threshold sample. + */ + wp_input(); + + /* read in the M2N data. + */ + m2n_input(); + input_maxbcg_counts(); + + Work.imodel=2; + Work.chi2=1; + + /* Since we're at constant halo overdensity wrt RHO_CRIT, + * set the overdensity of the halo + */ + DELTA_HALO = delta_halo_rhoc/OMEGA_M; + + + srand48(32498793); + + /* Find the number of free parameters in the minimization + * for the real-space correlation function. + */ + for(n=0,i=1;i<100;++i) + { + n+=HOD.free[i]; + /* if(i>N_HOD_PARAMS && HOD.free[i])MCMC=3;*/ + if(OUTPUT) + printf("mcmc_min> free[%i] = %d\n",i,HOD.free[i]); + } + if(USE_ERRORS) + n+=3; + wp.ncf=n; + + /* Find out which free parameter is for CVIR_FAC + */ + j=0; + if(HOD.free[6]) + for(i=0;i<6;++i) + if(HOD.free[i])j++; + icvir=j+1; + + if(HOD.free[0]) + { + wp.ngal = GALAXY_DENSITY; + wp.ngal_err = 0.1*wp.ngal; + FIX_PARAM = 0; + } + + if(OUTPUT) + printf("mcmc_min> %d free parameters\n",n); + + a=dvector(1,n); + start_dev=dvector(1,n); + aprev=dvector(1,n); + atemp=dvector(1,n); + cov1=dmatrix(1,n,1,n); + avg1=dvector(1,n); + + tmp=dmatrix(1,n,1,n); + tmp1=dmatrix(1,n,1,1); + evect=dmatrix(1,n,1,n); + eval=dvector(1,n); + eval_prev=dvector(1,n); + + chain=dmatrix(1,imax_chain,1,n); + iweight = ivector(1,imax_chain); + for(i=1;i<=imax_chain;++i) + iweight[i] = 0; + + IDUM=IDUM_MCMC; + + chi2prev=m2n_initialize(a,cov1,avg1,start_dev); + niter++; + for(i=1;i<=n;++i) + { + aprev[i] = a[i]; + chain[1][i] = a[i]; + } + + pcnt=0; + pcheck[pcnt]=1; + + stepfac=1; + while(niter1) + { + RESET_COSMOLOGY++; + j=0; + for(i=1;i<=N_HOD_PARAMS;++i)if(HOD.free[i])j++; + i=N_HOD_PARAMS; + if(HOD.free[++i])OMEGA_M = a[++j]; + if(HOD.free[++i])SIGMA_8 = a[++j]; + if(HOD.free[++i])VBIAS = a[++j]; + if(HOD.free[++i])VBIAS_C = a[++j]; + if(HOD.free[++i])GAMMA = a[++j]; + if(HOD.free[++i])SPECTRAL_INDX = a[++j]; + if(HOD.free[++i])HUBBLE = a[++j]; + } + if(VBIAS_C<0)continue; + + if(USE_ERRORS) + { + M2N.mf_amp = a[++j]; + M2N.bias_amp = a[++j]; + M2N.scalebias_amp = a[++j]; + } + + /* Hard-wire CVIR variation + */ + if(HOD.free[6]) + CVIR_FAC = a[icvir]; + + /* Since we're at constant halo overdensity wrt RHO_CRIT, + * set the overdensity of the halo + */ + DELTA_HALO = delta_halo_rhoc/OMEGA_M; + + // Check to see if any of our parameters are out of range. + if(parameter_out_of_range(a))continue; + + + /* Draw random value of cvir from prior. + */ + /* if(CVIR_FAC<0.3 || CVIR_FAC>1.2)continue; */ + /* CVIR_FAC = 0.9*drand48()+0.3; */ + /* GAMMA = gasdev(&IDUM)*0.02 + 0.15; */ + + + chi2=m2n_chi2_wp_wrapper(a); + // reset cosmology for z=0.25 + SIGMA_8 = SIGMA_8*growthfactor(0.25); + RESET_COSMOLOGY++; + if(MCMC>1 && chi2<1.0E7)chi2+= chi2a = chi2_m2n(); + if(MCMC>1 && chi2<1.0E7)chi2+= chi2b = chi2_number_profiles(); + + if(!ThisTask){ + printf("TRY %d ",++count); + for(i=1;i<=n;++i) + printf("%.4e ",a[i]); + printf("%e\n",chi2);fflush(stdout); + } + pcheck[pcnt]=1; + if(!(chi21) + { + RESET_COSMOLOGY++; + j=0; + for(i=1;i<=N_HOD_PARAMS;++i)if(HOD.free[i])j++; + i=N_HOD_PARAMS; + if(HOD.free[++i])OMEGA_M = a[++j]; + if(HOD.free[++i])SIGMA_8 = a[++j]; + if(HOD.free[++i])VBIAS = a[++j]; + if(HOD.free[++i])VBIAS_C = a[++j]; + if(HOD.free[++i])GAMMA = a[++j]; + if(HOD.free[++i])SPECTRAL_INDX = a[++j]; + if(HOD.free[++i])HUBBLE = a[++j]; + } + if(VBIAS_C<0)continue; + + if(USE_ERRORS) + { + M2N.mf_amp = a[++j]; + M2N.bias_amp = a[++j]; + M2N.scalebias_amp = a[++j]; + } + + /* Hard-wire CVIR variation + */ + if(HOD.free[6]) + CVIR_FAC = a[icvir]; + + /* Since we're at constant halo overdensity wrt RHO_CRIT, + * set the overdensity of the halo + */ + DELTA_HALO = delta_halo_rhoc/OMEGA_M; + + // Check to see if any of our parameters are out of range. + if(parameter_out_of_range(a))continue; + + + /* Draw random value of cvir from prior. + */ + /* CVIR_FAC = a[n]; */ + /* if(CVIR_FAC<0.3 || CVIR_FAC>1.2)continue; */ + /* CVIR_FAC = 0.7*drand48()+0.3; */ + /* GAMMA = gasdev(&IDUM)*0.02 + 0.15; */ + // printf("GAMMA %d %f %f\n",count+1,GAMMA,CVIR_FAC); + + chi2=m2n_chi2_wp_wrapper(a); + // reset cosmology for z=0.25 + SIGMA_8 = SIGMA_8*growthfactor(0.25); + RESET_COSMOLOGY++; + if(MCMC>1 && chi2<1.0E7)chi2 += chi2a = chi2_m2n(); + if(MCMC>1 && chi2<1.0E7)chi2 += chi2b = chi2_number_profiles(); + + tprev = t0; + t0 = second(); + ++count; + if(!ThisTask) { + printf("TRY %d ",count); + for(i=1;i<=n;++i) + printf("%.4e ",a[i]); + if(RESTART==2) { + printf("%e %e %.2f\n",chi2,chi2/(1+exp(-count/100.0)), + timediff(tprev,t0));fflush(stdout); } + else { + printf("%e %.2f\n",chi2, + timediff(tprev,t0));fflush(stdout); } + } + if(0) { + printf("CPU%02d %d ",ThisTask,count); + for(i=1;i<=n;++i) + printf("%.4e ",a[i]); + if(RESTART==2) { + printf("%e %e %.2f\n",chi2,chi2/(1+exp(-count/100.0)), + timediff(tprev,t0));fflush(stdout); } + else { + printf("%e %.2f\n",chi2, + timediff(tprev,t0));fflush(stdout); } + } + + pcheck[pcnt]=0; + if(!(chi2NSTEP_MAX) + { + convergence = 1; + for(i=1;i<=n;++i) + { + x1=fabs(eval[i]-eval_prev[i])/eval_prev[i]; + if(x1>0.01)convergence = 0; + printf("CONVERGENCE CHECK %d %d %e %e %e\n",niter/NSTEP_MAX,i,x1,eval[i],eval_prev[i]); + } + for(i=1;i<=n;++i) + eval_prev[i] = eval[i]; + convergence = 0; + + if(convergence) + printf("CONVERGENCE ACCOMPLISHED %d %d \n",niter,count); + } + if(niter==NSTEP_MAX) + { + for(i=1;i<=n;++i) + eval_prev[i] = eval[i]; + } + + + for(i=1;i<=n;++i) + chain[niter][i]=a[i]; + for(i=1;i<=n;++i) + avg1[i] += a[i]; + for(i=1;i<=n;++i) + aprev[i] = a[i]; + for(i=1;i<=n;++i) + for(j=1;j<=n;++j) + cov1[i][j] += a[i]*a[j]; + chi2prev=chi2; + + if(!ThisTask) { + printf("ACCEPT %d %d ",niter,count); + for(i=1;i<=n;++i) + printf("%e ",a[i]); + printf("%e %e %e %e\n",chi2,chi2a,chi2b,chi2-chi2a-chi2b);fflush(stdout); + + if(MCMC==1) + { + printf("HSTATS %d %e %e %e %e\n",niter,HOD.M_min,number_weighted_halo_mass(), + number_weighted_central_mass(), + qromo(func_satellite_density,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY); + + fsat = qromo(func_satfrac,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY; + printf("FSAT %d %e %e %e %e\n",niter,fsat,HOD.M_min,HOD.sigma_logM,qromo(func_galaxy_bias,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY); + } + } + + } +} + + +/* This is a routine where i can hand-set some boundaries for the + * cosmological parameters (and such) + */ +int parameter_out_of_range(double *a) +{ + int i; + i=N_HOD_PARAMS; + if(HOD.free[++i])//OMEGA_M = a[++j]; + if(OMEGA_M<0.15 || OMEGA_M>0.4) return 1; + if(HOD.free[++i])//SIGMA_8 = a[++j]; + if(SIGMA_8<0.55 || SIGMA_8>1.1) return 1; + if(HOD.free[++i])//VBIAS = a[++j]; + ; + if(HOD.free[++i])//VBIAS_C = a[++j]; + ; + if(HOD.free[++i])//GAMMA = a[++j]; + ; + if(HOD.free[++i])//SPECTRAL_INDX = a[++j]; + if(SPECTRAL_INDX<0.88 || SPECTRAL_INDX>1.05) return 1; + if(HOD.free[++i])//HUBBLE = a[++j]; + if(HUBBLE < 0.6 || HUBBLE > 0.8) return 1; + if(HOD.free[6])//CVIR_FAC + if(CVIR_FAC<0.2 || CVIR_FAC>2) return 1; + if(USE_ERRORS) + { + if(M2N.bias_amp > 1.10 || M2N.bias_amp < 0.9) return 1; + if(M2N.mf_amp > 1.10 || M2N.mf_amp < 0.9) return 1; + if(M2N.scalebias_amp > 1.30 || M2N.scalebias_amp < 0.7) return 1; + } + return 0; +} + +double m2n_chi2_wp_wrapper(double *a) +{ + static int flag=1; + static double *b; + int i,j; + + if(flag) + { + b=dvector(1,100); + flag=0; + } + + /* check to make sure that none of the HOD parameters + * are NEGATIVE. (with exception of sigma_logM) + */ + for(j=0,i=1;i<=N_HOD_PARAMS;++i) { + if(HOD.free[i] && i!=5) { + if(a[++j]<=0) { printf("NEG %d %d %e\n",i,j,a[j]); return(1.0E7); } } + if(HOD.free[i] && i==5) { + ++j; } + } + + /* check to make sure that none of the cosmological + * parameters are negative, either. + */ + for(i=N_HOD_PARAMS+1;i<100;++i) + if(HOD.free[i]) + if(a[++j]<=0) { printf("NEG %d %d %e\n",i,j,a[j]); return(1.0E7); } + + i=0;j=0; + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M_min */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M1 */ + if(HOD.free[++i]){j++;b[j]=a[j];} /* alpha */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M_cut */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* sigma_logM */ + if(HOD.free[++i]){j++;b[j]=a[j];} /* cvir_fac */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* MaxCen */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M_sat_break */ + if(HOD.free[++i]){j++;b[j]=a[j];} /* alpha1 */ + + return(chi2_wp(b)); +} + +double m2n_initialize(double *a, double **cov1, double *avg1, double *start_dev) +{ + int i,j=0; + double x1,x2,omega_m; + long IDUM = -556; + + omega_m = 1; + //if(MCMC>1) + //omega_m = OMEGA_M; + + i=0;j=0; + if(HOD.free[++i]){ a[++j]=log10(HOD.M_min/omega_m);start_dev[j]=0.001; } + if(HOD.free[++i]){ a[++j]=log10(HOD.M1/omega_m);start_dev[j]=0.001; } //.0005 + if(HOD.free[++i]){ a[++j]=HOD.alpha;start_dev[j]=0.03; } //.005 + if(HOD.free[++i]){ a[++j]=log10(HOD.M_cut/omega_m);start_dev[j]=0.01; } //.001 + if(HOD.free[++i]){ a[++j]=log10(HOD.sigma_logM);start_dev[j]=0.01; } + if(HOD.free[++i]){ a[++j]=CVIR_FAC;start_dev[j]=0.02; } + if(HOD.pdfc==7) { + if(HOD.free[++i])a[++j]=log10(HOD.M_cen_max/omega_m); start_dev[j]=0.001; } + else { + if(HOD.free[++i])a[++j]=HOD.MaxCen; start_dev[j]=0.02; } + if(HOD.free[++i]){ a[++j]=log10(HOD.M_sat_break/omega_m);start_dev[j]=0.001; } + if(HOD.free[++i]){ a[++j]=HOD.alpha1;start_dev[j]=0.02; } + + if(MCMC>1) + { + if(HOD.free[++i])a[++j]=OMEGA_M; + if(HOD.free[++i])a[++j]=SIGMA_8; + if(HOD.free[++i])a[++j]=VBIAS; + if(HOD.free[++i])a[++j]=VBIAS_C; + if(HOD.free[++i])a[++j]=GAMMA; + if(HOD.free[++i])a[++j]=SPECTRAL_INDX; + if(HOD.free[++i])a[++j]=HUBBLE; + } + if(USE_ERRORS) + { + a[++j]=1; + a[++j]=1; + a[++j]=1; + } + + if(!ThisTask) + { + printf("INITIAL VALUES: "); + for(i=1;i<=wp.ncf;++i)printf("%e ",a[i]); + printf("\n"); + } + + for(i=1;i<=wp.ncf;++i) + { + avg1[i]=a[i]; + for(j=1;j<=wp.ncf;++j) + cov1[i][j]=a[i]*a[j]; + } + + if(MCMC>1) + { + RESET_COSMOLOGY++; + j=0; + for(i=1;i<=N_HOD_PARAMS;++i)if(HOD.free[i])j++; + i=N_HOD_PARAMS; + if(HOD.free[++i]){ OMEGA_M = a[++j]; start_dev[j] = 0.01; } + if(HOD.free[++i]){ SIGMA_8 = a[++j]; start_dev[j] = 0.01; } + if(HOD.free[++i]){ VBIAS = a[++j]; start_dev[j] = 0.01; } + if(HOD.free[++i]){ VBIAS_C = a[++j]; start_dev[j] = 0.02; } + if(HOD.free[++i]){ GAMMA = a[++j]; start_dev[j] = 0.015; } + if(HOD.free[++i]){ SPECTRAL_INDX = a[++j]; start_dev[j] = 0.02; } + if(HOD.free[++i]){ HUBBLE = a[++j]; start_dev[j] = 0.02; } + } + + if(USE_ERRORS) + { + M2N.bias_amp = a[++j]; start_dev[j] = 0.01; + M2N.mf_amp = a[++j]; start_dev[j] = 0.01; + M2N.scalebias_amp = a[++j]; start_dev[j] = 0.02; + } + + x1=m2n_chi2_wp_wrapper(a); + // reset cosmology for z=0.25 + SIGMA_8 = SIGMA_8*growthfactor(0.25); + RESET_COSMOLOGY++; + if(MCMC>1 && x1<1.0E7)x1+=chi2_m2n(); + if(MCMC>1 && x1<1.0E7)x1+=chi2_number_profiles(); + + if(!ThisTask) { + printf("TRY 0 "); + for(i=1;i<=wp.ncf;++i) + printf("%.4e ",a[i]); + printf("%e\n",x1+x2);fflush(stdout); + printf("INITIAL CHI2: %e\n",x1); + fflush(stdout); + } + return(x1); +} + +/* get the input data. + * -------------------- + * + * M2N data. (first off) + * + * N(R) density profiles for each Ngals bin (later) + * + */ + +void m2n_input() +{ + int i; + FILE *fp; + char aa[1000]; + float x1; // dummy for mass error + + sprintf(M2N.m2n_filename,"/home/tinker/SDSS/DENSITY_PROFILES/M2N_erin_ngals10.data"); + fp = openfile(M2N.m2n_filename); + M2N.ndata = filesize(fp); + + M2N.mass = vector(1,M2N.ndata); + M2N.radius = vector(1,M2N.ndata); + M2N.m2n = vector(1,M2N.ndata); + M2N.err = vector(1,M2N.ndata); + M2N.Ngals_lo = ivector(1,M2N.ndata); + M2N.Ngals_hi = ivector(1,M2N.ndata); + + M2N.model_mass = dvector(1,M2N.ndata); + M2N.model_m2n = dvector(1,M2N.ndata); + + for(i=1;i<=M2N.ndata;++i) + { + fscanf(fp,"%f %f %f %f %d %d",&M2N.mass[i], &x1, &M2N.m2n[i], &M2N.err[i], + &M2N.Ngals_lo[i], &M2N.Ngals_hi[i]); + fgets(aa,1000,fp); + M2N.radius[i] = pow(3*M2N.mass[i]/(4*PI*200*RHO_CRIT),THIRD); + } + fprintf(stderr,"Done reading [%d] lines from [%s]\n",M2N.ndata,M2N.m2n_filename); +} + + +/* Calculate the chi2 for the M2N data. + * ---------------------------------------------------------------------------- + * + * For each Ngals, calculate the mean halo mass and the mean number of galaxies. + * + * M_bar(N_gals) = \int dM dn/dM P(N_gals|Mass) Mass + * divided by \int dM dn/dM P(N_gals|Mass) + * + * N_bar(N_gals) = \int dM dn/dM P(N_gals|Mass) N_true(Mass) + * divided by \int dM dn/dM P(N_gals|Mass) + * + * Where P(N_true|Mass) is the Poisson distribution for satellites + nearest int for centrals. + * + * Where P(N_gals|N_true) is something we have yet to determine. + * + * For bins in Ngals that are wider than one, do a weighted sum between all the + * values of Ngals. + * + * How many systems do you find at a fixed Ngals? + * + * n(N_gals) = \int dM dn/dM P(N_gals|Mass) + * + */ +double chi2_m2n() +{ + int i,j,k,n; + double mbar, nbar, nsys, m2n, chi2, x1, vol; + static int iter=0; + + chi2 = 0; + iter++; + + // calculate the number densities of the clusters for the current cosmology + vol = comoving_volume(0.1,0.3); + for(i=1;i<=M2N.counts_nbins;++i) + M2N.ndens_N200[i] = M2N.counts_N200[i]/vol; + + for(i=1;i<=M2N.ndata;++i) + { + mbar = nbar = nsys = x1 = 0; + M2N.current_bin = i; + //for(j=M2N.Ngals_lo[i];j<=M2N.Ngals_lo[i];++j) + for(j=M2N.Ngals_lo[i];j<=M2N.Ngals_hi[i];++j) + { + M2N.current_Ngals = j; + if(!M2N.counts_N200[j])continue; + mbar += qromo(m2n_func1,log(HOD.M_min),log(HOD.M_max),midpnt); + nbar += qromo(m2n_func2,log(HOD.M_min),log(HOD.M_max),midpnt); + nsys += qromo(m2n_func3,log(HOD.M_min),log(HOD.M_max),midpnt); + x1 += qromo(m2n_func1a,log(HOD.M_min),log(HOD.M_max),midpnt); + } + m2n = mbar/nbar; + M2N.model_m2n[i] = m2n; + M2N.model_mass[i] = mbar/nsys; + x1 /= nsys; + chi2 += (M2N.m2n[i] - m2n)*(M2N.m2n[i] - m2n)/(M2N.err[i]*M2N.err[i]); + + if(OUTPUT) + printf("CHIM2N %d %d %e %e %e %e %e %e %e %e\n",iter,i,M2N.m2n[i],M2N.err[i],m2n,M2N.mass[i],M2N.model_mass[i],chi2,x1,exp(-0.12)*pow(M2N.Ngals_lo[i]/40.,1.15)*4e14*HUBBLE); + //exit(0); + } + return chi2; +} + + +/* THis is the integrand of the mean mass integral: + * dM dn/dM P(N_gals|M) Mass + * + * The PDF of P(M|N_gals) is a lognormal with + * mean = = exp(B) pow(N_gals/40,alpha) + * sigma = 0.48 + * + * with B = -0.12 + * with alpha = 1.15 + */ +double m2n_func1(double m) +{ + int i; + double x, logm, mu, sig, c, rvir, rs, rhos, mtrue; + + logm = m; + m = exp(m); + i = M2N.current_bin; + + //mu = exp(-0.12)*pow(M2N.current_Ngals/40.0,1.15); + //mu = B_rozo + alpha_rozo*log(M2N.current_Ngals/40.0) + log(4e14*HUBBLE); + sig = 0.48; + mu = B_rozo - sig*sig/2 + alpha_rozo*log(M2N.current_Ngals/40.0) + log(4e14*HUBBLE); + + x = exp(-(mu - logm)*(mu - logm)/(2*sig*sig))/(RT2PI*sig)/m; + + // extrapolate the HOD profile out/in to the mean radius of the bin + c = halo_concentration(m); + rvir = pow(3*m/(4*PI*RHO_CRIT*OMEGA_M*DELTA_HALO),THIRD); + rs = rvir/c; + rhos = m/(4*PI*rvir*rvir*rvir*HK_func(rs/rvir)); + mtrue = 4*PI*rhos*pow(M2N.radius[i],3.0)*HK_func(rs/M2N.radius[i]); + + return mtrue*m*M2N.ndens_N200[M2N.current_Ngals]*x; + return mtrue*m*dndM_interp(m)*x; +} + +double m2n_func1a(double m) +{ + int i; + double x, logm, mu, sig, c, rvir, rs, rhos, mtrue; + + logm = m; + m = exp(m); + i = M2N.current_bin; + + //mu = exp(-0.12)*pow(M2N.current_Ngals/40.0,1.15); + //mu = B_rozo + alpha_rozo*log(M2N.current_Ngals/40.0) + log(4e14*HUBBLE); + sig = 0.48; + mu = B_rozo - sig*sig/2 + alpha_rozo*log(M2N.current_Ngals/40.0) + log(4e14*HUBBLE); + + x = exp(-(mu - logm)*(mu - logm)/(2*sig*sig))/(RT2PI*sig)/m; + return m*m*M2N.ndens_N200[M2N.current_Ngals]*x; + return m*m*dndM_interp(m)*x; +} + + +/* THis is the integrand of the mean number integral: + * dM dn/dM P(N_gals|M) N_true(M) + * + * NB! need to do a correction for the fact that the radius for N + * isn't R200 exactly for all masses-- it's R200 for the mean mass in the bin. + * + */ +double m2n_func2(double m) +{ + int i; + double x, logm, mu, sig, c, rvir, rs, rhos, nsat; + + logm = m; + m = exp(m); + i = M2N.current_bin; + + //mu = exp(-0.12)*pow(M2N.current_Ngals/40.0,1.15); + //mu = B_rozo + alpha_rozo*log(M2N.current_Ngals/40.0) + log(4e14*HUBBLE); + sig = 0.48; + mu = B_rozo - sig*sig/2 + alpha_rozo*log(M2N.current_Ngals/40.0) + log(4e14*HUBBLE); + + x = exp(-(mu - logm)*(mu - logm)/(2*sig*sig))/(RT2PI*sig)/m; + + // extrapolate the HOD profile out/in to the mean radius of the bin + c = CVIR_FAC*halo_concentration(m); + rvir = pow(3*m/(4*PI*RHO_CRIT*OMEGA_M*DELTA_HALO),THIRD); + rs = rvir/c; + rhos = N_sat(m)/(4*PI*rvir*rvir*rvir*HK_func(rs/rvir)); + nsat = 4*PI*rhos*pow(M2N.radius[i],3.0)*HK_func(rs/M2N.radius[i]); + //printf("%e %e %e %e\n",m,rvir,M2N.radius[i],nsat/N_sat(m)); + + return m*nsat*M2N.ndens_N200[M2N.current_Ngals]*x; + return m*nsat*dndM_interp(m)*x; +} + +/* THis is the integrand of the number of systems + * dM dn/dM P(N_gals|M) + * + */ +double m2n_func3(double m) +{ + int i; + double x, logm, mu, sig; + + logm = m; + m = exp(m); + + //mu = exp(-0.12)*pow(M2N.current_Ngals/40.0,1.15); + sig = 0.48; + mu = B_rozo - sig*sig/2 + alpha_rozo*log(M2N.current_Ngals/40.0) + log(4e14*HUBBLE); + + x = exp(-(mu - logm)*(mu - logm)/(2*sig*sig))/(RT2PI*sig)/m; + //printf("%e %e %e %f %f\n",m,dndM_interp(m),x,mu,logm); + + return m*M2N.ndens_N200[M2N.current_Ngals]*x; + return m*dndM_interp(m)*x; +} + + + + +double chi2_number_profiles() +{ + double chi2, c, rvir, rhos, rho, rr, m, rs; + float x1; + int i, j, ibin[6] = { 6, 7, 8, 9, 10, 11 }; + char fname[1000]; + FILE *fp; + + static int flag = 1, nbins, nrad=14, iter=0; + static float **ngal, **rad, **err; + + if(flag) + { + nbins = M2N.ndata; + ngal = matrix(1,nbins,1,nrad); + rad = matrix(1,nbins,1,nrad); + err = matrix(1,nbins,1,nrad); + flag = 0; + + for(i=1;i<=nbins;++i) + { + sprintf(fname,"/home/tinker/SDSS/DENSITY_PROFILES/ngals3D_bin%02d.dat",ibin[i-1]); + fp = openfile(fname); + for(j=1;j<=nrad;++j) + { + fscanf(fp,"%f %f %f %f",&rad[i][j],&ngal[i][j],&err[i][j],&x1); + rad[i][j] /= 1.25; // put in comoving units + ngal[i][j]/=(M2N.mass[i]/M2N.m2n[i]); //normalize to unity + err[i][j]/=(M2N.mass[i]/M2N.m2n[i]); //normalize to unity + } + fprintf(stderr,"Done reading [%d] lines from [%s]\n",nrad,fname); + } + } + + for(i=1;i<=M2N.ndata;++i) + { + x1 = 0; + m = M2N.model_mass[i]; + c = CVIR_FAC*halo_concentration(m); + rvir = pow(3*m/(4*PI*RHO_CRIT*OMEGA_M*DELTA_HALO),THIRD); + rs = rvir/c; + rhos = 1/(4*PI*rvir*rvir*rvir*HK_func(1/c)); // normalize to unity + for(j=1;j<=nrad;++j) + { + if(rad[i][j]>M2N.radius[i])break; + rr = rad[i][j]/rs; + rho = rhos/(rr*(1+rr)*(1+rr)); + printf("PROFILE%d %e %e %e %e\n",i,rad[i][j],ngal[i][j],err[i][j],rho); + x1 += (ngal[i][j]-rho)*(ngal[i][j]-rho)/(err[i][j]*err[i][j]); + } + printf("CHIPROF%d %d %e %f %f %e %e\n",iter,i,x1, M2N.radius[i],rvir, + M2N.mass[i],M2N.model_mass[i]); + + chi2 += x1; + } + exit(0); + ++iter; + return chi2; +} + +double meanN_givenM(double m) +{ + static int flag = 1, n=1000; + static double *mass, *nbar, *yy; + int i,j,k; + double logm, dlogm, mlo, mhi, x, pn, ptot, mu, a, sig; + + if(flag) + { + flag = 0; + mass = dvector(1,n); + nbar = dvector(1,n); + yy = dvector(1,n); + + mlo = 1.0E12; + mhi = 1.0E16; + dlogm = log(mhi/mlo)/(n-1); + for(i=1;i<=n;++i) + { + mass[i] = exp(dlogm*(i-1))*mlo; + logm = log(mass[i]); + + pn = ptot = 0; + sig = 0.48; + for(j=1;j<=220;++j) + { + mu = B_rozo - sig*sig/2 + alpha_rozo*log(i/40.0) + log(4e14*HUBBLE); + x = exp(-(mu - logm)*(mu - logm)/(2*sig*sig))/(RT2PI*sig)/m; + ptot += x; + pn += x*i; + } + nbar[i] = log(pn/ptot); + mass[i] = logm; + } + spline(mass,nbar,n,1.0E+30,1.0E+30,yy); + } + splint(mass,nbar,yy,n,log(m),&a); + return exp(a); +} + +/* testing to see if i can back out the P(N|M) from P(M|N) + */ +void test_pdf() +{ + int i,j,k; + double m, sig, mu, x, logm, ptot=0, xx[200], Nbar, pn = 0; + + m = 2.0e13; + logm = log(m); + for(i=1;i<=100;++i) + { + sig = 0.48; + mu = B_rozo - sig*sig/2 + alpha_rozo*log(i/40.0) + log(4e14*HUBBLE); + x = exp(-(mu - logm)*(mu - logm)/(2*sig*sig))/(RT2PI*sig)/m; + ptot += x; + pn += x*i; + xx[i] = x; + } + mu = exp(B_rozo + log(4e14*HUBBLE))/1.6; + Nbar = log(pow(m/mu,1/alpha_rozo)*40); + Nbar = log(pn/ptot); + fprintf(stderr,"%f %f\n",exp(Nbar),pn/ptot); + sig = 0.48/alpha_rozo; + mu = Nbar - sig*sig/2; + for(i=1;i<=100;++i) + { + x = exp(-(mu - log(i))*(mu - log(i))/(2*sig*sig))/(RT2PI*sig)/i; + printf("PDF %d %e %e\n",i,xx[i]/ptot,x); + } + exit(0); +} + +// 41266 degrees in the sky +void input_maxbcg_counts() +{ + FILE *fp; + char fname[100]; + int i,j,n,nf; + + sprintf(fname,"/home/tinker/SDSS/MAXBCG_ML/CATALOG/public_counts.dat"); + fp = openfile(fname); + nf = filesize(fp); + n = 220; + M2N.counts_N200 = ivector(1,n); + M2N.ndens_N200 = dvector(1,n); + for(i=1;i<=n;++i) + M2N.counts_N200[i] = 0; + muh(0); + for(i=1;i<=nf;++i) + fscanf(fp,"%d %d",&j,&M2N.counts_N200[j]); + fclose(fp); + M2N.counts_nbins = n; + fprintf(stderr,"Done reading [%d] lines from [%s]\n",nf,fname); +} + +double comoving_volume(double zlo, double zhi) +{ + return 7500./41266.*pow(qromo(efunc1,zlo,zhi,midpnt)*c_on_H0,3.0)*4./3.*PI; +} +double efunc1(double z) +{ + return pow(OMEGA_M*(1+z)*(1+z)*(1+z) + (1-OMEGA_M),-0.5); +} diff --git a/c_tools/hod/m2n_mcmc_new.c b/c_tools/hod/m2n_mcmc_new.c new file mode 100644 index 0000000..45027e5 --- /dev/null +++ b/c_tools/hod/m2n_mcmc_new.c @@ -0,0 +1,1047 @@ +#include +#include +#include +#include + +#ifdef PARALLEL +#include +#endif + +#include "header.h" + +// parameters of Eduardo's P(M|N200) +#define B_rozo -0.12596 +#define alpha_rozo 1.149 +#define sig_rozo 0.48 + +/* External functions from wp_minimization.c + */ +void wp_input(void); +double poisson_prob(int n, double nave); + +/* Internal functions. + */ +double m2n_chi2_wp_wrapper(double *a); +double m2n_initialize(double *a, double **cov1, double *avg1, double *start_dev); +void m2n_input(void); +double chi2_m2n(void); +double chi2_number_profiles(void); +int parameter_out_of_range(double *a); + +double prob_ngals_ntrue(double m, int ngals, int ntrue); +double prob_ntrue_mass(double m, double ntrue); +double m2n_func1(double m); +double m2n_func1a(double m); +double m2n_func2(double m); +double m2n_func3(double m); + +void test_pdf(void); +double meanN_givenM(double m); + +/* Variables. + */ +int USE_IWEIGHT; + +/****************************************************************** + * + * HOD.free[] also controls which variables will be held constant/vary + * during MCMC minimization. Since this routine will also so z-space + * minimization if requested, indices>6 are cosmological. + * + * i variable + * --- -------- + * [1] -> M_min + * [2] -> M1 + * [3] -> alpha + * [4] -> M_cut + * [5] -> sigmaM + * [6] -> CVIR_FAC + * [7] -> MaxCen (or M_cen_max) + * [8] -> M_sat_break + * [9] -> alpha1 + * + * [10]-> OMEGA_M + * [11]-> SIGMA_8 + * [12]-> VBIAS + * [13]-> VBIAS_C + * [14]-> GAMMA + * [15]-> SPECTRAL_INDX + * [16]-> HUBBLE PARAMETER [used for P(k)] + * + * [0] -> The galaxy_density will be considered data with errors on it, + * and therefore no variable will be fixed by the galaxy density. + * + */ +void m2n_mcmc() +{ + double stepfac=1; + double error=1,tolerance=0,**cov1,**tmp,*a,*avg1,chi2,chi2prev, + **evect,*eval,*aprev,*atemp,**tmp1,*opar,x1,fsat,**chain,*start_dev,*eval_prev; + int n,i,j,k,nrot,niter=0,count=0,imax_chain=100000,NSTEP=50,NSTEP_MAX=10000,convergence=0; + long IDUM=-555; + + int *pcheck,pcnt,ptot=20,firstflag=1,*iweight,total_weight; + double t0,tprev,temp,chi2a,chi2b; + + double delta_halo_rhoc = 200; + + int icvir; + + //test_pdf(); + + // initialize use of SYSTEMATIC ERROR + USE_ERRORS = 1; + M2N.IDUM = -5555; + + opar=dvector(1,100); + + MCMC=Task.MCMC; + + pcheck=calloc(ptot,sizeof(int)); + + /* read in the wp data for a single luminosity threshold sample. + */ + wp_input(); + + /* read in the M2N data. + */ + m2n_input(); + + Work.imodel=2; + Work.chi2=1; + + /* Since we're at constant halo overdensity wrt RHO_CRIT, + * set the overdensity of the halo + */ + DELTA_HALO = delta_halo_rhoc/OMEGA_M; + + + srand48(32498793); + + /* Find the number of free parameters in the minimization + * for the real-space correlation function. + */ + for(n=0,i=1;i<100;++i) + { + n+=HOD.free[i]; + /* if(i>N_HOD_PARAMS && HOD.free[i])MCMC=3;*/ + if(OUTPUT) + printf("mcmc_min> free[%i] = %d\n",i,HOD.free[i]); + } + if(USE_ERRORS) + n+=3; + wp.ncf=n; + + /* Find out which free parameter is for CVIR_FAC + */ + j=0; + if(HOD.free[6]) + for(i=0;i<6;++i) + if(HOD.free[i])j++; + icvir=j+1; + + if(HOD.free[0]) + { + wp.ngal = GALAXY_DENSITY; + wp.ngal_err = 0.1*wp.ngal; + FIX_PARAM = 0; + } + + if(OUTPUT) + printf("mcmc_min> %d free parameters\n",n); + + a=dvector(1,n); + start_dev=dvector(1,n); + aprev=dvector(1,n); + atemp=dvector(1,n); + cov1=dmatrix(1,n,1,n); + avg1=dvector(1,n); + + tmp=dmatrix(1,n,1,n); + tmp1=dmatrix(1,n,1,1); + evect=dmatrix(1,n,1,n); + eval=dvector(1,n); + eval_prev=dvector(1,n); + + chain=dmatrix(1,imax_chain,1,n); + iweight = ivector(1,imax_chain); + for(i=1;i<=imax_chain;++i) + iweight[i] = 0; + + IDUM=IDUM_MCMC; + + chi2prev=m2n_initialize(a,cov1,avg1,start_dev); + niter++; + for(i=1;i<=n;++i) + { + aprev[i] = a[i]; + chain[1][i] = a[i]; + } + + pcnt=0; + pcheck[pcnt]=1; + + stepfac=1; + while(niter1) + { + RESET_COSMOLOGY++; + j=0; + for(i=1;i<=N_HOD_PARAMS;++i)if(HOD.free[i])j++; + i=N_HOD_PARAMS; + if(HOD.free[++i])OMEGA_M = a[++j]; + if(HOD.free[++i])SIGMA_8 = a[++j]; + if(HOD.free[++i])VBIAS = a[++j]; + if(HOD.free[++i])VBIAS_C = a[++j]; + if(HOD.free[++i])GAMMA = a[++j]; + if(HOD.free[++i])SPECTRAL_INDX = a[++j]; + if(HOD.free[++i])HUBBLE = a[++j]; + } + if(VBIAS_C<0)continue; + + if(USE_ERRORS) + { + M2N.mf_amp = a[++j]; + M2N.bias_amp = a[++j]; + M2N.scalebias_amp = a[++j]; + } + + /* Hard-wire CVIR variation + */ + if(HOD.free[6]) + CVIR_FAC = a[icvir]; + + /* Since we're at constant halo overdensity wrt RHO_CRIT, + * set the overdensity of the halo + */ + DELTA_HALO = delta_halo_rhoc/OMEGA_M; + + // Check to see if any of our parameters are out of range. + if(parameter_out_of_range(a))continue; + + + /* Draw random value of cvir from prior. + */ + /* if(CVIR_FAC<0.3 || CVIR_FAC>1.2)continue; */ + /* CVIR_FAC = 0.9*drand48()+0.3; */ + /* GAMMA = gasdev(&IDUM)*0.02 + 0.15; */ + + + chi2=m2n_chi2_wp_wrapper(a); + // reset cosmology for z=0.25 + SIGMA_8 = SIGMA_8*growthfactor(0.25); + RESET_COSMOLOGY++; + if(MCMC>1 && chi2<1.0E7)chi2+= chi2a = chi2_m2n(); + if(MCMC>1 && chi2<1.0E7)chi2+= chi2b = chi2_number_profiles(); + + if(!ThisTask){ + printf("TRY %d ",++count); + for(i=1;i<=n;++i) + printf("%.4e ",a[i]); + printf("%e\n",chi2);fflush(stdout); + } + pcheck[pcnt]=1; + if(!(chi21) + { + RESET_COSMOLOGY++; + j=0; + for(i=1;i<=N_HOD_PARAMS;++i)if(HOD.free[i])j++; + i=N_HOD_PARAMS; + if(HOD.free[++i])OMEGA_M = a[++j]; + if(HOD.free[++i])SIGMA_8 = a[++j]; + if(HOD.free[++i])VBIAS = a[++j]; + if(HOD.free[++i])VBIAS_C = a[++j]; + if(HOD.free[++i])GAMMA = a[++j]; + if(HOD.free[++i])SPECTRAL_INDX = a[++j]; + if(HOD.free[++i])HUBBLE = a[++j]; + } + if(VBIAS_C<0)continue; + + if(USE_ERRORS) + { + M2N.mf_amp = a[++j]; + M2N.bias_amp = a[++j]; + M2N.scalebias_amp = a[++j]; + } + + /* Hard-wire CVIR variation + */ + if(HOD.free[6]) + CVIR_FAC = a[icvir]; + + /* Since we're at constant halo overdensity wrt RHO_CRIT, + * set the overdensity of the halo + */ + DELTA_HALO = delta_halo_rhoc/OMEGA_M; + + // Check to see if any of our parameters are out of range. + if(parameter_out_of_range(a))continue; + + + /* Draw random value of cvir from prior. + */ + /* CVIR_FAC = a[n]; */ + /* if(CVIR_FAC<0.3 || CVIR_FAC>1.2)continue; */ + /* CVIR_FAC = 0.7*drand48()+0.3; */ + /* GAMMA = gasdev(&IDUM)*0.02 + 0.15; */ + // printf("GAMMA %d %f %f\n",count+1,GAMMA,CVIR_FAC); + + chi2=m2n_chi2_wp_wrapper(a); + // reset cosmology for z=0.25 + SIGMA_8 = SIGMA_8*growthfactor(0.25); + RESET_COSMOLOGY++; + if(MCMC>1 && chi2<1.0E7)chi2 += chi2a = chi2_m2n(); + if(MCMC>1 && chi2<1.0E7)chi2 += chi2b = chi2_number_profiles(); + + tprev = t0; + t0 = second(); + ++count; + if(!ThisTask) { + printf("TRY %d ",count); + for(i=1;i<=n;++i) + printf("%.4e ",a[i]); + if(RESTART==2) { + printf("%e %e %.2f\n",chi2,chi2/(1+exp(-count/100.0)), + timediff(tprev,t0));fflush(stdout); } + else { + printf("%e %.2f\n",chi2, + timediff(tprev,t0));fflush(stdout); } + } + if(0) { + printf("CPU%02d %d ",ThisTask,count); + for(i=1;i<=n;++i) + printf("%.4e ",a[i]); + if(RESTART==2) { + printf("%e %e %.2f\n",chi2,chi2/(1+exp(-count/100.0)), + timediff(tprev,t0));fflush(stdout); } + else { + printf("%e %.2f\n",chi2, + timediff(tprev,t0));fflush(stdout); } + } + + pcheck[pcnt]=0; + if(!(chi2NSTEP_MAX) + { + convergence = 1; + for(i=1;i<=n;++i) + { + x1=fabs(eval[i]-eval_prev[i])/eval_prev[i]; + if(x1>0.01)convergence = 0; + printf("CONVERGENCE CHECK %d %d %e %e %e\n",niter/NSTEP_MAX,i,x1,eval[i],eval_prev[i]); + } + for(i=1;i<=n;++i) + eval_prev[i] = eval[i]; + convergence = 0; + + if(convergence) + printf("CONVERGENCE ACCOMPLISHED %d %d \n",niter,count); + } + if(niter==NSTEP_MAX) + { + for(i=1;i<=n;++i) + eval_prev[i] = eval[i]; + } + + + for(i=1;i<=n;++i) + chain[niter][i]=a[i]; + for(i=1;i<=n;++i) + avg1[i] += a[i]; + for(i=1;i<=n;++i) + aprev[i] = a[i]; + for(i=1;i<=n;++i) + for(j=1;j<=n;++j) + cov1[i][j] += a[i]*a[j]; + chi2prev=chi2; + + if(!ThisTask) { + printf("ACCEPT %d %d ",niter,count); + for(i=1;i<=n;++i) + printf("%e ",a[i]); + printf("%e %e %e %e\n",chi2,chi2a,chi2b,chi2-chi2a-chi2b);fflush(stdout); + + if(MCMC==1) + { + printf("HSTATS %d %e %e %e %e\n",niter,HOD.M_min,number_weighted_halo_mass(), + number_weighted_central_mass(), + qromo(func_satellite_density,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY); + + fsat = qromo(func_satfrac,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY; + printf("FSAT %d %e %e %e %e\n",niter,fsat,HOD.M_min,HOD.sigma_logM,qromo(func_galaxy_bias,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY); + } + } + + } +} + + +/* This is a routine where i can hand-set some boundaries for the + * cosmological parameters (and such) + */ +int parameter_out_of_range(double *a) +{ + int i; + i=N_HOD_PARAMS; + if(HOD.free[++i])//OMEGA_M = a[++j]; + if(OMEGA_M<0.15 || OMEGA_M>0.4) return 1; + if(HOD.free[++i])//SIGMA_8 = a[++j]; + if(SIGMA_8<0.55 || SIGMA_8>1.1) return 1; + if(HOD.free[++i])//VBIAS = a[++j]; + ; + if(HOD.free[++i])//VBIAS_C = a[++j]; + ; + if(HOD.free[++i])//GAMMA = a[++j]; + ; + if(HOD.free[++i])//SPECTRAL_INDX = a[++j]; + if(SPECTRAL_INDX<0.88 || SPECTRAL_INDX>1.05) return 1; + if(HOD.free[++i])//HUBBLE = a[++j]; + if(HUBBLE < 0.6 || HUBBLE > 0.8) return 1; + if(HOD.free[6])//CVIR_FAC + if(CVIR_FAC<0.2 || CVIR_FAC>2) return 1; + if(USE_ERRORS) + { + if(M2N.bias_amp > 1.10 || M2N.bias_amp < 0.9) return 1; + if(M2N.mf_amp > 1.10 || M2N.mf_amp < 0.9) return 1; + if(M2N.scalebias_amp > 1.30 || M2N.scalebias_amp < 0.7) return 1; + } + return 0; +} + +double m2n_chi2_wp_wrapper(double *a) +{ + static int flag=1; + static double *b; + int i,j; + + if(flag) + { + b=dvector(1,100); + flag=0; + } + + /* check to make sure that none of the HOD parameters + * are NEGATIVE. (with exception of sigma_logM) + */ + for(j=0,i=1;i<=N_HOD_PARAMS;++i) { + if(HOD.free[i] && i!=5) { + if(a[++j]<=0) { printf("NEG %d %d %e\n",i,j,a[j]); return(1.0E7); } } + if(HOD.free[i] && i==5) { + ++j; } + } + + /* check to make sure that none of the cosmological + * parameters are negative, either. + */ + for(i=N_HOD_PARAMS+1;i<100;++i) + if(HOD.free[i]) + if(a[++j]<=0) { printf("NEG %d %d %e\n",i,j,a[j]); return(1.0E7); } + + i=0;j=0; + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M_min */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M1 */ + if(HOD.free[++i]){j++;b[j]=a[j];} /* alpha */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M_cut */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* sigma_logM */ + if(HOD.free[++i]){j++;b[j]=a[j];} /* cvir_fac */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* MaxCen */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M_sat_break */ + if(HOD.free[++i]){j++;b[j]=a[j];} /* alpha1 */ + + return(chi2_wp(b)); +} + +double m2n_initialize(double *a, double **cov1, double *avg1, double *start_dev) +{ + int i,j=0; + double x1,x2,omega_m; + long IDUM = -556; + + omega_m = 1; + //if(MCMC>1) + //omega_m = OMEGA_M; + + i=0;j=0; + if(HOD.free[++i]){ a[++j]=log10(HOD.M_min/omega_m);start_dev[j]=0.001; } + if(HOD.free[++i]){ a[++j]=log10(HOD.M1/omega_m);start_dev[j]=0.001; } //.0005 + if(HOD.free[++i]){ a[++j]=HOD.alpha;start_dev[j]=0.03; } //.005 + if(HOD.free[++i]){ a[++j]=log10(HOD.M_cut/omega_m);start_dev[j]=0.01; } //.001 + if(HOD.free[++i]){ a[++j]=log10(HOD.sigma_logM);start_dev[j]=0.01; } + if(HOD.free[++i]){ a[++j]=CVIR_FAC;start_dev[j]=0.02; } + if(HOD.pdfc==7) { + if(HOD.free[++i])a[++j]=log10(HOD.M_cen_max/omega_m); start_dev[j]=0.001; } + else { + if(HOD.free[++i])a[++j]=HOD.MaxCen; start_dev[j]=0.02; } + if(HOD.free[++i]){ a[++j]=log10(HOD.M_sat_break/omega_m);start_dev[j]=0.001; } + if(HOD.free[++i]){ a[++j]=HOD.alpha1;start_dev[j]=0.02; } + + if(MCMC>1) + { + if(HOD.free[++i])a[++j]=OMEGA_M; + if(HOD.free[++i])a[++j]=SIGMA_8; + if(HOD.free[++i])a[++j]=VBIAS; + if(HOD.free[++i])a[++j]=VBIAS_C; + if(HOD.free[++i])a[++j]=GAMMA; + if(HOD.free[++i])a[++j]=SPECTRAL_INDX; + if(HOD.free[++i])a[++j]=HUBBLE; + } + if(USE_ERRORS) + { + a[++j]=1; + a[++j]=1; + a[++j]=1; + } + + if(!ThisTask) + { + printf("INITIAL VALUES: "); + for(i=1;i<=wp.ncf;++i)printf("%e ",a[i]); + printf("\n"); + } + + for(i=1;i<=wp.ncf;++i) + { + avg1[i]=a[i]; + for(j=1;j<=wp.ncf;++j) + cov1[i][j]=a[i]*a[j]; + } + + if(MCMC>1) + { + RESET_COSMOLOGY++; + j=0; + for(i=1;i<=N_HOD_PARAMS;++i)if(HOD.free[i])j++; + i=N_HOD_PARAMS; + if(HOD.free[++i]){ OMEGA_M = a[++j]; start_dev[j] = 0.01; } + if(HOD.free[++i]){ SIGMA_8 = a[++j]; start_dev[j] = 0.01; } + if(HOD.free[++i]){ VBIAS = a[++j]; start_dev[j] = 0.01; } + if(HOD.free[++i]){ VBIAS_C = a[++j]; start_dev[j] = 0.02; } + if(HOD.free[++i]){ GAMMA = a[++j]; start_dev[j] = 0.015; } + if(HOD.free[++i]){ SPECTRAL_INDX = a[++j]; start_dev[j] = 0.02; } + if(HOD.free[++i]){ HUBBLE = a[++j]; start_dev[j] = 0.02; } + } + + if(USE_ERRORS) + { + M2N.bias_amp = a[++j]; start_dev[j] = 0.01; + M2N.mf_amp = a[++j]; start_dev[j] = 0.01; + M2N.scalebias_amp = a[++j]; start_dev[j] = 0.02; + } + + x1=m2n_chi2_wp_wrapper(a); + // reset cosmology for z=0.25 + SIGMA_8 = SIGMA_8*growthfactor(0.25); + RESET_COSMOLOGY++; + if(MCMC>1 && x1<1.0E7)x1+=chi2_m2n(); + if(MCMC>1 && x1<1.0E7)x1+=chi2_number_profiles(); + + if(!ThisTask) { + printf("TRY 0 "); + for(i=1;i<=wp.ncf;++i) + printf("%.4e ",a[i]); + printf("%e\n",x1+x2);fflush(stdout); + printf("INITIAL CHI2: %e\n",x1); + fflush(stdout); + } + return(x1); +} + +/* get the input data. + * -------------------- + * + * M2N data. (first off) + * + * N(R) density profiles for each Ngals bin (later) + * + */ + +void m2n_input() +{ + int i; + FILE *fp; + char aa[1000]; + float x1; // dummy for mass error + + sprintf(M2N.m2n_filename,"/home/tinker/SDSS/DENSITY_PROFILES/M2N_erin_ngals10.data"); + fp = openfile(M2N.m2n_filename); + M2N.ndata = filesize(fp); + + M2N.mass = vector(1,M2N.ndata); + M2N.radius = vector(1,M2N.ndata); + M2N.m2n = vector(1,M2N.ndata); + M2N.err = vector(1,M2N.ndata); + M2N.Ngals_lo = ivector(1,M2N.ndata); + M2N.Ngals_hi = ivector(1,M2N.ndata); + + M2N.model_mass = dvector(1,M2N.ndata); + M2N.model_m2n = dvector(1,M2N.ndata); + + for(i=1;i<=M2N.ndata;++i) + { + fscanf(fp,"%f %f %f %f %d %d",&M2N.mass[i], &x1, &M2N.m2n[i], &M2N.err[i], + &M2N.Ngals_lo[i], &M2N.Ngals_hi[i]); + fgets(aa,1000,fp); + M2N.radius[i] = pow(3*M2N.mass[i]/(4*PI*200*RHO_CRIT),THIRD); + } + fprintf(stderr,"Done reading [%d] lines from [%s]\n",M2N.ndata,M2N.m2n_filename); +} + + +/* Calculate the chi2 for the M2N data. + * ---------------------------------------------------------------------------- + * + * For each Ngals, calculate the mean halo mass and the mean number of galaxies. + * + * M_bar(N_gals) = \int dM dn/dM P(N_gals|Mass) Mass + * divided by \int dM dn/dM P(N_gals|Mass) + * + * N_bar(N_gals) = \int dM dn/dM P(N_gals|Mass) N_true(Mass) + * divided by \int dM dn/dM P(N_gals|Mass) + * + * Where P(N_true|Mass) is the Poisson distribution for satellites + nearest int for centrals. + * + * Where P(N_gals|N_true) is something we have yet to determine. + * + * For bins in Ngals that are wider than one, do a weighted sum between all the + * values of Ngals. + * + * How many systems do you find at a fixed Ngals? + * + * n(N_gals) = \int dM dn/dM P(N_gals|Mass) + * + */ +double chi2_m2n() +{ + int i,j,k,n; + double mbar, nbar, nsys, m2n, chi2, x1; + static int iter=0; + + chi2 = 0; + iter++; + + for(i=1;i<=M2N.ndata;++i) + { + mbar = nbar = nsys = x1 = 0; + M2N.current_bin = i; + //for(j=M2N.Ngals_lo[i];j<=M2N.Ngals_lo[i];++j) + for(j=M2N.Ngals_lo[i];j<=M2N.Ngals_hi[i];++j) + { + M2N.current_Ngals = j; + mbar += qromo(m2n_func1,log(HOD.M_min),log(HOD.M_max),midpnt); + nbar += qromo(m2n_func2,log(HOD.M_min),log(HOD.M_max),midpnt); + nsys += qromo(m2n_func3,log(HOD.M_min),log(HOD.M_max),midpnt); + x1 += qromo(m2n_func1a,log(HOD.M_min),log(HOD.M_max),midpnt); + } + m2n = mbar/nbar; + M2N.model_m2n[i] = m2n; + M2N.model_mass[i] = mbar/nsys; + x1 /= nsys; + chi2 += (M2N.m2n[i] - m2n)*(M2N.m2n[i] - m2n)/(M2N.err[i]*M2N.err[i]); + + if(OUTPUT) + printf("CHIM2N %d %d %e %e %e %e %e %e %e %e\n",iter,i,M2N.m2n[i],M2N.err[i],m2n,M2N.mass[i],M2N.model_mass[i],chi2,x1,exp(-0.12)*pow(M2N.Ngals_lo[i]/40.,1.15)*4e14*HUBBLE); + //exit(0); + } + exit(0); + return chi2; +} + + +/* THis is the integrand of the mean mass integral: + * dM dn/dM P(N_gals|M) Mass + * + * The PDF of P(M|N_gals) is a lognormal with + * mean = = exp(B) pow(N_gals/40,alpha) + * sigma = 0.48 + * + * with B = -0.12 + * with alpha = 1.15 + */ +double m2n_func1(double m) +{ + int i; + double x, logm, mu, sig, c, rvir, rs, rhos, mtrue, j, logj; + + logm = m; + m = exp(m); + i = M2N.current_bin; + j = M2N.current_Ngals; + logj = log(j); + + //mu = exp(-0.12)*pow(M2N.current_Ngals/40.0,1.15); + //mu = B_rozo + alpha_rozo*log(M2N.current_Ngals/40.0) + log(4e14*HUBBLE); + sig = sig_rozo/alpha_rozo; + //mu = B_rozo - sig*sig/2 + alpha_rozo*log(M2N.current_Ngals/40.0) + log(4e14*HUBBLE); + mu = log(meanN_givenM(m)) - sig*sig/2; + x = exp(-(mu - logj)*(mu - logj)/(2*sig*sig))/(RT2PI*sig)/j; + + // extrapolate the HOD profile out/in to the mean radius of the bin + c = halo_concentration(m); + rvir = pow(3*m/(4*PI*RHO_CRIT*OMEGA_M*DELTA_HALO),THIRD); + rs = rvir/c; + rhos = m/(4*PI*rvir*rvir*rvir*HK_func(rs/rvir)); + mtrue = 4*PI*rhos*pow(M2N.radius[i],3.0)*HK_func(rs/M2N.radius[i]); + + return mtrue*m*dndM_interp(m)*x; +} + +double m2n_func1a(double m) +{ + int i; + double x, logm, mu, sig, c, rvir, rs, rhos, mtrue, j, logj; + + logm = m; + m = exp(m); + i = M2N.current_bin; + j = M2N.current_Ngals; + logj = log(j); + + //mu = exp(-0.12)*pow(M2N.current_Ngals/40.0,1.15); + //mu = B_rozo + alpha_rozo*log(M2N.current_Ngals/40.0) + log(4e14*HUBBLE); + sig = sig_rozo/alpha_rozo; + //mu = B_rozo - sig*sig/2 + alpha_rozo*log(M2N.current_Ngals/40.0) + log(4e14*HUBBLE); + mu = log(meanN_givenM(m)) - sig*sig/2; + x = exp(-(mu - logj)*(mu - logj)/(2*sig*sig))/(RT2PI*sig)/j; + + return m*m*dndM_interp(m)*x; +} + + +/* THis is the integrand of the mean number integral: + * dM dn/dM P(N_gals|M) N_true(M) + * + * NB! need to do a correction for the fact that the radius for N + * isn't R200 exactly for all masses-- it's R200 for the mean mass in the bin. + * + */ +double m2n_func2(double m) +{ + int i; + double x, logm, mu, sig, c, rvir, rs, rhos, nsat, j,logj; + + logm = m; + m = exp(m); + i = M2N.current_bin; + j = M2N.current_Ngals; + logj = log(j); + + //mu = exp(-0.12)*pow(M2N.current_Ngals/40.0,1.15); + //mu = B_rozo + alpha_rozo*log(M2N.current_Ngals/40.0) + log(4e14*HUBBLE); + sig = sig_rozo/alpha_rozo; + //mu = B_rozo - sig*sig/2 + alpha_rozo*log(M2N.current_Ngals/40.0) + log(4e14*HUBBLE); + mu = log(meanN_givenM(m)) - sig*sig/2; + x = exp(-(mu - logj)*(mu - logj)/(2*sig*sig))/(RT2PI*sig)/j; + + // extrapolate the HOD profile out/in to the mean radius of the bin + c = CVIR_FAC*halo_concentration(m); + rvir = pow(3*m/(4*PI*RHO_CRIT*OMEGA_M*DELTA_HALO),THIRD); + rs = rvir/c; + rhos = N_sat(m)/(4*PI*rvir*rvir*rvir*HK_func(rs/rvir)); + nsat = 4*PI*rhos*pow(M2N.radius[i],3.0)*HK_func(rs/M2N.radius[i]); + //printf("%e %e %e %e\n",m,rvir,M2N.radius[i],nsat/N_sat(m)); + + return m*nsat*dndM_interp(m)*x; +} + +/* THis is the integrand of the number of systems + * dM dn/dM P(N_gals|M) + * + */ +double m2n_func3(double m) +{ + int i; + double x, logm, mu, sig, j, logj; + + logm = m; + m = exp(m); + j = M2N.current_Ngals; + logj = log(j); + + //mu = exp(-0.12)*pow(M2N.current_Ngals/40.0,1.15); + sig = sig_rozo/alpha_rozo; + //mu = B_rozo - sig*sig/2 + alpha_rozo*log(M2N.current_Ngals/40.0) + log(4e14*HUBBLE); + mu = log(meanN_givenM(m)) - sig*sig/2; + x = exp(-(mu - logj)*(mu - logj)/(2*sig*sig))/(RT2PI*sig)/j; + + //printf("%e %e %e %f %f\n",m,dndM_interp(m),x,mu,logm); + + return m*dndM_interp(m)*x; +} + + + + +double chi2_number_profiles() +{ + double chi2, c, rvir, rhos, rho, rr, m, rs; + float x1; + int i, j, ibin[6] = { 6, 7, 8, 9, 10, 11 }; + char fname[1000]; + FILE *fp; + + static int flag = 1, nbins, nrad=14, iter=0; + static float **ngal, **rad, **err; + + if(flag) + { + nbins = M2N.ndata; + ngal = matrix(1,nbins,1,nrad); + rad = matrix(1,nbins,1,nrad); + err = matrix(1,nbins,1,nrad); + flag = 0; + + for(i=1;i<=nbins;++i) + { + sprintf(fname,"/home/tinker/SDSS/DENSITY_PROFILES/ngals3D_bin%02d.dat",ibin[i-1]); + fp = openfile(fname); + for(j=1;j<=nrad;++j) + { + fscanf(fp,"%f %f %f %f",&rad[i][j],&ngal[i][j],&err[i][j],&x1); + rad[i][j] /= 1.25; // put in comoving units + ngal[i][j]/=(M2N.mass[i]/M2N.m2n[i]); //normalize to unity + err[i][j]/=(M2N.mass[i]/M2N.m2n[i]); //normalize to unity + } + fprintf(stderr,"Done reading [%d] lines from [%s]\n",nrad,fname); + } + } + + for(i=1;i<=M2N.ndata;++i) + { + x1 = 0; + m = M2N.model_mass[i]; + c = CVIR_FAC*halo_concentration(m); + rvir = pow(3*m/(4*PI*RHO_CRIT*OMEGA_M*DELTA_HALO),THIRD); + rs = rvir/c; + rhos = 1/(4*PI*rvir*rvir*rvir*HK_func(1/c)); // normalize to unity + for(j=1;j<=nrad;++j) + { + if(rad[i][j]>M2N.radius[i])break; + rr = rad[i][j]/rs; + rho = rhos/(rr*(1+rr)*(1+rr)); + //printf("PROFILE%d %e %e %e %e\n",i,rad[i][j],ngal[i][j],err[i][j],rho); + x1 += (ngal[i][j]-rho)*(ngal[i][j]-rho)/(err[i][j]*err[i][j]); + } + printf("CHIPROF%d %d %e %f %f %e %e\n",iter,i,x1, M2N.radius[i],rvir, + M2N.mass[i],M2N.model_mass[i]); + + chi2 += x1; + } + ++iter; + return chi2; +} + +double meanN_givenM(double m) +{ + static int flag = 1, n=1000; + static double *mass, *nbar, *yy; + int i,j,k; + double logm, dlogm, mlo, mhi, x, pn, ptot, mu, a, sig; + + if(flag) + { + flag = 0; + mass = dvector(1,n); + nbar = dvector(1,n); + yy = dvector(1,n); + + mlo = 1.0E12; + mhi = 1.0E16; + dlogm = log(mhi/mlo)/(n-1); + for(i=1;i<=n;++i) + { + mass[i] = exp(dlogm*(i-1))*mlo; + logm = log(mass[i]); + + pn = ptot = 0; + sig = sig_rozo; + for(j=1;j<=220;++j) + { + mu = B_rozo - sig*sig/2 + alpha_rozo*log(j/40.0) + log(4e14*HUBBLE); + x = exp(-(mu - logm)*(mu - logm)/(2*sig*sig))/(RT2PI*sig)/m; + ptot += x; + pn += x*j; + } + nbar[i] = log(pn/ptot); + mass[i] = logm; + } + spline(mass,nbar,n,1.0E+30,1.0E+30,yy); + } + splint(mass,nbar,yy,n,log(m),&a); + return exp(a); +} + +/* testing to see if i can back out the P(N|M) from P(M|N) + */ +void test_pdf() +{ + int i,j,k; + double m, sig, mu, x, logm, ptot=0, xx[200], Nbar, pn = 0; + + m = 2.0e13; + logm = log(m); + for(i=1;i<=100;++i) + { + sig = sig_rozo; + mu = B_rozo - sig*sig/2 + alpha_rozo*log(i/40.0) + log(4e14*HUBBLE); + x = exp(-(mu - logm)*(mu - logm)/(2*sig*sig))/(RT2PI*sig)/m; + ptot += x; + pn += x*i; + xx[i] = x; + } + mu = exp(B_rozo + log(4e14*HUBBLE))/1.6; + Nbar = log(pow(m/mu,1/alpha_rozo)*40); + Nbar = log(pn/ptot); + fprintf(stderr,"%f %f\n",exp(Nbar),pn/ptot); + sig = sig_rozo/alpha_rozo; + mu = Nbar - sig*sig/2; + for(i=1;i<=100;++i) + { + x = exp(-(mu - log(i))*(mu - log(i))/(2*sig*sig))/(RT2PI*sig)/i; + printf("PDF %d %e %e\n",i,xx[i]/ptot,x); + } + exit(0); +} diff --git a/c_tools/hod/m2n_mcmc_using_PMN.c b/c_tools/hod/m2n_mcmc_using_PMN.c new file mode 100644 index 0000000..8aa18aa --- /dev/null +++ b/c_tools/hod/m2n_mcmc_using_PMN.c @@ -0,0 +1,1036 @@ +#include +#include +#include +#include + +#ifdef PARALLEL +#include +#endif + +#include "header.h" + +// parameters of Eduardo's P(M|N200) +#define B_rozo -0.12596 +#define alpha_rozo 1.149 + + +/* External functions from wp_minimization.c + */ +void wp_input(void); +double poisson_prob(int n, double nave); + +/* Internal functions. + */ +double m2n_chi2_wp_wrapper(double *a); +double m2n_initialize(double *a, double **cov1, double *avg1, double *start_dev); +void m2n_input(void); +double chi2_m2n(void); +double chi2_number_profiles(void); +int parameter_out_of_range(double *a); + +double prob_ngals_ntrue(double m, int ngals, int ntrue); +double prob_ntrue_mass(double m, double ntrue); +double m2n_func1(double m); +double m2n_func1a(double m); +double m2n_func2(double m); +double m2n_func3(double m); + +void test_pdf(void); + +/* Variables. + */ +int USE_IWEIGHT; + +/****************************************************************** + * + * HOD.free[] also controls which variables will be held constant/vary + * during MCMC minimization. Since this routine will also so z-space + * minimization if requested, indices>6 are cosmological. + * + * i variable + * --- -------- + * [1] -> M_min + * [2] -> M1 + * [3] -> alpha + * [4] -> M_cut + * [5] -> sigmaM + * [6] -> CVIR_FAC + * [7] -> MaxCen (or M_cen_max) + * [8] -> M_sat_break + * [9] -> alpha1 + * + * [10]-> OMEGA_M + * [11]-> SIGMA_8 + * [12]-> VBIAS + * [13]-> VBIAS_C + * [14]-> GAMMA + * [15]-> SPECTRAL_INDX + * [16]-> HUBBLE PARAMETER [used for P(k)] + * + * [0] -> The galaxy_density will be considered data with errors on it, + * and therefore no variable will be fixed by the galaxy density. + * + */ +void m2n_mcmc() +{ + double stepfac=1; + double error=1,tolerance=0,**cov1,**tmp,*a,*avg1,chi2,chi2prev, + **evect,*eval,*aprev,*atemp,**tmp1,*opar,x1,fsat,**chain,*start_dev,*eval_prev; + int n,i,j,k,nrot,niter=0,count=0,imax_chain=100000,NSTEP=50,NSTEP_MAX=10000,convergence=0; + long IDUM=-555; + + int *pcheck,pcnt,ptot=20,firstflag=1,*iweight,total_weight; + double t0,tprev,temp,chi2a,chi2b; + + double delta_halo_rhoc = 200; + + int icvir; + + test_pdf(); + + // initialize use of SYSTEMATIC ERROR + USE_ERRORS = 1; + M2N.IDUM = -5555; + + opar=dvector(1,100); + + MCMC=Task.MCMC; + + pcheck=calloc(ptot,sizeof(int)); + + /* read in the wp data for a single luminosity threshold sample. + */ + wp_input(); + + /* read in the M2N data. + */ + m2n_input(); + + Work.imodel=2; + Work.chi2=1; + + /* Since we're at constant halo overdensity wrt RHO_CRIT, + * set the overdensity of the halo + */ + DELTA_HALO = delta_halo_rhoc/OMEGA_M; + + + srand48(32498793); + + /* Find the number of free parameters in the minimization + * for the real-space correlation function. + */ + for(n=0,i=1;i<100;++i) + { + n+=HOD.free[i]; + /* if(i>N_HOD_PARAMS && HOD.free[i])MCMC=3;*/ + if(OUTPUT) + printf("mcmc_min> free[%i] = %d\n",i,HOD.free[i]); + } + if(USE_ERRORS) + n+=3; + wp.ncf=n; + + /* Find out which free parameter is for CVIR_FAC + */ + j=0; + if(HOD.free[6]) + for(i=0;i<6;++i) + if(HOD.free[i])j++; + icvir=j+1; + + if(HOD.free[0]) + { + wp.ngal = GALAXY_DENSITY; + wp.ngal_err = 0.1*wp.ngal; + FIX_PARAM = 0; + } + + if(OUTPUT) + printf("mcmc_min> %d free parameters\n",n); + + a=dvector(1,n); + start_dev=dvector(1,n); + aprev=dvector(1,n); + atemp=dvector(1,n); + cov1=dmatrix(1,n,1,n); + avg1=dvector(1,n); + + tmp=dmatrix(1,n,1,n); + tmp1=dmatrix(1,n,1,1); + evect=dmatrix(1,n,1,n); + eval=dvector(1,n); + eval_prev=dvector(1,n); + + chain=dmatrix(1,imax_chain,1,n); + iweight = ivector(1,imax_chain); + for(i=1;i<=imax_chain;++i) + iweight[i] = 0; + + IDUM=IDUM_MCMC; + + chi2prev=m2n_initialize(a,cov1,avg1,start_dev); + niter++; + for(i=1;i<=n;++i) + { + aprev[i] = a[i]; + chain[1][i] = a[i]; + } + + pcnt=0; + pcheck[pcnt]=1; + + stepfac=1; + while(niter1) + { + RESET_COSMOLOGY++; + j=0; + for(i=1;i<=N_HOD_PARAMS;++i)if(HOD.free[i])j++; + i=N_HOD_PARAMS; + if(HOD.free[++i])OMEGA_M = a[++j]; + if(HOD.free[++i])SIGMA_8 = a[++j]; + if(HOD.free[++i])VBIAS = a[++j]; + if(HOD.free[++i])VBIAS_C = a[++j]; + if(HOD.free[++i])GAMMA = a[++j]; + if(HOD.free[++i])SPECTRAL_INDX = a[++j]; + if(HOD.free[++i])HUBBLE = a[++j]; + } + if(VBIAS_C<0)continue; + + if(USE_ERRORS) + { + M2N.mf_amp = a[++j]; + M2N.bias_amp = a[++j]; + M2N.scalebias_amp = a[++j]; + } + + /* Hard-wire CVIR variation + */ + if(HOD.free[6]) + CVIR_FAC = a[icvir]; + + /* Since we're at constant halo overdensity wrt RHO_CRIT, + * set the overdensity of the halo + */ + DELTA_HALO = delta_halo_rhoc/OMEGA_M; + + // Check to see if any of our parameters are out of range. + if(parameter_out_of_range(a))continue; + + + /* Draw random value of cvir from prior. + */ + /* if(CVIR_FAC<0.3 || CVIR_FAC>1.2)continue; */ + /* CVIR_FAC = 0.9*drand48()+0.3; */ + /* GAMMA = gasdev(&IDUM)*0.02 + 0.15; */ + + + chi2=m2n_chi2_wp_wrapper(a); + // reset cosmology for z=0.25 + SIGMA_8 = SIGMA_8*growthfactor(0.25); + RESET_COSMOLOGY++; + if(MCMC>1 && chi2<1.0E7)chi2+= chi2a = chi2_m2n(); + if(MCMC>1 && chi2<1.0E7)chi2+= chi2b = chi2_number_profiles(); + + if(!ThisTask){ + printf("TRY %d ",++count); + for(i=1;i<=n;++i) + printf("%.4e ",a[i]); + printf("%e\n",chi2);fflush(stdout); + } + pcheck[pcnt]=1; + if(!(chi21) + { + RESET_COSMOLOGY++; + j=0; + for(i=1;i<=N_HOD_PARAMS;++i)if(HOD.free[i])j++; + i=N_HOD_PARAMS; + if(HOD.free[++i])OMEGA_M = a[++j]; + if(HOD.free[++i])SIGMA_8 = a[++j]; + if(HOD.free[++i])VBIAS = a[++j]; + if(HOD.free[++i])VBIAS_C = a[++j]; + if(HOD.free[++i])GAMMA = a[++j]; + if(HOD.free[++i])SPECTRAL_INDX = a[++j]; + if(HOD.free[++i])HUBBLE = a[++j]; + } + if(VBIAS_C<0)continue; + + if(USE_ERRORS) + { + M2N.mf_amp = a[++j]; + M2N.bias_amp = a[++j]; + M2N.scalebias_amp = a[++j]; + } + + /* Hard-wire CVIR variation + */ + if(HOD.free[6]) + CVIR_FAC = a[icvir]; + + /* Since we're at constant halo overdensity wrt RHO_CRIT, + * set the overdensity of the halo + */ + DELTA_HALO = delta_halo_rhoc/OMEGA_M; + + // Check to see if any of our parameters are out of range. + if(parameter_out_of_range(a))continue; + + + /* Draw random value of cvir from prior. + */ + /* CVIR_FAC = a[n]; */ + /* if(CVIR_FAC<0.3 || CVIR_FAC>1.2)continue; */ + /* CVIR_FAC = 0.7*drand48()+0.3; */ + /* GAMMA = gasdev(&IDUM)*0.02 + 0.15; */ + // printf("GAMMA %d %f %f\n",count+1,GAMMA,CVIR_FAC); + + chi2=m2n_chi2_wp_wrapper(a); + // reset cosmology for z=0.25 + SIGMA_8 = SIGMA_8*growthfactor(0.25); + RESET_COSMOLOGY++; + if(MCMC>1 && chi2<1.0E7)chi2 += chi2a = chi2_m2n(); + if(MCMC>1 && chi2<1.0E7)chi2 += chi2b = chi2_number_profiles(); + + tprev = t0; + t0 = second(); + ++count; + if(!ThisTask) { + printf("TRY %d ",count); + for(i=1;i<=n;++i) + printf("%.4e ",a[i]); + if(RESTART==2) { + printf("%e %e %.2f\n",chi2,chi2/(1+exp(-count/100.0)), + timediff(tprev,t0));fflush(stdout); } + else { + printf("%e %.2f\n",chi2, + timediff(tprev,t0));fflush(stdout); } + } + if(0) { + printf("CPU%02d %d ",ThisTask,count); + for(i=1;i<=n;++i) + printf("%.4e ",a[i]); + if(RESTART==2) { + printf("%e %e %.2f\n",chi2,chi2/(1+exp(-count/100.0)), + timediff(tprev,t0));fflush(stdout); } + else { + printf("%e %.2f\n",chi2, + timediff(tprev,t0));fflush(stdout); } + } + + pcheck[pcnt]=0; + if(!(chi2NSTEP_MAX) + { + convergence = 1; + for(i=1;i<=n;++i) + { + x1=fabs(eval[i]-eval_prev[i])/eval_prev[i]; + if(x1>0.01)convergence = 0; + printf("CONVERGENCE CHECK %d %d %e %e %e\n",niter/NSTEP_MAX,i,x1,eval[i],eval_prev[i]); + } + for(i=1;i<=n;++i) + eval_prev[i] = eval[i]; + convergence = 0; + + if(convergence) + printf("CONVERGENCE ACCOMPLISHED %d %d \n",niter,count); + } + if(niter==NSTEP_MAX) + { + for(i=1;i<=n;++i) + eval_prev[i] = eval[i]; + } + + + for(i=1;i<=n;++i) + chain[niter][i]=a[i]; + for(i=1;i<=n;++i) + avg1[i] += a[i]; + for(i=1;i<=n;++i) + aprev[i] = a[i]; + for(i=1;i<=n;++i) + for(j=1;j<=n;++j) + cov1[i][j] += a[i]*a[j]; + chi2prev=chi2; + + if(!ThisTask) { + printf("ACCEPT %d %d ",niter,count); + for(i=1;i<=n;++i) + printf("%e ",a[i]); + printf("%e %e %e %e\n",chi2,chi2a,chi2b,chi2-chi2a-chi2b);fflush(stdout); + + if(MCMC==1) + { + printf("HSTATS %d %e %e %e %e\n",niter,HOD.M_min,number_weighted_halo_mass(), + number_weighted_central_mass(), + qromo(func_satellite_density,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY); + + fsat = qromo(func_satfrac,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY; + printf("FSAT %d %e %e %e %e\n",niter,fsat,HOD.M_min,HOD.sigma_logM,qromo(func_galaxy_bias,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY); + } + } + + } +} + + +/* This is a routine where i can hand-set some boundaries for the + * cosmological parameters (and such) + */ +int parameter_out_of_range(double *a) +{ + int i; + i=N_HOD_PARAMS; + if(HOD.free[++i])//OMEGA_M = a[++j]; + if(OMEGA_M<0.15 || OMEGA_M>0.4) return 1; + if(HOD.free[++i])//SIGMA_8 = a[++j]; + if(SIGMA_8<0.55 || SIGMA_8>1.1) return 1; + if(HOD.free[++i])//VBIAS = a[++j]; + ; + if(HOD.free[++i])//VBIAS_C = a[++j]; + ; + if(HOD.free[++i])//GAMMA = a[++j]; + ; + if(HOD.free[++i])//SPECTRAL_INDX = a[++j]; + if(SPECTRAL_INDX<0.88 || SPECTRAL_INDX>1.05) return 1; + if(HOD.free[++i])//HUBBLE = a[++j]; + if(HUBBLE < 0.6 || HUBBLE > 0.8) return 1; + if(HOD.free[6])//CVIR_FAC + if(CVIR_FAC<0.2 || CVIR_FAC>2) return 1; + if(USE_ERRORS) + { + if(M2N.bias_amp > 1.10 || M2N.bias_amp < 0.9) return 1; + if(M2N.mf_amp > 1.10 || M2N.mf_amp < 0.9) return 1; + if(M2N.scalebias_amp > 1.30 || M2N.scalebias_amp < 0.7) return 1; + } + return 0; +} + +double m2n_chi2_wp_wrapper(double *a) +{ + static int flag=1; + static double *b; + int i,j; + + if(flag) + { + b=dvector(1,100); + flag=0; + } + + /* check to make sure that none of the HOD parameters + * are NEGATIVE. (with exception of sigma_logM) + */ + for(j=0,i=1;i<=N_HOD_PARAMS;++i) { + if(HOD.free[i] && i!=5) { + if(a[++j]<=0) { printf("NEG %d %d %e\n",i,j,a[j]); return(1.0E7); } } + if(HOD.free[i] && i==5) { + ++j; } + } + + /* check to make sure that none of the cosmological + * parameters are negative, either. + */ + for(i=N_HOD_PARAMS+1;i<100;++i) + if(HOD.free[i]) + if(a[++j]<=0) { printf("NEG %d %d %e\n",i,j,a[j]); return(1.0E7); } + + i=0;j=0; + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M_min */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M1 */ + if(HOD.free[++i]){j++;b[j]=a[j];} /* alpha */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M_cut */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* sigma_logM */ + if(HOD.free[++i]){j++;b[j]=a[j];} /* cvir_fac */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* MaxCen */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M_sat_break */ + if(HOD.free[++i]){j++;b[j]=a[j];} /* alpha1 */ + + return(chi2_wp(b)); +} + +double m2n_initialize(double *a, double **cov1, double *avg1, double *start_dev) +{ + int i,j=0; + double x1,x2,omega_m; + long IDUM = -556; + + omega_m = 1; + //if(MCMC>1) + //omega_m = OMEGA_M; + + i=0;j=0; + if(HOD.free[++i]){ a[++j]=log10(HOD.M_min/omega_m);start_dev[j]=0.001; } + if(HOD.free[++i]){ a[++j]=log10(HOD.M1/omega_m);start_dev[j]=0.001; } //.0005 + if(HOD.free[++i]){ a[++j]=HOD.alpha;start_dev[j]=0.03; } //.005 + if(HOD.free[++i]){ a[++j]=log10(HOD.M_cut/omega_m);start_dev[j]=0.01; } //.001 + if(HOD.free[++i]){ a[++j]=log10(HOD.sigma_logM);start_dev[j]=0.01; } + if(HOD.free[++i]){ a[++j]=CVIR_FAC;start_dev[j]=0.02; } + if(HOD.pdfc==7) { + if(HOD.free[++i])a[++j]=log10(HOD.M_cen_max/omega_m); start_dev[j]=0.001; } + else { + if(HOD.free[++i])a[++j]=HOD.MaxCen; start_dev[j]=0.02; } + if(HOD.free[++i]){ a[++j]=log10(HOD.M_sat_break/omega_m);start_dev[j]=0.001; } + if(HOD.free[++i]){ a[++j]=HOD.alpha1;start_dev[j]=0.02; } + + if(MCMC>1) + { + if(HOD.free[++i])a[++j]=OMEGA_M; + if(HOD.free[++i])a[++j]=SIGMA_8; + if(HOD.free[++i])a[++j]=VBIAS; + if(HOD.free[++i])a[++j]=VBIAS_C; + if(HOD.free[++i])a[++j]=GAMMA; + if(HOD.free[++i])a[++j]=SPECTRAL_INDX; + if(HOD.free[++i])a[++j]=HUBBLE; + } + if(USE_ERRORS) + { + a[++j]=1; + a[++j]=1; + a[++j]=1; + } + + if(!ThisTask) + { + printf("INITIAL VALUES: "); + for(i=1;i<=wp.ncf;++i)printf("%e ",a[i]); + printf("\n"); + } + + for(i=1;i<=wp.ncf;++i) + { + avg1[i]=a[i]; + for(j=1;j<=wp.ncf;++j) + cov1[i][j]=a[i]*a[j]; + } + + if(MCMC>1) + { + RESET_COSMOLOGY++; + j=0; + for(i=1;i<=N_HOD_PARAMS;++i)if(HOD.free[i])j++; + i=N_HOD_PARAMS; + if(HOD.free[++i]){ OMEGA_M = a[++j]; start_dev[j] = 0.01; } + if(HOD.free[++i]){ SIGMA_8 = a[++j]; start_dev[j] = 0.01; } + if(HOD.free[++i]){ VBIAS = a[++j]; start_dev[j] = 0.01; } + if(HOD.free[++i]){ VBIAS_C = a[++j]; start_dev[j] = 0.02; } + if(HOD.free[++i]){ GAMMA = a[++j]; start_dev[j] = 0.015; } + if(HOD.free[++i]){ SPECTRAL_INDX = a[++j]; start_dev[j] = 0.02; } + if(HOD.free[++i]){ HUBBLE = a[++j]; start_dev[j] = 0.02; } + } + + if(USE_ERRORS) + { + M2N.bias_amp = a[++j]; start_dev[j] = 0.01; + M2N.mf_amp = a[++j]; start_dev[j] = 0.01; + M2N.scalebias_amp = a[++j]; start_dev[j] = 0.02; + } + + x1=m2n_chi2_wp_wrapper(a); + // reset cosmology for z=0.25 + SIGMA_8 = SIGMA_8*growthfactor(0.25); + RESET_COSMOLOGY++; + if(MCMC>1 && x1<1.0E7)x1+=chi2_m2n(); + if(MCMC>1 && x1<1.0E7)x1+=chi2_number_profiles(); + + if(!ThisTask) { + printf("TRY 0 "); + for(i=1;i<=wp.ncf;++i) + printf("%.4e ",a[i]); + printf("%e\n",x1+x2);fflush(stdout); + printf("INITIAL CHI2: %e\n",x1); + fflush(stdout); + } + return(x1); +} + +/* get the input data. + * -------------------- + * + * M2N data. (first off) + * + * N(R) density profiles for each Ngals bin (later) + * + */ + +void m2n_input() +{ + int i; + FILE *fp; + char aa[1000]; + float x1; // dummy for mass error + + sprintf(M2N.m2n_filename,"/home/tinker/SDSS/DENSITY_PROFILES/M2N_erin_ngals10.data"); + fp = openfile(M2N.m2n_filename); + M2N.ndata = filesize(fp); + + M2N.mass = vector(1,M2N.ndata); + M2N.radius = vector(1,M2N.ndata); + M2N.m2n = vector(1,M2N.ndata); + M2N.err = vector(1,M2N.ndata); + M2N.Ngals_lo = ivector(1,M2N.ndata); + M2N.Ngals_hi = ivector(1,M2N.ndata); + + M2N.model_mass = dvector(1,M2N.ndata); + M2N.model_m2n = dvector(1,M2N.ndata); + + for(i=1;i<=M2N.ndata;++i) + { + fscanf(fp,"%f %f %f %f %d %d",&M2N.mass[i], &x1, &M2N.m2n[i], &M2N.err[i], + &M2N.Ngals_lo[i], &M2N.Ngals_hi[i]); + fgets(aa,1000,fp); + M2N.radius[i] = pow(3*M2N.mass[i]/(4*PI*200*RHO_CRIT),THIRD); + } + fprintf(stderr,"Done reading [%d] lines from [%s]\n",M2N.ndata,M2N.m2n_filename); +} + + +/* Calculate the chi2 for the M2N data. + * ---------------------------------------------------------------------------- + * + * For each Ngals, calculate the mean halo mass and the mean number of galaxies. + * + * M_bar(N_gals) = \int dM dn/dM P(N_gals|Mass) Mass + * divided by \int dM dn/dM P(N_gals|Mass) + * + * N_bar(N_gals) = \int dM dn/dM P(N_gals|Mass) N_true(Mass) + * divided by \int dM dn/dM P(N_gals|Mass) + * + * Where P(N_true|Mass) is the Poisson distribution for satellites + nearest int for centrals. + * + * Where P(N_gals|N_true) is something we have yet to determine. + * + * For bins in Ngals that are wider than one, do a weighted sum between all the + * values of Ngals. + * + * How many systems do you find at a fixed Ngals? + * + * n(N_gals) = \int dM dn/dM P(N_gals|Mass) + * + */ +double chi2_m2n() +{ + int i,j,k,n; + double mbar, nbar, nsys, m2n, chi2, x1; + static int iter=0; + + chi2 = 0; + iter++; + + for(i=1;i<=M2N.ndata;++i) + { + mbar = nbar = nsys = x1 = 0; + M2N.current_bin = i; + //for(j=M2N.Ngals_lo[i];j<=M2N.Ngals_lo[i];++j) + for(j=M2N.Ngals_lo[i];j<=M2N.Ngals_hi[i];++j) + { + M2N.current_Ngals = j; + mbar += qromo(m2n_func1,log(HOD.M_min),log(HOD.M_max),midpnt); + nbar += qromo(m2n_func2,log(HOD.M_min),log(HOD.M_max),midpnt); + nsys += qromo(m2n_func3,log(HOD.M_min),log(HOD.M_max),midpnt); + x1 += qromo(m2n_func1a,log(HOD.M_min),log(HOD.M_max),midpnt); + } + m2n = mbar/nbar; + M2N.model_m2n[i] = m2n; + M2N.model_mass[i] = mbar/nsys; + x1 /= nsys; + chi2 += (M2N.m2n[i] - m2n)*(M2N.m2n[i] - m2n)/(M2N.err[i]*M2N.err[i]); + + if(OUTPUT) + printf("CHIM2N %d %d %e %e %e %e %e %e %e %e\n",iter,i,M2N.m2n[i],M2N.err[i],m2n,M2N.mass[i],M2N.model_mass[i],chi2,x1,exp(-0.12)*pow(M2N.Ngals_lo[i]/40.,1.15)*4e14*HUBBLE); + //exit(0); + } + exit(0); + return chi2; +} + + +/* THis is the integrand of the mean mass integral: + * dM dn/dM P(N_gals|M) Mass + * + * The PDF of P(M|N_gals) is a lognormal with + * mean = = exp(B) pow(N_gals/40,alpha) + * sigma = 0.48 + * + * with B = -0.12 + * with alpha = 1.15 + */ +double m2n_func1(double m) +{ + int i; + double x, logm, mu, sig, c, rvir, rs, rhos, mtrue; + + logm = m; + m = exp(m); + i = M2N.current_bin; + + //mu = exp(-0.12)*pow(M2N.current_Ngals/40.0,1.15); + //mu = B_rozo + alpha_rozo*log(M2N.current_Ngals/40.0) + log(4e14*HUBBLE); + sig = 0.48; + mu = B_rozo - sig*sig/2 + alpha_rozo*log(M2N.current_Ngals/40.0) + log(4e14*HUBBLE); + + x = exp(-(mu - logm)*(mu - logm)/(2*sig*sig))/(RT2PI*sig)/m; + + // extrapolate the HOD profile out/in to the mean radius of the bin + c = halo_concentration(m); + rvir = pow(3*m/(4*PI*RHO_CRIT*OMEGA_M*DELTA_HALO),THIRD); + rs = rvir/c; + rhos = m/(4*PI*rvir*rvir*rvir*HK_func(rs/rvir)); + mtrue = 4*PI*rhos*pow(M2N.radius[i],3.0)*HK_func(rs/M2N.radius[i]); + + return mtrue*m*dndM_interp(m)*x; +} + +double m2n_func1a(double m) +{ + int i; + double x, logm, mu, sig, c, rvir, rs, rhos, mtrue; + + logm = m; + m = exp(m); + i = M2N.current_bin; + + //mu = exp(-0.12)*pow(M2N.current_Ngals/40.0,1.15); + //mu = B_rozo + alpha_rozo*log(M2N.current_Ngals/40.0) + log(4e14*HUBBLE); + sig = 0.48; + mu = B_rozo - sig*sig/2 + alpha_rozo*log(M2N.current_Ngals/40.0) + log(4e14*HUBBLE); + + x = exp(-(mu - logm)*(mu - logm)/(2*sig*sig))/(RT2PI*sig)/m; + return m*m*dndM_interp(m)*x; +} + + +/* THis is the integrand of the mean number integral: + * dM dn/dM P(N_gals|M) N_true(M) + * + * NB! need to do a correction for the fact that the radius for N + * isn't R200 exactly for all masses-- it's R200 for the mean mass in the bin. + * + */ +double m2n_func2(double m) +{ + int i; + double x, logm, mu, sig, c, rvir, rs, rhos, nsat; + + logm = m; + m = exp(m); + i = M2N.current_bin; + + //mu = exp(-0.12)*pow(M2N.current_Ngals/40.0,1.15); + //mu = B_rozo + alpha_rozo*log(M2N.current_Ngals/40.0) + log(4e14*HUBBLE); + sig = 0.48; + mu = B_rozo - sig*sig/2 + alpha_rozo*log(M2N.current_Ngals/40.0) + log(4e14*HUBBLE); + + x = exp(-(mu - logm)*(mu - logm)/(2*sig*sig))/(RT2PI*sig)/m; + + // extrapolate the HOD profile out/in to the mean radius of the bin + c = CVIR_FAC*halo_concentration(m); + rvir = pow(3*m/(4*PI*RHO_CRIT*OMEGA_M*DELTA_HALO),THIRD); + rs = rvir/c; + rhos = N_sat(m)/(4*PI*rvir*rvir*rvir*HK_func(rs/rvir)); + nsat = 4*PI*rhos*pow(M2N.radius[i],3.0)*HK_func(rs/M2N.radius[i]); + //printf("%e %e %e %e\n",m,rvir,M2N.radius[i],nsat/N_sat(m)); + + return m*nsat*dndM_interp(m)*x; +} + +/* THis is the integrand of the number of systems + * dM dn/dM P(N_gals|M) + * + */ +double m2n_func3(double m) +{ + int i; + double x, logm, mu, sig; + + logm = m; + m = exp(m); + + //mu = exp(-0.12)*pow(M2N.current_Ngals/40.0,1.15); + sig = 0.48; + mu = B_rozo - sig*sig/2 + alpha_rozo*log(M2N.current_Ngals/40.0) + log(4e14*HUBBLE); + + x = exp(-(mu - logm)*(mu - logm)/(2*sig*sig))/(RT2PI*sig)/m; + //printf("%e %e %e %f %f\n",m,dndM_interp(m),x,mu,logm); + + return m*dndM_interp(m)*x; +} + + + + +double chi2_number_profiles() +{ + double chi2, c, rvir, rhos, rho, rr, m, rs; + float x1; + int i, j, ibin[6] = { 6, 7, 8, 9, 10, 11 }; + char fname[1000]; + FILE *fp; + + static int flag = 1, nbins, nrad=14, iter=0; + static float **ngal, **rad, **err; + + if(flag) + { + nbins = M2N.ndata; + ngal = matrix(1,nbins,1,nrad); + rad = matrix(1,nbins,1,nrad); + err = matrix(1,nbins,1,nrad); + flag = 0; + + for(i=1;i<=nbins;++i) + { + sprintf(fname,"/home/tinker/SDSS/DENSITY_PROFILES/ngals3D_bin%02d.dat",ibin[i-1]); + fp = openfile(fname); + for(j=1;j<=nrad;++j) + { + fscanf(fp,"%f %f %f %f",&rad[i][j],&ngal[i][j],&err[i][j],&x1); + rad[i][j] /= 1.25; // put in comoving units + ngal[i][j]/=(M2N.mass[i]/M2N.m2n[i]); //normalize to unity + err[i][j]/=(M2N.mass[i]/M2N.m2n[i]); //normalize to unity + } + fprintf(stderr,"Done reading [%d] lines from [%s]\n",nrad,fname); + } + } + + for(i=1;i<=M2N.ndata;++i) + { + x1 = 0; + m = M2N.model_mass[i]; + c = CVIR_FAC*halo_concentration(m); + rvir = pow(3*m/(4*PI*RHO_CRIT*OMEGA_M*DELTA_HALO),THIRD); + rs = rvir/c; + rhos = 1/(4*PI*rvir*rvir*rvir*HK_func(1/c)); // normalize to unity + for(j=1;j<=nrad;++j) + { + if(rad[i][j]>M2N.radius[i])break; + rr = rad[i][j]/rs; + rho = rhos/(rr*(1+rr)*(1+rr)); + //printf("PROFILE%d %e %e %e %e\n",i,rad[i][j],ngal[i][j],err[i][j],rho); + x1 += (ngal[i][j]-rho)*(ngal[i][j]-rho)/(err[i][j]*err[i][j]); + } + printf("CHIPROF%d %d %e %f %f %e %e\n",iter,i,x1, M2N.radius[i],rvir, + M2N.mass[i],M2N.model_mass[i]); + + chi2 += x1; + } + ++iter; + return chi2; +} + +double meanN_givenM(double m) +{ + static int flag = 1, n=1000; + static double *mass, *nbar, *yy; + int i,j,k; + double logm, dlogm, mlo, mhi, x, pn, ptot, mu, a, sig; + + if(flag) + { + flag = 0; + mass = dvector(1,n); + nbar = dvector(1,n); + yy = dvector(1,n); + + mlo = 1.0E12; + mhi = 1.0E16; + dlogm = log(mhi/mlo)/(n-1); + for(i=1;i<=n;++i) + { + mass[i] = exp(dlogm*(i-1))*mlo; + logm = log(mass[i]); + + pn = ptot = 0; + sig = 0.48; + for(j=1;j<=220;++j) + { + mu = B_rozo - sig*sig/2 + alpha_rozo*log(i/40.0) + log(4e14*HUBBLE); + x = exp(-(mu - logm)*(mu - logm)/(2*sig*sig))/(RT2PI*sig)/m; + ptot += x; + pn += x*i; + } + nbar[i] = log(pn/ptot); + mass[i] = logm; + } + spline(mass,nbar,n,1.0E+30,1.0E+30,yy); + } + splint(mass,nbar,yy,n,log(m),&a); + return exp(a); +} + +/* testing to see if i can back out the P(N|M) from P(M|N) + */ +void test_pdf() +{ + int i,j,k; + double m, sig, mu, x, logm, ptot=0, xx[200], Nbar, pn = 0; + + m = 2.0e13; + logm = log(m); + for(i=1;i<=100;++i) + { + sig = 0.48; + mu = B_rozo - sig*sig/2 + alpha_rozo*log(i/40.0) + log(4e14*HUBBLE); + x = exp(-(mu - logm)*(mu - logm)/(2*sig*sig))/(RT2PI*sig)/m; + ptot += x; + pn += x*i; + xx[i] = x; + } + mu = exp(B_rozo + log(4e14*HUBBLE))/1.6; + Nbar = log(pow(m/mu,1/alpha_rozo)*40); + Nbar = log(pn/ptot); + fprintf(stderr,"%f %f\n",exp(Nbar),pn/ptot); + sig = 0.48/alpha_rozo; + mu = Nbar - sig*sig/2; + for(i=1;i<=100;++i) + { + x = exp(-(mu - log(i))*(mu - log(i))/(2*sig*sig))/(RT2PI*sig)/i; + printf("PDF %d %e %e\n",i,xx[i]/ptot,x); + } + exit(0); +} diff --git a/c_tools/hod/main.c b/c_tools/hod/main.c new file mode 100644 index 0000000..a3b8a0e --- /dev/null +++ b/c_tools/hod/main.c @@ -0,0 +1,109 @@ +#include +#include +#include +#include + +#ifdef PARALLEL +#include +#endif + +#include "header.h" + +/* test file routines. + */ +void test(int argc, char **argv); +void chi2_grid(int argc, char **argv); +void fit_scale_bias(int argc, char **argv); +void aspen_breakout(void); +void populate_simulation_clf(void); + +int main(int argc, char **argv) +{ + double s1; + int i; + +#ifdef PARALLEL + printf("STARTING>>>\n"); + fflush(stdout); + MPI_Init(&argc, &argv); + MPI_Comm_rank(MPI_COMM_WORLD, &ThisTask); + MPI_Comm_size(MPI_COMM_WORLD, &NTask); + printf("TASK %d reporting for duty.\n",ThisTask); + fflush(stdout); +#endif + + OUTPUT=0; + + for(i=1;i<=99;++i) + HOD.free[i]=0; + wp.esys=0; + + Work.chi2=0; + Work.imodel=1; + + USE_ERRORS = 0; + ITRANS=4; + HUBBLE=0.7; + BEST_FIT = 0; + HOD.M_sat_break = 1.0e14; + HOD.alpha1 = 1.0; + + if(argc==1) + endrun("./HOD.x hod.bat_file > output"); + + read_parameter_file(argv[1]); + + /* If there's no cross-correlation function, + * set the second number density equal to the first + */ + if(!XCORR) + GALAXY_DENSITY2 = GALAXY_DENSITY; + + /* Initialize the non-linear power spectrum. + */ + nonlinear_sigmac(8.0); + sigmac_interp(1.0E13); + sigmac_radius_interp(1.0); + + if(argc>2) + IDUM_MCMC=atoi(argv[2]); + // if(MCMC)m2n_mcmc(); + + /* Get the galaxy bias factor + */ + s1=qromo(func_galaxy_bias,log(HOD.M_low),log(HOD.M_max),midpnt); + GALAXY_BIAS=s1/GALAXY_DENSITY; + if(OUTPUT) + fprintf(stdout,"Galaxy Bias bg= %f\n",GALAXY_BIAS); + + /* Get the galaxy satellite fraction + */ + s1=qromo(func_satellite_density,log(HOD.M_low),log(HOD.M_max),midpnt)/ + GALAXY_DENSITY; + if(OUTPUT) + fprintf(stdout,"fsat %e\n",s1); + + /* Mean halo mass. + */ + if(OUTPUT) + fprintf(stdout,"M_eff %e\n",number_weighted_halo_mass()); + + /* Set up BETA for wp integration. + */ + BETA = pow(OMEGA_M,0.6)/GALAXY_BIAS; + if(OUTPUT) + printf("BETA = %f\n",BETA); + + /* Check for extra commands: + * arg==999 goes to the test program, superceding tasks. + * arg<0 supercedes the MCMC random number in the batfile. + */ + if(argc>2) + { + if(atoi(argv[2])==999) + test(argc,argv); + } + + tasks(argc,argv); +} + diff --git a/c_tools/hod/mass2number.c b/c_tools/hod/mass2number.c new file mode 100644 index 0000000..0c6608c --- /dev/null +++ b/c_tools/hod/mass2number.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include + +#ifdef PARALLEL +#include +#endif + +#include "header.h" + +int g31_number; + +double poisson_prob(int n, double nave); + +double func1_m2n(double m); +double func2_m2n(double m); + +void mass2number() +{ + int i,j,k,n; + double s1,s2,mbar; + char fname[1000]; + FILE *fp; + + sprintf(fname,"%s.M2N",Task.root_filename); + fp = fopen(fname,"w"); + + for(i=2;i<=10;++i) + { + g31_number = i; + s1 = qromo(func1_m2n,log(HOD.M_low),log(HOD.M_max),midpnt); + s2 = qromo(func2_m2n,log(HOD.M_low),log(HOD.M_max),midpnt); + mbar = s1/s2; + fprintf(fp,"%d %e %e\n",i,mbar,mbar/i); + } + + for(i=20;i<=150;i+=10) + { + g31_number = i; + s1 = qromo(func1_m2n,log(HOD.M_low),log(HOD.M_max),midpnt); + s2 = qromo(func2_m2n,log(HOD.M_low),log(HOD.M_max),midpnt); + mbar = s1/s2; + fprintf(fp,"%d %e %e\n",i,mbar,mbar/i); + } + fclose(fp); +} + +double func1_m2n(double m) +{ + double ncen,nsat,x; + m = exp(m); + ncen = N_cen(m); + nsat = N_sat(m); + x = poisson_prob(g31_number-1,nsat); + // printf("%e %e %e %e %e\n",m,ncen,nsat,poisson_prob(g31_number-1,nsat)); + if(isnan(x))x = 0; + return ncen*x*m*m*dndM_interp(m); +} +double func2_m2n(double m) +{ + double ncen,nsat,x; + m = exp(m); + ncen = N_cen(m); + nsat = N_sat(m); + x = poisson_prob(g31_number-1,nsat); + if(isnan(x))x = 0; + return ncen*x*m*dndM_interp(m); +} diff --git a/c_tools/hod/mcmc.c b/c_tools/hod/mcmc.c new file mode 100644 index 0000000..26c809f --- /dev/null +++ b/c_tools/hod/mcmc.c @@ -0,0 +1,469 @@ +#include +#include +#include +#include + +#ifdef PARALLEL +#include +#endif + +#include "header.h" + +/* External functions from wp_minimization.c + */ +void wp_input(void); +double mcmc_initialize(double *a, double **cov1, double *avg1, double *start_dev); + +/* Internal functions. + */ +double chi2_wp_wrapper(double *a); + +int USE_IWEIGHT = 0; + + +/****************************************************************** + * + * HOD.free[] also controls which variables will be held constant/vary + * during MCMC minimization. Since this routine will also so z-space + * minimization if requested, indices>6 are cosmological. + * + * i variable + * --- -------- + * [1] -> M_min + * [2] -> M1 + * [3] -> alpha + * [4] -> M_cut + * [5] -> sigmaM + * [6] -> CVIR_FAC + * [7] -> MaxCen (or M_cen_max) + * [8] -> M_sat_break + * [9] -> alpha1 + * + * [10]-> OMEGA_M + * [11]-> SIGMA_8 + * [12]-> VBIAS + * [13]-> VBIAS_C + * [14]-> GAMMA + * [15]-> SPECTRAL_INDX + * + * [0] -> The galaxy_density will be considered data with errors on it, + * and therefore no variable will be fixed by the galaxy density. + * + */ +void mcmc_minimization() +{ + double stepfac=1; + double error=1,tolerance=0,**cov1,**tmp,*a,*avg1,chi2,chi2prev, + **evect,*eval,*aprev,*atemp,**tmp1,*opar,x1,fsat,**chain,*start_dev,*eval_prev; + int n,i,j,k,nrot,niter=0,count=0,imax_chain=100000,NSTEP=50,NSTEP_MAX=10000,convergence=0; + long IDUM=-555; + + int *pcheck,pcnt,ptot=20,firstflag=1,*iweight,total_weight,icvir; + double t0,tprev,temp,chi2a,chi2b; + + FILE *fpmcmc; + char fname[1000]; + + sprintf(fname,"%s.MCMC",Task.root_filename); + fpmcmc = fopen(fname,"w"); + + opar=dvector(1,100); + + MCMC=Task.MCMC; + + pcheck=calloc(ptot,sizeof(int)); + + wp_input(); + + Work.imodel=2; + Work.chi2=1; + + OUTPUT=0; + + srand48(32498793); + + /* Find the number of free parameters in the minimization + * for the real-space correlation function. + */ + for(n=0,i=1;i<100;++i) + { + n+=HOD.free[i]; + if(OUTPUT) + printf("mcmc_min> free[%i] = %d\n",i,HOD.free[i]); + } + wp.ncf=n; + + /* Find out which free parameter is for CVIR_FAC + */ + j=0; + if(HOD.free[6]) + for(i=0;i<6;++i) + if(HOD.free[i])j++; + icvir=j+1; + + + + if(HOD.free[0]) + { + wp.ngal = GALAXY_DENSITY; + wp.ngal_err = 0.1*wp.ngal; + FIX_PARAM = 0; + } + + if(OUTPUT) + printf("mcmc_min> %d free parameters\n",n); + + a=dvector(1,n); + start_dev=dvector(1,n); + aprev=dvector(1,n); + atemp=dvector(1,n); + cov1=dmatrix(1,n,1,n); + avg1=dvector(1,n); + + tmp=dmatrix(1,n,1,n); + tmp1=dmatrix(1,n,1,1); + evect=dmatrix(1,n,1,n); + eval=dvector(1,n); + eval_prev=dvector(1,n); + + chain=dmatrix(1,imax_chain,1,n); + iweight = ivector(1,imax_chain); + for(i=1;i<=imax_chain;++i) + iweight[i] = 0; + + IDUM=IDUM_MCMC; + + + chi2prev=mcmc_initialize(a,cov1,avg1,start_dev); + niter++; + for(i=1;i<=n;++i) + { + aprev[i] = a[i]; + chain[1][i] = a[i]; + } + + pcnt=0; + pcheck[pcnt]=1; + + stepfac=1; + while(niter1) + { + RESET_COSMOLOGY++; + j=0; + for(i=1;i<=N_HOD_PARAMS;++i)if(HOD.free[i])j++; + i=N_HOD_PARAMS; + if(HOD.free[++i])OMEGA_M = a[++j]; + if(HOD.free[++i])SIGMA_8 = a[++j]; + if(HOD.free[++i])VBIAS = a[++j]; + if(HOD.free[++i])VBIAS_C = a[++j]; + if(HOD.free[++i])GAMMA = a[++j]; + if(HOD.free[++i])SPECTRAL_INDX = a[++j]; + } + if(VBIAS_C<0)continue; + + /* Hard-wire CVIR variation + */ + if(HOD.free[6]) + CVIR_FAC = a[icvir]; + + chi2=chi2_wp_wrapper(a); + + pcheck[pcnt]=1; + if(!(chi21) + { + RESET_COSMOLOGY++; + j=0; + for(i=1;i<=N_HOD_PARAMS;++i)if(HOD.free[i])j++; + i=N_HOD_PARAMS; + if(HOD.free[++i])OMEGA_M = a[++j]; + if(HOD.free[++i])SIGMA_8 = a[++j]; + if(HOD.free[++i])VBIAS = a[++j]; + if(HOD.free[++i])VBIAS_C = a[++j]; + if(HOD.free[++i])GAMMA = a[++j]; + if(HOD.free[++i])SPECTRAL_INDX = a[++j]; + /* if(HOD.free[++i])SIGV = a[++j]; */ + } + if(VBIAS_C<0)continue; + + /* Hard-wire CVIR variation + */ + if(HOD.free[6]) + CVIR_FAC = a[icvir]; + + + chi2=chi2_wp_wrapper(a); + + tprev = t0; + t0 = second(); + ++count; + + pcheck[pcnt]=0; + if(!(chi2NSTEP_MAX) + { + convergence = 1; + for(i=1;i<=n;++i) + { + x1=fabs(eval[i]-eval_prev[i])/eval_prev[i]; + if(x1>0.01)convergence = 0; + printf("CONVERGENCE CHECK %d %d %e %e %e\n",niter/NSTEP_MAX,i,x1,eval[i],eval_prev[i]); + } + for(i=1;i<=n;++i) + eval_prev[i] = eval[i]; + convergence = 0; + + if(convergence) + printf("CONVERGENCE ACCOMPLISHED %d %d \n",niter,count); + } + if(niter==NSTEP_MAX) + { + for(i=1;i<=n;++i) + eval_prev[i] = eval[i]; + } + + + for(i=1;i<=n;++i) + chain[niter][i]=a[i]; + for(i=1;i<=n;++i) + avg1[i] += a[i]; + for(i=1;i<=n;++i) + aprev[i] = a[i]; + for(i=1;i<=n;++i) + for(j=1;j<=n;++j) + cov1[i][j] += a[i]*a[j]; + chi2prev=chi2; + + if(!ThisTask) { + fprintf(fpmcmc,"%d %d ",niter,count); + for(i=1;i<=n;++i) + printf("%e ",a[i]); + printf("%e\n",chi2);fflush(fpmcmc); + } + + + } +} + +double chi2_wp_wrapper(double *a) +{ + static int flag=1; + static double *b; + int i,j; + + if(flag) + { + b=dvector(1,100); + flag=0; + } + + for(j=0,i=1;i<=N_HOD_PARAMS;++i) { + if(HOD.free[i] && i!=5) { + if(a[++j]<=0) { printf("NEG %d %d %e\n",i,j,a[j]); return(1.0E7); } } + if(HOD.free[i] && i==5) { + ++j; } + } + + i=0;j=0; + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M_min */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M1 */ + if(HOD.free[++i]){j++;b[j]=a[j];} /* alpha */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M_cut */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* sigma_logM */ + if(HOD.free[++i]){j++;b[j]=a[j];} /* cvir_fac */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* MaxCen */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M_sat_break */ + if(HOD.free[++i]){j++;b[j]=a[j];} /* alpha1 */ + + return(chi2_wp(b)); +} + +double mcmc_initialize(double *a, double **cov1, double *avg1, double *start_dev) +{ + int i,j=0; + double x1,x2,omega_m; + long IDUM = -556; + + omega_m = 1; + if(MCMC>1) + omega_m = OMEGA_M; + + i=0;j=0; + if(HOD.free[++i]){ a[++j]=log10(HOD.M_min/omega_m);start_dev[j]=0.001; } + if(HOD.free[++i]){ a[++j]=log10(HOD.M1/omega_m);start_dev[j]=0.001; } //.0005 + if(HOD.free[++i]){ a[++j]=HOD.alpha;start_dev[j]=0.03; } //.005 + if(HOD.free[++i]){ a[++j]=log10(HOD.M_cut/omega_m);start_dev[j]=0.01; } //.001 + if(HOD.free[++i]){ a[++j]=log10(HOD.sigma_logM);start_dev[j]=0.01; } + if(HOD.free[++i]){ a[++j]=CVIR_FAC;start_dev[j]=0.02; } + if(HOD.pdfc==7) { + if(HOD.free[++i])a[++j]=log10(HOD.M_cen_max/omega_m); start_dev[j]=0.001; } + else { + if(HOD.free[++i])a[++j]=HOD.MaxCen; start_dev[j]=0.02; } + if(HOD.free[++i]){ a[++j]=log10(HOD.M_sat_break/omega_m);start_dev[j]=0.001; } + if(HOD.free[++i]){ a[++j]=HOD.alpha1;start_dev[j]=0.02; } + + if(MCMC>1) + { + if(HOD.free[++i])a[++j]=OMEGA_M; + if(HOD.free[++i])a[++j]=SIGMA_8; + if(HOD.free[++i])a[++j]=VBIAS; + if(HOD.free[++i])a[++j]=VBIAS_C; + if(HOD.free[++i])a[++j]=GAMMA; + if(HOD.free[++i])a[++j]=SPECTRAL_INDX; + } + if(!ThisTask) + { + printf("INITIAL VALUES: "); + for(i=1;i<=wp.ncf;++i)printf("%e ",a[i]); + printf("\n"); + } + + for(i=1;i<=wp.ncf;++i) + { + avg1[i]=a[i]; + for(j=1;j<=wp.ncf;++j) + cov1[i][j]=a[i]*a[j]; + } + + if(MCMC>1) + { + RESET_COSMOLOGY++; + j=0; + for(i=1;i<=N_HOD_PARAMS;++i)if(HOD.free[i])j++; + i=N_HOD_PARAMS; + if(HOD.free[++i]){ OMEGA_M = a[++j]; start_dev[j] = 0.01; } + if(HOD.free[++i]){ SIGMA_8 = a[++j]; start_dev[j] = 0.01; } + if(HOD.free[++i]){ VBIAS = a[++j]; start_dev[j] = 0.01; } + if(HOD.free[++i]){ VBIAS_C = a[++j]; start_dev[j] = 0.02; } + if(HOD.free[++i]){ GAMMA = a[++j]; start_dev[j] = 0.015; } + if(HOD.free[++i]){ SPECTRAL_INDX = a[++j]; start_dev[j] = 0.02; } + } + + x1=chi2_wp_wrapper(a); + + x2=0; + + if(!ThisTask) { + printf("TRY 0 "); + for(i=1;i<=wp.ncf;++i) + printf("%.4e ",a[i]); + printf("%e\n",x1+x2);fflush(stdout); + printf("INITIAL CHI2: %e %e\n",x1,x2); + fflush(stdout); + } + return(x1+x2); +} + diff --git a/c_tools/hod/mcmc_color.c b/c_tools/hod/mcmc_color.c new file mode 100644 index 0000000..4a415a2 --- /dev/null +++ b/c_tools/hod/mcmc_color.c @@ -0,0 +1,539 @@ +#include +#include +#include +#include + +#ifdef PARALLEL +#include +#endif + +#include "header.h" + + +/* External functions from wp_minimization.c + */ +void wp_input(void); +void wp_color_input(void); +double chi2_wp_color(double *a); +double chi2_wp_color_wrapper(double *a); + +/* inteernal functions + */ +double mcmc_color_initialize(double *a, double **cov1, double *avg1, double *start_dev); + + +void mcmc_color_minimization() +{ + double stepfac=1; + double error=1,tolerance=0,**cov1,**tmp,*a,*avg1,chi2,chi2prev, + **evect,*eval,*aprev,*atemp,**tmp1,*opar,x1,fsat,**chain,*start_dev,*eval_prev; + int n,i,j,k,nrot,niter=0,count=0,imax_chain=100000,NSTEP=50,NSTEP_MAX=10000,convergence=0; + long IDUM=-555; + + int *pcheck,pcnt,ptot=20,firstflag=1,*iweight,total_weight; + double t0,tprev,temp,chi2a,chi2b; + + opar=dvector(1,100); + + MCMC=Task.MCMC; + + pcheck=calloc(ptot,sizeof(int)); + + Work.imodel=2; + Work.chi2=1; + + + OUTPUT=1; + + + fprintf(stderr,"\n\nMCMC OF W_P(R_P) COLOR DATA..........\n"); + fprintf(stderr, "--------------------------------------------\n\n"); + + HOD.blue_fraction = 0.5857; /* <- Millenium fraction (sloan);; SDSS fraction -> 0.565; */ + HOD.blue_fraction = 0.6555; /* <- Millenium fraction (B-V>0.8) */ + HOD.blue_fraction = 0.565; /* SDSS -19,-20 */ + HOD.blue_fraction = 0.492; /* SDSS -20,-21 */ + HOD.blue_fraction = 0.379; /* SDSS -21 */ + + wp_color.ON = 1; + + wp_color_input(); + + + srand48(32498793); + + /* Find the number of free parameters in the minimization + * for the real-space correlation function. + */ + for(n=0,i=1;i<12;++i) + { + n+=HOD.free[i]; + /* if(i>N_HOD_PARAMS && HOD.free[i])MCMC=3;*/ + if(OUTPUT) + printf("mcmc_min> free[%i] = %d\n",i,HOD.free[i]); + } + + // add 3 parameters for the color stuff + n+=3; + wp.ncf=n; + + if(HOD.free[0]) + { + wp.ngal = GALAXY_DENSITY; + wp.ngal_err = 0.1*wp.ngal; + FIX_PARAM = 0; + } + + if(OUTPUT) + printf("mcmc_min> %d free parameters\n",n); + + a=dvector(1,n); + start_dev=dvector(1,n); + aprev=dvector(1,n); + atemp=dvector(1,n); + cov1=dmatrix(1,n,1,n); + avg1=dvector(1,n); + + tmp=dmatrix(1,n,1,n); + tmp1=dmatrix(1,n,1,1); + evect=dmatrix(1,n,1,n); + eval=dvector(1,n); + eval_prev=dvector(1,n); + + chain=dmatrix(1,imax_chain,1,n); + iweight = ivector(1,imax_chain); + for(i=1;i<=imax_chain;++i) + iweight[i] = 0; + + IDUM=IDUM_MCMC; + + //chi2prev=mcmc_initialize(a,cov1,avg1,start_dev); + chi2prev=mcmc_color_initialize(a,cov1,avg1,start_dev); + //initial_color_values(a,pp,yy); + + niter++; + for(i=1;i<=n;++i) + { + aprev[i] = a[i]; + chain[1][i] = a[i]; + } + + pcnt=0; + pcheck[pcnt]=1; + + stepfac=1; + while(niter1) + { + RESET_COSMOLOGY++; + j=0; + for(i=1;i<=N_HOD_PARAMS;++i)if(HOD.free[i])j++; + i=N_HOD_PARAMS; + if(HOD.free[++i])OMEGA_M = a[++j]; + if(HOD.free[++i])SIGMA_8 = a[++j]; + if(HOD.free[++i])VBIAS = a[++j]; + if(HOD.free[++i])VBIAS_C = a[++j]; + if(HOD.free[++i])GAMMA = a[++j]; + if(HOD.free[++i])SPECTRAL_INDX = a[++j]; + /* if(HOD.free[++i])SIGV = a[++j]; */ + } + if(VBIAS_C<0)continue; + + /* Hard-wire CVIR variation + */ + if(HOD.free[6]) + CVIR_FAC = a[3]; + + chi2=chi2_wp_color_wrapper(a); + + if(!ThisTask){ + printf("TRY %d ",++count); + for(i=1;i<=n;++i) + printf("%.4e ",a[i]); + printf("%e\n",chi2);fflush(stdout); + } + + pcheck[pcnt]=1; + if(!(chi2NSTEP_MAX && niter%NSTEP_MAX!=0)goto SKIP_MATRIX; + + for(j=1;j<=n;++j) + { + avg1[j]=0; + for(k=1;k<=n;++k) + cov1[j][k]=0; + } + total_weight = 0; + for(i=1;i<=niter;++i) + { + for(j=1;j<=n;++j) + { + avg1[j]+=chain[i][j]*iweight[i]; + for(k=1;k<=n;++k) + cov1[j][k]+=chain[i][j]*chain[i][k]*iweight[i]; + } + total_weight+=iweight[i]; + } + + for(i=1;i<=n;++i) + for(j=1;j<=n;++j) + tmp[i][j] = cov1[i][j]/total_weight - avg1[i]*avg1[j]/(total_weight*total_weight); + + jacobi(tmp,n,eval,evect,&nrot); + gaussj(evect,n,tmp1,1); + + SKIP_MATRIX: + if(RESTART==4)convergence = 1; + + if(RESTART && count==0)stepfac=0; + for(i=1;i<=n;++i) + atemp[i] = gasdev(&IDUM)*sqrt(eval[i])*stepfac; + + for(i=1;i<=n;++i) + for(a[i]=0,j=1;j<=n;++j) + a[i] += atemp[j]*evect[j][i]; + + for(i=1;i<=n;++i) + a[i] += aprev[i]; + + /* We seem to be having a problem with this. + * So, broadcast the model params from the root processor. + */ +#ifdef PARALLEL + MPI_Bcast(&a[1],n,MPI_DOUBLE_PRECISION,0,MPI_COMM_WORLD); +#endif + + // CHeck that the chi2 for the last point in the restart chain + // is recovered. + /* + if(RESTART && !count) + for(i=1;i<=n;++i) + a[i] = aprev[i]; + */ + if(RESTART==5) + { + j = count+1; + if(j>4000)exit(0); + for(i=1;i<=n;++i) + a[i] = chain[j][i]; + } + + /* + if(!ThisTask) + for(i=1;i<=n;++i) + { + printf("COV %d %d %e ",count,i,sqrt(eval[i])); + for(j=1;j<=n;++j) + printf("%e ",evect[j][i]); + printf("\n"); + } + */ + + /* Using only variances + */ + //for(i=1;i<=n;++i) + // a[i] = aprev[i] + gasdev(&IDUM)*sqrt(tmp[i][i])*stepfac; + + if(MCMC>1) + { + RESET_COSMOLOGY++; + j=0; + for(i=1;i<=N_HOD_PARAMS;++i)if(HOD.free[i])j++; + i=N_HOD_PARAMS; + if(HOD.free[++i])OMEGA_M = a[++j]; + if(HOD.free[++i])SIGMA_8 = a[++j]; + if(HOD.free[++i])VBIAS = a[++j]; + if(HOD.free[++i])VBIAS_C = a[++j]; + if(HOD.free[++i])GAMMA = a[++j]; + if(HOD.free[++i])SPECTRAL_INDX = a[++j]; + /* if(HOD.free[++i])SIGV = a[++j]; */ + } + if(VBIAS_C<0)continue; + + /* Hard-wire CVIR variation + */ + if(HOD.free[6]) + CVIR_FAC = a[3]; + + chi2=chi2_wp_color_wrapper(a); + + tprev = t0; + t0 = second(); + ++count; + if(!ThisTask) { + printf("TRY %d ",count); + for(i=1;i<=n;++i) + printf("%.4e ",a[i]); + if(RESTART==2) { + printf("%e %e %.2f\n",chi2,chi2/(1+exp(-count/100.0)), + timediff(tprev,t0));fflush(stdout); } + else { + printf("%e %.2f\n",chi2, + timediff(tprev,t0));fflush(stdout); } + } + if(0) { + printf("CPU%02d %d ",ThisTask,count); + for(i=1;i<=n;++i) + printf("%.4e ",a[i]); + if(RESTART==2) { + printf("%e %e %.2f\n",chi2,chi2/(1+exp(-count/100.0)), + timediff(tprev,t0));fflush(stdout); } + else { + printf("%e %.2f\n",chi2, + timediff(tprev,t0));fflush(stdout); } + } + + pcheck[pcnt]=0; + if(!(chi2NSTEP_MAX) + { + convergence = 1; + for(i=1;i<=n;++i) + { + x1=fabs(eval[i]-eval_prev[i])/eval_prev[i]; + if(x1>0.01)convergence = 0; + printf("CONVERGENCE CHECK %d %d %e %e %e\n",niter/NSTEP_MAX,i,x1,eval[i],eval_prev[i]); + } + for(i=1;i<=n;++i) + eval_prev[i] = eval[i]; + convergence = 0; + + if(convergence) + printf("CONVERGENCE ACCOMPLISHED %d %d \n",niter,count); + } + if(niter==NSTEP_MAX) + { + for(i=1;i<=n;++i) + eval_prev[i] = eval[i]; + } + + + for(i=1;i<=n;++i) + chain[niter][i]=a[i]; + for(i=1;i<=n;++i) + avg1[i] += a[i]; + for(i=1;i<=n;++i) + aprev[i] = a[i]; + for(i=1;i<=n;++i) + for(j=1;j<=n;++j) + cov1[i][j] += a[i]*a[j]; + chi2prev=chi2; + + if(!ThisTask) { + printf("ACCEPT %d %d ",niter,count); + for(i=1;i<=n;++i) + printf("%e ",a[i]); + printf("%e\n",chi2);fflush(stdout); + + printf("FSAT %d %e %e %e %e\n",niter,HOD.M_min,wp.fsat_red,wp.fsat_blue,wp.fsat_all); + if(MCMC==1) + { + printf("HSTATS %d %e %e %e %e\n",niter,HOD.M_min,number_weighted_halo_mass(), + number_weighted_central_mass(), + qromo(func_satellite_density,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY); + + fsat = qromo(func_satfrac,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY; + } + } + + } +} + +double chi2_wp_color_wrapper(double *a) +{ + static int flag=1; + static double *b; + int i,j; + + if(flag) + { + b=dvector(1,100); + flag=0; + } + + for(j=0,i=1;i<=N_HOD_PARAMS;++i) { + if(HOD.free[i] && i!=5) { + if(a[++j]<=0) { printf("NEG %d %d %e\n",i,j,a[j]); return(1.0E7); } } + if(HOD.free[i] && i==5) { + ++j; } + } + + i=0;j=0; + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M_min */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M1 */ + if(HOD.free[++i]){j++;b[j]=a[j];} /* alpha */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M_cut */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* sigma_logM */ + if(HOD.free[++i]){j++;b[j]=a[j];} /* cvir_fac */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* MaxCen */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M_sat_break */ + if(HOD.free[++i]){j++;b[j]=a[j];} /* alpha1 */ + + // now the 3 color params + ++j; + b[j] = a[j]; + ++j; + b[j] = a[j]; + ++j; + b[j] = a[j]; + + muh(1); + + return(chi2_wp_color(b)); +} + +double mcmc_color_initialize(double *a, double **cov1, double *avg1, double *start_dev) +{ + int i,j=0; + double x1,x2,omega_m; + long IDUM = -556; + + i=0;j=0; + if(HOD.free[++i]){ a[++j]=log10(HOD.M_min); start_dev[j]=0.001; } + if(HOD.free[++i]){ a[++j]=log10(HOD.M1); start_dev[j] = 0.001; } + if(HOD.free[++i]){ a[++j]=HOD.alpha; start_dev[j] = 0.03; } + if(HOD.free[++i]){ a[++j]=log10(HOD.M_cut); start_dev[j] = 0.01; } + if(HOD.free[++i]){ a[++j]=log10(HOD.sigma_logM); start_dev[j] = 0.01; } + if(HOD.free[++i]){ a[++j]=CVIR_FAC; start_dev[j] = 0.02; } + if(HOD.pdfc>=7){ + if(HOD.free[++i]){ a[++j]=log10(HOD.M_cen_max); start_dev[j] = 0.001; }} + else { + if(HOD.free[++i]) { a[++j]=log10(HOD.MaxCen); start_dev[j] = 0.001; }} + + a[++j] = HOD.fblue0_sat; + start_dev[j] = 0.01; + a[++j] = HOD.sigma_fblue_sat; + start_dev[j] = 0.01; + a[++j] = HOD.sigma_fblue_cen; + start_dev[j] = 0.01; + + if(!ThisTask) + { + printf("INITIAL VALUES: "); + for(i=1;i<=wp.ncf;++i)printf("%e ",a[i]); + printf("\n"); + } + + + for(i=1;i<=wp.ncf;++i) + { + avg1[i]=a[i]; + for(j=1;j<=wp.ncf;++j) + cov1[i][j]=a[i]*a[j]; + } + + + x1=chi2_wp_color_wrapper(a); + x2 = 0; + + if(!ThisTask) { + printf("TRY 0 "); + for(i=1;i<=wp.ncf;++i) + printf("%.4e ",a[i]); + printf("%e\n",x1+x2);fflush(stdout); + printf("INITIAL CHI2: %e %e\n",x1,x2); + fflush(stdout); + } + return(x1+x2); +} + diff --git a/c_tools/hod/mcmc_exp.c b/c_tools/hod/mcmc_exp.c new file mode 100644 index 0000000..648e17f --- /dev/null +++ b/c_tools/hod/mcmc_exp.c @@ -0,0 +1,632 @@ +#include +#include +#include +#include + +#ifdef PARALLEL +#include +#endif + +#include "header.h" + +/* External functions from wp_minimization.c + */ +void wp_input(void); +double mcmc_initialize(double *a, double **cov1, double *avg1, double *start_dev); + +/* Internal functions. + */ +double chi2_wp_wrapper(double *a); +void mcmc_restart2(double *start_dev, int np); +int mcmc_restart3(double **chain, int n, double *chi2_prev, int *iweight); + +int USE_IWEIGHT = 0; + +/****************************************************************** + * + * HOD.free[] also controls which variables will be held constant/vary + * during MCMC minimization. Since this routine will also so z-space + * minimization if requested, indices>6 are cosmological. + * + * i variable + * --- -------- + * [1] -> M_min + * [2] -> M1 + * [3] -> alpha + * [4] -> M_cut + * [5] -> sigmaM + * [6] -> CVIR_FAC + * [7] -> MaxCen (or M_cen_max) + * [8] -> M_sat_break + * [9] -> alpha1 + * + * [10]-> OMEGA_M + * [11]-> SIGMA_8 + * [12]-> VBIAS + * [13]-> VBIAS_C + * [14]-> GAMMA + * [15]-> SPECTRAL_INDX + * + * [0] -> The galaxy_density will be considered data with errors on it, + * and therefore no variable will be fixed by the galaxy density. + * + */ +void mcmc_minimization() +{ + double stepfac=1; + double error=1,tolerance=0,**cov1,**tmp,*a,*avg1,chi2,chi2prev, + **evect,*eval,*aprev,*atemp,**tmp1,*opar,x1,fsat,**chain,*start_dev,*eval_prev; + int n,i,j,k,nrot,niter=0,count=0,imax_chain=100000,NSTEP=150,NSTEP_MAX=1000,convergence=0; + long IDUM=-555; + + int *pcheck,pcnt,ptot=20,firstflag=1,*iweight,total_weight; + double t0,tprev,temp; + + opar=dvector(1,100); + + MCMC=Task.MCMC; + + pcheck=calloc(ptot,sizeof(int)); + + if(MCMC>1 && !COVAR) + wp.esys=0.05; + + if(!ThisTask)printf("ESYS %f %d\n",wp.esys,MCMC); + wp_input(); + + Work.imodel=2; + Work.chi2=1; + + /* + OUTPUT=0; + */ + + srand48(32498793); + + /* Find the number of free parameters in the minimization + * for the real-space correlation function. + */ + for(n=0,i=1;i<100;++i) + { + n+=HOD.free[i]; + /* if(i>N_HOD_PARAMS && HOD.free[i])MCMC=3;*/ + if(OUTPUT) + printf("mcmc_min> free[%i] = %d\n",i,HOD.free[i]); + } + wp.ncf=n; + + if(HOD.free[0]) + { + wp.ngal = GALAXY_DENSITY; + wp.ngal_err = 0.1*wp.ngal; + FIX_PARAM = 0; + } + + if(OUTPUT) + printf("mcmc_min> %d free parameters\n",n); + + a=dvector(1,n); + start_dev=dvector(1,n); + aprev=dvector(1,n); + atemp=dvector(1,n); + cov1=dmatrix(1,n,1,n); + avg1=dvector(1,n); + + tmp=dmatrix(1,n,1,n); + tmp1=dmatrix(1,n,1,1); + evect=dmatrix(1,n,1,n); + eval=dvector(1,n); + eval_prev=dvector(1,n); + + chain=dmatrix(1,imax_chain,1,n); + iweight = ivector(1,imax_chain); + for(i=1;i<=imax_chain;++i) + iweight[i] = 0; + + IDUM=IDUM_MCMC; + + if(RESTART) + { + niter = mcmc_restart3(chain,n,&chi2prev,iweight); + if(niter < NSTEP) + { + if(ThisTask==0) + fprintf(stderr,"Not enough points in restart chain: %d<=%d\n",niter,NSTEP); + exit(0); + } + for(i=1;i<=n;++i) + aprev[i] = chain[niter][i]; + goto RESTART_POINT; + } + + chi2prev=mcmc_initialize(a,cov1,avg1,start_dev); + niter++; + for(i=1;i<=n;++i) + { + aprev[i] = a[i]; + chain[1][i] = a[i]; + } + + pcnt=0; + pcheck[pcnt]=1; + + if(RESTART==2) + { + mcmc_restart2(start_dev,n); + } + + stepfac=1; + while(niter1) + { + RESET_COSMOLOGY++; + j=0; + for(i=1;i<=N_HOD_PARAMS;++i)if(HOD.free[i])j++; + i=N_HOD_PARAMS; + if(HOD.free[++i])OMEGA_M = a[++j]; + if(HOD.free[++i])SIGMA_8 = a[++j]; + if(HOD.free[++i])VBIAS = a[++j]; + if(HOD.free[++i])VBIAS_C = a[++j]; + if(HOD.free[++i])GAMMA = a[++j]; + if(HOD.free[++i])SPECTRAL_INDX = a[++j]; + /* if(HOD.free[++i])SIGV = a[++j]; */ + } + if(VBIAS_C<0)continue; + + /* Hard-wire CVIR variation + */ + if(HOD.free[6]) + CVIR_FAC = a[3]; + + /* Draw random value of cvir from prior. + */ + /* if(CVIR_FAC<0.3 || CVIR_FAC>1.2)continue; */ + /* CVIR_FAC = 0.9*drand48()+0.3; */ + /* GAMMA = gasdev(&IDUM)*0.02 + 0.15; */ + + chi2=chi2_wp_wrapper(a); + + if(MCMC>2 && chi2<1.0E7)chi2+=chi2_zspace(a); + + if(!ThisTask){ + printf("TRY %d ",++count); + for(i=1;i<=n;++i) + printf("%.4e ",a[i]); + printf("%e\n",chi2);fflush(stdout); + } + + pcheck[pcnt]=1; + if(!(chi2NSTEP_MAX && niter%NSTEP_MAX!=0)goto SKIP_MATRIX; + + for(j=1;j<=n;++j) + { + avg1[j]=0; + for(k=1;k<=n;++k) + cov1[j][k]=0; + } + total_weight = 0; + for(i=1;i<=niter;++i) + { + for(j=1;j<=n;++j) + { + avg1[j]+=chain[i][j]*iweight[i]; + for(k=1;k<=n;++k) + cov1[j][k]+=chain[i][j]*chain[i][k]*iweight[i]; + } + total_weight+=iweight[i]; + } + + for(i=1;i<=n;++i) + for(j=1;j<=n;++j) + tmp[i][j] = cov1[i][j]/total_weight - avg1[i]*avg1[j]/(total_weight*total_weight); + + jacobi(tmp,n,eval,evect,&nrot); + gaussj(evect,n,tmp1,1); + + SKIP_MATRIX: + if(RESTART==4)convergence = 1; + + for(i=1;i<=n;++i) + atemp[i] = gasdev(&IDUM)*sqrt(eval[i])*stepfac; + + for(i=1;i<=n;++i) + for(a[i]=0,j=1;j<=n;++j) + a[i] += atemp[j]*evect[j][i]; + + for(i=1;i<=n;++i) + a[i] += aprev[i]; + + if(!ThisTask) + for(i=1;i<=n;++i) + { + printf("COV %d %d %e ",count,i,sqrt(eval[i])); + for(j=1;j<=n;++j) + printf("%e ",evect[j][i]); + printf("\n"); + } + + /* Using only variances + */ + //for(i=1;i<=n;++i) + // a[i] = aprev[i] + gasdev(&IDUM)*sqrt(tmp[i][i])*stepfac; + + if(MCMC>1) + { + RESET_COSMOLOGY++; + j=0; + for(i=1;i<=N_HOD_PARAMS;++i)if(HOD.free[i])j++; + i=N_HOD_PARAMS; + if(HOD.free[++i])OMEGA_M = a[++j]; + if(HOD.free[++i])SIGMA_8 = a[++j]; + if(HOD.free[++i])VBIAS = a[++j]; + if(HOD.free[++i])VBIAS_C = a[++j]; + if(HOD.free[++i])GAMMA = a[++j]; + if(HOD.free[++i])SPECTRAL_INDX = a[++j]; + /* if(HOD.free[++i])SIGV = a[++j]; */ + } + if(VBIAS_C<0)continue; + + /* Hard-wire CVIR variation + */ + if(HOD.free[6]) + CVIR_FAC = a[3]; + + /* Draw random value of cvir from prior. + */ + /* CVIR_FAC = a[n]; */ + /* if(CVIR_FAC<0.3 || CVIR_FAC>1.2)continue; */ + /* CVIR_FAC = 0.7*drand48()+0.3; */ + /* GAMMA = gasdev(&IDUM)*0.02 + 0.15; */ + // printf("GAMMA %d %f %f\n",count+1,GAMMA,CVIR_FAC); + + chi2=chi2_wp_wrapper(a); + if(MCMC>2 && chi2<1.0E7)chi2+=chi2_zspace(a); + + tprev = t0; + t0 = second(); + if(!ThisTask) { + printf("TRY %d ",++count); + for(i=1;i<=n;++i) + printf("%.4e ",a[i]); + printf("%e %.2f\n",chi2,timediff(tprev,t0));fflush(stdout); + } + + pcheck[pcnt]=0; + if(!(chi2NSTEP_MAX) + { + convergence = 1; + for(i=1;i<=n;++i) + { + x1=fabs(eval[i]-eval_prev[i])/eval_prev[i]; + if(x1>0.01)convergence = 0; + printf("CONVERGENCE CHECK %d %d %e %e %e\n",niter/NSTEP_MAX,i,x1,eval[i],eval_prev[i]); + } + for(i=1;i<=n;++i) + eval_prev[i] = eval[i]; + convergence = 0; + + if(convergence) + printf("CONVERGENCE ACCOMPLISHED %d %d \n",niter,count); + } + if(niter==NSTEP_MAX) + { + for(i=1;i<=n;++i) + eval_prev[i] = eval[i]; + } + + + for(i=1;i<=n;++i) + chain[niter][i]=a[i]; + for(i=1;i<=n;++i) + avg1[i] += a[i]; + for(i=1;i<=n;++i) + aprev[i] = a[i]; + for(i=1;i<=n;++i) + for(j=1;j<=n;++j) + cov1[i][j] += a[i]*a[j]; + chi2prev=chi2; + + if(!ThisTask) { + printf("ACCEPT %d %d ",niter,count); + for(i=1;i<=n;++i) + printf("%e ",a[i]); + printf("%e\n",chi2);fflush(stdout); + + printf("HSTATS %d %e %e %e %e\n",niter,HOD.M_min,number_weighted_halo_mass(), + number_weighted_central_mass(), + qromo(func_satellite_density,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY); + + fsat = qromo(func_satfrac,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY; + printf("FSAT %d %e %e %e %e\n",niter,fsat,HOD.M_min,HOD.sigma_logM,CVIR_FAC); + } + + } +} + +double chi2_wp_wrapper(double *a) +{ + static int flag=1; + static double *b; + int i,j; + + if(flag) + { + b=dvector(1,100); + flag=0; + } + + for(j=0,i=1;i<=N_HOD_PARAMS;++i) { + if(HOD.free[i] && i!=5) { + if(a[++j]<=0) { printf("NEG %d %d %e\n",i,j,a[j]); return(1.0E7); } } + if(HOD.free[i] && i==5) { + ++j; } + } + + i=0;j=0; + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M_min */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M1 */ + if(HOD.free[++i]){j++;b[j]=a[j];} /* alpha */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M_cut */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* sigma_logM */ + if(HOD.free[++i]){j++;b[j]=a[j];} /* cvir_fac */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* MaxCen */ + if(HOD.free[++i]){j++;b[j]=pow(10.0,a[j]);} /* M_sat_break */ + if(HOD.free[++i]){j++;b[j]=a[j];} /* alpha1 */ + + return(chi2_wp(b)); +} + +double mcmc_initialize(double *a, double **cov1, double *avg1, double *start_dev) +{ + int i,j=0; + double x1,x2; + long IDUM = -556; + + i=0;j=0; + if(HOD.free[++i]){ a[++j]=log10(HOD.M_min);start_dev[j]=0.001; } + if(HOD.free[++i]){ a[++j]=log10(HOD.M1);start_dev[j]=0.001; } //.0005 + if(HOD.free[++i]){ a[++j]=HOD.alpha;start_dev[j]=0.03; } //.005 + if(HOD.free[++i]){ a[++j]=log10(HOD.M_cut);start_dev[j]=0.01; } //.001 + if(HOD.free[++i]){ a[++j]=log10(HOD.sigma_logM);start_dev[j]=0.01; } + if(HOD.free[++i]){ a[++j]=CVIR_FAC;start_dev[j]=0.02; } + if(HOD.pdfc==7) { + if(HOD.free[++i])a[++j]=log10(HOD.M_cen_max); start_dev[j]=0.001; } + else { + if(HOD.free[++i])a[++j]=HOD.MaxCen; start_dev[j]=0.02; } + if(HOD.free[++i]){ a[++j]=log10(HOD.M_sat_break);start_dev[j]=0.001; } + if(HOD.free[++i]){ a[++j]=HOD.alpha1;start_dev[j]=0.02; } + + if(MCMC>1) + { + if(HOD.free[++i])a[++j]=OMEGA_M; + if(HOD.free[++i])a[++j]=SIGMA_8; + if(HOD.free[++i])a[++j]=VBIAS; + if(HOD.free[++i])a[++j]=VBIAS_C; + if(HOD.free[++i])a[++j]=GAMMA; + if(HOD.free[++i])a[++j]=SPECTRAL_INDX; + } + printf("INITIAL VALUES: "); + for(i=1;i<=wp.ncf;++i)printf("%e ",a[i]); + printf("\n"); + + for(i=1;i<=wp.ncf;++i) + { + avg1[i]=a[i]; + for(j=1;j<=wp.ncf;++j) + cov1[i][j]=a[i]*a[j]; + } + + if(MCMC>1) + { + RESET_COSMOLOGY++; + j=0; + for(i=1;i<=N_HOD_PARAMS;++i)if(HOD.free[i])j++; + i=N_HOD_PARAMS; + if(HOD.free[++i]){ OMEGA_M = a[++j]; start_dev[j] = 0.01; } + if(HOD.free[++i]){ SIGMA_8 = a[++j]; start_dev[j] = 0.01; } + if(HOD.free[++i]){ VBIAS = a[++j]; start_dev[j] = 0.01; } + if(HOD.free[++i]){ VBIAS_C = a[++j]; start_dev[j] = 0.02; } + if(HOD.free[++i]){ GAMMA = a[++j]; start_dev[j] = 0.015; } + if(HOD.free[++i]){ SPECTRAL_INDX = a[++j]; start_dev[j] = 0.02; } + } + + x1=chi2_wp_wrapper(a); + + if(MCMC>2) + x2=chi2_zspace(a); + else + x2=0; + + if(!ThisTask) { + printf("TRY 0 "); + for(i=1;i<=wp.ncf;++i) + printf("%.4e ",a[i]); + printf("%e\n",x1+x2);fflush(stdout); + printf("INITIAL CHI2: %e %e\n",x1,x2); + fflush(stdout); + } + return(x1+x2); +} + +/* This is to look at a chain and get the variances in each parameter. + */ +void mcmc_restart2(double *start_dev, int np) +{ + int n,i,j,k,i1,i2; + FILE *fp; + char aa[100]; + float xbar[10],xsqr[10],x; + + fp = openfile(RESTART_FILE); + n = filesize(fp); + + for(i=0;i +#include +#include +#include + +#ifdef PARALLEL +#include +#endif + +#include "header.h" + +/* External functions from wp_minimization.c + */ +void wp_input(void); +double mcmc_initialize(double *a, double **cov1, double *avg1); + + +/* Internal functions. + */ +void choose_bias_fit(void); +double chi2_wp_wrapper(double *); +void choose_dndM_fit(void); + +/****************************************************************** + * + * HOD.free[] also controls which variables will be held constant/vary + * during MCMC minimization. Since this routine will also so z-space + * minimization if requested, indices>6 are cosmological. + * + * i variable + * --- -------- + * [1] -> M_min + * [2] -> M1 + * [3] -> alpha + * [4] -> M_cut + * [5] -> sigmaM + * [6] -> CVIR_FAC + * [7] -> OMEGA_M + * [8] -> SIGMA_8 + * [9] -> VBIAS + * + */ +void mcmc_minimization() +{ + int EJENK=1,EBIAS=0; + double stepfac=1; + double error=1,tolerance=0,**cov1,**tmp,*a,*avg1,chi2,chi2prev, + **evect,*eval,*aprev,*atemp,**tmp1; + int n,i,j,nrot,niter=0,count=0; + long IDUM=-555; + + float original_jenkins_a, + original_jenkins_b, + original_jenkins_c; + + int *pcheck,pcnt,ptot=10; + + original_jenkins_a=JENKINS_A; + original_jenkins_b=JENKINS_B; + original_jenkins_c=JENKINS_C; + + pcheck=calloc(ptot,sizeof(int)); + + if(MCMC>1) + wp.esys=0.08; + + wp_input(); + + Work.imodel=2; + Work.chi2=1; + MCMC=Task.MCMC; + + OUTPUT=0; + + srand48(32498793); + + /* Find the number of free parameters in the minimization + * for the real-space correlation function. + */ + for(n=0,i=1;i<=10;++i) + { + n+=HOD.free[i]; + if(OUTPUT) + printf("mcmc_min> free[%i] = %d\n",i,HOD.free[i]); + } + wp.ncf=n; + + if(OUTPUT) + printf("mcmc_min> %d free parameters\n",n); + + a=dvector(1,n); + aprev=dvector(1,n); + atemp=dvector(1,n); + cov1=dmatrix(1,n,1,n); + avg1=dvector(1,n); + + tmp=dmatrix(1,n,1,n); + tmp1=dmatrix(1,n,1,1); + evect=dmatrix(1,n,1,n); + eval=dvector(1,n); + + chi2prev=mcmc_initialize(a,cov1,avg1); + niter++; + for(i=1;i<=n;++i) + aprev[i] = a[i]; + + IDUM=IDUM_MCMC; + + pcnt=0; + pcheck[pcnt]=1; + + stepfac=1; + while(niter<10) + { + pcnt++; + if(pcnt==ptot) + { + for(j=i=0;i1) + { + RESET_COSMOLOGY++; + j=0; + for(i=1;i<=6;++i)if(HOD.free[i])j++; + i=6; + if(HOD.free[++i])OMEGA_M = a[++j]; + if(HOD.free[++i])SIGMA_8 = a[++j]; + if(HOD.free[++i])VBIAS = a[++j]; + if(HOD.free[++i])VBIAS_C = a[++j]; + } + + /* Take the parameters of the Jenkins + * mass function from Gaussian distributions. + */ + /* + RESET_COSMOLOGY++; + if(EJENK) + choose_dndM_fit(); + if(EBIAS) + choose_bias_fit(); + */ + + chi2=chi2_wp_wrapper(a); + if(MCMC>1)chi2+=chi2_zspace(a); + + printf("TRY %d ",++count); + for(i=1;i<=n;++i) + printf("%.4e ",a[i]); + printf("%e\n",chi2);fflush(stdout); + + pcheck[pcnt]=0; + if(!(chi2tolerance) + { + pcnt++; + if(pcnt==ptot) + { + for(j=i=0;i1) + { + RESET_COSMOLOGY++; + j=0; + for(i=1;i<=6;++i)if(HOD.free[i])j++; + i=6; + if(HOD.free[++i])OMEGA_M = a[++j]; + if(HOD.free[++i])SIGMA_8 = a[++j]; + if(HOD.free[++i])VBIAS = a[++j]; + if(HOD.free[++i])VBIAS_C = a[++j]; + } + + /* Take the parameters of the Jenkins + * mass function from Gaussian distributions. + */ + + RESET_COSMOLOGY++; + if(EJENK) + { + /* + JENKINS_A = original_jenkins_a*(1+gasdev(&IDUM)*sqrt(3.919662e-07)); + JENKINS_B = original_jenkins_b*(1+gasdev(&IDUM)*sqrt(9.265636e-06)); + JENKINS_C = original_jenkins_c*(1+gasdev(&IDUM)*sqrt(2.365370e-03)); + choose_dndM_fit(); + */ + } + if(EBIAS) + choose_bias_fit(); + + chi2=chi2_wp_wrapper(a); + if(MCMC>1)chi2+=chi2_zspace(a); + + printf("TRY %d ",++count); + for(i=1;i<=n;++i) + printf("%.4e ",a[i]); + printf("%e\n",chi2);fflush(stdout); + + pcheck[pcnt]=0; + if(!(chi21) + { + if(HOD.free[++i])a[++j]=OMEGA_M; + if(HOD.free[++i])a[++j]=SIGMA_8; + if(HOD.free[++i])a[++j]=VBIAS; + if(HOD.free[++i])a[++j]=VBIAS_C; + } + printf("INITIAL VALUES: "); + for(i=1;i<=wp.ncf;++i)printf("%e ",a[i]); + printf("\n"); + + for(i=1;i<=wp.ncf;++i) + { + avg1[i]=a[i]; + for(j=1;j<=wp.ncf;++j) + cov1[i][j]=a[i]*a[j]; + } + + if(MCMC>1) + { + RESET_COSMOLOGY++; + j=0; + for(i=1;i<=6;++i)if(HOD.free[i])j++; + i=6; + if(HOD.free[++i])OMEGA_M = a[++j]; + if(HOD.free[++i])SIGMA_8 = a[++j]; + if(HOD.free[++i])VBIAS = a[++j]; + if(HOD.free[++i])VBIAS_C = a[++j]; + } + + x1=chi2_wp_wrapper(a); + + if(MCMC>1) + x2=chi2_zspace(a); + else + x2=0; + + printf("TRY 0 "); + for(i=1;i<=wp.ncf;++i) + printf("%.4e ",a[i]); + printf("%e\n",x1+x2);fflush(stdout); + + printf("INITIAL CHI2: %e %e\n",x1,x2); + fflush(stdout); + return(x1+x2); +} + +void choose_bias_fit() +{ + static long IDUM1=-444; + static int flag=1,n; + static float *a,*b,*c; + + FILE *fp; + int i; + char string[1000]; + + if(flag) + { + flag=0; + fp=openfile("/home/tinker/TABLES/bias_errors.dat"); + n=filesize(fp); + a=vector(1,n); + b=vector(1,n); + c=vector(1,n); + for(i=1;i<=n;++i) + { + fscanf(fp,"%f %f %f",&a[i],&b[i],&c[i]); + fgets(string,1000,fp); + } + } + + i=(int)(ran1(&IDUM1)*n) + 1; + BIAS_A = a[i]; + BIAS_B = b[i]; + BIAS_C = c[i]; + /* + printf("BIAS %f %f %f\n",a[i],b[i],c[i]); + */ +} + +void choose_dndM_fit() +{ + static long IDUM1=-444; + static int flag=1,n; + static float *a,*b,*c,*d,*e; + + FILE *fp; + int i; + char string[1000]; + + if(flag) + { + flag=0; + fp=openfile("/home/tinker/TABLES/dndM_errors.dat"); + n=filesize(fp); + a=vector(1,n); + b=vector(1,n); + c=vector(1,n); + d=vector(1,n); + e=vector(1,n); + for(i=1;i<=n;++i) + { + fscanf(fp,"%f %f %f %f %f",&a[i],&b[i],&c[i],&d[i],&e[i]); + fgets(string,1000,fp); + } + } + + i=(int)(ran1(&IDUM1)*n) + 1; + DNDM_PARAMS[1] = a[i]; + DNDM_PARAMS[2] = b[i]; + DNDM_PARAMS[3] = c[i]; + DNDM_PARAMS[4] = d[i]; + DNDM_PARAMS[5] = e[i]; +} diff --git a/c_tools/hod/meshlink2.c b/c_tools/hod/meshlink2.c new file mode 100644 index 0000000..20118cf --- /dev/null +++ b/c_tools/hod/meshlink2.c @@ -0,0 +1,91 @@ +/* PROGRAM MESHLINK2 + + --- meshlink2(np,nmesh,smin,smax,rmax,x,y,z,meshparts,meshstart) + --- creates a linked list for efficient neighbor searching. + --- tag particles according to their mesh + --- adapted from DHW's linklist.c + --- version2 has all arrays pushed to the end + + * np = number of particles + * x,y,z = arrays of particle coordinates. + * smin,smax = particles are located in a box running from + (smin,smin,smin) to (smax,smax,smax). + * rmax = max. radius of a mesh. All neighbors closer than + rmax. are included in a mesh.- to determine size of mesh + * meshparts = on return, pointer to particle link list. + * meshstart = on return, pointer to array of pointers to the + first particle in each mesh. + * nmesh = on return,dimension of mesh array in each dimension. + + Notes: 09/09/96 + +*/ + +#include +#include +#include + +#define sqr(x) ((x)*(x)) +#define max(A,B) ((A) > (B) ? (A) : (B)) +#define min(A,B) ((A) < (B) ? (A) : (B)) +#define mabs(A) ((A) < 0.0 ? -(A) : (A)) +#define pi 3.1415926535898 +#define ind(a,b,c) (a)*n*n+(b)*n+(c) +#define ALLOC3D(type,dim0,dim1,dim2) \ + (type***)a3alloc((unsigned)dim0,(unsigned)dim1,(unsigned)dim2,(unsigned)sizeof(type)) +#define NLATMAX 600 /* maximum lattice dimension */ + +int ***i3tensor_2(long nrl, long nrh, long ncl, long nch, long ndl, long ndh); + +/* +void meshlink2(np1,nmesh,smin,smax,rmax,x1,y1,z1,meshparts,meshstart,meshfac) +int np1; +float smin,smax,rmax; +float *x1,*y1,*z1; +int **meshparts,****meshstart; +int *nmesh; +int meshfac; +*/ +void meshlink2(int np1,int *nmesh,float smin,float smax,float rmax,float *x1,float *y1,float *z1, + int **meshparts,int ****meshstart,int meshfac) +{ + int nlatt; + int i,j,k; + int ix,iy,iz; + float sinv; + + nlatt=(int)((smax-smin)/rmax); + if (nlatt>NLATMAX) nlatt=NLATMAX ; + + /* + *meshstart=ALLOC3D(int,nlatt,nlatt,nlatt); + */ + fprintf(stderr,"nlatt= %d %f %f %f\n",nlatt,smin,smax,rmax); + *meshstart=(int ***)i3tensor_2(0,nlatt-1,0,nlatt-1,0,nlatt-1); + fprintf(stderr,"done here\n"); + *meshparts=(int *)calloc(np1,sizeof(int)); + fprintf(stderr,"done here\n"); + + for(i=0;i +#define NRANSI +#include "nrutil.h" +#define GOLD 1.618034 +#define GLIMIT 100.0 +#define TINY 1.0e-20 +#define SHFT(a,b,c,d) (a)=(b);(b)=(c);(c)=(d); + +void mnbrak(double *ax, double *bx, double *cx, double *fa, double *fb, double *fc, + double (*func)(double)) +{ + double ulim,u,r,q,fu,dum; + + *fa=(*func)(*ax); + *fb=(*func)(*bx); + if (*fb > *fa) { + SHFT(dum,*ax,*bx,dum) + SHFT(dum,*fb,*fa,dum) + } + *cx=(*bx)+GOLD*(*bx-*ax); + *fc=(*func)(*cx); + while (*fb > *fc) { + r=(*bx-*ax)*(*fb-*fc); + q=(*bx-*cx)*(*fb-*fa); + u=(*bx)-((*bx-*cx)*q-(*bx-*ax)*r)/ + (2.0*SIGN(FMAX(fabs(q-r),TINY),q-r)); + ulim=(*bx)+GLIMIT*(*cx-*bx); + if ((*bx-u)*(u-*cx) > 0.0) { + fu=(*func)(u); + if (fu < *fc) { + *ax=(*bx); + *bx=u; + *fa=(*fb); + *fb=fu; + return; + } else if (fu > *fb) { + *cx=u; + *fc=fu; + return; + } + u=(*cx)+GOLD*(*cx-*bx); + fu=(*func)(u); + } else if ((*cx-u)*(u-ulim) > 0.0) { + fu=(*func)(u); + if (fu < *fc) { + SHFT(*bx,*cx,u,*cx+GOLD*(*cx-*bx)) + SHFT(*fb,*fc,fu,(*func)(u)) + } + } else if ((u-ulim)*(ulim-*cx) >= 0.0) { + u=ulim; + fu=(*func)(u); + } else { + u=(*cx)+GOLD*(*cx-*bx); + fu=(*func)(u); + } + SHFT(*ax,*bx,*cx,u) + SHFT(*fa,*fb,*fc,fu) + } +} +#undef GOLD +#undef GLIMIT +#undef TINY +#undef SHFT +#undef NRANSI diff --git a/c_tools/hod/mstar.c b/c_tools/hod/mstar.c new file mode 100644 index 0000000..5aced0f --- /dev/null +++ b/c_tools/hod/mstar.c @@ -0,0 +1,39 @@ +#include +#include +#include +#include "header.h" + +/* This function calculates M_star (non-linear mass scale) for the given + * cosmological paramters. + */ + +double sigma_Mmdelta_c(double lnM); +double pnorm1; + +double mstar() +{ + double sig,lnMmin,lnMmax,M_star; + + sig=sigmac(8.0); + pnorm1 = SIGMA_8/sig; + + lnMmin=log(1e7); + lnMmax=log(1e18); + M_star=zbrent(sigma_Mmdelta_c,lnMmin,lnMmax,1e-5); + M_star=exp(M_star); + if(!ThisTask) + fprintf(stderr,"M_star = %e h^{-1}M_sol\n",M_star); + return(M_star); +} + +/*** solve for M_* ***/ +double sigma_Mmdelta_c(double lnM) +{ + double sig,M,rm; + + M=exp(lnM); + rm=pow(3.0*M/(4.0*PI*OMEGA_M*RHO_CRIT),1.0/3.0); + sig=pnorm1*sigmac(rm); + + return sig-DELTA_CRIT; +} diff --git a/c_tools/hod/nbody_xi.c b/c_tools/hod/nbody_xi.c new file mode 100644 index 0000000..c4742d8 --- /dev/null +++ b/c_tools/hod/nbody_xi.c @@ -0,0 +1,432 @@ +#include +#include +#include +#include +#include + +#include "header.h" + +#define NBINLOOKUP 10000 + +/* Loocal functions. + */ +void nbody_covar(double *rad, double *xi, int nr); + +/* External functions. + */ +void nbrsfind2(float smin,float smax,float rmax,int nmesh,float xpos,float ypos,float zpos, + int *nbrmax,int *indx,float *rsqr,float *x,float *y,float *z, + int *meshparts,int ***meshstart,int ip); +void meshlink2(int np1,int *nmesh,float smin,float smax,float rmax,float *x1,float *y1,float *z1, + int **meshparts,int ****meshstart,int meshfac); +void free_i3tensor(int ***t, long nrl, long nrh, long ncl, long nch, + long ndl, long ndh); + +double nbody_xi(double r) +{ + static int flag=1,n=30; + static double *x,*y,*y2; + double a; + int i; + + if(flag || RESET_FLAG_1H) + { + if(flag) + { + x=dvector(1,n); + y=dvector(1,n); + y2=dvector(1,n); + } + flag=0; + if(OUTPUT) + printf("Calculating nbody xi(r)...\n"); + nbody_covar(x,y,n); + if(OUTPUT) + printf("finished\n"); + for(i=1;i<=n;++i) + y[i]=log(y[i]); + spline(x,y,n,1.0E+30,1.0E+30,y2); + RESET_FLAG_1H=0; + } + r=log(r); + splint(x,y,y2,n,r,&a); + return(exp(a)); +} + + +void nbody_covar(double *rad, double *xi, int nr) +{ + float rmax,rmin,lrstep,binfac,rcube,weight0,fac,rlow,density,weightrandom,vol,r; + int ibin,kbin,nbin,i,j,k,*binlookup,*npair,ngal,ngal_temp; + + float *rupp,*rsqr,reduction_factor,*vxt,*vyt,*vzt; + int *meshparts, ***meshstart,nmesh,meshfac,nbrmax,*indx; + double *rbar,galden; + + static float *xg,*yg,*zg,*xt,*yt,*zt; + + static int flag = 1; + + rmin=0.1; + rmax=30.0; + nbin=nr; + rcube=BOX_SIZE; + + if(flag) { + galden = GALAXY_DENSITY; + if(HOD.color == 1) galden = wp_color.ngal_blue; + if(HOD.color == 2) galden = wp_color.ngal_red; + ngal = galden*rcube*rcube*rcube*2; + reduction_factor = 1; + if(galden > 0.005)reduction_factor = 0.2; + if(wp_color.ON)reduction_factor = 0.5; + xg = malloc(reduction_factor*ngal*sizeof(float)); + yg = malloc(reduction_factor*ngal*sizeof(float)); + zg = malloc(reduction_factor*ngal*sizeof(float)); + + xt = malloc(ngal*sizeof(float)); + yt = malloc(ngal*sizeof(float)); + zt = malloc(ngal*sizeof(float)); + flag = 1; + } + + printf("Starting population...\n"); + ngal = internal_populate_simulation(xt,yt,zt,1.0,0,vxt,vyt,vzt); + printf("Done. [%d] galaxies [%.0f]\n",ngal,galden*rcube*rcube*rcube); + fflush(stdout); + + ngal_temp=0; + for(i=0;ireduction_factor)continue; + xg[ngal_temp] = xt[i]; + yg[ngal_temp] = yt[i]; + zg[ngal_temp] = zt[i]; + ngal_temp++; + } + ngal = ngal_temp; + + indx=malloc(ngal*sizeof(int)); + rsqr=malloc(ngal*sizeof(float)); + + /*********************** + * initializing the logarithmic bins + */ + rupp = (float *) calloc(nbin+1,sizeof(float)) ; + lrstep=log(rmax/rmin)/(float)(nbin-1) ; + binlookup=(int *)calloc(NBINLOOKUP+2,sizeof(int)) ; + ibin=0 ; + for (i=0;i<=NBINLOOKUP;i++) { + r=rmax*i/NBINLOOKUP ; + if (r>0) { + kbin=(int)floor(log(r/rmin)/lrstep+1.0) ; + } + else { + kbin=0 ; + } + if (kbin<0) kbin=0 ; + if (kbin>ibin) { + rupp[ibin]=r ; + ibin=kbin ; + } + binlookup[i]=kbin ; + } + binlookup[NBINLOOKUP+1]=nbin ; + rupp[nbin-1]=rmax ; + rupp[nbin]=rmax ; + binfac=NBINLOOKUP/rmax ; + + rbar=calloc(nbin,sizeof(double)); + npair=calloc(nbin,sizeof(int)); + + nmesh=0; + meshlink2(ngal,&nmesh,0.0,rcube,rmax,xg,yg,zg,&meshparts,&meshstart,meshfac); + + for(i=0;i=nbin)continue; + npair[kbin]++; + rbar[kbin]+=r; + } + } + + density=ngal/(rcube*rcube*rcube) ; + + rlow=0; + for (kbin=0;kbin0.0) { + fac=1./weight0 ; + rbar[kbin] *= fac ; + } + else { /* avoid errors in empty bins */ + rbar[kbin]=(rupp[kbin]+rlow)*0.5; + } + + /* compute xi, dividing summed weight by that expected for a random set */ + vol=4.*PI/3.*(rupp[kbin]*rupp[kbin]*rupp[kbin]-rlow*rlow*rlow) ; + weightrandom=ngal*density*vol ; + + rad[kbin+1]=log(rbar[kbin]); + xi[kbin+1]=weight0/weightrandom-1 ; + rlow=rupp[kbin] ; + + if(OUTPUT>1) + { + fprintf(stdout,"nbody_xi> %f %f %.0f\n",rbar[kbin],xi[kbin+1],weight0); + fflush(stdout); + } + } + + + free(indx); + free(rsqr); + free(rupp); + free(binlookup); + free(npair); + free(rbar); + + free_i3tensor(meshstart,0,nmesh-1,0,nmesh-1,0,nmesh-1); +} + +int internal_populate_simulation(float *x, float *y, float *z, float reduction_factor, int ivel, + float *vx, float *vy, float *vz) +{ + FILE *fp,*fpa[9],*fp2,*fpb[9],*fpc[9],*fps[9]; + int i,j,k,n,imass,n1,j_start=0,i1,galcnt[1000],halocnt[1000],imag; + double mass,xg[3],vg[3],nsat,nc[10],ncen,mlo,mag,err1,err2,r,high_density_f0,low_density_f0; + char aa[1000],fname[100]; + float x1,xh[3],vh[3],vgf[3]; + long IDUM = -445, IDUM3 = -445; + + float **galarr; + int *galid,id1=0,id2=0,j1,ii,*indx; + float dx,dy,dz,dr,drh,rv1,rv2,rmin,rmax,temp1,temp2,fac,sigma; + float **haloarr,**temp_pos,*temp_den,**temp_vel; + int ngal,nsati[9],ALL_FILES=0,TRACK_GALAXIES=0; + + + static int + flag = 1, + nhalo, + SO_FILE = 0; + + FILE *fp3; + + static float + **halo_pos, + **halo_vel, + *hdensity, + *halo_mass; + + + if(flag){ + + fp = openfile(Files.HaloFile); + nhalo = filesize(fp); + + if(DENSITY_DEPENDENCE) + { + fp2 = openfile(Files.HaloDensityFile); + if(nhalo != filesize(fp2)) + { + fprintf(stderr,"ERROR: filesize mismatch with [%s] and [%s]\n", + Files.HaloFile, Files.HaloDensityFile); + exit(0); + } + } + + halo_pos = matrix(1,nhalo,0,2); + halo_mass = vector(1,nhalo); + temp_pos = matrix(1,nhalo,0,2); + halo_vel = matrix(1,nhalo,0,2); + temp_vel = matrix(1,nhalo,0,2); + indx = ivector(1,nhalo); + + fprintf(stderr,"HERE %d halos\n",nhalo); + + if(DENSITY_DEPENDENCE) + { + temp_den = vector(1,nhalo); + hdensity = vector(1,nhalo); + } + + for(i=1;i<=nhalo;++i) + { + if(DENSITY_DEPENDENCE) + fscanf(fp2,"%f",&temp_den[i]); + if(SO_FILE) + { + fscanf(fp,"%d %lf %f %f %f %f %f %f %f %f", + &j,&mass,&x1,&x1,&xh[0],&xh[1],&xh[2],&vh[0],&vh[1],&vh[2]); + halo_mass[i] = -mass; + } + else + { + fscanf(fp,"%d %d %e %e %e %e %e %e %e", + &j,&imass,&xh[0],&xh[1],&xh[2],&x1,&vh[0],&vh[1],&vh[2]); + mass=imass*RHO_CRIT*OMEGA_M*pow(RESOLUTION,3.0); + halo_mass[i]= - imass*RHO_CRIT*OMEGA_M*pow(RESOLUTION,3.0); + } + for(j=0;j<3;++j) { + temp_pos[i][j] = xh[j]; + temp_vel[i][j] = vh[j]; } + indx[i] = i; + } + sort2(nhalo,halo_mass,indx); + + for(i=1;i<=nhalo;++i) + { + halo_mass[i] *= -1; + for(j=0;j<3;++j) { + halo_pos[i][j] = temp_pos[indx[i]][j]; + halo_vel[i][j] = temp_vel[indx[i]][j]; } + if(DENSITY_DEPENDENCE) + hdensity[i] = temp_den[indx[i]]; + } + free_matrix(temp_pos,1,nhalo,0,2); + free_matrix(temp_vel,1,nhalo,0,2); + free_ivector(indx,1,nhalo); + flag = 0; + + fclose(fp); + if(DENSITY_DEPENDENCE) + fclose(fp2); + } + + if(wp_color.ON) + { + temp1 = HOD.M_min; + temp2 = HOD.M_low; + } + HOD.M_min = 0; + set_HOD_params(); + if(DENSITY_DEPENDENCE) + dd_hod_functions(halo_mass,hdensity,nhalo); + if(wp_color.ON) + { + HOD.M_min = temp1; + HOD.M_low = temp2; + fprintf(stderr,"true M_min = %e\n",HOD.M_min); + } + HOD.M_low = set_low_mass(); + mlo = HOD.M_low; + if(HOD.M_min_fac<0) + mlo *= HOD.M_min_fac; + + high_density_f0 = HOD.fblue0_cen; + low_density_f0 = (1 - HOD.M_min_fac*(1-HOD.fblue0_cen)); + + fac=sqrt(4.499E-48)*pow(4*DELTA_HALO*PI*OMEGA_M*RHO_CRIT/3,1.0/6.0)*3.09E19; + + fprintf(stderr,"%e %e %e\n",HOD.M_min,HOD.M_low,halo_mass[1]); + + sprintf(fname,"%s.mock_halo",Task.root_filename); + fp2 = fopen(fname,"w"); + + for(ii=1;ii<=nhalo;++ii) + { + // printf("%d\n",ii); + //fflush(stdout); + mass=halo_mass[ii]; + if(massreduction_factor)continue; + + for(i=0;i<3;++i) + { + xh[i] = halo_pos[ii][i]; + if(xh[i]<0)xh[i]+=BOX_SIZE; + if(xh[i]>BOX_SIZE)xh[i]-=BOX_SIZE; + if(ivel) + vh[i] = halo_vel[ii][i]; + } + + nsat = N_sat(mass); + if(nsat>250) + n1 = gasdev(&IDUM3)*sqrt(nsat) + nsat; + else + n1 = poisson_deviate(nsat); + + for(i=1;i<=n1;++i) + { + r = NFW_position(mass,xg); + for(k=0;k<3;++k) + { + xg[k]+=xh[k]; + if(xg[k]<0)xg[k]+=BOX_SIZE; + if(xg[k]>BOX_SIZE)xg[k]-=BOX_SIZE; + } + if(ivel) { + NFW_velocity(mass,vg,mag); + vx[id2] = vg[0]+vh[0]; + vy[id2] = vg[1]+vh[1]; + vz[id2] = vg[2]+vh[2]; + } + x[id2] = xg[0]; + y[id2] = xg[1]; + z[id2] = xg[2]; + id2++; + fprintf(fp2,"%d\n",ii); + + } + if(DENSITY_DEPENDENCE && !wp_color.ON) + { + // printf("%e %e\n",mass,hdensity[ii]); + HOD.M_min=HOD.M_min_hiden; + if(hdensity[ii]ncen)continue; + sigma=fac*pow(mass,1.0/3.0)/sqrt(2.0); + x[id2] = xh[0]; + y[id2] = xh[1]; + z[id2] = xh[2]; + if(ivel) { + vx[id2] = vh[0] + gasdev(&IDUM)*VBIAS_C*sigma; + vy[id2] = vh[1] + gasdev(&IDUM)*VBIAS_C*sigma; + vz[id2] = vh[2] + gasdev(&IDUM)*VBIAS_C*sigma; + } + id2++; + fprintf(fp2,"%d\n",ii); + } + fclose(fp2); + + muh(999); + // ivel = 1; + if(ivel) { + sprintf(aa,"%s.mock",Task.root_filename); + fp = fopen(aa,"w"); + for(i=0;i +#include +#include +#define sqr(x) ((x)*(x)) +#define max(A,B) ((A) > (B) ? (A) : (B)) +#define min(A,B) ((A) < (B) ? (A) : (B)) +#define mabs(A) ((A) < 0.0 ? -(A) : (A)) +#define pi 3.1415926535898 + +/* +void nbrsfind2(smin,smax,rmax,nmesh,xpos,ypos,zpos,nbrmax,indx,rsqr,x,y,z,meshparts,meshstart) + +float smin,smax,rmax; +float *x,*y,*z; +int *meshparts,***meshstart; +int nmesh; +float xpos,ypos,zpos; +int *indx; +float *rsqr; +int *nbrmax; +*/ + +void nbrsfind2(float smin,float smax,float rmax,int nmesh,float xpos,float ypos,float zpos, + int *nbrmax,int *indx,float *rsqr,float *x,float *y,float *z, + int *meshparts,int ***meshstart,int ip) +{ + int i,j,k,ir; + int ix,iy,iz, + iix,iiy,iiz, + iiix,iiiy,iiiz, + nbr,p; + float rmax2,r2,side,side2,sinv,dx,dy,dz; + + side=(smax-smin); + side2=side/2.; + sinv=1./side; + + /* printf("nbrsfind2> %f %f %f %f %f %f %d %d\n",smin,smax,rmax,xpos,ypos,zpos,nmesh,*nbrmax); + */ + + /* ix=(int)(nmesh*(xpos-smin)*sinv); + iy=(int)(nmesh*(ypos-smin)*sinv); + iz=(int)(nmesh*(zpos-smin)*sinv); + + if (ix>=nmesh||iy>=nmesh||iz>=nmesh ||ix<0||iy<0||iz<0){ + fprintf(stderr,"nbrsfind2> error in position or lattice parameters\n"); + fprintf(stderr,"nbrsfind2> nmesh, ix, iy, iz = %d %d %d %d\n",nmesh,ix,iy,iz) ; + exit(-1) ; + } +*/ + + ix=(int)(nmesh*(xpos-smin)*sinv); + if(ix>=nmesh) + { + fprintf(stderr,"meshlink> Warning: Particle at x = %f ix = %d\n",xpos,ix); + ix=ix-1; + } + + + iy=(int)(nmesh*(ypos-smin)*sinv); + if(iy>=nmesh) + { + fprintf(stderr,"meshlink> Warning: Particle at y = %f iy = %d\n",ypos,iy); + iy=iy-1; + } + + + iz=(int)(nmesh*(zpos-smin)*sinv); + if(iz>=nmesh) + { + fprintf(stderr,"meshlink> Warning: Particle at z = %f iz = %d\n",zpos,iz); + iz=iz-1; + } + + + rmax2=rmax*rmax; + nbr=0; + ir=(int)(nmesh*rmax*sinv)+1; + + for(iix=-ir;iix<=ir;iix++) + for(iiy=-ir;iiy<=ir;iiy++) + for(iiz=-ir;iiz<=ir;iiz++){ + iiix=(ix+iix+nmesh)%nmesh ; + iiiy=(iy+iiy+nmesh)%nmesh ; + iiiz=(iz+iiz+nmesh)%nmesh ; + p=meshstart[iiix][iiiy][iiiz] ; + + while(p>=0){ + dx=mabs(xpos-x[p]) ; + dy=mabs(ypos-y[p]) ; + dz=mabs(zpos-z[p]) ; + if (dx>side2) dx=side-dx ; + if (dy>side2) dy=side-dy ; + if (dz>side2) dz=side-dz ; + r2=dx*dx+dy*dy+dz*dz ; + + if(r2<=rmax2) { + indx[nbr]=p; + rsqr[nbr]=r2; + nbr++; + } + if(nbr>*nbrmax){ + fprintf(stderr,"nbrsfind2>too many particles in indx list\n"); + fprintf(stderr,"nbrsfind2>reset nbrmax and try again\n"); + fprintf(stderr,"nbr = %d\n",nbr); + exit(-1) ; + } + p=meshparts[p]; + } + } + *nbrmax=nbr; +} diff --git a/c_tools/hod/nfw_transform.c b/c_tools/hod/nfw_transform.c new file mode 100644 index 0000000..94e524e --- /dev/null +++ b/c_tools/hod/nfw_transform.c @@ -0,0 +1,36 @@ +#include +#include +#include + +#include "header.h" + +void cisi(double x, double *ci, double *si); + +/* The Fourier transform of the NFW profile. + * Inputs are wavenumber and halo mass. + * NB! -> Function assumes that profile of satellite GALAXIES is + * desired, therefore uses CVIR_FAC + */ + +double nfw_transform(double xk, double m) +{ + double c,rvir,kappa1,kappa2,f,y,ci1,ci2,si1,si2; + + c=halo_concentration(m)*CVIR_FAC; + rvir=pow(3.0*m/(4.0*DELTA_HALO*PI*OMEGA_M*RHO_CRIT),1.0/3.0); + + kappa1=xk*rvir/c; + kappa2=kappa1*(1.0+c); + f=log(1.0+c)-c/(1.0+c); + f=1.0/f; + + cisi(kappa1,&ci1,&si1); + cisi(kappa2,&ci2,&si2); + + y=-sin(kappa1*c)/kappa2; + y=y+sin(kappa1)*(si2-si1)+cos(kappa1)*(ci2-ci1); + y=f*y; + + return(y); +} + diff --git a/c_tools/hod/nonlinear_power_spectrum.c b/c_tools/hod/nonlinear_power_spectrum.c new file mode 100644 index 0000000..e08e141 --- /dev/null +++ b/c_tools/hod/nonlinear_power_spectrum.c @@ -0,0 +1,204 @@ +#include +#include +#include + +#include "header.h" + +/* This is my implementation of the Halo Model fitting function + * described in Appendix C of Smith, Peacock, et al. 2003 MNRAS 341, 1311 + * + * Comparison to Smith et al. program halofit.f output is successful. + */ + +/* Internal functions + */ +double func_nl(double r); +void tabulate_pk_nl(double *kk, double *pknl, int nk); + +/* This returns the linear power + * Delta = 4pi*k^3 P(k)/(2pi)^3 + */ +double linear_power_spectrum(double xk) +{ + static double *kk,*pknl,*y2,pnorm=-1,ahi,bhi; + static int flag=1,nk=1000,prev_cosmology=0; + double a,psp,x1[4],y1[4]; + int i; + + if(pnorm<0 || prev_cosmology!=RESET_COSMOLOGY) + { + pnorm=SIGMA_8/sigmac(8.0); + pnorm*=pnorm; + prev_cosmology=RESET_COSMOLOGY; + } + if(ITRANS>0) + psp=pow(xk,SPECTRAL_INDX)*pow(transfnc(xk),2.); + else + psp=pow(xk,SPECTRAL_INDX); + psp=psp*pnorm*xk*xk*xk/(2*PI*PI); + return(psp); +} + +double nonlinear_power_spectrum(double xk) +{ + static double *kk,*pknl,*y2,pnorm=-1,ahi,bhi; + static int flag=1,nk=1000,prev_cosmology=0; + double a,psp,x1[4],y1[4],xklog; + int i; + + if(flag || RESET_COSMOLOGY!=prev_cosmology) + { + prev_cosmology=RESET_COSMOLOGY; + pnorm=SIGMA_8/sigmac(8.0); + flag=0; + kk=dvector(1,nk); + pknl=dvector(1,nk); + y2=dvector(1,nk); + tabulate_pk_nl(kk,pknl,nk); + spline(kk,pknl,nk,1.0E+30,1.0E+30,y2); + + /* This takes the last four points in the power spectrum at high k + * and fits a power law to them for extrapolation. + */ + for(i=0;i<4;++i) + { + x1[i]=(kk[nk-3+i]); + y1[i]=(pknl[nk-3+i]); + } + least_squares(x1,y1,4,&ahi,&bhi); + + } + + xklog=log(xk); + + /* If xk is less than the smallest k value tabulates, return linear power. + */ + if(xklogkk[nk]) + return((exp((ahi+bhi*xklog)))); + + splint(kk,pknl,y2,nk,xklog,&a); + return(exp(a)); + +} +void tabulate_pk_nl(double *kk, double *pknl, int nk) +{ + double r_nl,pnorm,DeltaQ,DeltaLin,DeltaH,psp,neff,s1,s2,n1,n2,ncurve, + lnk_lo,lnk_hi,dlnk,xk1,y,xk,fy; + double an,bn,cn,f1b,f2b,f3b,alpha,beta,gamma,nu,mu; + int i,j,n=10000; + + /* First normalize the linear power spectrum. + */ + pnorm=SIGMA_8/sigmac(8.0); + + /* Calculate the non-linear scale. + */ + r_nl = exp(zbrent(func_nl,log(0.01),log(10.0),1.0E-4)); + if(OUTPUT) + fprintf(stdout,"R_NL= %f\n",r_nl); + + /* Calculate the effective spectral index at the non-linear scale. + */ + s1=pnorm*sigmac(-r_nl*0.999); + s2=pnorm*sigmac(-r_nl*1.001); + neff=-(3+2*(s2-s1)/0.002); + if(OUTPUT) + fprintf(stderr,"neff= %f\n",neff); + + /* Spectral curvature. + */ + lnk_hi=10.0; + lnk_lo=-10.0; + dlnk=(lnk_hi-lnk_lo)/n; + s1=0; + for(i=1;i<=n;++i) + { + xk1=exp(lnk_lo+(i-0.5)*dlnk); + y=xk1*r_nl; + DeltaLin=linear_power_spectrum(xk1); + s1+=DeltaLin*y*y*(1-y*y)*exp(-y*y)*dlnk; + } + ncurve=(3+neff)*(3+neff)+4*s1; + if(OUTPUT) + fprintf(stderr,"ncurve= %f\n",ncurve); + + /* Coefficients of the model. + */ + an=pow(10.0,1.4861 + 1.8369*neff + 1.6762*neff*neff + 0.7940*neff*neff*neff + + 0.1670*pow(neff,4.0) - 0.6202*ncurve); + bn=pow(10.0,0.9463 + 0.9466*neff + 0.3084*neff*neff - 0.9400*ncurve); + + cn= pow(10.0,-0.2807 + 0.6669*neff + 0.3214*neff*neff - 0.0793*ncurve); + + gamma = 0.8649 + 0.2989*neff + 0.1631*ncurve; + alpha = 1.3884 + 0.3700*neff - 0.1452*neff*neff; + beta = 0.8291 + 0.9854*neff + 0.3401*neff*neff; + mu = pow(10.0,-3.5442 + 0.1908*neff); + nu = pow(10.0, 0.9589 + 1.2857*neff); + + /* Testing the parameter dependence. + * TESTING TESTING + */ + /* + alpha *= 0.3; + beta *= 0.3; + */ + + /* Omega-dependent functions (FLAT LAMBDA COSMOLOGY) + */ + f1b = pow(OMEGA_M,-0.0307); + f2b = pow(OMEGA_M,-0.0585); + f3b = pow(OMEGA_M,+0.0743); + + + /* Tabulate the power spectrum + */ + lnk_lo=log(0.001); + lnk_hi=log(1000.0); + dlnk=(lnk_hi-lnk_lo)/(nk-1); + + for(i=1;i<=nk;++i) + { + xk=exp(lnk_lo+(i-1)*dlnk); + y=xk*r_nl; + fy=y/4.0 + y*y/8.0; + + /* TEST */ + /* fy*=1.2; */ + + DeltaLin=linear_power_spectrum(xk); + + DeltaQ = DeltaLin*pow(1+DeltaLin,beta)/(1+alpha*DeltaLin)*exp(-fy); + + DeltaH = an*pow(y,3*f1b)/(1+bn*pow(y,f2b)+pow(cn*f3b*y,3-gamma)); + + DeltaH*= 1.0/(1+mu/y+nu/(y*y)); + + kk[i]=log(xk); + pknl[i]=log(DeltaQ + DeltaH); + } +} + +/* This is a function to find the non-linear scale. Similar to M_star, + * but here we're using a Guassian smoothing window rather than top hat. + * (And we're finding the scale at which the variance = 1, not 1.686). + */ +double func_nl(double r) +{ + static int prev_cosmology=0; + double sig; + static double pnorm=-1; + + if(pnorm<0 || RESET_COSMOLOGY!=prev_cosmology) + pnorm=SIGMA_8/sigmac(8.0); + prev_cosmology=RESET_COSMOLOGY; + + r=exp(r); + sig=pnorm*sigmac(-r); + return sig-1.0; +} diff --git a/c_tools/hod/nrutil.c b/c_tools/hod/nrutil.c new file mode 100644 index 0000000..49cae58 --- /dev/null +++ b/c_tools/hod/nrutil.c @@ -0,0 +1,293 @@ +/* CAUTION: This is the ANSI C (only) version of the Numerical Recipes + utility file nrutil.c. Do not confuse this file with the same-named + file nrutil.c that is supplied in the 'misc' subdirectory. + *That* file is the one from the book, and contains both ANSI and + traditional K&R versions, along with #ifdef macros to select the + correct version. *This* file contains only ANSI C. */ + +#include +#include +#include +#define NR_END 1 +#define FREE_ARG char* + +void nrerror(char error_text[]) +/* Numerical Recipes standard error handler */ +{ + fprintf(stderr,"Numerical Recipes run-time error...\n"); + fprintf(stderr,"%s\n",error_text); + fprintf(stderr,"...now exiting to system...\n"); + exit(1); +} + +float *vector(long nl, long nh) +/* allocate a float vector with subscript range v[nl..nh] */ +{ + float *v; + + v=(float *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(float))); + if (!v) nrerror("allocation failure in vector()"); + return v-nl+NR_END; +} + +int *ivector(long nl, long nh) +/* allocate an int vector with subscript range v[nl..nh] */ +{ + int *v; + + v=(int *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(int))); + if (!v) nrerror("allocation failure in ivector()"); + return v-nl+NR_END; +} + +unsigned char *cvector(long nl, long nh) +/* allocate an unsigned char vector with subscript range v[nl..nh] */ +{ + unsigned char *v; + + v=(unsigned char *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(unsigned char))); + if (!v) nrerror("allocation failure in cvector()"); + return v-nl+NR_END; +} + +unsigned long *lvector(long nl, long nh) +/* allocate an unsigned long vector with subscript range v[nl..nh] */ +{ + unsigned long *v; + + v=(unsigned long *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(long))); + if (!v) nrerror("allocation failure in lvector()"); + return v-nl+NR_END; +} + +double *dvector(long nl, long nh) +/* allocate a double vector with subscript range v[nl..nh] */ +{ + double *v; + + v=(double *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(double))); + if (!v) nrerror("allocation failure in dvector()"); + return v-nl+NR_END; +} + +float **matrix(long nrl, long nrh, long ncl, long nch) +/* allocate a float matrix with subscript range m[nrl..nrh][ncl..nch] */ +{ + long i, nrow=nrh-nrl+1,ncol=nch-ncl+1; + float **m; + + /* allocate pointers to rows */ + m=(float **) malloc((size_t)((nrow+NR_END)*sizeof(float*))); + if (!m) nrerror("allocation failure 1 in matrix()"); + m += NR_END; + m -= nrl; + + /* allocate rows and set pointers to them */ + m[nrl]=(float *) malloc((size_t)((nrow*ncol+NR_END)*sizeof(float))); + if (!m[nrl]) nrerror("allocation failure 2 in matrix()"); + m[nrl] += NR_END; + m[nrl] -= ncl; + + for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol; + + /* return pointer to array of pointers to rows */ + return m; +} + +double **dmatrix(long nrl, long nrh, long ncl, long nch) +/* allocate a double matrix with subscript range m[nrl..nrh][ncl..nch] */ +{ + long i, nrow=nrh-nrl+1,ncol=nch-ncl+1; + double **m; + + /* allocate pointers to rows */ + m=(double **) malloc((size_t)((nrow+NR_END)*sizeof(double*))); + if (!m) nrerror("allocation failure 1 in matrix()"); + m += NR_END; + m -= nrl; + + /* allocate rows and set pointers to them */ + m[nrl]=(double *) malloc((size_t)((nrow*ncol+NR_END)*sizeof(double))); + if (!m[nrl]) nrerror("allocation failure 2 in matrix()"); + m[nrl] += NR_END; + m[nrl] -= ncl; + + for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol; + + /* return pointer to array of pointers to rows */ + return m; +} + +int **imatrix(long nrl, long nrh, long ncl, long nch) +/* allocate a int matrix with subscript range m[nrl..nrh][ncl..nch] */ +{ + long i, nrow=nrh-nrl+1,ncol=nch-ncl+1; + int **m; + + /* allocate pointers to rows */ + m=(int **) malloc((size_t)((nrow+NR_END)*sizeof(int*))); + if (!m) nrerror("allocation failure 1 in matrix()"); + m += NR_END; + m -= nrl; + + + /* allocate rows and set pointers to them */ + m[nrl]=(int *) malloc((size_t)((nrow*ncol+NR_END)*sizeof(int))); + if (!m[nrl]) nrerror("allocation failure 2 in matrix()"); + m[nrl] += NR_END; + m[nrl] -= ncl; + + for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol; + + /* return pointer to array of pointers to rows */ + return m; +} + +float **submatrix(float **a, long oldrl, long oldrh, long oldcl, long oldch, + long newrl, long newcl) +/* point a submatrix [newrl..][newcl..] to a[oldrl..oldrh][oldcl..oldch] */ +{ + long i,j,nrow=oldrh-oldrl+1,ncol=oldcl-newcl; + float **m; + + /* allocate array of pointers to rows */ + m=(float **) malloc((size_t) ((nrow+NR_END)*sizeof(float*))); + if (!m) nrerror("allocation failure in submatrix()"); + m += NR_END; + m -= newrl; + + /* set pointers to rows */ + for(i=oldrl,j=newrl;i<=oldrh;i++,j++) m[j]=a[i]+ncol; + + /* return pointer to array of pointers to rows */ + return m; +} + +float **convert_matrix(float *a, long nrl, long nrh, long ncl, long nch) +/* allocate a float matrix m[nrl..nrh][ncl..nch] that points to the matrix +declared in the standard C manner as a[nrow][ncol], where nrow=nrh-nrl+1 +and ncol=nch-ncl+1. The routine should be called with the address +&a[0][0] as the first argument. */ +{ + long i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1; + float **m; + + /* allocate pointers to rows */ + m=(float **) malloc((size_t) ((nrow+NR_END)*sizeof(float*))); + if (!m) nrerror("allocation failure in convert_matrix()"); + m += NR_END; + m -= nrl; + + /* set pointers to rows */ + m[nrl]=a-ncl; + for(i=1,j=nrl+1;i (dmaxarg2) ?\ + (dmaxarg1) : (dmaxarg2)) + +static double dminarg1,dminarg2; +#define DMIN(a,b) (dminarg1=(a),dminarg2=(b),(dminarg1) < (dminarg2) ?\ + (dminarg1) : (dminarg2)) + +static float maxarg1,maxarg2; +#define FMAX(a,b) (maxarg1=(a),maxarg2=(b),(maxarg1) > (maxarg2) ?\ + (maxarg1) : (maxarg2)) + +static float minarg1,minarg2; +#define FMIN(a,b) (minarg1=(a),minarg2=(b),(minarg1) < (minarg2) ?\ + (minarg1) : (minarg2)) + +static long lmaxarg1,lmaxarg2; +#define LMAX(a,b) (lmaxarg1=(a),lmaxarg2=(b),(lmaxarg1) > (lmaxarg2) ?\ + (lmaxarg1) : (lmaxarg2)) + +static long lminarg1,lminarg2; +#define LMIN(a,b) (lminarg1=(a),lminarg2=(b),(lminarg1) < (lminarg2) ?\ + (lminarg1) : (lminarg2)) + +static int imaxarg1,imaxarg2; +#define IMAX(a,b) (imaxarg1=(a),imaxarg2=(b),(imaxarg1) > (imaxarg2) ?\ + (imaxarg1) : (imaxarg2)) + +static int iminarg1,iminarg2; +#define IMIN(a,b) (iminarg1=(a),iminarg2=(b),(iminarg1) < (iminarg2) ?\ + (iminarg1) : (iminarg2)) + +#define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a)) + +void nrerror(char error_text[]); +float *vector(long nl, long nh); +int *ivector(long nl, long nh); +unsigned char *cvector(long nl, long nh); +unsigned long *lvector(long nl, long nh); +double *dvector(long nl, long nh); +float **matrix(long nrl, long nrh, long ncl, long nch); +double **dmatrix(long nrl, long nrh, long ncl, long nch); +int **imatrix(long nrl, long nrh, long ncl, long nch); +float **submatrix(float **a, long oldrl, long oldrh, long oldcl, long oldch, + long newrl, long newcl); +float **convert_matrix(float *a, long nrl, long nrh, long ncl, long nch); +float ***f3tensor(long nrl, long nrh, long ncl, long nch, long ndl, long ndh); +void free_vector(float *v, long nl, long nh); +void free_ivector(int *v, long nl, long nh); +void free_cvector(unsigned char *v, long nl, long nh); +void free_lvector(unsigned long *v, long nl, long nh); +void free_dvector(double *v, long nl, long nh); +void free_matrix(float **m, long nrl, long nrh, long ncl, long nch); +void free_dmatrix(double **m, long nrl, long nrh, long ncl, long nch); +void free_imatrix(int **m, long nrl, long nrh, long ncl, long nch); +void free_submatrix(float **b, long nrl, long nrh, long ncl, long nch); +void free_convert_matrix(float **b, long nrl, long nrh, long ncl, long nch); +void free_f3tensor(float ***t, long nrl, long nrh, long ncl, long nch, + long ndl, long ndh); + +#endif /* _NR_UTILS_H_ */ diff --git a/c_tools/hod/old.c b/c_tools/hod/old.c new file mode 100644 index 0000000..535841a --- /dev/null +++ b/c_tools/hod/old.c @@ -0,0 +1,376 @@ +#include +#include +#include +#include "header.h" + +double delta_pdf(double delta, double r); + +void vdelta_v4(double m0, double m1, double rad, double theta, double binsize, + double v0, int nv, double *a, double *pv, double *pt, double *pz, + double wgal[3], double sgal[4]) +{ + static double pnorm=-1,flag=0; + static double *rho,*mu,*pdelta; + static int prev_cosmo=0; + + int i,j,k,nrho=75,halo_pair_only=0,use_file_coeff=0; + double dlogrho,sintheta,costheta,tan2theta,rho_min,rho_max,w,b0, + collapse_factor,rho200,ptot,v,sigv,rho0,x1,x2,x3,rvir0,rho200t,sigvt,alpha,alphat, + rvir1,rvirmax,rvir2,vfac,sr1,sr2,sr3,sr4,st1,st2,st3,st4,sz1,sz2,sz3,sz4, + gnorm1,gnorm2,gnorm3,gnorm4,vv,pmax,rcrit,sig20,sig10,sig5; + + int direction,iend; + double sigz1[76],sigz2[76],sigz3[76],sigz4[76], + g1[76],g2[76],g3[76],g4[76],minp,xfit[3],yfit[3],afit,bfit; + + double t0,t1,tt1,tt2; + int ii=0; + + double vfac0 = 0.97; /* factor om rho200[t,r]. was 0.97 */ + + for(i=1;i<=nv;++i) + /* pt[i]=pv[i]=*/ pz[i]=0; + + rvir0=(pow(3*m0/(4*DELTA_HALO*PI*RHO_CRIT*OMEGA_M),1.0/3.0) + + pow(3*m1/(4*DELTA_HALO*PI*RHO_CRIT*OMEGA_M),1.0/3.0)); + rvir1=pow(3*m1/(4*DELTA_HALO*PI*RHO_CRIT*OMEGA_M),1.0/3.0); + rvir2=pow(3*m0/(4*DELTA_HALO*PI*RHO_CRIT*OMEGA_M),1.0/3.0); + b0=(bias_interp(m0,-1)+bias_interp(m1,-1)); + + /* 0.5 comes from ellipsoidal halo exclusion. + */ + if(radpmax){ pmax=pdelta[i]; j=i; } + } + + pmax*=1.0E-4; + for(i=1;i=pmax)break; + rho_min=rho[i]; + for(i=j+1;i<50;++i) + if(pdelta[i]<=pmax)break; + rho_max=rho[i]; + + /* Tabulate the spherical collapse model, density, and p(delta). + */ + dlogrho=log(rho_max/rho_min)/(nrho-1); + ptot=0; + + for(i=1;i<=nrho;++i) + { + rho[i]=rho_min*exp((i-1)*dlogrho); + pdelta[i]=exp(-rho0/rho[i])*delta_pdf(rho[i]-1,rad)*rho[i]; + ptot+=pdelta[i]*dlogrho; + if(pdelta[i]>pdelta[j])j=i; + + x1=-(100*rad)*pow(OMEGA_M,0.6)*(rho[i]-1)/3; + + /* If underdense region, use linear theory. + */ + if(rho[i]<=1) + { + mu[i]=x1; + continue; + } + + x2=(rad)*spherical_collapse_model(rho[i]-1)*exp(-(4.5/rad/rho[i])*(4.5/rad/rho[i])); + if(x2>0)x2=0; + + /* If small separation, use spherical collapse model only. + */ + if(rad<=4) + { + mu[i]=x2; + continue; + } + + /* If intermediate separation, use linear combination of v_sph & v_lin. + */ + if(rad<=20) + { + w=-0.62*log(rad)+1.86; + mu[i]=w*x2 + (1-w)*x1; + continue; + } + + /* In linear regime. Use linear theory. + */ + mu[i]=x1; + } + + if(rad<=rcrit) + for(i=1;i<=nrho;++i) + mu[i]=mu[j]; + + for(i=1;i<=nrho;++i) + pdelta[i]/=ptot; + + vfac=pow(OMEGA_M/0.3,0.6)*(SIGMA_8/0.8)*vfac0; + + /* If Halos only, then set all the galaxy velocity dispersions + * and weights to be zero. + */ + if(!HOD.pdfs) + { + sgal[0]=sgal[1]=sgal[2]=0; + wgal[0]=wgal[1]=wgal[2]=0; + } + + + for(i=1;i<=nrho;++i) + { + sigv=200*pow(rho[i]/rho200,alpha)*vfac; + sigvt=200*pow(rho[i]/rho200t,alphat)*vfac; + + + sr1=sigv*sigv + sgal[0]; + sr2=sigv*sigv + sgal[1]; + sr3=sigv*sigv + sgal[2]; + sr4=sigv*sigv + sgal[3]; + + st1=sigvt*sigvt + sgal[0]; + st2=sigvt*sigvt + sgal[1]; + st3=sigvt*sigvt + sgal[2]; + st4=sigvt*sigvt + sgal[3]; + + sz1=2*(st1+tan2theta*sr1)*costheta*costheta; + sz2=2*(st2+tan2theta*sr2)*costheta*costheta; + sz3=2*(st3+tan2theta*sr3)*costheta*costheta; + sz4=2*(st4+tan2theta*sr4)*costheta*costheta; + + sigz1[i]=sz1; + sigz2[i]=sz2; + sigz3[i]=sz3; + sigz4[i]=sz4; + + gnorm1=wgal[0]/(RT2PI*sqrt(st1*sr1)*sqrt(1.0/(sr1) + tan2theta/(st1))); + gnorm2=wgal[1]/(RT2PI*sqrt(st2*sr2)*sqrt(1.0/(sr2) + tan2theta/(st2))); + gnorm3=wgal[2]/(RT2PI*sqrt(st3*sr3)*sqrt(1.0/(sr3) + tan2theta/(st3))); + gnorm4=(1-wgal[0]-wgal[1]-wgal[2])/ + (RT2PI*sqrt(st4*sr4)*sqrt(1.0/(sr4) + tan2theta/(st4))); + + g1[i]=gnorm1; + g2[i]=gnorm2; + g3[i]=gnorm3; + g4[i]=gnorm4; + } + + /* Find the mode of the distribution. Start at vz=0 and work either way. + */ + for(k=1,j=nv/2;j<=nv;++j,++k) + { + for(i=1;i<=nrho;++i) + { + v=v0+(j-1)*binsize; + vv=(v-sintheta*mu[i])*(v-sintheta*mu[i]); + pz[j]+=pdelta[i]*dlogrho/costheta* + (g1[i]*exp(-vv/(sigz1[i])) + g2[i]*exp(-vv/(sigz2[i])) + + g3[i]*exp(-vv/(sigz3[i])) + g4[i]*exp(-vv/(sigz4[i]))); + } + if(k==2){ + if(pz[j-1]>pz[j])direction=-1; + else direction=1; + break; + } + } + + direction=1; + if(direction==1)iend=nv; + else iend=1; + + for(k=1,j=nv/2-direction;j!=iend;j+=direction,++k) + { + if(pz[j]>0)goto SKIP1; + for(i=1;i<=nrho;++i) + { + v=v0+(j-1)*binsize; + vv=(v-sintheta*mu[i])*(v-sintheta*mu[i]); + pz[j]+=pdelta[i]*dlogrho/costheta* + (g1[i]*exp(-vv/(sigz1[i])) + g2[i]*exp(-vv/(sigz2[i])) + + g3[i]*exp(-vv/(sigz3[i])) + g4[i]*exp(-vv/(sigz4[i]))); + } + SKIP1: + if(k<3)continue; + if(direction>0) { + /*printf("%d %e %e %e\n",j,pz[j],pz[j-1],pz[j-2]);*/ + if(pz[j-1]>pz[j] && pz[j-1]>pz[j-2]) { + minp = pz[j-1]*0.001; break; } + } else { + /*printf("%d %e %e %e\n",j,pz[j],pz[j+1],pz[j+2]);*/ + if(pz[j+1]>pz[j] && pz[j+1]>pz[j+2]) { + minp = pz[j+1]*0.001; break; } + } + } + + for(j=nv/2;j<=nv;++j) + { + if(pz[j]>0)continue; + for(i=1;i<=nrho;++i) + { + v=v0+(j-1)*binsize; + vv=(v-sintheta*mu[i])*(v-sintheta*mu[i]); + pz[j]+=pdelta[i]*dlogrho/costheta* + (g1[i]*exp(-vv/(sigz1[i])) + g2[i]*exp(-vv/(sigz2[i])) + + g3[i]*exp(-vv/(sigz3[i])) + g4[i]*exp(-vv/(sigz4[i]))); + } + if(pz[j]<=minp && nv-j>=3)break; + } + + + /* Now extrapolate the rest of the PVD from the last three points. + */ + for(k=0,i=j-2;i<=j;++i,++k) + { + yfit[k]=log(pz[i]); + xfit[k]=v0+(i-1)*binsize; + } + least_squares(xfit,yfit,3,&afit,&bfit); + + + for(i=j+1;i<=nv;++i) + pz[i] = exp(afit + bfit*(v0+(i-1)*binsize)); + + /* Now go from the mode to i=0 + */ + for(j=nv/2-1;j>=1;--j) + { + if(pz[j]>0)continue; + for(i=1;i<=nrho;++i) + { + v=v0+(j-1)*binsize; + vv=(v-sintheta*mu[i])*(v-sintheta*mu[i]); + pz[j]+=pdelta[i]*dlogrho/costheta* + (g1[i]*exp(-vv/(sigz1[i])) + g2[i]*exp(-vv/(sigz2[i])) + + g3[i]*exp(-vv/(sigz3[i])) + g4[i]*exp(-vv/(sigz4[i]))); + } + if(pz[j]<=minp && j>=3)break; + } + + + /* Now extrapolate the rest of the PVD from the last three points. + */ + for(k=2,i=j+2;i>=j;--i,--k) + { + yfit[k]=log(pz[i]); + xfit[k]=v0+(i-1)*binsize; + } + least_squares(xfit,yfit,3,&afit,&bfit); + + for(i=j-1;i>0;--i) + pz[i] = exp(afit + bfit*(v0+(i-1)*binsize)); + + + /* Do this just to get rid of any numerical roundoff errors and such. + * (It whould already be one by construction if I didn't have the + * linear extrapolation at the end of each side, but the correction + * shouldn't be much.) + */ + for(ptot=0,i=1;i<=nv;++i) + ptot+=pz[i]*binsize; + + for(i=1;i<=nv;++i) + pz[i]/=ptot; + + + if(isnan(ptot)) + { + printf("NAN ptot %f %f %f %f %f %f\n",rho200,rho200t,alpha,rho0,sr4,st4); + fflush(stdout); + for(i=1;i<=nv;++i) + pt[i]=pz[i]=pv[i]=0; + return; + } + + + return; + +} + +/* This is the standard log-normal 1-pt distribution of dark + * matter densities (non-linear) at top-hat smoothing scale r. + */ +double delta_pdf(double delta, double r) +{ + static int model_prev=0; + static double pnorm=-1,rprev=0,sig0,sig1sqr; + double pnorm1; + + if(pnorm<0 || RESET_COSMOLOGY!=model_prev) + { + pnorm1=SIGMA_8/sigmac(8.0); + /*printf("NORM %e %e %e\n",pnorm1,sigmac(8.0),nonlinear_sigmac(8.0));*/ + pnorm=pnorm1*sigmac(80.0)/nonlinear_sigmac(80.0); + rprev=0; + /*printf("NORM %e %e %e %e %f\n",pnorm,sigmac(8.0),sigmac(80.0),nonlinear_sigmac(80.0),SIGMA_8);*/ + } + if(r!=rprev) + { + sig0=pnorm*nonlinear_sigmac(r); + sig1sqr=log(1+sig0*sig0); + /*printf("NORM %f %f %e %e %e\n",r,sig0,pnorm,nonlinear_sigmac(8.0),sigmac(8.0));*/ + } + rprev=r; + model_prev=RESET_COSMOLOGY; + return(1.0/(RT2PI*sqrt(sig1sqr))*exp(-pow(log((1+delta))+sig1sqr*0.5,2.0)/ + (2*sig1sqr))/(1+delta)); + +} diff --git a/c_tools/hod/one_halo_rspace.c b/c_tools/hod/one_halo_rspace.c new file mode 100644 index 0000000..5a7aacb --- /dev/null +++ b/c_tools/hod/one_halo_rspace.c @@ -0,0 +1,231 @@ +#include +#include +#include + +#include "header.h" + +/* These routines control the real-space one-halo term. + * For specifics, see: + * + * Berlind, A.\ A., \& Weinberg, D.\ H.\ 2002, \apj, 575, 587 + * Zheng, Z. 2003, \apj, 610, 61 + * Tinker, Weinberg, Zheng, Zehavi 2005 Apj 631 (App B) + * + */ + +/* Local functions. + */ +void calc_real_space_one_halo(double *r, double *xi, int n); +double func1(double m); +double func1cs(double m); +double func1satsat(double m); +double func1_xcorr(double m); +double one_halo_ss(double r); +double one_halo_cs(double r); + +double *xi_cs_g2,*xi_ss_g2,*xi_rad_g2; + +/* These are the local globals to use during the qromo integration + */ +double r_g2; + + +/* This function tabulates the one-halo real-space term for spline interpolation. + * If the requested radius is out-of-bounds of the tabulated function, a value of + * zero is returned. + */ +double one_halo_real_space(double r) +{ + static int flag=0; + static double *x,*y,*y2; + int i,n=100; + double a; + + if(!HOD.pdfs)return(0); + + if(!flag || RESET_FLAG_1H) + { + if(!flag) + { + x=dvector(1,n); + y=dvector(1,n); + y2=dvector(1,n); + } + flag=1; + RESET_FLAG_1H=0; + calc_real_space_one_halo(x,y,n); + spline(x,y,n,2.0E+30,2.0E+30,y2); + } + if(r>x[n])return(0); + if(r2*R_vir(M_max). + */ +void calc_real_space_one_halo(double *r, double *xi, int n) +{ + static int ncnt=0; + double fac,s1,rhi=1,rlo=-2,dr,mlo,x1,x2; + int i,j; + FILE *fp; + char fname[100]; + + ncnt++; + rlo=log(0.01); + rhi=log(1.9*pow(3*HOD.M_max/(4*PI*DELTA_HALO*RHO_CRIT*OMEGA_M),1.0/3.0)); + dr=(rhi-rlo)/(n-1); + + if(OUTPUT>1) + printf("calc_one_halo> starting...\n"); + if(!XCORR) + GALAXY_DENSITY2 = GALAXY_DENSITY; + + for(i=1;i<=n;++i) + { + r_g2=r[i]=exp((i-1)*dr + rlo); + fac=1.0/(2*PI*r_g2*r_g2*GALAXY_DENSITY*GALAXY_DENSITY2); + + mlo = 4./3.*PI*RHO_CRIT*DELTA_HALO*OMEGA_M*pow(r[i]*.5,3.0); + if(mlo1) + printf("calc_one_halo> %f %e %e\n",r[i],s1,fac); + continue; + } +} + +/* This is the function passed to qromo in the above routine. + * It is the number density of + * galaxy pairs in halos of mass m at separation r_g2. + * See Equation (11) from Berlind & Weinberg. + */ +double func1(double m) +{ + double N,n,fac2,rvir,f_ss,f_cs,cvir,x,rfof,ncen,nsat; + + m=exp(m); + cvir=halo_concentration(m)*CVIR_FAC; + + n=dndM_interp(m); + + nsat=N_sat(m); + ncen=N_cen(m); + + rvir=2*pow(3.0*m/(4*DELTA_HALO*PI*OMEGA_M*RHO_CRIT),1.0/3.0); + + /* Break up the contribution of pairs into + * central-satellite (cs) and satellite-satellite (ss) pairs. + */ + f_ss=dFdx_ss(r_g2/rvir,cvir)*moment_ss(m)*0.5; + f_cs=dFdx_cs(r_g2/rvir,cvir)*nsat*ncen; + x=n*(f_ss+f_cs)/rvir*m; + return(x); + +} + +double func1satsat(double m) +{ + double N,n,fac2,rvir,f_ss,f_cs,cvir,x,rfof,ncen,nsat; + + m=exp(m); + cvir=halo_concentration(m)*CVIR_FAC; + + n=dndM_interp(m); + + nsat=N_sat(m); + ncen=N_cen(m); + + rvir=2*pow(3.0*m/(4*DELTA_HALO*PI*OMEGA_M*RHO_CRIT),1.0/3.0); + + /* Break up the contribution of pairs into + * central-satellite (cs) and satellite-satellite (ss) pairs. + */ + f_ss=dFdx_ss(r_g2/rvir,cvir)*moment_ss(m)*0.5; + x=n*(f_ss)/rvir*m; + return(x); + +} + +double func1cs(double m) +{ + double N,n,fac2,rvir,f_ss,f_cs,cvir,x,rfof,ncen,nsat; + + m=exp(m); + cvir=halo_concentration(m)*CVIR_FAC; + + n=dndM_interp(m); + + nsat=N_sat(m); + ncen=N_cen(m); + + rvir=2*pow(3.0*m/(4*DELTA_HALO*PI*OMEGA_M*RHO_CRIT),1.0/3.0); + + /* Break up the contribution of pairs into + * central-satellite (cs) and satellite-satellite (ss) pairs. + */ + f_cs=dFdx_cs(r_g2/rvir,cvir)*nsat*ncen; + x=n*(f_cs)/rvir*m; + + return(x); +} + +/* Same as above, only now we're calculating the number of pairs + * in the cross-correlation. + * + * NB! -- We're assuming that the satellite galaxy profiles + * of both HODs are the same. + */ +double func1_xcorr(double m) +{ + double N,n,fac2,rvir,f_ss=0,f_cs=0,cvir,x,rfof,ncen1,nsat1,ncen2,nsat2; + + m=exp(m); + cvir=halo_concentration(m)*CVIR_FAC; + n=dndM_interp(m); + + nsat1=N_sat(m); + ncen1=N_cen(m); + + nsat2=N_sat2(m); + ncen2=N_cen2(m); + + rvir=2*pow(3.0*m/(4*DELTA_HALO*PI*OMEGA_M*RHO_CRIT),1.0/3.0); + + /* Break up the contribution of pairs into + * central-satellite (cs) and satellite-satellite (ss) pairs. + * But for x-corr, we have c1-s2, c2-s1, s1-s2. + */ + f_ss=dFdx_ss(r_g2/rvir,cvir)*nsat1*nsat2; + f_cs=dFdx_cs(r_g2/rvir,cvir)*(nsat1*ncen2 + nsat2*ncen1); + x=n*(f_ss+f_cs)/rvir*m; + + return(x); + +} + +/* The public version doesn't currently support cross-correlations. + */ +double N_sat2(double m) +{ + return 0; +} +double N_cen2(double m) +{ + return 0; +} diff --git a/c_tools/hod/output_params.c b/c_tools/hod/output_params.c new file mode 100644 index 0000000..bb5664a --- /dev/null +++ b/c_tools/hod/output_params.c @@ -0,0 +1,349 @@ +#include +#include +#include +#include + +#include "header.h" + +/* This function is taken from Volker Springel's GADGET code and + * modified for the parameters used for the HOD.x code. + */ + +/* Ths is the same as intput_params.c, but it is called after + * model fitting to data, and uses the new values whenever + * applicable. + */ + +/* + * This function parses the parameterfile in a simple way. + * Each paramater is defined by a keyword (`tag'), and can be + * either of type douple, int, or character string. + * The routine makes sure that each parameter appears + * exactly once in the parameterfile. + */ +void output_parameter_file(char *fname) +{ +#define DOUBLE 1 +#define STRING 2 +#define INT 3 +#define CHAR 4 +#define LONG 4 +#define MAXTAGS 300 + + FILE *fd,*fdout; + + char buf[200],buf1[200],buf2[200],buf3[200]; + int i,j,nt; + int id[MAXTAGS]; + void *addr[MAXTAGS]; + char tag[MAXTAGS][200]; + int errorFlag=0; + int IDUM_MCMC_TEMP=-555; + + nt=0; + + strcpy(tag[nt],"GAMMA"); + addr[nt]=&GAMMA; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"OMEGA_M"); + addr[nt]=&OMEGA_M; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"SIGMA_8"); + addr[nt]=&SIGMA_8; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"RHO_CRIT"); + addr[nt]=&RHO_CRIT; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"ITRANS"); + addr[nt]=&ITRANS; + id[nt++]=INT; + + strcpy(tag[nt],"LINEAR_PSP"); + addr[nt]=&LINEAR_PSP; + id[nt++]=INT; + + strcpy(tag[nt],"KAISER"); + addr[nt]=&KAISER; + id[nt++]=INT; + + strcpy(tag[nt],"BETA"); + addr[nt]=&BETA; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"SIGV"); + addr[nt]=&SIGV; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"IDUM_MCMC"); + addr[nt]=&IDUM_MCMC_TEMP; + id[nt++]=INT; + + strcpy(tag[nt],"SPECTRAL_INDX"); + addr[nt]=&SPECTRAL_INDX; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"DELTA_CRIT"); + addr[nt]=&DELTA_CRIT; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"DELTA_HALO"); + addr[nt]=&DELTA_HALO; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"BOX_SIZE"); + addr[nt]=&BOX_SIZE; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"RESOLUTION"); + addr[nt]=&RESOLUTION; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"VBIAS"); + addr[nt]=&VBIAS; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"VBIAS_C"); + addr[nt]=&VBIAS_C; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"TF_file"); + addr[nt]=Files.TF_file; + id[nt++]=STRING; + + strcpy(tag[nt],"M1"); + addr[nt]=&HOD.M1; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"M_min"); + addr[nt]=&HOD.M_min; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"M_cen_max"); + addr[nt]=&HOD.M_cen_max; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"M_cut"); + addr[nt]=&HOD.M_cut; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"M_max"); + addr[nt]=&HOD.M_max; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"sigma_logM"); + addr[nt]=&HOD.sigma_logM; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"MaxCen"); + addr[nt]=&HOD.MaxCen; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"alpha"); + addr[nt]=&HOD.alpha; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"pdfc"); + addr[nt]=&HOD.pdfc; + id[nt++]=INT; + + strcpy(tag[nt],"pdfs"); + addr[nt]=&HOD.pdfs; + id[nt++]=INT; + + strcpy(tag[nt],"GALAXY_DENSITY"); + addr[nt]=&GALAXY_DENSITY; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"EXCLUSION"); + addr[nt]=&EXCLUSION; + id[nt++]=INT; + + strcpy(tag[nt],"FIX_PARAM"); + addr[nt]=&FIX_PARAM; + id[nt++]=INT; + + strcpy(tag[nt],"POWELL"); + addr[nt]=&POWELL; + id[nt++]=INT; + + strcpy(tag[nt],"OUTPUT"); + addr[nt]=&OUTPUT; + id[nt++]=INT; + + for(i=1;i<=11;++i) + { + sprintf(tag[nt],"free[%d]",i); + addr[nt]=&HOD.free[i]; + id[nt++]=INT; + } + + strcpy(tag[nt],"All"); + addr[nt]=&Task.All; + id[nt++]=INT; + + strcpy(tag[nt],"real_space_xi"); + addr[nt]=&Task.real_space_xi; + id[nt++]=INT; + + strcpy(tag[nt],"z_space_xi"); + addr[nt]=&Task.z_space_xi; + id[nt++]=INT; + + strcpy(tag[nt],"kaiser_xi"); + addr[nt]=&Task.kaiser_xi; + id[nt++]=INT; + + strcpy(tag[nt],"multipoles"); + addr[nt]=&Task.multipoles; + id[nt++]=INT; + + strcpy(tag[nt],"r_half"); + addr[nt]=&Task.r_half; + id[nt++]=INT; + + strcpy(tag[nt],"wp_minimize"); + addr[nt]=&Task.wp_minimize; + id[nt++]=INT; + Task.wp_minimize=0; + + strcpy(tag[nt],"zspace_minimize"); + addr[nt]=&Task.zspace_minimize; + id[nt++]=INT; + Task.zspace_minimize=0; + + strcpy(tag[nt],"MCMC"); + addr[nt]=&Task.MCMC; + id[nt++]=INT; + Task.MCMC=0; + + strcpy(tag[nt],"COVAR"); + addr[nt]=&COVAR; + id[nt++]=INT; + COVAR=1; + + strcpy(tag[nt],"DEPROJECTED"); + addr[nt]=&DEPROJECTED; + id[nt++]=INT; + + strcpy(tag[nt],"fname_covar"); + addr[nt]=&wp.fname_covar; + id[nt++]=STRING; + + strcpy(tag[nt],"pi_max"); + addr[nt]=&wp.pi_max; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"esys"); + addr[nt]=&wp.esys; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"fname_wp"); + addr[nt]=&wp.fname_wp; + id[nt++]=STRING; + + strcpy(tag[nt],"wp_format"); + addr[nt]=&wp.format; + id[nt++]=INT; + + strcpy(tag[nt],"root_filename"); + addr[nt]=&Task.root_filename; + id[nt++]=STRING; + + strcpy(tag[nt],"CVIR_FAC"); + addr[nt]=&CVIR_FAC; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"JENKINS_A"); + addr[nt]=&JENKINS_A; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"JENKINS_C"); + addr[nt]=&JENKINS_C; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"JENKINS_B"); + addr[nt]=&JENKINS_B; + id[nt++]=DOUBLE; + + strcpy(tag[nt],"BEST_FIT"); + addr[nt]=&BEST_FIT; + id[nt++]=INT; + + + if((fd=fopen(fname,"r"))) + { + sprintf(buf,"%s.new",fname); + if(!(fdout=fopen(buf,"w"))) + { + fprintf(stdout,"error opening file '%s' \n",buf); + errorFlag=1; + } + else + { + while(!feof(fd)) + { + fgets(buf,200,fd); + if(sscanf(buf,"%s%s%s",buf1,buf2,buf3)<2) + continue; + + if(buf1[0]=='%') + continue; + + for(i=0,j=-1;i=0) + { + switch(id[j]) + { + case DOUBLE: + if(!((double)atof(buf2)!=*((double*)addr[j]))) + *((double*)addr[j])=atof(buf2); + fprintf(fdout,"%-35s%g\n",buf1,*((double*)addr[j])); + break; + case STRING: + strcpy(addr[j],buf2); + fprintf(fdout,"%-35s%s\n",buf1,buf2); + break; + case INT: + if(!(atoi(buf2)!=*((int*)addr[j]))) + *((int*)addr[j])=atoi(buf2); + fprintf(fdout,"%-35s%d\n",buf1,*((int*)addr[j])); + break; + case CHAR: + if(!(buf2[0]!=*((char*)addr[j]))) + *((char*)addr[j])=buf2[0]; + fprintf(fdout,"%-35s%c\n",buf1,*((int*)addr[j])); + break; + } + } + } + } + } + else + { + fprintf(stderr,"Parameter file %s not found.\n", fname); + exit(1); + } + + fprintf(fdout,"\n\n"); + fclose(fd); + fclose(fdout); + + +#undef DOUBLE +#undef STRING +#undef INT +#undef MAXTAGS +} + + diff --git a/c_tools/hod/pair_density.c b/c_tools/hod/pair_density.c new file mode 100644 index 0000000..1f5a744 --- /dev/null +++ b/c_tools/hod/pair_density.c @@ -0,0 +1,175 @@ +#include +#include +#include +#include "header.h" + +double m_g3,r_g3,*x_g3,*y_g3,*z_g3; +double n_g3; +int flag_g3=0; + +double func_ng(double m); +double func_ng2(double m); + +/* The restr + */ + +double restricted_number_density(double r) +{ + static int flag=1; + static double *x,*y,*y2; + int i,n=50,j; + double mlimit,dlogm,logm,mmin,sum=0,t0,t1,s1,s2,s3,m,r1,r2,ng2,rlim,rmin,rmax; + + if(flag) + { + n_g3 = n; + x_g3=dvector(1,n); + y_g3=dvector(1,n); + z_g3=dvector(1,n); + flag=0; + } + + /* Reset the static variables in this function. + */ + func_ng2(-1); + + r_g3=r; + ng2=GALAXY_DENSITY*GALAXY_DENSITY; + + /* Calculate the maximum allowable halo mass, which had + * rvir = r_g3 - rvir(M_low). + */ + r1=pow(3.*HOD.M_low/(4.*PI*DELTA_HALO*RHO_CRIT*OMEGA_M),1.0/3.0); + rlim = r_g3 - r1; + mlimit=log(4./3.*DELTA_HALO*RHO_CRIT*PI*rlim*rlim*rlim*OMEGA_M); + if(mlimit>log(HOD.M_max))mlimit=log(HOD.M_max); + mmin=log(HOD.M_low); + + if(HOD.color==2) + { + dlogm=(mlimit-mmin)/(n-1); + m = mmin; + for(i=1;i<=n;++i) + { + if(N_avg(exp(m))>0)break; + m += dlogm; + } + mmin = m; + r1=pow(3.*exp(mmin)/(4.*PI*DELTA_HALO*RHO_CRIT*OMEGA_M),1.0/3.0); + rlim = r_g3 - r1; + mlimit=log(4./3.*DELTA_HALO*RHO_CRIT*PI*rlim*rlim*rlim*OMEGA_M); + } + + if(EXCLUSION==2) { + dlogm=(mlimit-mmin)/(n-1); + x_g3[1] = mmin; + y_g3[1] = qromo(func_galaxy_density,mmin,mmin+dlogm,midpnt); + for(i=2;i<=n;++i) + { + x_g3[i] = i*dlogm+mmin; + y_g3[i] = y_g3[i-1] + qromo(func_galaxy_density,(i-1)*dlogm+mmin,mmin+i*dlogm,midpnt); + } + spline(x_g3,y_g3,n,1.0E+30,1.0E+30,z_g3); + s1 = qromo(func_ng2,mmin,mlimit,midpnt); + return(sqrt(s1)); + } + + /* Calculate the double integral at specified masses. + */ + dlogm=(mlimit-mmin)/(n-1); + for(i=1;i<=n;++i) + { + logm=(i-0.5)*dlogm+mmin; + m_g3=exp(logm); + r2 = pow(3*m_g3/(4*PI*DELTA_HALO*RHO_CRIT*OMEGA_M),1.0/3.0); + if(EXCLUSION==3) { + if(ellipsoidal_exclusion_probability(r1/r2,r_g3/(r1+r2))==0)break; } + else { + if(r1+r2>r_g3)break; } + s1=qtrap(func_ng,mmin,mlimit,1.0E-4); + sum+=s1*m_g3*dlogm; + if(s1==0)break; + if(sum>=ng2)break; + } + return sqrt(sum); +} + +double func_ng2(double m) +{ + static double fac2=-1,fac1=-1; + double s1,rv1,n,N,m1,mx; + + if(m<0) + { + fac1=fac2=-1; + return(0); + } + + m1=exp(m); + if(fac2<0) + fac2=pow(3.0/(4.*PI*DELTA_HALO*RHO_CRIT*OMEGA_M),1.0/3.0); + if(fac1<0) + fac1=4./3.*PI*RHO_CRIT*DELTA_HALO*OMEGA_M; + + rv1 = r_g3 - pow(m1,1.0/3.0)*fac2; + rv1 = rv1; + mx = fac1*rv1*rv1*rv1; + + n=dndM_interp(m1); + N=N_avg(m1); + splint(x_g3,y_g3,z_g3,n_g3,log(mx),&s1); + return(n*N*s1*m1); +} + + +double func_ng(double m) +{ + static double fac2=-1; + double s1,rv1,rv2,exfac=1,n,N; + + m=exp(m); + if(fac2<0) + fac2=pow(3.0/(4*DELTA_HALO*PI*RHO_CRIT*OMEGA_M),1.0/3.0); + rv1=pow(m_g3,1.0/3.0)*fac2; + rv2=pow(m,1.0/3.0)*fac2; + + if(EXCLUSION==3) + { + if(0.5*(rv1+rv2)>r_g3)return(0); + if(1.5*(rv1+rv2)>r_g3)exfac=ellipsoidal_exclusion_probability(rv2/rv1,r_g3/(rv2+rv1)); + } + else + { + if(rv1+rv2>r_g3)return(0); + } + + n=dndM_interp(m)*dndM_interp(m_g3); + N=N_avg(m)*N_avg(m_g3); + return(exfac*n*N*m); +} + +/* This is the probability that two halos do not overlap, given their + * radii and separation. Of course, for spherical halos P(x) is a step function + * at x = (r1+r2)/r_sep = 1, but for ellipsoidal halos there is a chance + * that they could be closer. In detail, P(x) changes depending on the mass + * ratio of the halos, but using tabulated values does not appear to make + * significant difference in the results for xi_2h(r). The function below is + * a fit to Monte Carlo results for a halos with a distribution of axis ratios + * which is lognormal in e_b = (1-b/a) and e_c = (1-c/a) with dispersions of 0.2 + * mean =0.9 and =0.8 (pretty reasonable values). + */ +double ellipsoidal_exclusion_probability(double rv, double r) +{ + static int flag=0,nr=101,nratio=31; + static double **xprob,*rad,*ratio,rhi,rlo,mhi,mlo,dr,dm; + float x1,x2,x3; + int i,j,im,ir; + FILE *fp; + + if(rv<1)rv=1.0/rv; + + r=(r-0.8)/0.29; + if(r>1)return(1.0); + if(r<0)return(0.0); + return(3*r*r-2*r*r*r); +} diff --git a/c_tools/hod/polint.c b/c_tools/hod/polint.c new file mode 100644 index 0000000..4fe22fa --- /dev/null +++ b/c_tools/hod/polint.c @@ -0,0 +1,39 @@ +#include +#include +#define NRANSI +#include "nrutil.h" + +void polint(double xa[], double ya[], int n, double x, double *y, double *dy) +{ + int i,m,ns=1; + double den,dif,dift,ho,hp,w; + double *c,*d; + + dif=fabs(x-xa[1]); + c=dvector(1,n); + d=dvector(1,n); + for (i=1;i<=n;i++) { + if ( (dift=fabs(x-xa[i])) < dif) { + ns=i; + dif=dift; + } + c[i]=ya[i]; + d[i]=ya[i]; + } + *y=ya[ns--]; + for (m=1;m +#include +#include +#include +#include + +#include "header.h" + +#define NBINLOOKUP 10000 + +/* This function reads in a halo file and creates a mock galaxy distribution + * by populating the dark matter halos with galaxies with the currently specified + * HOD functions. + * + * The format of the halo file needs to be in ASCII: + * col 1 - halo ID (not used) + * col 2 - number of particles in halo + * cols 3-5 - x,y,z position of halo, in Mpc/h + * col 6 - space velocity of halo (not used) + * cols 7-9 - vx,vy,vz velocity of halo, in km/s + * + * The values of RESOLUTION, BOX_SIZE, OMEGA_M from the batch file are used + * to convert particle number into mass, and to box-wrap galaxies. + * If you want another file format, by all means edit. + * + * Output: mock galaxies are printed to [root].mock + * in format: x,y,z [Mpc/h] vz,vy,vz [km/s] + * + * Output: HOD calculated from populated halos (for cross-checking with true HOD) + * [root].binned_HOD in format: bin id, log10(mass), , N_halo + * + * Satellite positions are chosen from a random sampling of the NFW profile + * for the mass of the halo being populated. If CVIR_FAC is specified, then that value + * will be used to adjust the NFW profile. Satellite velocities are chosen + * from a Gaussin distribution with width = to virial dispersion of halo (plus + * halo center-of-mass). + * + * NB-- If you are using the code to calculate M_min from a desired space density, + * be sure that the linear matter power spectrum is the same as that used in the + * simulation, or else the space densities won't match. [Mass function is used for this + * purpose]. + * + */ +double NFW_central_velocity(double mass, double v[], double mag); +void calc_nbody_two_halo(float **gal, int *id, int ngal); + +double *g21_rad, *g21_xi; +int g21_nrad; + +/* External functions. + */ +void nbrsfind2(float smin,float smax,float rmax,int nmesh,float xpos,float ypos,float zpos, + int *nbrmax,int *indx,float *rsqr,float *x,float *y,float *z, + int *meshparts,int ***meshstart,int ip); +void meshlink2(int np1,int *nmesh,float smin,float smax,float rmax,float *x1,float *y1,float *z1, + int **meshparts,int ****meshstart,int meshfac); +void free_i3tensor(int ***t, long nrl, long nrh, long ncl, long nch, + long ndl, long ndh); + + +void populate_simulation() +{ + FILE *fp,*fpa[9],*fp2,*fpb[9],*fpc[9],*fps[9],*fpt; + int i,j,k,n,imass,n1,j_start=0,i1,galcnt[1000],halocnt[1000],imag; + double mass,xg[3],vg[3],nsat,nc[10],ncen,mlo,mag,err1,err2,r,fac,sigv; + char aa[1000]; + float x1,xh[3],vh[3],vgf[3]; + long IDUM3 = -445; + + float **galarr; + int *galid,id1=0,id2=0,j1; + float dx,dy,dz,dr,drh,rv1,rv2,rmin,rmax; + float **haloarr; + int ngal,nsati[9],ALL_FILES=0,TRACK_GALAXIES=0,WARREN_MASS_CORRECTION=0,haloid; + int nadded; + FILE *fpBuh; + char buhFile[1000]; + + nadded = 0; + + float *xt,*yt,*zt,*vxt,*vyt,*vzt; + + int SO_FILE = 1, + JEANS_DISPERSION = 0; + + // if(RESOLUTION > 1.6) + // WARREN_MASS_CORRECTION = 1; + + TRACK_GALAXIES=1; + + // srand48(IDUM_MCMC); + + galarr = matrix(1,1000000000,0,5); + haloarr = matrix(1,1000000000,0,6); + galid = ivector(1,1000000000); + + fp=openfile(Files.HaloFile); + sprintf(aa,"%s.mock",Task.root_filename); + fp2 = fopen(aa,"w"); + sprintf(aa,"%s.mock_halo",Task.root_filename); + fpt = fopen(aa,"w"); + sprintf(buhFile,"%s.buh",Task.root_filename); + fpBuh = fopen(buhFile,"w"); + + fprintf(fp2, "%f\n", BOX_SIZE); + fprintf(fp2, "%f\n", OMEGA_M); + fprintf(fp2, "%f\n", HUBBLE); + fprintf(fp2, "%f\n", REDSHIFT); + fprintf(fp2, "%d\n", RESOLUTION*RESOLUTION*RESOLUTION); + + for(i=0;i<1000;++i) + halocnt[i]=0; + for(i=0;i<1000;++i) + galcnt[i]=0; + + set_HOD_params(); + mlo = HOD.M_low; + printf("MLO %e %e %f\n",mlo,HOD.M_min,HOD.sigma_logM); + printf("BOX_SIZE %f\n",BOX_SIZE); + fflush(stdout); + + int numHalos = 0; + printf("FORMAT IS %s\n", Files.HaloFileFormat); + printf("FILE IS %s\n", Files.HaloFile); + int numLines = 0; + int dummy = 0; + char* dummyString[200]; + while(!feof(fp)) + { + numLines++; + if(SO_FILE) + { + if (strcmp(Files.HaloFileFormat, "multidark") == 0) { + fscanf(fp,"%f,%f,%f,%f,%f,%f,%lf,%lf,%f,%f,%f,%f", + &xh[0],&xh[1],&xh[2],&vh[0],&vh[1],&vh[2],&mass,&x1,&x1,&x1,&x1,&x1); + } else if (strcmp(Files.HaloFileFormat, "lanl") == 0 || + strcmp(Files.HaloFileFormat, "sdf") == 0) { + fscanf(fp,"%lf %f %f %f %f %f %f\n", + &mass, &xh[0],&xh[1],&xh[2],&vh[0],&vh[1],&vh[2]); + } else if (strcmp(Files.HaloFileFormat, "fnl") == 0) { + if (numLines <= 1) { + fscanf(fp, "%s %s %s %s %s %s %s %s %s\n", dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString); + continue; + } + fscanf(fp,"%d %f %f %f %f %f %f %lf\n", + &dummy, &xh[0],&xh[1],&xh[2],&vh[0],&vh[1],&vh[2],&mass); + } else if (strcmp(Files.HaloFileFormat, "ahf") == 0) { + if (numLines <= 1) { + fscanf(fp,"%s\n", dummyString); + continue; + } else if (numLines <= 2) { + fscanf(fp,"%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s\n", + dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, + dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, + dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, + dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, + dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, + dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, + dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString, dummyString + ); + continue; + } + fscanf(fp,"%d %d %d %lf %d %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\n", + &dummy, &dummy, &dummy, &mass, &dummy, &xh[0], &xh[1], &xh[2], &vh[0], &vh[1], &vh[2], + &x1, &x1, &x1, &x1, &x1, &x1, &x1, &x1, &x1, + &x1, &x1, &x1, &x1, &x1, &x1, &x1, &x1, &x1, &x1, + &x1, &x1, &x1, &x1, &x1, &x1, &x1, &x1, &x1, &x1, + &x1, &x1, &x1, &x1, &x1, &x1, &x1, &x1, &x1, &x1, + &x1, &x1, &x1, &x1, &x1, &x1, &x1, &x1, &x1, &x1, + &x1, &x1, &x1, &x1, &x1, &x1, &x1, &x1, &x1, &x1 + ); + xh[0] /= 1000.; + xh[1] /= 1000.; + xh[2] /= 1000.; + } else { + printf("Unsupported format: %s!\n", Files.HaloFileFormat); + exit(-1); + } + //if (numHalos < 10) { + // printf("READ %e %e %e %e\n", mass, xh[0], xh[1], xh[2]); + //} + //&mass,&x1,&x1,&xh[0],&xh[1],&xh[2],&vh[0],&vh[1],&vh[2]); + //fscanf(fp,"%d %lf %f %f %f %f %f %f %f %f", + // &i,&mass,&x1,&x1,&xh[0],&xh[1],&xh[2],&vh[0],&vh[1],&vh[2]); + /* + fac=sqrt(4.499E-48)*pow(4*DELTA_HALO*PI*OMEGA_M*RHO_CRIT/3,1.0/6.0)*3.09E19; + sigv=fac*pow(mass,1.0/3.0)/sqrt(2.0); + printf("%e %e %f\n",mass,sigv,VBIAS); + if(i==2) + one_halo(1,1); + */ + haloid = numHalos; + numHalos++; + } + else + { + fscanf(fp,"%d %d %e %e %e %e %e %e %e", + &i,&imass,&xh[0],&xh[1],&xh[2],&x1,&vh[0],&vh[1],&vh[2]); + mass=imass*RHO_CRIT*OMEGA_M*pow(RESOLUTION,3.0); + } + haloid = i; + if(mass>HOD.M_max)continue; + + if(WARREN_MASS_CORRECTION) + mass = imass*(1-pow(imass,-0.6))*RHO_CRIT*OMEGA_M*pow(RESOLUTION,3.0); + + + if(massBOX_SIZE)xh[i]-=BOX_SIZE; + } + + i1 = (int)(log10(mass)/0.1); + halocnt[i1]++; + ncen=N_cen(mass); + if(drand48()>ncen)goto SATELLITES; + if(VBIAS_C>0) + { + NFW_central_velocity(mass,vg,mag); + for(i=0;i<3;++i) + vh[i]+=vg[i]; + } + fprintf(fp2,"%d %e %e %e %e %e %e %e\n",nadded,xh[0],xh[1],xh[2],vh[2],vh[1],vh[0], mass); + nadded++; + //fprintf(fp2,"%e %e %e %e %e %e\n",xh[0],xh[1],xh[2],vh[0],vh[1],vh[2]); + fprintf(fpt,"%d\n",haloid); + + // THis mocks up the ~22 columns of the MR mocks + // fprintf(fpt,"%d %d %d %e %e %e 0.0 0.0 0.0 %e %e %e 0.0 0.0 0.0 0.0 0.0 0.0 %e 0.0 0.0\n", + // 0,0,0,xh[0],xh[1],xh[2],vh[0],vh[1],vh[2],log10(mass)); + + if(VBIAS_C>0) + { + for(i=0;i<3;++i) + vh[i]-=vg[i]; + } + + galcnt[i1]++; + + if(TRACK_GALAXIES) + { + id2++; + galid[id2] = haloid; + galarr[id2][0] = xh[0]; + galarr[id2][1] = xh[1]; + galarr[id2][2] = xh[2]; + galarr[id2][3] = vh[0]; + galarr[id2][4] = vh[1]; + galarr[id2][5] = vh[2]; + } + + if(TRACK_GALAXIES) + { + id1++; + haloarr[id1][0] = xh[0]; + haloarr[id1][1] = xh[1]; + haloarr[id1][2] = xh[2]; + haloarr[id1][3] = vh[0]; + haloarr[id1][4] = vh[1]; + haloarr[id1][5] = vh[2]; + haloarr[id1][6] = mass; + } + + SATELLITES: + + nsat = N_sat(mass); + if(nsat>250) + n1 = gasdev(&IDUM3)*sqrt(nsat) + nsat; + else + n1 = poisson_deviate(nsat); + ///* + if(nsat>=1) + fprintf(fpBuh,"%d %f %e %d %e %f\n",haloid,nsat,mass,n1,HOD.M1,pow(mass/HOD.M1,HOD.alpha)); + //fprintf(stdout,"BUH %d %f %e %d %e %f\n",haloid,nsat,mass,n1,HOD.M1,pow(mass/HOD.M1,HOD.alpha)); + // */ + + for(i=1;i<=n1;++i) + { + r = NFW_position(mass,xg); + if(JEANS_DISPERSION) + jeans_dispersion(mass,r,vg); + else + NFW_velocity(mass,vg,mag); + for(k=0;k<3;++k) + { + xg[k]+=xh[k]; + if(xg[k]<0)xg[k]+=BOX_SIZE; + if(xg[k]>BOX_SIZE)xg[k]-=BOX_SIZE; + vg[k]+=vh[k]; + /* vg[k] = vgf[k]; */ + /* + vg[k] = gasdev(&IDUM3)*500; + vg[k] = non_gaussian_velocity(); + */ + } + fprintf(fp2,"%d %e %e %e %e %e %e %e\n",i, xg[0],xg[1],xg[2],vg[2],vg[1],vg[0],mass); + //fprintf(fp2,"%e %e %e %e %e %e\n",xg[0],xg[1],xg[2],vg[0],vg[1],vg[2]); + fprintf(fpt,"%d\n",haloid); + + // fprintf(fpt,"%d %d %d %e %e %e 0.0 0.0 0.0 %e %e %e 0.0 0.0 0.0 0.0 0.0 0.0 %e 0.0 0.0\n",1,1,1,xg[0],xg[1],xg[2],vg[0],vg[1],vg[2],log10(mass)); + + if(TRACK_GALAXIES) + { + id2++; + galid[id2] = haloid; + galarr[id2][0] = xg[0]; + galarr[id2][1] = xg[1]; + galarr[id2][2] = xg[2]; + galarr[id2][3] = vg[0]; + galarr[id2][4] = vg[1]; + galarr[id2][5] = vg[2]; + } + + /* Bin up the galaxies by halo mass to check the HOD + */ + galcnt[i1]++; + } + + if(feof(fp))break; + } + fprintf(fp2, "-99 -99 -99 -99 -99 -99 -99 -99\n"); // signals end of particle list + fclose(fp2); + fclose(fpt); + fclose(fpBuh); + + printf("GALAXY DENSITY %e\n", GALAXY_DENSITY); + /* output the binned HOD + */ + sprintf(aa,"%s.binned_HOD",Task.root_filename); + fp2=fopen(aa,"w"); + for(i=0;i<1000;++i) + if(galcnt[i]>0) + fprintf(fp2,"%d %f %f %d %d\n", + i,(i+0.5)*0.1,(float)galcnt[i]/halocnt[i],galcnt[i],halocnt[i]); + fclose(fp2); + + /* Calculate the two-halo term + */ + if(TRACK_GALAXIES) + { + fprintf(stderr,"Calling nbody_2halo...\n"); + calc_nbody_two_halo(galarr,galid,id2); + } + return ; + + /* Track the close pairs - for Non-Tinkers, don't worry about this. + */ + rmin = 1.5; + rmax = 2.5; + for(i=1;i<=id2;++i) + for(j=i+1;j<=id2;++j) + { + if(galid[i]==galid[j])continue; + dx = galarr[i][0] - galarr[j][0]; + if(dx>BOX_SIZE/2)dx = BOX_SIZE-dx; + if(dx>rmax)continue; + dy = galarr[i][1] - galarr[j][1]; + if(dy>BOX_SIZE/2)dy = BOX_SIZE-dy; + if(dy>rmax)continue; + dz = galarr[i][2] - galarr[j][2]; + if(dz>BOX_SIZE/2)dz = BOX_SIZE-dz; + if(dz>rmax)continue; + dr = sqrt(dx*dx+dy*dy+dz*dz); + if(drrmax)continue; + + i1 = galid[i]; + j1 = galid[j]; + dx = haloarr[i1][0] - haloarr[j1][0]; + if(dx>BOX_SIZE/2)dx = BOX_SIZE-dx; + dy = haloarr[i1][1] - haloarr[j1][1]; + if(dy>BOX_SIZE/2)dy = BOX_SIZE-dy; + dz = haloarr[i1][2] - haloarr[j1][2]; + if(dz>BOX_SIZE/2)dz = BOX_SIZE-dz; + drh = sqrt(dx*dx+dy*dy+dz*dz); + + rv1 = pow(3*haloarr[i1][6]/(4*DELTA_HALO*PI*RHO_CRIT*OMEGA_M),1.0/3.0); + rv2 = pow(3*haloarr[j1][6]/(4*DELTA_HALO*PI*RHO_CRIT*OMEGA_M),1.0/3.0); + if(dr < rv1+rv2) + { + dx = galarr[i][3] - galarr[j][3]; + dy = galarr[i][4] - galarr[j][4]; + dz = galarr[i][5] - galarr[j][5]; + printf("%e %e %e %e %e %e %e\n",dr,rv1+rv2,haloarr[i1][6],haloarr[j1][6],dx,dy,dz); + fflush(stdout); + } + } + + exit(0); +} + +/* Generate a random integer based on a Poisson distribution + * with mean given as input. + */ +int poisson_deviate(double nave) +{ + static int flag=0; + double p,pp; + int n; + + p=0; + pp=1; + + while(p0) + for(i=1;i<=n;++i) + fac*=nave/i; + + return((float)(fac*exp(-nave))); +} + +/* Randomy generates a position away from the origin with + * a probability given by the NFW profile for a halo of the input + * mass (and including the CVIR_FAC) + */ +double NFW_position(double mass, double x[]) +{ + double r,pr,max_p,costheta,sintheta,phi1,signs,rvir,rs,cvir; + + cvir=halo_concentration(mass)*CVIR_FAC; + rvir=pow(3*mass/(4*DELTA_HALO*PI*RHO_CRIT*OMEGA_M),1.0/3.0); + rs=rvir/cvir; + max_p=NFW_density(rs,rs,1.0)*rs*rs*4.0*PI; + + for(;;) { + r=drand48()*rvir; + pr=NFW_density(r,rs,1.0)*r*r*4.0*PI/max_p; + + if(drand48()<=pr) + { + costheta=2.*(drand48()-.5); + sintheta=sqrt(1.-costheta*costheta); + signs=2.*(drand48()-.5); + costheta=signs*costheta/fabs(signs); + phi1=2.0*PI*drand48(); + + x[0]=r*sintheta*cos(phi1); + x[1]=r*sintheta*sin(phi1); + x[2]=r*costheta; + return r; + } + } +} + +/* This is the NFW density profile + */ +double NFW_density(double r, double rs, double ps) +{ + return(ps*rs/(r*(1+r/rs)*(1+r/rs))); +} + +/* This sets the velocity to be isotropic Gaussian. + */ +double NFW_velocity(double mass, double v[], double mag) +{ + static long IDUM2=-455; + static double fac = -1; + double sigv,vbias=1; + int i; + + if(fac<0) + fac=sqrt(4.499E-48)*pow(4*DELTA_HALO*PI*OMEGA_M*RHO_CRIT/3,1.0/6.0)*3.09E19; + sigv=fac*pow(mass,1.0/3.0)/sqrt(2.0); + for(i=0;i<3;++i) + v[i]=gasdev(&IDUM2)*sigv*VBIAS; + return(0); +} + +/* This sets the velocity to be isotropic Gaussian. + */ +double NFW_central_velocity(double mass, double v[], double mag) +{ + static long IDUM2=-455; + static double fac = -1; + double sigv,vbias=1; + int i; + + if(fac<0) + fac=sqrt(4.499E-48)*pow(4*DELTA_HALO*PI*OMEGA_M*RHO_CRIT/3,1.0/6.0)*3.09E19; + sigv=fac*pow(mass,1.0/3.0)/sqrt(2.0); + for(i=0;i<3;++i) + v[i]=gasdev(&IDUM2)*sigv*VBIAS_C; + return(0); +} + + +/* This is the routine where we tabulate the 2-halo term and + * interpolate as needed. + */ +double nbody_two_halo(double r) +{ + static int flag=1,n=30; + static double *x,*y,*y2; + double a; + int i; + + if(flag || RESET_FLAG_1H) + { + populate_simulation(); + if(flag) + { + n = g21_nrad; + x=dvector(1,n); + y=dvector(1,n); + y2=dvector(1,n); + } + flag=0; + for(i=1;i<=n;++i) + { + x[i] = g21_rad[i]; + y[i] = g21_xi[i]; + } + /* + if(OUTPUT) + printf("Calculating nbody xi(r)...\n"); + calc_nbody_two_halo(x,y,n); + if(OUTPUT) + printf("finished\n"); + for(i=1;i<=n;++i) + y[i]=log(y[i]); + */ + spline(x,y,n,1.0E+30,1.0E+30,y2); + RESET_FLAG_1H=0; + } + // r=log(r); + if(r<0.2)return(-1); + splint(x,y,y2,n,r,&a); + return(a); + // return(exp(a)); +} + +/* This is the two-halo term. + */ +void calc_nbody_two_halo(float **gal, int *id, int ngal) +{ + float rmax,rmin,lrstep,binfac,rcube,weight0,fac,rlow,density,weightrandom,vol,r; + int ibin,kbin,nbin,i,j,k,*binlookup,*npair,ngal_temp; + + float *rupp,*rsqr,reduction_factor,*vxt,*vyt,*vzt; + int *meshparts, ***meshstart,nmesh,meshfac,nbrmax,*indx; + double *rbar,galden; + + float *xg,*yg,*zg,*xt,*yt,*zt; + + static float *rad, *xi; + static int nr, flag = 0; + + char fname[100]; + FILE *fp; + + sprintf(fname,"%s.nbody_2halo",Task.root_filename); + fp = fopen(fname,"w"); + + rmax = 30; + rmin = 0.1; + nbin = nr = 20; + + rad = vector(1,nr); + xi = vector(1,nr); + g21_rad = dvector(1,nr); + g21_xi = dvector(1,nr); + g21_nrad = nr; + + xg = malloc(ngal*sizeof(float)); + yg = malloc(ngal*sizeof(float)); + zg = malloc(ngal*sizeof(float)); + + ngal_temp=0; + for(i=1;i<=ngal;++i) + { + xg[ngal_temp] = gal[i][0]; + yg[ngal_temp] = gal[i][1]; + zg[ngal_temp] = gal[i][2]; + ngal_temp++; + } + ngal = ngal_temp; + + indx=malloc(ngal*sizeof(int)); + rsqr=malloc(ngal*sizeof(float)); + + /*********************** + * initializing the logarithmic bins + */ + rupp = (float *) calloc(nbin+1,sizeof(float)) ; + lrstep=log(rmax/rmin)/(float)(nbin-1) ; + binlookup=(int *)calloc(NBINLOOKUP+2,sizeof(int)) ; + ibin=0 ; + for (i=0;i<=NBINLOOKUP;i++) { + r=rmax*i/NBINLOOKUP ; + if (r>0) { + kbin=(int)floor(log(r/rmin)/lrstep+1.0) ; + } + else { + kbin=0 ; + } + if (kbin<0) kbin=0 ; + if (kbin>ibin) { + rupp[ibin]=r ; + ibin=kbin ; + } + binlookup[i]=kbin ; + } + binlookup[NBINLOOKUP+1]=nbin ; + rupp[nbin-1]=rmax ; + rupp[nbin]=rmax ; + binfac=NBINLOOKUP/rmax ; + + rbar=calloc(nbin,sizeof(double)); + npair=calloc(nbin,sizeof(int)); + + rcube = BOX_SIZE; + + nmesh=0; + printf("STARTING MESHLINK\n"); + printf("PARAMETERS: %e %e %e\n", 0.0, rcube, rmax); + meshlink2(ngal,&nmesh,0.0,rcube,rmax,xg,yg,zg,&meshparts,&meshstart,meshfac); + printf("DONE WITH MESHLINK\n"); + + + for(i=0;i=nbin)continue; + npair[kbin]++; + rbar[kbin]+=r; + } + } + + density=ngal/(rcube*rcube*rcube) ; + + rlow=0; + for (kbin=0;kbin0.0) { + fac=1./weight0 ; + rbar[kbin] *= fac ; + } + else { /* avoid errors in empty bins */ + rbar[kbin]=(rupp[kbin]+rlow)*0.5; + } + + /* compute xi, dividing summed weight by that expected for a random set */ + vol=4.*PI/3.*(rupp[kbin]*rupp[kbin]*rupp[kbin]-rlow*rlow*rlow) ; + weightrandom=ngal*density*vol ; + + g21_rad[kbin+1] = rad[kbin+1]=log(rbar[kbin]); + g21_xi[kbin+1] = xi[kbin+1]=weight0/weightrandom-1 ; + rlow=rupp[kbin] ; + + fprintf(fp,"%e %e %.0f\n",rbar[kbin],xi[kbin+1],weight0); + + if(OUTPUT>1) + { + fprintf(stdout,"nbody_xi> %f %f %.0f\n",rbar[kbin],xi[kbin+1],weight0); + fflush(stdout); + } + } + fclose(fp); + + free(indx); + free(rsqr); + free(rupp); + free(binlookup); + free(npair); + free(rbar); + + free_i3tensor(meshstart,0,nmesh-1,0,nmesh-1,0,nmesh-1); +} + diff --git a/c_tools/hod/powell.c b/c_tools/hod/powell.c new file mode 100644 index 0000000..b634bdc --- /dev/null +++ b/c_tools/hod/powell.c @@ -0,0 +1,58 @@ +#include +#define NRANSI +#include "nrutil.h" +#define ITMAX 200 + +void powell(double p[], double **xi, int n, double ftol, int *iter, double *fret, + double (*func)(double [])) +{ + void linmin(double p[], double xi[], int n, double *fret, + double (*func)(double [])); + int i,ibig,j; + double del,fp,fptt,t,*pt,*ptt,*xit; + + pt=dvector(1,n); + ptt=dvector(1,n); + xit=dvector(1,n); + *fret=(*func)(p); + for (j=1;j<=n;j++) pt[j]=p[j]; + for (*iter=1;;++(*iter)) { + fp=(*fret); + ibig=0; + del=0.0; + for (i=1;i<=n;i++) { + for (j=1;j<=n;j++) xit[j]=xi[j][i]; + fptt=(*fret); + linmin(p,xit,n,fret,func); + if (fabs(fptt-(*fret)) > del) { + del=fabs(fptt-(*fret)); + ibig=i; + } + } + if (2.0*fabs(fp-(*fret)) <= ftol*(fabs(fp)+fabs(*fret))) { + free_dvector(xit,1,n); + free_dvector(ptt,1,n); + free_dvector(pt,1,n); + return; + } + if (*iter == ITMAX) nrerror("powell exceeding maximum iterations."); + for (j=1;j<=n;j++) { + ptt[j]=2.0*p[j]-pt[j]; + xit[j]=p[j]-pt[j]; + pt[j]=p[j]; + } + fptt=(*func)(ptt); + if (fptt < fp) { + t=2.0*(fp-2.0*(*fret)+fptt)*SQR(fp-(*fret)-del)-del*SQR(fp-fptt); + if (t < 0.0) { + linmin(p,xit,n,fret,func); + for (j=1;j<=n;j++) { + xi[j][ibig]=xi[j][n]; + xi[j][n]=xit[j]; + } + } + } + } +} +#undef ITMAX +#undef NRANSI diff --git a/c_tools/hod/powspec.c b/c_tools/hod/powspec.c new file mode 100644 index 0000000..1d5bbff --- /dev/null +++ b/c_tools/hod/powspec.c @@ -0,0 +1,214 @@ +#include "header.h" + +double sig8; // value of sigma_8 +double rho; // current density of universe (solar mass/Mpc^3) +double G0; // present day density cst +double Gl; // Cosmological Constant densty +double H0; // Hubble cst km/s.MPc +double pow_n; // Scalar spectral index +double bfrac; // Baryon fraction of total density +double Gamma; // P(k) parameter - normally unused +double pow_norm; // power spectrum normalisation +double NB_density; // Nbody density being modelled +int pow_spec_type=2; // choice of power spectrum + +// set up rho and power spectrum normalisation +void nm_power_eh() +{ + double r, mass, sigmasq; + + rho = 3.*G0*(3.236e-20*H0)*(3.236e-20*H0)/(8.*pi*G_cst*M_sun/(Mpc*Mpc*Mpc)); + fprintf(stderr,"h=%g, rho=%g\n",H0/100.,rho); + + r = 8.0; + mass = 4./3.*pi*r*r*r*rho; + pow_norm=1.; + sigmasq=qmidinf(Sigth_eh,1.0,1.e40,r)/(2.*pi*pi); + pow_norm=(sig8*sig8)/sigmasq; + fprintf(stderr,"r=%g, mass=%g, sig8=%g, nor=%g\n",r,mass,sig8, pow_norm); +} + +// Sigmasq no filter : return D^2(k) +double Sig_eh(double lnk) { + double k; + k = pow(10.,lnk); + return k*k*k*Pk(k)/(2.*pi*pi); +} + +// Sigmasq for a top hat filter - integrate 0..infinity +double Sigth_eh( double kplus1, double R ) +{ + double k, x, W; + + k = kplus1-1.0; + x = k*R; + W = 3.*(sin(x) - x*cos(x))/(x*x*x); + + return W*W*k*k*Pk(k); +} + +// Power spectrum +float Pk(float k) +{ + float pn=0.0; + float q, tf, tfsq=0.0; + float tk_eh(float); + if(k==0.) return 0.; + + switch(pow_spec_type) { + + // BBKS + case 1: + q = k/Gamma; + tf = log(1.+2.34*q)/(2.34*q); + tfsq = tf*tf/sqrt(1.0+q*(3.89+q*(259.21+q*(162.77+q*2027.17)))); + pn = pow_norm*pow(k,pow_n)*tfsq; + break; + + // Eisenstein & Hu + case 2: + tf = tk_eh(k); + tfsq = tf*tf; + pn = pow_norm*pow(k,pow_n)*tfsq; + break; + + // Power law k^(pow_n) + case 3: + tfsq = 1.0; + pn = pow_norm*pow(k,pow_n)*tfsq; + break; + + // DEFW P(k) + case 4: + q = k/Gamma; + tf = pow(1.+pow(6.4*q+pow(3.0*q,1.5)+pow(1.7*q,2.),1.13),(-1./1.13)); + tfsq = tf*tf; + pn = pow_norm*pow(k,pow_n)*tfsq; + break; + + // baryonic fit + // case 5: + // pn = sin(fit_phi+k/fit_kc); + // pn = pow_norm*(1.+fit_a*k+fit_b*k*k)*pn*pn; + // break; + + // Eisenstein & Hu + non-linear approximation + case 6: + tf = tk_eh(k); + tfsq = tf*tf; + pn = pow_norm*pow(k,pow_n)*tfsq; + if(k>0.2) pn = exp( 2.0*(1.+log(k)-log(0.2))*log(pn) ); + break; + + // Eisenstein & Hu + shot noise + case 7: + tf = tk_eh(k); + tfsq = tf*tf; + pn = pow_norm*pow(k,pow_n)*tfsq; + if(k<=(2.*2.*pi*pow(NB_density,1./3.))) pn += 1.0/NB_density; + break; + + } + + return pn; +} + +// Transfer function of Eisenstein & Hu 1998 +// (Equation numbers refer to this paper) + +float tk_eh(float k) +{ + float rk,e,thet,thetsq,thetpf,b1,b2,zd,ze,rd,re,rke,s,rks,q,y,g; + float ab,a1,a2,ac,bc,f,c1,c2,tc,bb,bn,ss,tb,tk_eh; + float h,hsq,om_mhsq,om_b,om_m; + + // set up cosmology + h = H0/100.0; + om_m = G0; + om_b = bfrac*om_m; + + // convert k to Mpc^-1 rather than hMpc^-1 + rk=k*h; + hsq=h*h; + om_mhsq=om_m*hsq; + + // constants + e=exp(1.); + thet=2.728/2.7; + thetsq=thet*thet; + thetpf=thetsq*thetsq; + + // Equation 4 - redshift of drag epoch + b1=0.313*pow(om_mhsq,-0.419)*(1.+0.607*pow(om_mhsq,0.674)); + b2=0.238*pow(om_mhsq,0.223); + zd=1291.*(1.+b1*pow(om_b*hsq,b2))*pow(om_mhsq,0.251) + /(1.+0.659*pow(om_mhsq,0.828)); + + // Equation 2 - redshift of matter-radiation equality + ze=2.50e4*om_mhsq/thetpf; + + // value of R=(ratio of baryon-photon momentum density) at drag epoch + rd=31500.*om_b*hsq/(thetpf*zd); + + // value of R=(ratio of baryon-photon momentum density) at epoch of matter-radiation equality + re=31500.*om_b*hsq/(thetpf*ze); + + // Equation 3 - scale of ptcle horizon at matter-radiation equality + rke=7.46e-2*om_mhsq/(thetsq); + + // Equation 6 - sound horizon at drag epoch + s=(2./3./rke)*sqrt(6./re)*log((sqrt(1.+rd)+sqrt(rd+re))/(1.+sqrt(re))); + + // Equation 7 - silk damping scale + rks=1.6*pow(om_b*hsq,0.52)*pow(om_mhsq,0.73)*(1.+pow(10.4*om_mhsq,-0.95)); + + // Equation 10 - define q + q=rk/13.41/rke; + + // Equations 11 - CDM transfer function fits + a1=pow(46.9*om_mhsq,0.670)*(1.+pow(32.1*om_mhsq,-0.532)); + a2=pow(12.0*om_mhsq,0.424)*(1.+pow(45.0*om_mhsq,-0.582)); + ac=pow(a1,(-om_b/om_m))*pow(a2,pow(-(om_b/om_m),3.)); + + // Equations 12 - CDM transfer function fits + b1=0.944/(1.+pow(458.*om_mhsq,-0.708)); + b2=pow(0.395*om_mhsq,-0.0266); + bc=1./(1.+b1*(pow(1.-om_b/om_m,b2)-1.)); + + // Equation 18 + f=1./(1.+pow(rk*s/5.4,4.)); + + // Equation 20 + c1=14.2 + 386./(1.+69.9*pow(q,1.08)); + c2=14.2/ac + 386./(1.+69.9*pow(q,1.08)); + + // Equation 17 - CDM transfer function + tc=f*log(e+1.8*bc*q)/(log(e+1.8*bc*q)+c1*q*q) + + (1.-f)*log(e+1.8*bc*q)/(log(e+1.8*bc*q)+c2*q*q); + + // Equation 15 + y=(1.+ze)/(1.+zd); + g=y*(-6.*sqrt(1.+y)+(2.+3.*y)*log((sqrt(1.+y)+1.)/(sqrt(1.+y)-1.))); + + // Equation 14 + ab=g*2.07*rke*s/pow(1.+rd,0.75); + + // Equation 23 + bn=8.41*pow(om_mhsq,0.435); + + // Equation 22 + ss=s/pow(1.+pow(bn/rk/s,3.),1./3.); + + // Equation 24 + bb=0.5+(om_b/om_m) + (3.-2.*om_b/om_m)*sqrt(pow(17.2*om_mhsq,2.)+1.); + + // Equations 19 & 21 + tb=log(e+1.8*q)/(log(e+1.8*q)+c1*q*q)/(1+pow(rk*s/5.2,2.)); + tb=(tb+ab*exp(-pow(rk/rks,1.4))/(1.+pow(bb/rk/s,3.)))*sin(rk*ss)/rk/ss; + + // Equation 8 + tk_eh=(om_b/om_m)*tb+(1.-om_b/om_m)*tc; + + return tk_eh; +} + diff --git a/c_tools/hod/qromo.c b/c_tools/hod/qromo.c new file mode 100644 index 0000000..6783f76 --- /dev/null +++ b/c_tools/hod/qromo.c @@ -0,0 +1,34 @@ +#include +#include +#include "header.h" +#define EPS 1.0e-6 +#define JMAX 14 +#define JMAXP (JMAX+1) +#define K 5 + +double qromo(double (*func)(double), double a, double b, + double (*choose)(double(*)(double), double, double, int)) +{ + void polint(double xa[], double ya[], int n, double x, double *y, double *dy); + void nrerror(char error_text[]); + int j; + double ss,dss,h[JMAXP+1],s[JMAXP+1]; + + h[1]=1.0; + for (j=1;j<=JMAX;j++) { + s[j]=(*choose)(func,a,b,j); + if (j >= K) { + polint(&h[j-K],&s[j-K],K,0.0,&ss,&dss); + if (fabs(dss) < EPS*fabs(ss)) return ss; + } + s[j+1]=s[j]; + h[j+1]=h[j]/9.0; + } + printf("ERROR: Too many steps in routing qromo\n"); + ERROR_FLAG=1; + return ss; +} +#undef EPS +#undef JMAX +#undef JMAXP +#undef K diff --git a/c_tools/hod/qtrap.c b/c_tools/hod/qtrap.c new file mode 100644 index 0000000..8e7e52e --- /dev/null +++ b/c_tools/hod/qtrap.c @@ -0,0 +1,20 @@ +#include +#include +#define JMAX 20 + +double qtrap(double (*func)(double), double a, double b, double EPS) +{ + double trapzd(double (*func)(double), double a, double b, int n); + /*void nrerror(char error_text[]);*/ + int j; + double s,olds,t1,t2; + + olds = -1.0e30; + for (j=1;j<=JMAX;j++) { + s=trapzd(func,a,b,j); + if (fabs(s-olds) < EPS*fabs(olds)) return s; + olds=s; + } + return s; +} +#undef JMAX diff --git a/c_tools/hod/ran1.c b/c_tools/hod/ran1.c new file mode 100644 index 0000000..af5cf9a --- /dev/null +++ b/c_tools/hod/ran1.c @@ -0,0 +1,47 @@ +#define IA 16807 +#define IM 2147483647 +#define AM (1.0/IM) +#define IQ 127773 +#define IR 2836 +#define NTAB 32 +#define NDIV (1+(IM-1)/NTAB) +#define EPS 1.2e-7 +#define RNMX (1.0-EPS) + +float ran1(long *idum) +{ + int j; + long k; + static long iy=0; + static long iv[NTAB]; + float temp; + + if (*idum <= 0 || !iy) { + if (-(*idum) < 1) *idum=1; + else *idum = -(*idum); + for (j=NTAB+7;j>=0;j--) { + k=(*idum)/IQ; + *idum=IA*(*idum-k*IQ)-IR*k; + if (*idum < 0) *idum += IM; + if (j < NTAB) iv[j] = *idum; + } + iy=iv[0]; + } + k=(*idum)/IQ; + *idum=IA*(*idum-k*IQ)-IR*k; + if (*idum < 0) *idum += IM; + j=iy/NDIV; + iy=iv[j]; + iv[j] = *idum; + if ((temp=AM*iy) > RNMX) return RNMX; + else return temp; +} +#undef IA +#undef IM +#undef AM +#undef IQ +#undef IR +#undef NTAB +#undef NDIV +#undef EPS +#undef RNMX diff --git a/c_tools/hod/ran2.c b/c_tools/hod/ran2.c new file mode 100644 index 0000000..8ae2f2a --- /dev/null +++ b/c_tools/hod/ran2.c @@ -0,0 +1,63 @@ +#define IM1 2147483563 +#define IM2 2147483399 +#define AM (1.0/IM1) +#define IMM1 (IM1-1) +#define IA1 40014 +#define IA2 40692 +#define IQ1 53668 +#define IQ2 52774 +#define IR1 12211 +#define IR2 3791 +#define NTAB 32 +#define NDIV (1+IMM1/NTAB) +#define EPS 1.2e-7 +#define RNMX (1.0-EPS) + +double ran2(long *idum) +{ + int j; + long k; + static long idum2=123456789; + static long iy=0; + static long iv[NTAB]; + double temp; + + if (*idum <= 0) { + if (-(*idum) < 1) *idum=1; + else *idum = -(*idum); + idum2=(*idum); + for (j=NTAB+7;j>=0;j--) { + k=(*idum)/IQ1; + *idum=IA1*(*idum-k*IQ1)-k*IR1; + if (*idum < 0) *idum += IM1; + if (j < NTAB) iv[j] = *idum; + } + iy=iv[0]; + } + k=(*idum)/IQ1; + *idum=IA1*(*idum-k*IQ1)-k*IR1; + if (*idum < 0) *idum += IM1; + k=idum2/IQ2; + idum2=IA2*(idum2-k*IQ2)-k*IR2; + if (idum2 < 0) idum2 += IM2; + j=iy/NDIV; + iy=iv[j]-idum2; + iv[j] = *idum; + if (iy < 1) iy += IMM1; + if ((temp=AM*iy) > RNMX) return RNMX; + else return temp; +} +#undef IM1 +#undef IM2 +#undef AM +#undef IMM1 +#undef IA1 +#undef IA2 +#undef IQ1 +#undef IQ2 +#undef IR1 +#undef IR2 +#undef NTAB +#undef NDIV +#undef EPS +#undef RNMX diff --git a/c_tools/hod/sigmac.c b/c_tools/hod/sigmac.c new file mode 100644 index 0000000..ca1912f --- /dev/null +++ b/c_tools/hod/sigmac.c @@ -0,0 +1,173 @@ +#include +#include +#include + +#include "header.h" + +/* + * sigmac calls qromo to evaluate the integral + + int_0^infty P_s(k) 4 pi k^2 dk / (2pi)^3 + + where P_s(k) is the power spectrum smoothed through a gaussian + window of radius rgaus and a top hat window of radius rth. + The power spectrum is a power law of index xindx, multiplied by + the square of the CDM transfer function if itrans = 1. + + If the smoothing radius [rad] is positive, a top-hat window + function is used. + If [rad<0], a gaussian window function is used. + +*/ + + +double rad1; +double func_sigmac(double xk); +double func_sigmac_nl(double xk); + +double sigmac_interp(double m) +{ + static int flag=0,prev_cosmo=0; + static double *x,*y,*y2, pnorm; + int i,n=100; + double dlogm,max=5.e16,min=1.0e7,a,b,m1,m2,dm1,xi,power,rm,sig,b1,b2,mass; + + if(!flag || RESET_COSMOLOGY!=prev_cosmo) + { + if(!ThisTask && OUTPUT) + fprintf(stdout,"RESET: resetting bias for %f %f\n",OMEGA_M,SIGMA_8); + if(!flag) + { + x=dvector(1,n); + y=dvector(1,n); + y2=dvector(1,n); + } + flag=1; + dlogm = (log(max) - log(min))/(n-1); + pnorm=SIGMA_8/sigmac(8.0); + for(i=1;i<=n;++i) + { + m = exp((i-1)*dlogm)*min; + rm=pow(3.0*m/(4.0*PI*OMEGA_M*RHO_CRIT),1.0/3.0); + sig=log(pnorm*sigmac(rm)); + x[i] = log(m); + y[i] = sig; + } + spline(x,y,n,2.0E+30,2.0E+30,y2); + prev_cosmo=RESET_COSMOLOGY; + + } + m=log(m); + splint(x,y,y2,n,m,&a); + return exp(a); +} + +double sigmac_radius_interp(double m) +{ + static int flag=0,prev_cosmo=0; + static double *x,*y,*y2, pnorm; + int i,n=100; + double dlogm,max=80.0,min=0.1,a,b,m1,m2,dm1,xi,power,rm,sig,b1,b2,mass; + + if(!flag || RESET_COSMOLOGY!=prev_cosmo) + { + if(!ThisTask && OUTPUT) + fprintf(stdout,"RESET: resetting bias for %f %f\n",OMEGA_M,SIGMA_8); + if(!flag) + { + x=dvector(1,n); + y=dvector(1,n); + y2=dvector(1,n); + } + flag=1; + dlogm = (log(max) - log(min))/(n-1); + pnorm=SIGMA_8/sigmac(8.0); + for(i=1;i<=n;++i) + { + rm = exp((i-1)*dlogm)*min; + sig=log(pnorm*sigmac(rm)); + x[i] = log(rm); + y[i] = sig; + } + spline(x,y,n,2.0E+30,2.0E+30,y2); + prev_cosmo=RESET_COSMOLOGY; + + } + m=log(m); + splint(x,y,y2,n,m,&a); + return exp(a); +} + + +double sigmac(double rad) +{ + double xk1,s1=1,s2=0,sigma0; + + rad1=rad; + xk1 = 1./(2.*PI*mabs(rad)); + s1=qromo(func_sigmac,0.0,xk1,midpnt); + s2=qromo(func_sigmac,xk1,1.e20,midinf); + sigma0=sqrt((s1+s2)*(4*PI)/pow(2*PI,3.0)); + return sigma0; + +} + +double func_sigmac(double xk) +{ + double xkr,w,psp; + + if(rad1>0) + { + xkr = xk*rad1; + w = 3*(sin(xkr)-xkr*cos(xkr))/(xkr*xkr*xkr); + w = w*w; + } + else + { + xkr = -rad1*xk; + w = exp(-xkr*xkr); + } + + if(ITRANS>0) + psp=pow(xk,SPECTRAL_INDX)*pow(transfnc(xk),2.0); + else + psp=pow(xk,SPECTRAL_INDX); + psp=psp*w*xk*xk; + return(psp); +} + +/* Same as above, but no instead of using the linear + * theory power spectrum, use the non-linear P(k) + */ +double nonlinear_sigmac(double rad) +{ + double xk1,s1=1,s2=0,sigma0; + + rad1=rad; + xk1 = 1./(2.*PI*mabs(rad)); + s1=qromo(func_sigmac_nl,0.0,xk1,midpnt); + s2=qromo(func_sigmac_nl,xk1,1.e20,midinf); + sigma0=sqrt((s1+s2)); + return sigma0; +} + +double func_sigmac_nl(double xk) +{ + double xkr,w,psp; + + if(rad1>0) + { + xkr = xk*rad1; + w = 3*(sin(xkr)-xkr*cos(xkr))/(xkr*xkr*xkr); + w = w*w; + } + else + { + xkr = -rad1*xk; + w = exp(-xkr*xkr); + } + + psp=nonlinear_power_spectrum(xk); + psp=psp*w/xk; + return(psp); +} diff --git a/c_tools/hod/sort2.c b/c_tools/hod/sort2.c new file mode 100644 index 0000000..8c9f126 --- /dev/null +++ b/c_tools/hod/sort2.c @@ -0,0 +1,81 @@ +#define NRANSI +#include "nrutil.h" +#define SWAP(a,b) temp=(a);(a)=(b);(b)=temp; +#define iSWAP(a,b) itemp=(a);(a)=(b);(b)=itemp; +#define M 7 +#define NSTACK 50 + +void sort2(unsigned long n, float arr[], int id[]) +{ + unsigned long i,ir=n,j,k,l=1; + int jstack=0,*istack; + float a,temp,temp_Id; + int temp_m,itemp; + + istack=ivector(1,NSTACK); + for (;;) { + if (ir-l < M) { + for (j=l+1;j<=ir;j++) { + a=arr[j]; + temp_m=id[j]; + for (i=j-1;i>=1;i--) { + if (arr[i] <= a) break; + arr[i+1]=arr[i]; + id[i+1]=id[i]; + } + arr[i+1]=a; + id[i+1]=temp_m; + } + if (jstack == 0) break; + ir=istack[jstack--]; + l=istack[jstack--]; + } else { + k=(l+ir) >> 1; + SWAP(arr[k],arr[l+1]); + iSWAP(id[k],id[l+1]); + if (arr[l+1] > arr[ir]) { + SWAP(arr[l+1],arr[ir]); + iSWAP(id[l+1],id[ir]); + } + if (arr[l] > arr[ir]) { + SWAP(arr[l],arr[ir]); + iSWAP(id[l],id[ir]); + } + if (arr[l+1] > arr[l]) { + SWAP(arr[l+1],arr[l]); + iSWAP(id[l+1],id[l]); + } + i=l+1; + j=ir; + a=arr[l]; + temp_m=id[l]; + for (;;) { + do i++; while (arr[i] < a); + do j--; while (arr[j] > a); + if (j < i) break; + SWAP(arr[i],arr[j]); + iSWAP(id[i],id[j]); + } + arr[l]=arr[j]; + id[l]=id[j]; + arr[j]=a; + id[j]=temp_m; + jstack += 2; + if (jstack > NSTACK) nrerror("NSTACK too small in sort."); + if (ir-i+1 >= j-l) { + istack[jstack]=ir; + istack[jstack-1]=i; + ir=j-1; + } else { + istack[jstack]=j-1; + istack[jstack-1]=l; + l=i; + } + } + } + free_ivector(istack,1,NSTACK); +} +#undef M +#undef NSTACK +#undef SWAP +#undef NRANSI diff --git a/c_tools/hod/splie2.c b/c_tools/hod/splie2.c new file mode 100644 index 0000000..9da5fff --- /dev/null +++ b/c_tools/hod/splie2.c @@ -0,0 +1,13 @@ +#include +#include +void splie2(double x1a[], double x2a[], double **ya, int m, int n, double **y2a) +{ + void spline(double x[], double y[], int n, double yp1, + double ypn, double y2[]); + int j; + + for (j=1;j<=m;j++) + { + spline(x2a,ya[j],n,1.0e30,1.0e30,y2a[j]); + } +} diff --git a/c_tools/hod/splin2.c b/c_tools/hod/splin2.c new file mode 100644 index 0000000..563299d --- /dev/null +++ b/c_tools/hod/splin2.c @@ -0,0 +1,23 @@ +#define NRANSI +#include "nrutil.h" + +void splin2(double x1a[], double x2a[], double **ya, double **y2a, int m, int n, + double x1, double x2, double *y) +{ + void spline(double x[], double y[], int n, double yp1, + double ypn, double y2[]); + void splint(double xa[], double ya[], double y2a[], int n, + double x, double *y); + int j; + double *ytmp,*yytmp; + + ytmp=dvector(1,n); + yytmp=dvector(1,n); + for (j=1;j<=m;j++) + splint(x2a,ya[j],y2a[j],n,x2,&yytmp[j]); + spline(x1a,yytmp,m,1.0e30,1.0e30,ytmp); + splint(x1a,yytmp,ytmp,m,x1,y); + free_dvector(yytmp,1,n); + free_dvector(ytmp,1,n); +} +#undef NRANSI diff --git a/c_tools/hod/spline.c b/c_tools/hod/spline.c new file mode 100644 index 0000000..36332bd --- /dev/null +++ b/c_tools/hod/spline.c @@ -0,0 +1,38 @@ +#define NRANSI +#include +#include +#include "nrutil.h" + +void spline(double x[], double y[], int n, double yp1, double ypn, double y2[]) +{ + int i,k; + double p,qn,sig,un,*u; + + u=dvector(1,n-1); + if (yp1 > 0.99e30) + y2[1]=u[1]=0.0; + else { + y2[1] = -0.5; + u[1]=(3.0/(x[2]-x[1]))*((y[2]-y[1])/(x[2]-x[1])-yp1); + } + for (i=2;i<=n-1;i++) { + sig=(x[i]-x[i-1])/(x[i+1]-x[i-1]); + p=sig*y2[i-1]+2.0; + y2[i]=(sig-1.0)/p; + u[i]=(y[i+1]-y[i])/(x[i+1]-x[i]) - (y[i]-y[i-1])/(x[i]-x[i-1]); + u[i]=(6.0*u[i]/(x[i+1]-x[i-1])-sig*u[i-1])/p; + } + if (ypn > 0.99e30) + qn=un=0.0; + else { + qn=0.5; + un=(3.0/(x[n]-x[n-1]))*(ypn-(y[n]-y[n-1])/(x[n]-x[n-1])); + } + y2[n]=(un-qn*u[n-1])/(qn*y2[n-1]+1.0); + for (k=n-1;k>=1;k--) + { + y2[k]=y2[k]*y2[k+1]+u[k]; + } + free_dvector(u,1,n-1); +} +#undef NRANSI diff --git a/c_tools/hod/splint.c b/c_tools/hod/splint.c new file mode 100644 index 0000000..6834ae9 --- /dev/null +++ b/c_tools/hod/splint.c @@ -0,0 +1,36 @@ +#include +#include +#include +void splint(double xa[], double ya[], double y2a[], int n, double x, double *y) +{ + void nrerror(char error_text[]); + int klo,khi,k,i; + double h,b,a; + + klo=1; + khi=n; + while (khi-klo > 1) { + k=(khi+klo) >> 1; + if (xa[k] > x) khi=k; + else klo=k; + } + h=xa[khi]-xa[klo]; + if(h == 0.0) { + printf("BADXA %d %f\n",n,x); + fflush(stdout); + } + if (h == 0.0) nrerror("Bad xa input to routine splint"); + a=(xa[khi]-x)/h; + b=(x-xa[klo])/h; + *y=a*ya[klo]+b*ya[khi]+((a*a*a-a)*y2a[klo]+(b*b*b-b)*y2a[khi])*(h*h)/6.0; + if(isnan(*y)) + { + /* + fprintf(stdout,"NAN %e %e %d %e %e %e %e %e %e\n",a,b,n,x,ya[klo],ya[khi], + y2a[khi],y2a[klo],h); + for(i=1;i<=n;++i) + printf("NAN %d %e %e %e %e\n",i,xa[i],ya[i],y2a[i],x); + */ + *y=0; + } +} diff --git a/c_tools/hod/tasks.c b/c_tools/hod/tasks.c new file mode 100644 index 0000000..ffc8318 --- /dev/null +++ b/c_tools/hod/tasks.c @@ -0,0 +1,170 @@ +#include +#include +#include +#ifdef PARALLEL +#include +#endif +#include "header.h" + +/*********************************************************************** + * This is the main function for controlling the activities of the code. + * If you ask for any sort of minimization or MCMC analysis, the code is + * redirected to another routine, but once finished will complete the rest + * of the tasks checked off (so if you want to minimize and then print out + * related statistics, the code will do that automatically if you ask it). + * + * + * Each task generates an output file using the "root_filename" in the hod.bat + * file and tacking on an extension at the end: + * + * [filename].r_space --> real space correlation function + * [filename].HOD --> prints out the mean N(M) + * + * See the full list below. + */ + + +void tasks(int argc, char **argv) +{ + int i,j,nsize,ix,iy,nr,i1,i2,n; + float x1,x2,x3,x4,x5,x6,err,npairs; + double r,rs,rp,dx1,dx2,dx3,dx4,dx5,**xi2d,*xx2d,*yy2d,**xi2d_data,**xi2d_kaiser, + xi0_m,xi2_m,xi0_k,xi2_k,xi0_d,xi2_d,xi_r,rlo,rhi,rr[50],rhalf[50],dr, + rphi,rshi,rslo,rplo,dlogm,m,sig; + FILE *fp,*fp2,*fp1; + char fname[100]; + + + + + /* This is for chi^2 minimization of data for the projected correlation + * function. + */ + if(Task.wp_minimize && !HOD.color) + wp_minimization(argv[1]); + + /* This is for Monte-Carlo Markov Chain exploration of the posterior + * distribution of the parameters, either real-space or redshift-space, + * depending on what MCMC is set to. + */ + if(Task.MCMC) + mcmc_minimization(); + + /* This is to output the shape of the mean occupation function and the + * scatter about the mean. + * File columns are: + * 1 - halo mass (M_sol/h) + * 2 - N_cen(M) + * 3 - N_sat(M) + * 4 - N_tot(M) + * 5 - + * 6 - ratio of scatter to Poisson scatter (often called "alpha") + */ + if(Task.HOD || Task.All) + { + sprintf(fname,"%s.HOD",Task.root_filename); + fp=fopen(fname,"w"); + dlogm=(log(HOD.M_max)-log(HOD.M_low))/99; + for(i=1;i<=100;++i) + { + m=exp((i-1)*dlogm)*HOD.M_low; + sig = N_sat(m)*N_sat(m) + N_cen(m)*(1-N_cen(m)); + fprintf(fp,"%e %e %e %e %e %e\n", + m,N_cen(m),N_sat(m),N_avg(m),sig,sig/(N_avg(m)*N_avg(m))); + } + fclose(fp); + } + + /* This sets in motion the calculation and tabulation of the real-space + * correlation function and outputs it to a file. + * File columns are: + * 1 - radius (Mpc/h) + * 2 - one-halo term (real-space) + * 3 - two-halo term (real-space) + * 4 - full xi(r) + * 5 - projected correlation function (1st column is now r_p) + * 6 - projected correlation function without z-space correction + */ + if(Task.real_space_xi || Task.All) + { + fprintf(stderr,"\n\nCALCULATING REAL-SPACE CORRELATION FUNCTION.\n"); + fprintf(stderr, "--------------------------------------------\n\n"); + + sprintf(fname,"%s.r_space",Task.root_filename); + fp=fopen(fname,"w"); + dr=(log(70.0)-log(0.01))/49.0; + for(i=0;i<50;++i) + { + r=exp(i*dr+log(0.01)); + x1=one_halo_real_space(r); + x2=two_halo_real_space(r); + x3=projected_xi(r); + x4 = projected_xi_rspace(r); + fprintf(fp,"%f %e %e %e %e %e\n",r,x1,x2,x1+x2,x3,x4); + fflush(fp); + } + fclose(fp); + } + + /* This takes a halofile from a simulation and populates the halos + * with galaxies according the HOD specified in the batch file. + */ + if(Task.populate_sim==1) + populate_simulation(); + + if(!ThisTask) + OUTPUT=1; + + /* Output the linear and non-linear dark matter power spectrum. + * Non-linear P(k) calculated using Smith et al. + * + * Format of file [root].matter_pk + * 1 - k [h/Mpc] + * 2 - linear P(k) [Mpc/h]^3 + * 3 - non-linear P(k) [Mpc/h]^3 + */ + if(Task.matter_pk) + output_matter_power_spectrum(); + + /* Output the linear and non-linear dark matter power spectrum. + * Non-linear xi(r) is Fourier transform of Smith et al (above) + * + * Format of file [root].matter_pk + * 1 - r [Mpc/h] + * 2 - linear xi(r) + * 3 - non-linear xi(r) + */ + if(Task.matter_xi) + output_matter_correlation_function(); + + /* Output the matter variance as a function of scale. + * + * Format of file [root].sigma_r + * 1 - r [Mpc/h] + * 2 - sigma(r) [linear] + * 3 - sigma(r) [non-linear, using Smith] + * 4 - mass [M_sol/h] mass = (4/3)*PI*r^3*rho_bar + */ + if(Task.sigma_r) + output_matter_variance(); + + /* Output the halo concentrations using Bullock et al (2001) model + * + * Format of file [root].civr + * 1 - mass [Msol/h] --> mass specified by DELTA_HALO (input file). + * 2 - halo concentration. (for the specified halo definition) + */ + if(Task.cvir) + output_halo_concentrations(); + + /* Output the halo mass function using the results of Tinker et al (2008) + * + * Format of the file [root].massfunc + * 1 - mass [Msol/h] + * 2 - dn/dM [Mph/c]^-3 (the differential mass function). + */ + if(Task.dndM) + output_halo_mass_function(); + + endrun("finished with tasks"); +} diff --git a/c_tools/hod/test.c b/c_tools/hod/test.c new file mode 100644 index 0000000..7e639ed --- /dev/null +++ b/c_tools/hod/test.c @@ -0,0 +1,5 @@ +#include "header.h" + +void test(int argc, char **argv) +{ +} diff --git a/c_tools/hod/tf_eisenstein_hu.c b/c_tools/hod/tf_eisenstein_hu.c new file mode 100644 index 0000000..d657322 --- /dev/null +++ b/c_tools/hod/tf_eisenstein_hu.c @@ -0,0 +1,140 @@ +#include +#include +#include +#include "header.h" + +// Transfer function of Eisenstein & Hu 1998 +// (Equation numbers refer to this paper) + +double calc_tf_eh(double k); + +double tf_eisenstein_hu(double k) +{ + static int flag=0,prev_cosmo=0; + static double *x,*y,*y2; + int n=1000,i; + double a,rlo=1.0E-4,rhi=1.0E+4,dlogr,klo; + double xi_linear_int(); + + if(!flag || RESET_COSMOLOGY!=prev_cosmo) + { + if(!flag) + { + x=dvector(1,n); + y=dvector(1,n); + y2=dvector(1,n); + } + flag=1; + + dlogr = (log(rhi)-log(rlo))/(n-1); + for(i=1;i<=n;++i) + { + x[i] = exp((i-1)*dlogr)*rlo; + y[i] = log(calc_tf_eh(x[i])); + //printf("TK %e %e %e %e %e\n",x[i],exp(y[i]),exp(y[i]),exp(y[i]),exp(y[i])); + x[i] = log(x[i]); + } + spline(x,y,n,2.0E+30,2.0E+30,y2); + prev_cosmo=RESET_COSMOLOGY; + } + + splint(x,y,y2,n,log(k),&a); + return(exp(a)); +} + +double calc_tf_eh(double k) +{ + double rk,e,thet,thetsq,thetpf,b1,b2,zd,ze,rd,re,rke,s,rks,q,y,g; + double ab,a1,a2,ac,bc,f,c1,c2,tc,bb,bn,ss,tb,tk_eh; + double h,hsq,om_mhsq,om_b,om_m; + + // set up cosmology + h = HUBBLE; + om_m = OMEGA_M; + om_b = OMEGA_B; + + // convert k to Mpc^-1 rather than hMpc^-1 + rk=k*h; + hsq=h*h; + om_mhsq=om_m*hsq; + + // constants + e=exp(1.); + thet=2.728/2.7; + thetsq=thet*thet; + thetpf=thetsq*thetsq; + + // Equation 4 - redshift of drag epoch + b1=0.313*pow(om_mhsq,-0.419)*(1.+0.607*pow(om_mhsq,0.674)); + b2=0.238*pow(om_mhsq,0.223); + zd=1291.*(1.+b1*pow(om_b*hsq,b2))*pow(om_mhsq,0.251) + /(1.+0.659*pow(om_mhsq,0.828)); + + // Equation 2 - redshift of matter-radiation equality + ze=2.50e4*om_mhsq/thetpf; + + // value of R=(ratio of baryon-photon momentum density) at drag epoch + rd=31500.*om_b*hsq/(thetpf*zd); + + // value of R=(ratio of baryon-photon momentum density) at epoch of matter-radiation equality + re=31500.*om_b*hsq/(thetpf*ze); + + // Equation 3 - scale of ptcle horizon at matter-radiation equality + rke=7.46e-2*om_mhsq/(thetsq); + + // Equation 6 - sound horizon at drag epoch + s=(2./3./rke)*sqrt(6./re)*log((sqrt(1.+rd)+sqrt(rd+re))/(1.+sqrt(re))); + + // Equation 7 - silk damping scale + rks=1.6*pow(om_b*hsq,0.52)*pow(om_mhsq,0.73)*(1.+pow(10.4*om_mhsq,-0.95)); + + // Equation 10 - define q + q=rk/13.41/rke; + + // Equations 11 - CDM transfer function fits + a1=pow(46.9*om_mhsq,0.670)*(1.+pow(32.1*om_mhsq,-0.532)); + a2=pow(12.0*om_mhsq,0.424)*(1.+pow(45.0*om_mhsq,-0.582)); + ac=pow(a1,(-om_b/om_m))*pow(a2,pow(-(om_b/om_m),3.)); + + // Equations 12 - CDM transfer function fits + b1=0.944/(1.+pow(458.*om_mhsq,-0.708)); + b2=pow(0.395*om_mhsq,-0.0266); + bc=1./(1.+b1*(pow(1.-om_b/om_m,b2)-1.)); + + // Equation 18 + f=1./(1.+pow(rk*s/5.4,4.)); + + // Equation 20 + c1=14.2 + 386./(1.+69.9*pow(q,1.08)); + c2=14.2/ac + 386./(1.+69.9*pow(q,1.08)); + + // Equation 17 - CDM transfer function + tc=f*log(e+1.8*bc*q)/(log(e+1.8*bc*q)+c1*q*q) + + (1.-f)*log(e+1.8*bc*q)/(log(e+1.8*bc*q)+c2*q*q); + + // Equation 15 + y=(1.+ze)/(1.+zd); + g=y*(-6.*sqrt(1.+y)+(2.+3.*y)*log((sqrt(1.+y)+1.)/(sqrt(1.+y)-1.))); + + // Equation 14 + ab=g*2.07*rke*s/pow(1.+rd,0.75); + + // Equation 23 + bn=8.41*pow(om_mhsq,0.435); + + // Equation 22 + ss=s/pow(1.+pow(bn/rk/s,3.),1./3.); + + // Equation 24 + bb=0.5+(om_b/om_m) + (3.-2.*om_b/om_m)*sqrt(pow(17.2*om_mhsq,2.)+1.); + + // Equations 19 & 21 + tb=log(e+1.8*q)/(log(e+1.8*q)+c1*q*q)/(1+pow(rk*s/5.2,2.)); + tb=(tb+ab*exp(-pow(rk/rks,1.4))/(1.+pow(bb/rk/s,3.)))*sin(rk*ss)/rk/ss; + + // Equation 8 + tk_eh=(om_b/om_m)*tb+(1.-om_b/om_m)*tc; + + return tk_eh; +} + diff --git a/c_tools/hod/transfnc.c b/c_tools/hod/transfnc.c new file mode 100644 index 0000000..02d6557 --- /dev/null +++ b/c_tools/hod/transfnc.c @@ -0,0 +1,70 @@ +/* PROGRAM TRANSFERFUNCTION + + --- transfnc(xk) + --- compute the transfer function T(k) of the power spectrum + --- T(k) defined as P(k) = k^{xindx}*T^{2}(k) + + * itrans=type of transfer function + 0 -> no change (returns 1) + 4 -> Efstathiou, Bond & White transfer function with Gamma as + specified (eqn. 7) + 5 -> Eisnstein & Hu + 11 -> read in TF from file (usually CMBFAST) + + NOTE: xk is in h/Mpc and is defined as k=2pi/lambda (not k=1/lambda) +*/ + +#include +#include +#include +#include "header.h" + +/* EBW CDM parameters */ + +#define aa 6.4 +#define bb 3.0 +#define cc 1.7 +#define xnu 1.13 +#define twopi 6.283185 +#define xnuinv -0.884956 + +double transfnc(double xk) +{ + double transf; + double q,t1,t2; + + if(xk==0.) + { + transf=1.; + return (double)transf; + } + + switch(ITRANS) + { + case 0: + transf=1.; + break; + + case 4: + q = xk/GAMMA; + t1=aa*q+pow((bb*q),1.5)+(cc*q)*(cc*q); + t2=pow(t1,xnu); + transf=pow((1.+t2),xnuinv); + break; + + case 5: + transf = tf_eisenstein_hu(xk); + break; + + case 11: + transf = transfunc_file(xk); + break; + + default: + fprintf(stderr,"transfnc> Unrecognized transfer function %d \n",ITRANS); + exit(-1); + break; + + } + return (double)transf; +} diff --git a/c_tools/hod/transfunc_file.c b/c_tools/hod/transfunc_file.c new file mode 100644 index 0000000..b5ccf32 --- /dev/null +++ b/c_tools/hod/transfunc_file.c @@ -0,0 +1,59 @@ +#include +#include +#include +#include "header.h" + +/* This routine reads in a transfer function from a file. + * - col 1 = k [h/Mpc] + * - col 2 = T(k) + * other columns not used. + * + * The TF is considered to be un-normalized, and will normalize all values + * by the entry in the first line. + * + * The TF is stored in arrays an spline interpolation is used at all k values. + * The interpolation is in log(k)/log(TF) to preserve the power-law dependence + * of T(k) on k outside the k-range of the file. + */ + +double transfunc_file(double xk) +{ + static double *x,*y,*y2; + static int flag=1,n; + int i; + double t,x0; + FILE *fp; + char a[1000]; + float x1,x2; + + if(flag) + { + flag=0; + + fp=openfile(Files.TF_file); + n=filesize(fp); + + x=dvector(1,n); + y=dvector(1,n); + y2=dvector(1,n); + for(i=1;i<=n;++i) + { + fscanf(fp,"%f %f",&x1,&x2); + x[i]=x1; + y[i]=x2; + if(i==1)x0=y[i]; + fgets(a,1000,fp); + y[i]/=x0; + x[i]=log(x[i]); + y[i]=log(y[i]); + } + fclose(fp); + spline(x,y,n,1.0E+30,1.0E+30,y2); + } + xk=log(xk); + splint(x,y,y2,n,xk,&t); + return(exp(t)); + +} + + diff --git a/c_tools/hod/trapzd.c b/c_tools/hod/trapzd.c new file mode 100644 index 0000000..5a42058 --- /dev/null +++ b/c_tools/hod/trapzd.c @@ -0,0 +1,89 @@ +#define FUNC(x) ((*func)(x)) + +double trapzd(double (*func)(double), double a, double b, int n) +{ + double x,tnm,sum,del; + static double s; + int it,j; + + if (n == 1) { + return (s=0.5*(b-a)*(FUNC(a)+FUNC(b))); + } else { + for (it=1,j=1;j +#include +#include +#include +#include "header.h" + + +/* This is the two-halo term of the correlation function in both real space. + * This is solved in Fourier space and requires the + * non-linear power spectrum P_nl(k), which is from the model of Smith et al. + * (see Smith et al, astro-ph/0207664). + * + * For specifics see Berlind & Weinberg (2002), Zheng (2003), Tinker et al (2005) + * + */ + +/* Internal functions. + */ +double func2(double m); +double func2_cen(double m); +double func2_sat(double m); +double func5(double xk); +double func_mlimit(double m); +void calc_real_space_two_halo(double *r, double *xi, int *n); +double HOD2_two_halo_real_space(double r); + +/* the restricted number density. + */ +double NG_MINUS2; + +/* Globals needed for the qromo functions. + */ +double r_g1, + k1; + +/* Global checkflag to stop doing the restricted + * number density. + */ +int checkflag; + +/* This tabulates the two-halo real-space term for future + * spline interpolation. + */ +double two_halo_real_space(double r) +{ + static int flag=0,n=45; + static double *x,*y,*y2; + int i; + double max=16,min=9,a,rvir_min; + float x1,x2; + FILE *fp; + + // if(r<25) + // return(nbody_two_halo(r)); + + if(!flag || RESET_FLAG_2H) + { + if(!LINEAR_PSP) + nonlinear_sigmac(8.0); + n=30; + if(!flag) + { + x=dvector(1,n); + y=dvector(1,n); + y2=dvector(1,n); + } + RESET_FLAG_2H=0; + flag=1; + if(OUTPUT>1) + fprintf(stdout,"Calculating real-space two-halo term...\n"); + calc_real_space_two_halo(x,y,&n); + if(!HOD.color==2) + check_for_smoothness(x,y,n,1.5); + XI_MAX_RADIUS=x[n]; + if(XCORR) + for(i=1;i<=n;++i) + { + a = HOD2_two_halo_real_space(x[i]); + y[i] = a*y[i]; + if(y[i]<0)y[i]=-1; + else y[i] = sqrt(y[i]); + } + spline(x,y,n,2.0E+30,2.0E+30,y2); + } + + if(rXI_MAX_RADIUS)return(-1); + splint(x,y,y2,n,r,&a); + + /* This check is against the spline interpolation, which + * sometimes has (smoothness) problems with the sharp truncation of xi_2h + * at small separations. + */ + if(a<-1)return(-1); + return(a); + +} + +void calc_real_space_two_halo(double *r, double *xi, int *nn) +{ + double xtemp[200],rtemp[200]; + double mlimit,s2,rlo,rhi=90,dr,klo,tolerance=1.0e-7,s1; + int i,j,imin=0,n; + double t0,t1,t2,t1s=0,t2s=0; + + n=*nn; + + /* Set the minimum separation of two-halo pairs. + */ + if(HOD.color) + { + while(N_avg(HOD.M_low)<0.001) + HOD.M_low*=1.01; + } + + rlo = 2.2*pow(3*HOD.M_low/(4*DELTA_HALO*PI*OMEGA_M*RHO_CRIT),1.0/3.0); + if(EXCLUSION==3) + rlo = rlo/1.3; + if(EXCLUSION==4) + rlo = rlo/2.1; + R_MIN_2HALO = rlo; + + rlo = log(rlo); + dr=(log(rhi)-rlo)/(n-1); + + checkflag=0; + + for(i=1;i<=n;++i) + { + r_g1=r[i]=exp(rlo+dr*(i-1)); + + if(r_g1>30) + { + GALAXY_BIAS = qromo(func_galaxy_bias,log(HOD.M_low),log(HOD.M_max),midpnt)/GALAXY_DENSITY; + xi[i]=xi_interp(r_g1)*GALAXY_BIAS*GALAXY_BIAS; + continue; + } + + /* Fourier transform. If BOX_SIZE specified, then truncate + * transform at that k. If no box, take integral to k=0. + */ + klo = 0; + if(BOX_SIZE)klo=1/BOX_SIZE; + + j=16; + s1 = qromo(func5,klo,j*TWOPI/r_g1,midpnt); + s2 = s1; + klo = j*TWOPI/r_g1; + + while(fabs(s1)>tolerance*s2) { + j+=16; + s1 = qromo(func5,klo,j*TWOPI/r_g1,midpnt); + s2 += s1; + klo = j*TWOPI/r_g1; + } + + /* Divide the integral by the restricted number density. + * (This is calculated in the pk_gg_2h function.) + */ + s2=s2/NG_MINUS2; + + /* Correction factor b/c we haven't been + * including all halos. + */ + xi[i]=(NG_MINUS2/GALAXY_DENSITY/GALAXY_DENSITY)*(1+s2)-1; + if(isnan(xi[i]))xi[i]=-1; + + if(xi[i]==-1)imin=i; + + if(OUTPUT>1) + printf("calc_2halo> %f %f %d\n",r[i],xi[i],checkflag); + //printf("calc_2halo> %f %f %d\n",r[i],xi[i],checkflag); + } + + /* Eliminate all entries which have xi=-1 + * (to eliminate a "wavy" spline fit at small r + */ + for(j=0,i=imin+1;i<=n;++i) + { + j++; + xtemp[j]=xi[i]; + rtemp[j]=r[i]; + } + n=j; + for(i=1;i<=n;++i) + { + r[i]=rtemp[i]; + xi[i]=xtemp[i]; + } + *nn=n; + R_MIN_2HALO=r[1]; + + /*printf("calc_2halo> %d %d %f\n",imin,n,r[1]);*/ +} + + +/* This calculates and tabulates the galaxy power spectrum. This is done + * by taking the galaxy-number-weighted halo bias (with scale-dependent + * halo bias and extended structure of halos taken into account) and multiplying + * it by the non-linear matter power spectrum. + * + * The galaxy-number-weighted average is an integral over the halo mass function + * (see Equations B10 & B12 in Appendix B of Tinker et al.) over all allowed halo + * pairs. + * + * The allowed number of halo pairs is controlled by the type of halo exclusion used: + * EXCLUSION = 1 --> only halos with Rvir < r/2 + * EXCLUSION = 2 --> only halo PAIRS with R1+R2 < r ("spherical eclusion") + * EXCLUSION = 3 --> same as 3 + * EXCLUSION = 4 --> only halos with Rvir < r + * + * 1 and 4 are fast b/c the integral is separable, calculated once and squared. Can drastically + * underestimate the number of small-sep pairs. + * + * for 2/3, I've incorporated the approximation in Tinker etal 2005 called the n_g-matched + * method, where instead of actually doing the double integral over halo_mass_1 and halo_mass_2, + * i calculate the number density of that type of exclusion, and calculate the effective + * radius for the 1/4-type exlcusion-- ie, halos with Rvir < [x]*r where 0.5<[x]<1.0. + */ + +double psp_gg_2h(double k, double r) +{ + static double rp=-1,*x,*y,*y2; + static int flag=0; + int n=60,i; + double a,dk,klo=-3,khi=3,xk,s1,s2,mhi,mlo,mhi1,mlo1; + + double t1,t0,ttot1,ttot2; + + + /* The fourier transform is done at each r, so tabulate the power spectrum + * at all k for a given r. If r has changed, re-tabulate. + */ + if(rp!=r) + { + mlo=HOD.M_low; + if(!flag) + { + flag=1; + x=dvector(1,n); + y=dvector(1,n); + y2=dvector(1,n); + } + dk=(khi-klo)/n; + + switch(EXCLUSION) { + case 1: + mhi=4./3.*DELTA_HALO*RHO_CRIT*PI*r*r*r*OMEGA_M*0.125; + if(mhi>HOD.M_max)mhi=HOD.M_max; + NG_MINUS2 = qromo(func_galaxy_density,log(mlo),log(mhi),midpnt); + NG_MINUS2*=NG_MINUS2; + for(i=n;i>=1;--i) + { + xk=pow(10.0,klo+dk*i); + k1=xk; + if(nfw_transform(xk,mhi)<0.999) + a=qromo(func2,log(mlo),log(mhi),midpnt); + x[i]=log(xk); + if(LINEAR_PSP) + y[i]=log(linear_power_spectrum(xk)*a*a); + else + y[i]=log(nonlinear_power_spectrum(xk)*a*a); + } + break; + case 2: + case 3: + if(!checkflag) + s2=restricted_number_density(r); + else + s2=GALAXY_DENSITY; + + mhi=4./3.*DELTA_HALO*RHO_CRIT*PI*r*r*r*OMEGA_M*0.125; + if(s2>=GALAXY_DENSITY || mhi>HOD.M_max) + { + s2=GALAXY_DENSITY; + mhi=log(HOD.M_max); + checkflag=1; + } + else + { + mhi=0; + NG_MINUS2=s2; + if(N_avg(HOD.M_low*1.001)>0) + { + if(qromo(func_galaxy_density,log(HOD.M_low),log(HOD.M_low*1.0001),midpnt) + >NG_MINUS2)mhi=log(HOD.M_low*1.0001); + } + if(qromo(func_galaxy_density,log(HOD.M_low),log(HOD.M_max*4.0),midpnt) + log(HOD.M_max))mhi=log(HOD.M_max); + } + NG_MINUS2=s2*s2; + for(i=n;i>=1;--i) + { + xk=pow(10.0,klo+dk*i); + k1=xk; + if(nfw_transform(xk,exp(mhi))<0.999) { + if(HOD.pdfc==7)/* || HOD.pdfc==6 || HOD.pdfc==9 || HOD.pdfc==8)*/ + { + a = qromo(func2_cen,log(HOD.M_low),log(HOD.M_cen_max),midpnt); + a += qromo(func2_sat,log(HOD.M_low),log(HOD.M_max),midpnt); + } + else { + MAG_21_CHECK: + a=qromo(func2,log(mlo),mhi,midpnt); + } + } + x[i]=log(xk); + if(LINEAR_PSP) + y[i]=log(linear_power_spectrum(xk)*a*a); + else + y[i]=log(nonlinear_power_spectrum(xk)*a*a); + } + break; + case 4: // where max halo mass is M(R=r) rather than M(R=r/2) + mhi=4./3.*DELTA_HALO*RHO_CRIT*PI*r*r*r*OMEGA_M; + if(mhi>HOD.M_max)mhi=HOD.M_max; + NG_MINUS2 = qromo(func_galaxy_density,log(mlo),log(mhi),midpnt); + NG_MINUS2*=NG_MINUS2; + for(i=n;i>=1;--i) + { + xk=pow(10.0,klo+dk*i); + k1=xk; + if(nfw_transform(xk,mhi)<0.999) + a=qromo(func2,log(mlo),log(mhi),midpnt); + x[i]=log(xk); + if(LINEAR_PSP) + y[i]=log(linear_power_spectrum(xk)*a*a); + else + y[i]=log(nonlinear_power_spectrum(xk)*a*a); + } + break; + + default: + endrun("Error: invalid choice of EXCLUSION"); + } + spline(x,y,n,2.0E+30,2.0E+30,y2); + rp=r; + } + k=log(k); + splint(x,y,y2,n,k,&a); + return(exp(a)); +} + + +/* The routine called by qromo for the integral in Zheng's Eq [7] + */ +double func2(double m) +{ + double n,N,b,yg,x,Ncen,Nsat; + + m=exp(m); + n=dndM_interp(m); + b=bias_interp(m,r_g1); + Ncen=N_cen(m); + Nsat=N_sat(m); + yg=nfw_transform(k1,m); + x = n*(Ncen + Nsat*yg)*b*m; + return(x); +} + + +/* The routine called by qromo for the integral in Zheng's Eq [7] + * FOR CENTRAL GALAXIES ONLY: This means no Fourier transform of NFW profile. + */ +double func2_cen(double m) +{ + double n,N,b,yg,x; + + m=exp(m); + n=dndM_interp(m); + b=bias_interp(m,r_g1); + N=N_cen(m); + x=n*N*b*m; + return(x); +} + +/* The routine called by qromo for the integral in Zheng's Eq [7] + * FOR SATELLITE GALAXIES ONLY. + */ +double func2_sat(double m) +{ + double n,N,b,yg,x; + + m=exp(m); + n=dndM_interp(m); + b=bias_interp(m,r_g1); + N=N_sat(m); + yg=nfw_transform(k1,m); + x=n*N*b*yg*m; + return(x); +} + + +/* This is the integrand of the Fourier transform + * of the two-halo power spectrum to correlation function + */ +double func5(double xk) +{ + double psp1; + double xk1,xk2,x3; + + if(xk==0)return(0); + psp1=psp_gg_2h(xk,r_g1); + xk1=r_g1*xk; + psp1*=sin(xk1)/xk1/xk; + return(psp1); +} + +/* This is the function sent to zbrent to calculate the halo mass + * which gives the matched restricted number density. + */ +double func_mlimit(double m) +{ + double s1; + if(N_avg(exp(m))>0) + s1=qromo(func_galaxy_density,log(HOD.M_low),m,midpnt); + else + s1=0; + return(s1-NG_MINUS2); +} + + +/* This tabulates the two-halo real-space term + * for the second HOD function for future + * spline interpolation. + */ +double HOD2_two_halo_real_space(double r) +{ + static int flag=0,n=45; + static double *x,*y,*y2; + int i; + double max=16,min=9,a,rvir_min,galtemp; + float x1,x2; + FILE *fp; + + if(!flag || RESET_FLAG_2H) + { + /* Switch HODs temporarily + */ + HODt.M_min = HOD.M_min; + HODt.M_low = HOD.M_low; + HODt.M1 = HOD.M1; + HODt.alpha = HOD.alpha; + HODt.M_cen_max = HOD.M_cen_max; + HODt.sigma_logM = HOD.sigma_logM; + HODt.M_max = HOD.M_max; + HODt.pdfc = HOD.pdfc; + HODt.pdfs = HOD.pdfs; + galtemp = GALAXY_DENSITY; + + HOD.M_min = HOD2.M_min; + HOD.M_low = HOD2.M_low; + HOD.M1 = HOD2.M1; + HOD.alpha = HOD2.alpha; + HOD.M_cen_max = HOD2.M_cen_max; + HOD.sigma_logM = HOD2.sigma_logM; + HOD.M_max = HOD2.M_max; + HOD.pdfc = HOD2.pdfc; + HOD.pdfs = HOD2.pdfs; + GALAXY_DENSITY = GALAXY_DENSITY2; + set_HOD_params(); + + if(!LINEAR_PSP) + nonlinear_sigmac(8.0); + n=30; + if(!flag) + { + x=dvector(1,n); + y=dvector(1,n); + y2=dvector(1,n); + } + RESET_FLAG_2H=0; + flag=1; + if(OUTPUT) + fprintf(stdout,"Calculating HOD2 real-space two-halo term...\n"); + calc_real_space_two_halo(x,y,&n); + check_for_smoothness(x,y,n,1.5); + XI_MAX_RADIUS=x[n]; + spline(x,y,n,2.0E+30,2.0E+30,y2); + + /* Switch HODs back + */ + HOD.M_min = HODt.M_min; + HOD.M_low = HODt.M_low; + HOD.M1 = HODt.M1; + HOD.alpha = HODt.alpha; + HOD.M_cen_max = HODt.M_cen_max; + HOD.sigma_logM = HODt.sigma_logM; + HOD.M_max = HODt.M_max; + HOD.pdfc = HODt.pdfc; + HOD.pdfs = HODt.pdfs; + GALAXY_DENSITY = galtemp; + set_HOD_params(); + } + + if(r>XI_MAX_RADIUS)return(-1); + if(r +#include +#include +#include +#include +#include "header.h" + +#ifdef PARALLEL +#include +#endif + +#define NR_END 1 +#define FREE_ARG char* + +/* returns the number of cpu-ticks in seconds that + * have elapsed. (or the wall-clock time) + */ +double second(void) +{ + return ((double)((unsigned int)clock()))/CLOCKS_PER_SEC; + + /* note: on AIX and presumably many other 32bit systems, + * clock() has only a resolution of 10ms=0.01sec + */ +} + + +/* returns the time difference between two measurements + * obtained with second(). The routine takes care of the + * possible overflow of the tick counter on 32bit systems. + */ +double timediff(double t0,double t1) +{ + double dt; + + dt=t1-t0; + + if(dt<0) /* overflow has occured */ + { + dt=t1 + pow(2,32)/CLOCKS_PER_SEC - t0; + } + + return dt; +} + + +void endrun(char *instring) +{ + fprintf(stderr,"endrun> %s\n",instring); + fflush(stderr); + /* + fprintf(stdout,"endrun> %s\n",instring); + fflush(stdout); + */ + +#ifdef PARALLEL + MPI_Abort(MPI_COMM_WORLD, 0); +#endif + exit(0); + + +} + +/* This takes a file and reads the number of lines in it, + * rewinds the file and returns the lines. + */ +int filesize(FILE *fp) +{ + int i=-1; + char a[1000]; + + while(!feof(fp)) + { + i++; + fgets(a,1000,fp); + } + rewind(fp); + return(i); +} + +/* This opens a file and has an error trap + * if the file does not exist. + */ +FILE *openfile(char *ff) +{ + FILE *fp; + if(!(fp=fopen(ff,"r"))) + { + fprintf(stderr,"ERROR opening [%s]\n",ff); + exit(0); + } + return(fp); +} + + +/* This is for allocating a 3-dimensional array of doubles, adapted from + * the numerical recipes f3tensor routine. + */ +double ***d3tensor(long nrl, long nrh, long ncl, long nch, long ndl, long ndh) +/* allocate a double 3tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */ +{ + long i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1; + double ***t; + + /* allocate pointers to pointers to rows */ + t=(double ***) malloc((size_t)((nrow+NR_END)*sizeof(double**))); + if (!t) nrerror("allocation failure 1 in f3tensor()"); + t += NR_END; + t -= nrl; + + /* allocate pointers to rows and set pointers to them */ + t[nrl]=(double **) malloc((size_t)((nrow*ncol+NR_END)*sizeof(double*))); + if (!t[nrl]) nrerror("allocation failure 2 in f3tensor()"); + t[nrl] += NR_END; + t[nrl] -= ncl; + + /* allocate rows and set pointers to them */ + t[nrl][ncl]=(double *) malloc((size_t)((nrow*ncol*ndep+NR_END)*sizeof(double))); + if (!t[nrl][ncl]) nrerror("allocation failure 3 in f3tensor()"); + t[nrl][ncl] += NR_END; + t[nrl][ncl] -= ndl; + + for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep; + for(i=nrl+1;i<=nrh;i++) { + t[i]=t[i-1]+ncol; + t[i][ncl]=t[i-1][ncl]+ncol*ndep; + for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep; + } + + /* return pointer to array of pointers to rows */ + return t; +} + +/* Free the memory allocated by d3tensor (see above) + */ +void free_d3tensor(double ***t, long nrl, long nrh, long ncl, long nch, + long ndl, long ndh) +{ + free((FREE_ARG) (t[nrl][ncl]+ndl-NR_END)); + free((FREE_ARG) (t[nrl]+ncl-NR_END)); + free((FREE_ARG) (t+nrl-NR_END)); +} diff --git a/c_tools/hod/wp_minimization.c b/c_tools/hod/wp_minimization.c new file mode 100644 index 0000000..9dc997b --- /dev/null +++ b/c_tools/hod/wp_minimization.c @@ -0,0 +1,745 @@ +#include +#include +#include +#include +#include + +#ifdef PARALLEL +#include +#endif + + +#include "header.h" + +/* This is a series of routines to calculate the projected correlation + * function from the real-space one (HOD calculation) and then chi2 + * minimize the parameters based on the SDSS data. + */ +int FIT_WITH_COSMO = 0, + FIRST_CALL = 0; + +double rp_g1; +double func_wp(double z); +double func_wp_rspace(double z); +double func_wp_matter(double z); +double chi2_wp(double *a); + +void wp_input(void); +void initial_wp_values(double *a, double **pp, double *yy); + +/* This integrates the calculated real-space correlation function + * along the line-of-sight to get the projected correlation function (wp(rp). + * The value passed if the projected separation. + * + * In most SDSS work, the maximum line of sight separation considered when + * claculating wp is pi=40 Mpc/h, which is the default, but can be set + * in the parameter file if desired. + * + * NB! - note that this routine uses a correction for redshift space distortions. + */ +double projected_xi(double r) +{ + double x,zmax; + + rp_g1=r*r; + two_halo_real_space(1.0); + zmax=sqrt(XI_MAX_RADIUS*XI_MAX_RADIUS-rp_g1); + if(zmax>wp.pi_max)zmax=wp.pi_max; + zmax = wp.pi_max; + x=2*qromo(func_wp,log(0.001),log(zmax),midpnt); + return(x); +} + +/* Same as above, but it projects the real-space correlation function + * directly, with no correction for redshift-space effects. + */ +double projected_xi_rspace(double r) +{ + double x,zmax; + + rp_g1=r*r; + two_halo_real_space(1.0); + zmax=sqrt(XI_MAX_RADIUS*XI_MAX_RADIUS-rp_g1); + if(zmax>wp.pi_max)zmax=wp.pi_max; + zmax = wp.pi_max; + x=2*qromo(func_wp_rspace,log(0.001),log(zmax),midpnt); + return(x); +} + +/* Same as above but for matter. + * I've set the maximum line-of-sight separation to be 50 Mpc/h, + * which should be good for visual comparison purposes. + */ +double projected_xi_matter(double r) +{ + double x,zmax; + + rp_g1=r*r; + zmax=50.0; + x=2*qtrap(func_wp_matter,log(0.001),log(zmax),1.0E-3); + return(x); +} + +/* Function called from qromo/qtrap to get xi->wp + * Note that the two-halo term has the linear Kaiser distortion correction. + */ +double func_wp(double z) +{ + double r; + z=exp(z); + r=sqrt(rp_g1 + z*z); + return(z*(one_halo_real_space(r)+linear_kaiser_distortion(r,z))); +} + +/* Function called from qromo/qtrap to get xi->wpm but without + * correction for redshift-space distortions in the two-halo term + */ +double func_wp_rspace(double z) +{ + double r; + z=exp(z); + r=sqrt(rp_g1 + z*z); + return(z*(one_halo_real_space(r)+two_halo_real_space(r))); +} + +/* Function called from qromo/qtrap to get xi->wp (dark matter) + */ +double func_wp_matter(double z) +{ + double r; + z=exp(z); + r=sqrt(rp_g1 + z*z); + return(z*(xi_interp(r))); +} + +/******************************************************************** + * Below is the actual minimization of the wp data. + * Relevant variables: [default] + * + * COVAR -> [1]=use covariance matrixl; 0=diagonal error bars + * DEPROJECTED -> [1]=we're fitting a real-space xi(r) [0]= fitting wp(rp) + * + * HOD.free[] is a vector which holds 1/0 as to whether or not a parameter is going + * to be help constant during the chi^2 minimization. 1==vary 0==constant. The default + * on any will be [0]. + * + * i variable + * --- -------- + * [1] -> M_min + * [2] -> M1 + * [3] -> alpha + * [4] -> M_cut + * [5] -> sigmaM + * [6] -> CVIR_FAC + * [7] -> MaxCen (M_cen_max) + * + * Currently I have no checks on whether the values of this vector line + * up correctly with the specific HOD pdfs, so double-check hod.bat files. + * + * Once the code is finished, it will output the values of the HOD parameters + * to a file called [filename].fit (+ the bias, satellite fraction, and chi^2). + * Then it outputs the mean _M to a file called [filename].HOD. + * Then it will go through all the TASKS asked for in the hod.bat file. + */ + +void wp_minimization(char *fname) +{ + int n,niter,i,j; + double *a,**pp,*yy,FTOL=1.0E-3,chi2min,s1,dlogm,m; + FILE *fp; + char aa[1000]; + + fprintf(stderr,"\n\nCHI2 MINIMIZATION OF W_P(R_P) DATA..........\n"); + fprintf(stderr, "--------------------------------------------\n\n"); + + OUTPUT = 0; + FIRST_CALL = 1; + + if(POWELL) + FTOL=1.0E-3; + else + FTOL=1.0E-4; + + for(n=0,i=1;i<=N_HOD_PARAMS;++i) + { + n+=HOD.free[i]; + if(!OUTPUT)continue; + printf("wp_min> free[%i] = %d\n",i,HOD.free[i]); + } + if(XCORR)n*=2; + if(OUTPUT)printf("wp_min> Number of free parameters: %d\n",n); + + printf("FNAME %s\n",Task.root_filename); + wp_input(); + + wp.ncf=n; + a=dvector(1,n); + if(POWELL) + pp=dmatrix(1,n,1,n); + else + pp=dmatrix(1,n+1,1,n); + yy=dvector(1,n+1); + + + initial_wp_values(a,pp,yy); + printf("IVALS %e %e %e %e\n",a[1],a[2],a[3],a[4]); + + + if(POWELL) + { + if(OUTPUT)printf("wp_min> starting powell.\n"); + powell(a,pp,n,FTOL,&niter,&chi2min,chi2_wp); + chi2min = chi2_wp(a); + } + else + { + if(OUTPUT)printf("wp_min> starting amoeba.\n"); + amoeba(pp,yy,n,FTOL,chi2_wp,&niter); + for(i=1;i<=n;++i)a[i]=pp[1][i]; + chi2min = chi2_wp(a); + } + + s1=qromo(func_galaxy_bias,log(HOD.M_low),log(HOD.M_max),midpnt); + GALAXY_BIAS=s1/GALAXY_DENSITY; + + printf("POWELL %e %e ",chi2min,HOD.M_min); + for(i=1;i<=n;++i)printf("%e ",a[i]); + printf(" %f\n",GALAXY_BIAS); + + /* These outputs are for easy cut & paste into + * another batch file. + */ + //output_parameter_file(fname); + + /* Output the fit and the HOD curve. + */ + printf("FNAME2 %s\n",Task.root_filename); + sprintf(aa,"%s.fit",Task.root_filename); + fp=fopen(aa,"w"); + fprintf(fp,"%e %e ",chi2min,HOD.M_min); + for(i=1;i<=n;++i)fprintf(fp,"%e ",a[i]); + fprintf(fp," %f\n",GALAXY_BIAS); + fclose(fp); + + sprintf(aa,"%s.HOD",Task.root_filename); + fp=fopen(aa,"w"); + dlogm=(log(HOD.M_max)-log(HOD.M_low))/99; + for(i=1;i<=100;++i) + { + m=exp((i-1)*dlogm)*HOD.M_low; + fprintf(fp,"%e %e %e %e\n",m,N_cen(m),N_sat(m),N_avg(m)); + } + fclose(fp); + + fprintf(stderr,"here\n"); + free_dvector(a,1,n); + if(POWELL) + free_dmatrix(pp,1,n,1,n); + else + free_dmatrix(pp,1,n+1,1,n); + free_dvector(yy,1,n+1); + fprintf(stderr,"here\n"); + + free_dvector(wp.r,1,wp.np); + free_dvector(wp.x,1,wp.np); + free_dvector(wp.e,1,wp.np); + if(COVAR) + free_dmatrix(wp.covar,1,wp.np,1,wp.np); + fprintf(stderr,"done in wp_min\n"); +} + +double integrated_wp_bin(double r) +{ + return(projected_xi(r)*r); +} +double integrated_xi_bin(double r) +{ + //return((1+one_halo_real_space(r))*r*r); + return((one_halo_real_space(r)+two_halo_real_space(r))*r*r); +} + +double chi2_wp(double *a) +{ + static int flag=1,niter=0,ichi=-1; + static double *x,mmin_prev=0,t0=-1,t1,sig_prev=0,chi2_prev,chi2_array[10]; + double **tmp,**tmp2,chi2,x1,ta1,ta2,dt1h,dt2h,par_chi,chi2ngal; + int i,j,k,ncf_hod; + + double rlo,rhi,rmin,rmax,dlogr,integrated_wp_bin(); + + if(FIRST_CALL) + { + flag = 1; + FIRST_CALL = 0; + } + + t0 = clock(); + if(HOD.free[1])FIX_PARAM = 0; + + wp.iter=niter; + + for(j=0,i=1;i<=N_HOD_PARAMS;++i) + if(HOD.free[i]) + if(a[++j]<=0) { printf("%d %e\n",j,a[j]); return(1.0E7); } + ncf_hod = j; + + RESET_FLAG_1H=1; + RESET_FLAG_2H=1; + RESET_KAISER++; + + i=0;j=0; + if(HOD.free[++i])HOD.M_min=a[++j]; + if(HOD.free[++i])HOD.M1=a[++j]; + if(HOD.free[++i])HOD.alpha=a[++j]; + if(HOD.free[++i])HOD.M_cut=a[++j]; + if(HOD.free[++i])HOD.sigma_logM=a[++j]; + + if(HOD.pdfc!=9) { + if(HOD.free[++i])CVIR_FAC=a[++j]; + if(HOD.pdfc>=7) { + if(HOD.free[++i])HOD.M_cen_max=a[++j]; } + else { + if(HOD.free[++i])HOD.MaxCen=a[++j]; } + } + if(HOD.free[++i])HOD.M_sat_break=a[++j]; + if(HOD.free[++i])HOD.alpha1=a[++j]; + + + if(XCORR) { + i=0; + if(HOD.free[++i])HOD2.M_min=a[++j]; + if(HOD.free[++i])HOD2.M1=a[++j]; + if(HOD.free[++i])HOD2.alpha=a[++j]; + if(HOD.free[++i])HOD2.M_cut=a[++j]; + if(HOD.free[++i])HOD2.sigma_logM=a[++j]; + + if(HOD2.pdfc!=9) { + if(HOD.free[++i])CVIR_FAC=a[++j]; + if(HOD2.pdfc>=7) { + if(HOD2.free[++i])HOD2.M_cen_max=a[++j]; } + else { + if(HOD2.free[++i])HOD2.MaxCen=a[++j]; } + } + } + + + if(!ThisTask) { + printf("START %d ",niter); + for(i=1;i<=ncf_hod;++i)printf("%e ",a[i]); + printf("\n"); + } + + if(HOD.pdfs==2 && HOD.M_cut<1.0e7)return(1.0e7); + if(HOD.pdfs==2 && HOD.M_cut>1.0e15)return(1.0e7); + + /* if(HOD.M_min>HOD.M_max)return(1.0e7); */ + + /* I've noticed some problems when sigma_logM gets to be + * unresonably high or low, so I've put some limits on the + * values they can have when doing mag-bin fitting. + */ + if(HOD.pdfc==6) { + if(HOD.sigma_logM<0.07)return(1.0e7); + if(HOD.sigma_logM>1.2)return(1.0e7); + } + if(HOD.pdfc==2 || HOD.pdfc==9) { + if(HOD.sigma_logM>1.8)return(1.0e7); + if(HOD.sigma_logM<0.05)return(1.0e7); + } + if(HOD.M1>1.0e17)return(1.0e7); + + if(FIX_PARAM==2) + { + HOD.M1=HOD.M_low; + x1=qromo(func_galaxy_density,log(HOD.M_low),log(HOD.M_max),midpnt); + if(x1GALAXY_DENSITY)return(1.0e7); + HOD.M1=0; + } + + + /* Check the make sure these are reasonable parameters + * (Assuming that M_min is NOT a FREE parameter but is + * calculated from the GALAXY_DENSITY.) + */ + if(FIX_PARAM==1 && !HOD.color) + { + HOD.M_min=pow(10.0,8.0); + HOD.M_low=set_low_mass(); + if(HOD.M_low<1.0e8)HOD.M_low=1.0e8; + x1=qromo(func_galaxy_density,log(HOD.M_low),log(HOD.M_max),midpnt); + // fprintf(stderr,"PC1 %e %e\n",x1,GALAXY_DENSITY); + if(x1GALAXY_DENSITY) { + fprintf(stdout,"PCHECK %e %e\n",x1,GALAXY_DENSITY); + return(1.0e7); } + HOD.M_min=0; + } + + if(ERROR_FLAG) + { + ERROR_FLAG=0; + return(1e7); + } + + if(HOD.free[0] || HOD.free[1]) + GALAXY_DENSITY=0; + + if(!HOD.color) + set_HOD_params(); + + /* + if(XCORR) + set_HOD2_params(); + */ + + if(HOD.free[0]) + { + chi2ngal = (GALAXY_DENSITY-wp.ngal)*(GALAXY_DENSITY-wp.ngal)/wp.ngal_err/wp.ngal_err; + if(chi2ngal>1.0E3)return(chi2ngal); + } + if(ERROR_FLAG) + { + ERROR_FLAG=0; + return(1e7); + } + + /* if(HOD.pdfs==3 && HOD.M_cutHOD.M1)return(1.0e7); + /* if(HOD.pdfs==3)if(HOD.M_cut=niter) + flag = 1; + + if(flag && COVAR) + { + // printf("INVERTING COVARIANCE MATRIX\n"); + flag=0; + tmp=dmatrix(1,wp.np,1,1); + tmp2=dmatrix(1,wp.np,1,wp.np); + for(i=1;i<=wp.np;++i) + for(j=1;j<=wp.np;++j) + tmp2[i][j]=wp.covar[i][j]; + gaussj(tmp2,wp.np,tmp,1); + for(i=1;i<=wp.np;++i) + for(j=1;j<=wp.np;++j) + wp.covar[i][j]=tmp2[i][j]; + free_dmatrix(tmp,1,wp.np,1,1); + free_dmatrix(tmp2,1,wp.np,1,wp.np); + x=dvector(1,wp.np); + + } + if(!COVAR) + x=dvector(1,wp.np); + + rmax = wp.r[wp.np]; + rmin = wp.r[1]; + dlogr = (log(rmax)-log(rmin))/(wp.np-1); + BETA = pow(OMEGA_M,0.6)/qromo(func_galaxy_bias,log(HOD.M_low),log(HOD.M_max),midpnt)* + GALAXY_DENSITY; + if(OUTPUT) + printf("BETA = %f\n",BETA); + + rlo = exp(log(rmin) - 0.5*dlogr); + for(i=1;i<=wp.np;++i) + { + rhi = exp(dlogr)*rlo; + if(DEPROJECTED) + x[i]=one_halo_real_space(wp.r[i])+two_halo_real_space(wp.r[i]); + else + { + x[i]=projected_xi(wp.r[i]); + if(wp.format==3) + x[i]/=wp.r[i]; + } + if(OUTPUT && !ThisTask) + printf("WP%d %f %e %e %e %e\n",niter+1,wp.r[i],wp.x[i],x[i],rlo,rhi); + rlo=rhi; + + } + + if(ERROR_FLAG) + { + ERROR_FLAG=0; + return(1e7); + } + + chi2=0; + + if(COVAR) + { + for(i=1;i<=wp.np;++i) + for(j=1;j<=wp.np;++j) + { + x1=(x[i]-wp.x[i])*(x[j]-wp.x[j])*wp.covar[i][j]; + chi2+=x1; + } + } + else + { + if(!PCA) + { + for(i=1;i<=wp.np;++i) + { + x1=(x[i]-wp.x[i])*(x[i]-wp.x[i])/ + (wp.e[i]*wp.e[i] + wp.esys*wp.esys*x[i]*x[i]); + chi2+=x1; + } + } + else + { + chi2=0; + for(i=1;i<=wp.npca;++i) + { + par_chi=0; + for(j=1;j<=wp.np;++j) + par_chi+=wp.covar[j][i]*(x[j]-wp.x[j])/wp.e[j]; + chi2+=par_chi*par_chi/wp.eigen[i]; + } + } + } + + /* + * From Peder Norberg's instructions for use of PCA: + + do i=1,npca + par_chi=0.d0 + do j=1,npoints + par_chi=par_chi+pca(j,i)*(xi_teo(j)-xi_data(j))/err_data(j) + enddo + chi2=chi2+(par_chi**2)/ev(i) ! (****) + enddo + + */ + + /* Add in the error on the galaxy density + */ + if(HOD.free[0]) + chi2+=chi2ngal; + + t1 = clock(); + t0 = difftime(t1,t0)/CLOCKS_PER_SEC; + niter++; + if(!ThisTask){ + printf("ITER %7d %e ",niter,chi2); + for(i=1;i<=ncf_hod;++i)printf("%e ",a[i]); + printf(" %.2f\n",t0); + fflush(stdout); + if(HOD.free[0]) + printf("NGAL %e %e %e\n",chi2ngal, + GALAXY_DENSITY,wp.ngal); + } + chi2_prev=chi2; + chi2_array[ichi]=chi2; + ichi++; + if(ichi==10)ichi=0; + fflush(stdout); + return(chi2); +} + +void initial_wp_values(double *a, double **pp, double *yy) +{ + static int flag=1; + int i,j; + double d[100]; + + + if(flag) { + i=0;j=0; + if(HOD.free[++i])a[++j]=HOD.M_min; + if(HOD.free[++i])a[++j]=HOD.M1; + if(HOD.free[++i])a[++j]=HOD.alpha; + if(HOD.free[++i])a[++j]=HOD.M_cut; + if(HOD.free[++i])a[++j]=HOD.sigma_logM; + if(HOD.free[++i])a[++j]=CVIR_FAC; + if(HOD.pdfc>=7){ + if(HOD.free[++i])a[++j]=HOD.M_cen_max; } + else { + if(HOD.free[++i])a[++j]=HOD.MaxCen; } + if(HOD.free[++i])a[++j]=HOD.M_sat_break; + if(HOD.free[++i])a[++j]=HOD.alpha1; + + if(XCORR){ + i=0; + if(HOD.free[++i])a[++j]=HOD2.M_min; + if(HOD.free[++i])a[++j]=HOD2.M1; + if(HOD.free[++i])a[++j]=HOD2.alpha; + if(HOD.free[++i])a[++j]=HOD2.M_cut; + if(HOD.free[++i])a[++j]=HOD2.sigma_logM; + if(HOD.free[++i])a[++j]=CVIR_FAC; + if(HOD2.pdfc>=7){ + if(HOD.free[++i])a[++j]=HOD2.M_cen_max; } + else { + if(HOD.free[++i])a[++j]=HOD2.MaxCen; } + } + printf("INITIAL VALUES: "); + for(i=1;i<=wp.ncf;++i)printf("%e ",a[i]); + printf("\n"); + } + //flag++; + + /* Make the starting stepsize 10% of the initial values. + */ + for(i=1;i<=wp.ncf;++i) + d[i]=a[i]*0.25/flag; + + + if(POWELL) + { + for(i=1;i<=wp.ncf;++i) + { + for(j=1;j<=wp.ncf;++j) + { + pp[i][j]=0; + if(i==j)pp[i][j]+=d[j]; + } + } + } + else + { + for(j=1;j<=wp.ncf;++j) + pp[1][j]=a[j]; + yy[1]=chi2_wp(a); + + for(i=1;i<=wp.ncf;++i) + { + a[i]+=d[i]; + if(i>1)a[i-1]-=d[i-1]; + yy[i+1]=chi2_wp(a); + for(j=1;j<=wp.ncf;++j) + pp[i+1][j]=a[j]; + } + a[wp.ncf]-=d[wp.ncf]; + } +} + + +/* This routine reads in the wp data and covariance matrix from + * the filenames specified. + * + * FILE FORMATS: + * + * - fname_wp -> r xi e_xi + * - fname_covar -> (i=1,np)(j=1,np) read(covar[i][j]) + * + */ +void wp_input() +{ + float x1,x2,x3; + FILE *fp; + int i,j,n; + char a[1000]; + + if(!(fp=fopen(wp.fname_wp,"r"))) + { + fprintf(stdout,"ERROR opening [%s]\n",wp.fname_wp); + endrun("error in wp_input"); + } + wp.np=filesize(fp); + + /* [wp.format==2] means that there are two header lines at + * the top of the file. + */ + if(wp.format==2) + { + wp.np-=2; + fgets(a,1000,fp); + fgets(a,1000,fp); + } + + /* [wp.format==3] means that there is one header lines at + * the top of the file. + */ + if(wp.format==3) + { + wp.np-=1; + fgets(a,1000,fp); + } + + wp.r=dvector(1,wp.np); + wp.x=dvector(1,wp.np); + wp.e=dvector(1,wp.np); + if(PCA) + { + wp.eigen=dvector(1,wp.np); + wp.covar=dmatrix(1,wp.np,1,wp.np); + } + + /* Read in the projected correlation function data. + * Standard format [wp.format==1] is linear r, linear wp, linear err. + * [wp.format==2] is log10 r, log10 wp, linear err. + * NB! Peder's format is to list the inner edge of the bin, so we're adding 0.1 to each number. + */ + for(i=1;i<=wp.np;++i) + { + fscanf(fp,"%f %f %f",&x1,&x2,&x3); + wp.r[i]=x1; + wp.x[i]=x2; + wp.e[i]=x3; + if(wp.format==2){ + wp.r[i] = pow(10.0,wp.r[i]+0.1); + wp.x[i] = pow(10.0,wp.x[i])*wp.r[i]; + wp.e[i] = wp.e[i]*wp.r[i]; + } + if(wp.format==3){ + fscanf(fp,"%f",&x3); + wp.e[i]=x3; + wp.r[i] = pow(10.0,wp.r[i]+0.1); + // wp.x[i] = wp.x[i]*wp.r[i]; + // wp.e[i] = wp.e[i]*wp.r[i]; + } + if(wp.format==3 && PCA) { + fscanf(fp,"%lf",&wp.eigen[i]); + for(j=1;j<=wp.np;++j) + fscanf(fp,"%lf",&wp.covar[j][i]); + if(wp.npca==0) + wp.npca = wp.np; + } + // if(wp.format==3 && !PCA) + fgets(a,1000,fp); + } + fclose(fp); + fprintf(stderr,"Done reading %d lines from [%s]\n",wp.np,wp.fname_wp); + + if(!COVAR || PCA) + return; + /* + if(wp.format==1) + { + Work.SDSS_bins=1; + for(i=1;i<=40;++i) + Work.rad[i] = i-0.5; + } + */ + if(!(fp=fopen(wp.fname_covar,"r"))) + { + fprintf(stdout,"ERROR opening [%s]\n",wp.fname_covar); + endrun("error in wp_input"); + } + wp.covar=dmatrix(1,wp.np,1,wp.np); + for(i=1;i<=wp.np;++i) + for(j=1;j<=wp.np;++j) + { + fscanf(fp,"%lf",&(wp.covar[i][j])); + /* printf("COVAR %d %d %e\n",i,j,wp.covar[i][j]); */ + } + fclose(fp); + if(!ThisTask) + fprintf(stdout,"Done reading %d lines from [%s]\n",wp.np,wp.fname_covar); + +} + diff --git a/c_tools/hod/xi_matter.c b/c_tools/hod/xi_matter.c new file mode 100644 index 0000000..2bec7b4 --- /dev/null +++ b/c_tools/hod/xi_matter.c @@ -0,0 +1,180 @@ +#include +#include +#include + +#include "header.h" + +/* This calculates and tabulates both the linear and non-linear + * matter correlation function. + * + * If the parameter BOX_SIZE is set, then the lower limits of the + * Fourier transform in 1/BOX_SIZE, else it starts at k=0. + * + * The integral (Smith etal 2003 MNRAS.341.1311S Eq [4]) to transform: + * + * Int_0^\infty Delta(k) sin(rk)/rk/k dk + * + * This integral sometimes gives qromo problems when calculating xi(r) at large r. + * Therefore, we cut off the integral at k = 10^3, which has negligible effect on the + * correlation function at the relevent scales. + */ + +double r_g4; +double xi_int(double xk); + +/* Calculates and tabulates the non-linear matter correlation function. + * Since this is only really needed for the scale-dependence of the bias, + * which is basically 1 at scales r>~8 Mpc/h, I won't calculate this much + * past that value. + */ +double xi_interp(double r) +{ + static int flag=0,prev_cosmo=0; + static double *x,*y,*y2; + int n=30,i,j; + double a,xi_int(),rhi=95,rlo=0.1,dlogr,klo,s1,s2,tolerance=1.0e-6; + + if(!flag || RESET_COSMOLOGY!=prev_cosmo) + { + if(!flag) + { + x=dvector(1,n); + y=dvector(1,n); + y2=dvector(1,n); + } + flag=1; + dlogr = (log(rhi)-log(rlo))/(n-1); + + for(i=1;i<=n;++i) + { + klo = 0; + if(BOX_SIZE>0)klo = 1/BOX_SIZE; + r_g4 = x[i] = exp((i-1)*dlogr)*rlo; + + j=1; + s1 = qromo(xi_int,klo,j/r_g4,midpnt); + s2 = s1; + klo = j/r_g4; + while(mabs(s1)>tolerance*mabs(s2)) { + j+=16; + s1 = qromo(xi_int,klo,j/r_g4,midpnt); + s2 += s1; + klo = j/r_g4; + } + y[i]=s2; + } + check_for_smoothness(x,y,n,0); + spline(x,y,n,2.0E+30,2.0E+30,y2); + prev_cosmo=RESET_COSMOLOGY; + } + + splint(x,y,y2,n,r,&a); + return(a); +} + + +/* This is the integrand of Smith et al Eq. [4] + */ +double xi_int(double xk) +{ + double xk1,xk2,psp; + + if(xk==0)return(0); + + /* power spectrum at xk + */ + psp=nonlinear_power_spectrum(xk); + + /* Integrand of Fourier transform + */ + xk1=r_g4*xk; + psp*=sin(xk1)/xk1/xk; + return psp; +} + + +double xi_linear_interp(double r) +{ + static int flag=0,prev_cosmo=0; + static double *x,*y,*y2; + int n=100,i; + double a,rlo=0.1,rhi=150,dlogr,klo; + double xi_linear_int(); + + if(!flag || RESET_COSMOLOGY!=prev_cosmo) + { + if(!flag) + { + x=dvector(1,n); + y=dvector(1,n); + y2=dvector(1,n); + } + flag=1; + + dlogr = (log(rhi)-log(rlo))/(n-1); + klo = 0; + if(BOX_SIZE>0)klo = 1/BOX_SIZE; + for(i=1;i<=n;++i) + { + r_g4 = x[i] = exp((i-1)*dlogr)*rlo; + y[i] = qromo(xi_linear_int,klo,1.0/r_g4,midpnt)+ + qromo(xi_linear_int,1.0/r_g4,1.0E+3,midpnt); + } + check_for_smoothness(x,y,n,0); + spline(x,y,n,2.0E+30,2.0E+30,y2); + prev_cosmo=RESET_COSMOLOGY; + } + + splint(x,y,y2,n,r,&a); + return(a); +} + +double xi_linear_int(xk) +double xk; +{ + double psp; + double xk1,xk2; + + /* power spectrum at xk + */ + psp=linear_power_spectrum(xk); + + /* Now take Fourier transform + */ + xk1=r_g4*xk; + psp*=sin(xk1)/xk1/xk; + + return psp; +} + +/* Sometimes one or two of the correlation function values will + * totally crap out, [a side-effect of qromo] so here we check for that and if + * we find it then we interpolate the values in log-space. + */ +void check_for_smoothness(double *x, double *y, int n, double r) +{ + int i,flag,flag2=0; + double m,b,new; + + for(i=2;i0)flag2=1; + if(y[i]<0 && !flag2)continue; + if(x[i]3.0 && fabs(y[i]/y[i+1])>3.0)flag=1; + if(fabs(y[i]/y[i-1])<0.2 && fabs(y[i]/y[i+1])<0.2)flag=1; + if(y[i]<0 && (y[i-1]>=0 && y[i+1]>=0))flag=1; + if(y[i+1]<0)flag=0; + if(!flag)continue; + + m=(log(y[i+1])-log(y[i-1]))/(log(x[i+1])-log(x[i-1])); + b=log(y[i+1])-m*log(x[i+1]); + new=m*log(x[i])+b; + + fprintf(stderr,"SMOOTHING: %e %e %e r= %f new=%e\n",y[i-1],y[i],y[i+1],x[i],exp(new)); + y[i]=exp(new); + } + + +} diff --git a/c_tools/hod/zbrent.c b/c_tools/hod/zbrent.c new file mode 100644 index 0000000..122ff23 --- /dev/null +++ b/c_tools/hod/zbrent.c @@ -0,0 +1,76 @@ +#include +#include "header.h" +#define ITMAX 100 +#define EPS 3.0e-8 + +double zbrent(double (*func)(double), double x1,double x2, double tol) +{ + int iter; + double a=x1,b=x2,c,d,e,min1,min2; + double fa=(*func)(a),fb=(*func)(b),fc,p,q,r,s,tol1,xm; + void nrerror(); + + if (fb*fa > 0.0) + { + printf("ERROR: Root must be bracketed in ZBRENT\n"); + ERROR_FLAG=1; + return (x1+x2)/2; + } + fc=fb; + for (iter=1;iter<=ITMAX;iter++) { + if (fb*fc > 0.0) { + c=a; + fc=fa; + e=d=b-a; + } + if (fabs(fc) < fabs(fb)) { + a=b; + b=c; + c=a; + fa=fb; + fb=fc; + fc=fa; + } + tol1=2.0*EPS*fabs(b)+0.5*tol; + xm=0.5*(c-b); + if (fabs(xm) <= tol1 || fb == 0.0) return b; + if (fabs(e) >= tol1 && fabs(fa) > fabs(fb)) { + s=fb/fa; + if (a == c) { + p=2.0*xm*s; + q=1.0-s; + } else { + q=fa/fc; + r=fb/fc; + p=s*(2.0*xm*q*(q-r)-(b-a)*(r-1.0)); + q=(q-1.0)*(r-1.0)*(s-1.0); + } + if (p > 0.0) q = -q; + p=fabs(p); + min1=3.0*xm*q-fabs(tol1*q); + min2=fabs(e*q); + if (2.0*p < (min1 < min2 ? min1 : min2)) { + e=d; + d=p/q; + } else { + d=xm; + e=d; + } + } else { + d=xm; + e=d; + } + a=b; + fa=fb; + if (fabs(d) > tol1) + b += d; + else + b += (xm > 0.0 ? fabs(tol1) : -fabs(tol1)); + fb=(*func)(b); + } + nrerror("Maximum number of iterations exceeded in ZBRENT"); + return(0); +} + +#undef ITMAX +#undef EPS