From 79b0fa75d62b0d83f45494775b311018b38dfbe2 Mon Sep 17 00:00:00 2001 From: "P.M. Sutter" Date: Mon, 16 Dec 2013 10:44:31 -0600 Subject: [PATCH 01/25] updated name and added instructions --- README | 4 ++-- install.pdf | Bin 0 -> 88379 bytes 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 install.pdf diff --git a/README b/README index 9a1b6ba..ab1889d 100644 --- a/README +++ b/README @@ -6,13 +6,13 @@ *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* -This is VIDE. The Void IDEntifier pipeline. +This is VIDE, the Void IDentification and Examination pipeline. License/Copyright information ----------------------------- -Copyright (C) 2010-2013 Guilhem Lavaux, 2011-2013 Paul M. Sutter. +Copyright (C) 2010-2013 Guilhem Lavaux, 2011-2013 P.M. Sutter. This software is put under the GNU Public License. Please see LICENSE for further information. diff --git a/install.pdf b/install.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b1c06ed9b89e065af7ff436fbf410fbe4ea507dc GIT binary patch literal 88379 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 L=g;Le74ZK7!@e~A literal 0 HcmV?d00001 From 34a32bfd2c56e35e052d35eb5379dfcc2e213fd3 Mon Sep 17 00:00:00 2001 From: "P.M. Sutter" Date: Thu, 19 Dec 2013 12:27:22 -0600 Subject: [PATCH 02/25] getting rid of funky center coordinated for observations --- c_tools/stacking/pruneVoids.cpp | 11 +- python_tools/void_python_tools/__init__.py | 1 + .../void_python_tools/partUtil/__init__.py | 20 +++ .../void_python_tools/partUtil/partUtil.py | 127 ++++++++++++++++++ 4 files changed, 153 insertions(+), 6 deletions(-) create mode 100644 python_tools/void_python_tools/partUtil/__init__.py create mode 100644 python_tools/void_python_tools/partUtil/partUtil.py diff --git a/c_tools/stacking/pruneVoids.cpp b/c_tools/stacking/pruneVoids.cpp index 08212d5..ddaae9a 100644 --- a/c_tools/stacking/pruneVoids.cpp +++ b/c_tools/stacking/pruneVoids.cpp @@ -1102,12 +1102,11 @@ void outputVoids(string outputDir, string sampleName, string prefix, outCenter[1] = outVoid.barycenter[1]; outCenter[2] = outVoid.barycenter[2]; - if (isObservation) { - outCenter[0] = (outVoid.barycenter[0]-boxLen[0]/2.)*100.; - outCenter[1] = (outVoid.barycenter[1]-boxLen[1]/2.)*100.; - outCenter[2] = (outVoid.barycenter[2]-boxLen[2]/2.)*100.; - } - + //if (isObservation) { + // outCenter[0] = (outVoid.barycenter[0]-boxLen[0]/2.)*100.; + // outCenter[1] = (outVoid.barycenter[1]-boxLen[1]/2.)*100.; + // outCenter[2] = (outVoid.barycenter[2]-boxLen[2]/2.)*100.; + //} fprintf(fpZobov, "%d %d %d %f %f %d %d %f %d %f %f\n", iVoid, diff --git a/python_tools/void_python_tools/__init__.py b/python_tools/void_python_tools/__init__.py index 5dd3665..fd37450 100644 --- a/python_tools/void_python_tools/__init__.py +++ b/python_tools/void_python_tools/__init__.py @@ -21,3 +21,4 @@ from void_python_tools.backend import * from void_python_tools.apTools import * from void_python_tools.plotting import * from void_python_tools.xcor import * +from void_python_tools.partUtil import * diff --git a/python_tools/void_python_tools/partUtil/__init__.py b/python_tools/void_python_tools/partUtil/__init__.py new file mode 100644 index 0000000..7e0c1f8 --- /dev/null +++ b/python_tools/void_python_tools/partUtil/__init__.py @@ -0,0 +1,20 @@ +#+ +# VIDE -- Void IDentification and Examination -- ./python_tools/void_python_tools/plotting/__init__.py +# Copyright (C) 2010-2013 Guilhem Lavaux +# Copyright (C) 2011-2013 P. M. Sutter +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +#+ +from partUtil import * diff --git a/python_tools/void_python_tools/partUtil/partUtil.py b/python_tools/void_python_tools/partUtil/partUtil.py new file mode 100644 index 0000000..7444939 --- /dev/null +++ b/python_tools/void_python_tools/partUtil/partUtil.py @@ -0,0 +1,127 @@ +#+ +# VIDE -- Void IDentification and Examination -- ./python_tools/void_python_tools/plotting/__init__.py +# Copyright (C) 2010-2013 Guilhem Lavaux +# Copyright (C) 2011-2013 P. M. Sutter +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +#+ + +# Various utilities for loading and modifying particle datasets + +import numpy as np +from netCDF4 import Dataset +import sys +from void_python_tools.backend import * +import void_python_tools.apTools as vp + +NetCDFFile = Dataset +ncFloat = 'f8' + +# ----------------------------------------------------------------------------- +def loadPart(workDir, sampleDir, sample): + #print " Loading particle data..." + sys.stdout.flush() + + infoFile = workDir+"/"+sampleDir+"/zobov_slice_"+sample.fullName+".par" + File = NetCDFFile(infoFile, 'r') + ranges = np.zeros((3,2)) + ranges[0][0] = getattr(File, 'range_x_min') + ranges[0][1] = getattr(File, 'range_x_max') + ranges[1][0] = getattr(File, 'range_y_min') + ranges[1][1] = getattr(File, 'range_y_max') + ranges[2][0] = getattr(File, 'range_z_min') + ranges[2][1] = getattr(File, 'range_z_max') + isObservation = getattr(File, 'is_observation') + maskIndex = getattr(File, 'mask_index') + File.close() + mul = np.zeros((3)) + mul[:] = ranges[:,1] - ranges[:,0] + + partFile = workDir+"/"+sampleDir+"/zobov_slice_"+sample.fullName + iLine = 0 + partData = [] + part = np.zeros((3)) + File = file(partFile) + chk = np.fromfile(File, dtype=np.int32,count=1) + Np = np.fromfile(File, dtype=np.int32,count=1) + chk = np.fromfile(File, dtype=np.int32,count=1) + + chk = np.fromfile(File, dtype=np.int32,count=1) + x = np.fromfile(File, dtype=np.float32,count=Np) + x *= mul[0] + if isObservation != 1: + x += ranges[0][0] + chk = np.fromfile(File, dtype=np.int32,count=1) + + chk = np.fromfile(File, dtype=np.int32,count=1) + y = np.fromfile(File, dtype=np.float32,count=Np) + y *= mul[1] + if isObservation != 1: + y += ranges[1][0] + chk = np.fromfile(File, dtype=np.int32,count=1) + + chk = np.fromfile(File, dtype=np.int32,count=1) + z = np.fromfile(File, dtype=np.float32,count=Np) + z *= mul[2] + if isObservation != 1: + z += ranges[2][0] + chk = np.fromfile(File, dtype=np.int32,count=1) + File.close() + + if isObservation == 1: + x = x[0:maskIndex]# * 100/300000 + y = y[0:maskIndex]# * 100/300000 + z = z[0:maskIndex]# * 100/300000 + + partData = np.column_stack((x,y,z)) + + boxLen = mul + + if isObservation == 1: + props = vp.getSurveyProps(sample.maskFile, sample.zBoundary[0], + sample.zBoundary[1], + sample.zBoundary[0], + sample.zBoundary[1], "all", + useLCDM=sample.useLCDM) + boxVol = props[0] + volNorm = maskIndex/boxVol + else: + boxVol = np.prod(boxLen) + volNorm = len(x)/boxVol + + isObservationData = isObservation == 1 + + return partData, boxLen, volNorm, isObservationData + +# ----------------------------------------------------------------------------- +def shiftPart(inPart, newCenter, periodicLine, boxLen): + + part = inPart.copy() + + part[:,0] -= newCenter[0] + part[:,1] -= newCenter[1] + part[:,2] -= newCenter[2] + + shiftUs = np.abs(part[:,0]) > boxLen[0]/2. + if ("x" in periodicLine): part[shiftUs,0] -= \ + np.copysign(boxLen[0], part[shiftUs,0]) + shiftUs = np.abs(part[:,1]) > boxLen[1]/2. + if ("y" in periodicLine): part[shiftUs,1] -= \ + np.copysign(boxLen[1], part[shiftUs,1]) + shiftUs = np.abs(part[:,2]) > boxLen[2]/2. + if ("z" in periodicLine): part[shiftUs,2] -= \ + np.copysign(boxLen[2], part[shiftUs,2]) + + return part From f268820a2e10d5763f70729ee96570ab07d429cb Mon Sep 17 00:00:00 2001 From: "P.M. Sutter" Date: Thu, 19 Dec 2013 12:38:05 -0600 Subject: [PATCH 03/25] switched variable name useLCDM to less confusing useComoving; make it sample-level rather than dataset-level --- c_tools/mock/generateFromCatalog.cpp | 6 ++--- c_tools/mock/generateFromCatalog.ggo | 2 +- c_tools/stacking/pruneVoids.cpp | 2 +- c_tools/stacking/pruneVoids.ggo | 2 +- pipeline/generateCatalog.py | 6 ++--- .../pipeline_source/prepareCatalogs.in.py | 2 +- .../void_python_tools/backend/classes.py | 6 ++--- .../void_python_tools/backend/launchers.py | 25 +++++++++---------- 8 files changed, 25 insertions(+), 26 deletions(-) diff --git a/c_tools/mock/generateFromCatalog.cpp b/c_tools/mock/generateFromCatalog.cpp index f114208..b9d09e2 100644 --- a/c_tools/mock/generateFromCatalog.cpp +++ b/c_tools/mock/generateFromCatalog.cpp @@ -115,7 +115,7 @@ void loadData(const string& fname, NYU_VData & data) } void generateGalaxiesInCube(NYU_VData& data, ParticleData& output_data, - bool useLCDM) + bool useComoving) { double d2r = M_PI/180; @@ -163,7 +163,7 @@ void generateGalaxiesInCube(NYU_VData& data, ParticleData& output_data, double ra = data[i].ra*d2r, dec = data[i].dec*d2r; Position& p = output_data.pos[i]; - if (useLCDM) { + if (useComoving) { //double pos = gsl_interp_eval(interp, redshifts, dL, data[i].cz, acc); gsl_integration_qng(&expanF, 1.e-6, data[i].cz/LIGHT_SPEED, 1.e-6, @@ -587,7 +587,7 @@ int main(int argc, char **argv) // We compute a cube holding all the galaxies + the survey surface mask cout << "Placing galaxies..." << endl; - generateGalaxiesInCube(data, output_data, args_info.useLCDM_flag); + generateGalaxiesInCube(data, output_data, args_info.useComoving_flag); generateSurfaceMask(args_info, mask, pixel_list, full_mask_list, data, output_data); diff --git a/c_tools/mock/generateFromCatalog.ggo b/c_tools/mock/generateFromCatalog.ggo index 792fa49..239ffa4 100644 --- a/c_tools/mock/generateFromCatalog.ggo +++ b/c_tools/mock/generateFromCatalog.ggo @@ -14,4 +14,4 @@ option "zMax" - "Maximum redshift of data" double required option "output" - "Filename of particle datafile" string required option "params" - "Output parameters of the datacube" string required -option "useLCDM" - "Convert to real space using LCDM cosmology" flag off +option "useComoving" - "Convert to real space using LCDM cosmology" flag off diff --git a/c_tools/stacking/pruneVoids.cpp b/c_tools/stacking/pruneVoids.cpp index ddaae9a..9ac1f88 100644 --- a/c_tools/stacking/pruneVoids.cpp +++ b/c_tools/stacking/pruneVoids.cpp @@ -724,7 +724,7 @@ int main(int argc, char **argv) { voids[iVoid].redshiftInMpc = voids[iVoid].redshiftInMpc; - if (args.useLCDM_flag) { + if (args.useComoving_flag) { redshift = gsl_interp_eval(interp, dL, redshifts, voids[iVoid].redshiftInMpc, acc); //printf("HELLO %e %e\n", redshift, args.zMax_arg); diff --git a/c_tools/stacking/pruneVoids.ggo b/c_tools/stacking/pruneVoids.ggo index 4d0c8ba..d7b84ee 100644 --- a/c_tools/stacking/pruneVoids.ggo +++ b/c_tools/stacking/pruneVoids.ggo @@ -23,7 +23,7 @@ option "numVoids" - "Number of voids" int required option "isObservation" - "We are working with observational data" flag off -option "useLCDM" - "Void positions are in comoving coordinates" flag off +option "useComoving" - "Void positions are in comoving coordinates" flag off option "zMin" - "Minimum redshift of sample" double optional default="0.0" option "zMax" - "Maximum redshift of sample" double optional default="10.0" diff --git a/pipeline/generateCatalog.py b/pipeline/generateCatalog.py index a76482b..bf71148 100755 --- a/pipeline/generateCatalog.py +++ b/pipeline/generateCatalog.py @@ -1,6 +1,6 @@ #!/usr/bin/env python #+ -# VIDE -- Void IDEntification pipeline -- ./pipeline/generateCatalog.py +# VIDE -- Void IDentification and Examination -- ./pipeline/generateCatalog.py # Copyright (C) 2010-2013 Guilhem Lavaux # Copyright (C) 2011-2013 P. M. Sutter # @@ -91,7 +91,7 @@ for sample in dataSampleList: launchGenerate(sample, GENERATE_PATH, workDir=workDir, inputDataDir=inputDataDir, zobovDir=zobovDir, - figDir=figDir, logFile=logFile, useLCDM=useLCDM, + figDir=figDir, logFile=logFile, useComoving=sample.useComoving, continueRun=continueRun, regenerate=regenerateFlag) # -------------------------------------------------------------------------- @@ -115,7 +115,7 @@ for sample in dataSampleList: launchPrune(sample, PRUNE_PATH, logFile=logFile, zobovDir=zobovDir, - useLCDM=useLCDM, continueRun=continueRun) + useComoving=sample.useComoving, continueRun=continueRun) # ------------------------------------------------------------------------- if (startCatalogStage <= 4) and (endCatalogStage >= 4): diff --git a/python_tools/pipeline_source/prepareCatalogs.in.py b/python_tools/pipeline_source/prepareCatalogs.in.py index 8f3a90f..f94b60c 100644 --- a/python_tools/pipeline_source/prepareCatalogs.in.py +++ b/python_tools/pipeline_source/prepareCatalogs.in.py @@ -150,7 +150,7 @@ freshStack = True errorBars = "CALCULATED" numIncoherentRuns = 100 ranSeed = 101010 -useLCDM = False +useComoving = False bias = 1.16 dataPortions = {dataPortions} diff --git a/python_tools/void_python_tools/backend/classes.py b/python_tools/void_python_tools/backend/classes.py index c15716c..7f9c84f 100644 --- a/python_tools/void_python_tools/backend/classes.py +++ b/python_tools/void_python_tools/backend/classes.py @@ -77,7 +77,7 @@ class Sample: includeInHubble = True partOfCombo = False isCombo = False - useLCDM = False # if True, convert population to comoving coordinates + useComoving = False # if True, convert population to comoving coordinates comboList = [] @@ -99,7 +99,7 @@ class Sample: comboList=(), profileBinSize=2.0, skyFraction=0.19, boxLen=1024, usePecVel=False, omegaM=0.27, numSubvolumes=1, mySubvolume=1, dataFormat="sdss", - useLCDM=False, + useComoving=False, dataType="observation", subsample=1.0, useLightCone=True, autoNumInStack=-1): self.dataFile = dataFile @@ -130,7 +130,7 @@ class Sample: self.subsample = subsample self.useLightCone = useLightCone self.dataUnit = dataUnit - self.useLCDM = useLCDM + self.useComoving = useComoving self.autoNumInStack = autoNumInStack self.stacks = [] diff --git a/python_tools/void_python_tools/backend/launchers.py b/python_tools/void_python_tools/backend/launchers.py index cc851bb..1df4543 100644 --- a/python_tools/void_python_tools/backend/launchers.py +++ b/python_tools/void_python_tools/backend/launchers.py @@ -43,7 +43,7 @@ ncFloat = 'f8' # Double precision # ----------------------------------------------------------------------------- def launchGenerate(sample, binPath, workDir=None, inputDataDir=None, - zobovDir=None, figDir=None, logFile=None, useLCDM=False, + zobovDir=None, figDir=None, logFile=None, useComoving=False, continueRun=None,regenerate=False): if sample.dataType == "observation": @@ -63,10 +63,10 @@ def launchGenerate(sample, binPath, workDir=None, inputDataDir=None, maskFile = sample.maskFile - if useLCDM: - useLCDMFlag = "useLCDM" + if useComoving: + useComovingFlag = "useComoving" else: - useLCDMFlag = "" + useComovingFlag = "" conf=""" catalog %s @@ -81,7 +81,7 @@ def launchGenerate(sample, binPath, workDir=None, inputDataDir=None, """ % (datafile, maskFile, outputFile, zobovDir+"/zobov_slice_"+sampleName+".par", sample.zBoundary[0], sample.zBoundary[1], sample.fakeDensity, - useLCDMFlag, inputParameterFlag) + useComovingFlag, inputParameterFlag) parmFile = os.getcwd()+"/generate_"+sample.fullName+".par" @@ -244,7 +244,7 @@ def launchGenerate(sample, binPath, workDir=None, inputDataDir=None, if sample.dataType == "observation": (boxVol, nbar) = vp.getSurveyProps(sample.maskFile, sample.zRange[0], sample.zRange[1], sample.zRange[0], sample.zRange[1], "all", - useLCDM=useLCDM) + useComoving=useComoving) else: iX = float(sample.mySubvolume[0]) iY = float(sample.mySubvolume[1]) @@ -357,7 +357,7 @@ def launchZobov(sample, binPath, zobovDir=None, logDir=None, continueRun=None, # ----------------------------------------------------------------------------- def launchPrune(sample, binPath, summaryFile=None, logFile=None, zobovDir=None, - continueRun=None, useLCDM=False): + continueRun=None, useComoving=False): sampleName = sample.fullName @@ -385,10 +385,10 @@ def launchPrune(sample, binPath, periodicLine = " --periodic='" + getPeriodic(sample) + "'" - if useLCDM: - useLCDMFlag = " --useLCDM" + if useComoving: + useComovingFlag = " --useComoving" else: - useLCDMFlag = "" + useComovingFlag = "" if not (continueRun and (jobSuccessful(logFile, "NetCDF: Not a valid ID\n") \ or jobSuccessful(logFile, "Done!\n"))): @@ -410,7 +410,7 @@ def launchPrune(sample, binPath, cmd += " --numVoids=" + str(numVoids) cmd += observationLine cmd += periodicLine - cmd += useLCDMFlag + cmd += useComovingFlag cmd += " --outputDir=" + zobovDir cmd += " --sampleName=" + str(sampleName) cmd += " &> " + logFile @@ -1460,7 +1460,6 @@ def launchHubble(dataPortions=None, dataSampleList=None, logDir=None, sys.stdout = open(logFile, 'w') sys.stderr = open(logFile, 'a') if doPlot: - print "DOING PLOT" if INCOHERENT: #plotTitle = "all samples, incoherent "+\ # thisDataPortion+" voids" @@ -1486,7 +1485,7 @@ def launchHubble(dataPortions=None, dataSampleList=None, logDir=None, else: #plotTitle = "all samples, "+thisDataPortion+\ # " voids (systematics corrected)" - plotTitle = setName + "(sysematics corrected)" + plotTitle = setName + "(systematics corrected)" vp.do_all_obs(zbase, allExpList, aveDistList, rlist, plotTitle=plotTitle, sampleNames=shortSampleNames, plotAve=True, mulfac = 1.16, From 5483cae9e9096931d23cbf141c056bad748776d3 Mon Sep 17 00:00:00 2001 From: "P.M. Sutter" Date: Thu, 19 Dec 2013 12:52:07 -0600 Subject: [PATCH 04/25] added integral of DE EoS in likelihood calculation --- .../void_python_tools/apTools/chi2/cosmologyTools.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python_tools/void_python_tools/apTools/chi2/cosmologyTools.py b/python_tools/void_python_tools/apTools/chi2/cosmologyTools.py index 341e7ec..a966858 100644 --- a/python_tools/void_python_tools/apTools/chi2/cosmologyTools.py +++ b/python_tools/void_python_tools/apTools/chi2/cosmologyTools.py @@ -27,11 +27,14 @@ __all__=['expansion', 'angularDiameter', 'expectedStretch', 'aveStretch', 'aveEx # returns 1/E(z) for the given cosmology def expansion(z, Om = 0.27, Ot = 1.0, w0 = -1.0, wa = 0.0): - wz = w0 + wa*z/(1+z) ez = Om * (1+z)**3 + (Ot-Om)# * (1+z)**(3.+3*wz) + #ez = Om * (1+z)**3 + (Ot-Om)# * integrade.quad(eosDE, 0.0, z, args=(w0,wa))[0] ez = 1./np.sqrt(ez) return ez +# returns DE value at redshift z +def eosDE(z, w0 = -1.0, wa = 0.0): + return = w0 + wa*z/(1+z) # returns D_A(z) for the given cosmology def angularDiameter(z, Om = 0.27, Ot = 1.0, w0 = -1.0, wa = 0.0): From d8108d3a8e6fd68e730bd0b1140121c6ccbde200 Mon Sep 17 00:00:00 2001 From: "P.M. Sutter" Date: Thu, 19 Dec 2013 22:32:47 -0600 Subject: [PATCH 05/25] default to improved jovoz --- python_tools/setup.py | 2 +- .../void_python_tools/apTools/chi2/cosmologyTools.py | 2 +- python_tools/void_python_tools/backend/launchers.py | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/python_tools/setup.py b/python_tools/setup.py index aa7286d..482837d 100644 --- a/python_tools/setup.py +++ b/python_tools/setup.py @@ -31,7 +31,7 @@ setup( cmdclass = {'build_ext': build_ext}, include_dirs = [np.get_include()], packages= - ['void_python_tools','void_python_tools.backend','void_python_tools.apTools', 'void_python_tools.xcor', + ['void_python_tools','void_python_tools.backend','void_python_tools.apTools', 'void_python_tools.xcor', 'void_python_tools.partUtil', 'void_python_tools.apTools.profiles','void_python_tools.apTools.chi2', 'void_python_tools.plotting'], #ext_modules = [Extension("void_python_tools.chi2.velocityProfileFitNative", ["void_python_tools/chi2/velocityProfileFitNative.pyx"], libraries=["gsl", "gslcblas"]), Extension("void_python_tools.chi2.likelihoo", ["void_python_tools/chi2/likelihood.pyx"], libraries=["gsl", "gslcblas"])] ext_modules = [ diff --git a/python_tools/void_python_tools/apTools/chi2/cosmologyTools.py b/python_tools/void_python_tools/apTools/chi2/cosmologyTools.py index a966858..e1c432c 100644 --- a/python_tools/void_python_tools/apTools/chi2/cosmologyTools.py +++ b/python_tools/void_python_tools/apTools/chi2/cosmologyTools.py @@ -34,7 +34,7 @@ def expansion(z, Om = 0.27, Ot = 1.0, w0 = -1.0, wa = 0.0): # returns DE value at redshift z def eosDE(z, w0 = -1.0, wa = 0.0): - return = w0 + wa*z/(1+z) + return w0 + wa*z/(1+z) # returns D_A(z) for the given cosmology def angularDiameter(z, Om = 0.27, Ot = 1.0, w0 = -1.0, wa = 0.0): diff --git a/python_tools/void_python_tools/backend/launchers.py b/python_tools/void_python_tools/backend/launchers.py index 1df4543..a615416 100644 --- a/python_tools/void_python_tools/backend/launchers.py +++ b/python_tools/void_python_tools/backend/launchers.py @@ -330,9 +330,8 @@ def launchZobov(sample, binPath, zobovDir=None, logDir=None, continueRun=None, cmd = "./%s >> %s 2>&1" % (vozScript, logFile) os.system(cmd) -#cmd = "%s/../c_tools/zobov2/jozov2/jozov2 %s %s %s %s %s %g %s >> %s 2>&1" % \ - - cmd = "%s/jozov %s %s %s %s %s %g %s >> %s 2>&1" % \ +# cmd = "%s/jozov %s %s %s %s %s %g %s >> %s 2>&1" % \ + cmd = "%s/../c_tools/zobov2/jozov2/jozov2 %s %s %s %s %s %g %s >> %s 2>&1" % \ (binPath, \ zobovDir+"/adj_"+sampleName+".dat", \ zobovDir+"/vol_"+sampleName+".dat", \ From 44cd0eb71f815906b521f372a38857eca4f80ad3 Mon Sep 17 00:00:00 2001 From: "P.M. Sutter" Date: Mon, 30 Dec 2013 22:48:07 -0600 Subject: [PATCH 06/25] 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 From 3a4b63604342c801deb97e48147ab74d89e59988 Mon Sep 17 00:00:00 2001 From: "P.M. Sutter" Date: Tue, 31 Dec 2013 08:20:56 -0600 Subject: [PATCH 07/25] HOD code now callable from prepareCatalogs script --- python_tools/pipeline_source/prepareCatalogs.in.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/python_tools/pipeline_source/prepareCatalogs.in.py b/python_tools/pipeline_source/prepareCatalogs.in.py index f94b60c..55a8e4e 100644 --- a/python_tools/pipeline_source/prepareCatalogs.in.py +++ b/python_tools/pipeline_source/prepareCatalogs.in.py @@ -831,7 +831,8 @@ if (args.hod or args.all) and haloFileBase != "": sampleName = getSampleName(prefix+"hod_"+thisHod['name'], redshift, False) tempFile = "./hod.out_"+sampleName - os.system(hodPath+" "+parFileName+">& " + tempFile) + HOD_PATH = "@CMAKE_BINARY_DIR@/c_tools/hod/hod" + os.system(HOD_PATH+" "+parFileName+">& " + tempFile) for line in open(tempFile): if "MLO" in line: print " (minimum halo mass = ", line.split()[1], ")" From deaa3b1f47d8e32284ff2428f20d3a9c5c6eca63 Mon Sep 17 00:00:00 2001 From: "P.M. Sutter" Date: Tue, 31 Dec 2013 08:56:21 -0600 Subject: [PATCH 08/25] changed the title in apAnalysis From f4eb343e5fb98d24392d4c3e66714bb38a55e6ce Mon Sep 17 00:00:00 2001 From: "P.M. Sutter" Date: Wed, 1 Jan 2014 01:04:05 -0600 Subject: [PATCH 09/25] AP analysis now multi-threaded for parallel execustion of separate stacks --- .../void_python_tools/backend/launchers.py | 95 +++++++++++-------- 1 file changed, 55 insertions(+), 40 deletions(-) diff --git a/python_tools/void_python_tools/backend/launchers.py b/python_tools/void_python_tools/backend/launchers.py index a615416..bcb270d 100644 --- a/python_tools/void_python_tools/backend/launchers.py +++ b/python_tools/void_python_tools/backend/launchers.py @@ -583,6 +583,9 @@ def launchStack(sample, stack, binPath, thisDataPortion=None, logDir=None, # periodicLine += "z" # periodicLine += "' " + launchDir = os.getcwd() + os.chdir(voidDir) + conf=""" desc %s partzone %s @@ -649,19 +652,21 @@ def launchStack(sample, stack, binPath, thisDataPortion=None, logDir=None, fp.write("doExtraction\n") fp.close() + jobString = " "+runSuffix+":" + if not (continueRun and jobSuccessful(logFile, "Done!\n")): cmd = "%s --configFile=%s &> %s" % \ (binPath, parmFile, logFile) os.system(cmd) if jobSuccessful(logFile, "Done!\n"): - print "done" + print jobString, "Stacking voids done" else: - print "FAILED!" + print jobString, "Stacking voids FAILED!" exit(-1) else: - print "already done!" + print jobString, "Stacking voids already done!" if os.access(parmFile, os.F_OK): os.unlink(parmFile) return @@ -693,7 +698,7 @@ def launchStack(sample, stack, binPath, thisDataPortion=None, logDir=None, os.unlink(voidDir+"/NOVOID") if (numVoids == "0"): - print " No voids found; skipping!" + print jobString, "No voids found; skipping!" fp = open(voidDir+"/NOVOID", "w") fp.write("no voids found\n") fp.close() @@ -704,7 +709,7 @@ def launchStack(sample, stack, binPath, thisDataPortion=None, logDir=None, if "EMPTY STACK" in line: emptyStack = True if emptyStack: - print " Stack is empty; skipping!" + print jobString, "Stack is empty; skipping!" fp = open(voidDir+"/NOVOID", "w") fp.write("empty stack\n") fp.close() @@ -771,30 +776,32 @@ def launchStack(sample, stack, binPath, thisDataPortion=None, logDir=None, fp.write(str(normalization)+"\n") fp.close() - os.system("mv %s %s" % ("tree.data", treeFile)) - os.system("mv %s %s" % ("void_indexes.txt", voidDir+"/")) - os.system("mv %s %s" % ("posx.nc", voidDir+"/")) - os.system("mv %s %s" % ("posy.nc", voidDir+"/")) - os.system("mv %s %s" % ("posz.nc", voidDir+"/")) - os.system("mv %s %s" % ("z_void_indexes.txt", voidDir+"/")) - os.system("mv %s %s" % ("z_posx.nc", voidDir+"/")) - os.system("mv %s %s" % ("z_posy.nc", voidDir+"/")) - os.system("mv %s %s" % ("z_posz.nc", voidDir+"/")) - os.system("mv %s %s" % ("redshifts.nc", voidDir+"/")) - os.system("mv %s %s" % ("indexes.nc", voidDir+"/")) - os.system("mv %s %s" % ("kdtree_stackvoids.dat", voidDir+"/")) - os.system("mv %s %s" % ("centers.txt", voidDir+"/")) - os.system("mv %s %s" % ("z_centers.txt", voidDir+"/")) - os.system("mv %s %s" % ("sky_positions.txt", voidDir+"/")) - os.system("mv %s %s" % ("check.txt", voidDir+"/")) - os.system("mv %s %s" % ("tracer.txt", voidDir+"/")) - os.system("mv %s %s" % ("normalizations.txt", voidDir+"/")) - os.system("mv %s %s" % ("boundaryDistances.txt", voidDir+"/")) + #os.system("mv %s %s" % ("tree.data", treeFile)) + #os.system("mv %s %s" % ("void_indexes.txt", voidDir+"/")) + #os.system("mv %s %s" % ("posx.nc", voidDir+"/")) + #os.system("mv %s %s" % ("posy.nc", voidDir+"/")) + #os.system("mv %s %s" % ("posz.nc", voidDir+"/")) + #os.system("mv %s %s" % ("z_void_indexes.txt", voidDir+"/")) + #os.system("mv %s %s" % ("z_posx.nc", voidDir+"/")) + #os.system("mv %s %s" % ("z_posy.nc", voidDir+"/")) + #os.system("mv %s %s" % ("z_posz.nc", voidDir+"/")) + #os.system("mv %s %s" % ("redshifts.nc", voidDir+"/")) + #os.system("mv %s %s" % ("indexes.nc", voidDir+"/")) + #os.system("mv %s %s" % ("kdtree_stackvoids.dat", voidDir+"/")) + #os.system("mv %s %s" % ("centers.txt", voidDir+"/")) + #os.system("mv %s %s" % ("z_centers.txt", voidDir+"/")) + #os.system("mv %s %s" % ("sky_positions.txt", voidDir+"/")) + #os.system("mv %s %s" % ("check.txt", voidDir+"/")) + #os.system("mv %s %s" % ("tracer.txt", voidDir+"/")) + #os.system("mv %s %s" % ("normalizations.txt", voidDir+"/")) + #os.system("mv %s %s" % ("boundaryDistances.txt", voidDir+"/")) if os.access(idListFile, os.F_OK): os.unlink(idListFile) if os.access(parmFile, os.F_OK): os.unlink(parmFile) + os.chdir(launchDir) + return # ----------------------------------------------------------------------------- @@ -805,6 +812,7 @@ def launchCombine(sample, stack, voidDir=None, logFile=None, runSuffix = getStackSuffix(stack.zMin, stack.zMax, stack.rMin, stack.rMax, thisDataPortion) + jobString = " "+runSuffix+":" sys.stdout = open(logFile, 'w') sys.stderr = open(logFile, 'a') @@ -1030,21 +1038,26 @@ def launchCombine(sample, stack, voidDir=None, logFile=None, sys.stderr = sys.__stderr__ if jobSuccessful(logFile, "Done!\n"): - print "done" + print jobString, "Combining stacks done" else: - print "FAILED!" + print jobString, "Combining stacks FAILED!" exit(-1) #else: # print "already done!" # ----------------------------------------------------------------------------- -def launchProfile(sample, stack, voidDir=None, logFile=None, continueRun=None): +def launchProfile(sample, stack, voidDir=None, logFile=None, continueRun=None, + thisDataPortion=None): sampleName = sample.fullName + runSuffix = getStackSuffix(stack.zMin, stack.zMax, stack.rMin, + stack.rMax, thisDataPortion) + jobString = " "+runSuffix+":" + if os.access(voidDir+"/NOVOID", os.F_OK): - print "no stack here; skipping!" + print jobString, "Profile no stack here; skipping!" return numVoids = open(voidDir+"/num_voids.txt", "r").readline() @@ -1083,13 +1096,13 @@ def launchProfile(sample, stack, voidDir=None, logFile=None, continueRun=None): sys.stderr = sys.__stderr__ if jobSuccessful(logFile, "Done!\n"): - print "done", numVoids + print jobString, "Profiling stacks done, (N_v=", numVoids,")" else: - print "FAILED!" + print jobString, "Profiling stacks FAILED!" exit(-1) else: - print "already done!" + print jobString, "Profiling stacks already done!" # ----------------------------------------------------------------------------- @@ -1101,14 +1114,16 @@ def launchFit(sample, stack, logFile=None, voidDir=None, figDir=None, runSuffix = getStackSuffix(stack.zMin, stack.zMax, stack.rMin, stack.rMax, thisDataPortion) + jobString = " "+runSuffix+":" + if not (continueRun and jobSuccessful(logFile, "Done!\n")): if os.access(voidDir+"/NOVOID", os.F_OK): - print "no voids here; skipping!" + print jobString, "Fitting no voids here; skipping!" return numVoids = int(open(voidDir+"/num_voids.txt", "r").readline()) if numVoids < 10: - print "not enough voids to fit; skipping!" + print jobString, "Fitting not enough voids to fit; skipping!" fp = open(voidDir+"/NOFIT", "w") fp.write("not enough voids: %d \n" % numVoids) fp.close() @@ -1119,18 +1134,18 @@ def launchFit(sample, stack, logFile=None, voidDir=None, figDir=None, # return if sample.partOfCombo or not sample.includeInHubble: - print "sample not needed for further analysis; skipping!" + print jobString, "Fitting sample not needed for further analysis; skipping!" fp = open(voidDir+"/NOFIT", "w") fp.write("sample not needed for hubble\n") fp.close() return if not stack.includeInHubble: - print "radius not needed for further analysis; skipping!" + print jobString, "Fitting radius not needed for further analysis; skipping!" return if not stack.includeInHubble: - print "redshift not needed for further analysis; skipping!" + print jobString, "Fitting redshift not needed for further analysis; skipping!" return if os.access(figDir+"/stackedVoid_"+sampleName+"_"+\ @@ -1195,9 +1210,9 @@ def launchFit(sample, stack, logFile=None, voidDir=None, figDir=None, sys.stdout = sys.__stdout__ sys.stderr = sys.__stderr__ if jobSuccessful(logFile, "Done!\n"): - print "done (", ntries, " tries)" + print jobString, "Fitting done (", ntries, " tries)" else: - print "FAILED!" + print jobString, "Fitting FAILED!" exit(-1) # record the measured stretch @@ -1209,14 +1224,14 @@ def launchFit(sample, stack, logFile=None, voidDir=None, figDir=None, if os.access(voidDir+"/NOFIT", os.F_OK): os.unlink(voidDir+"/NOFIT") if ntries > maxtries: - print " No reliable fit found; skipping!" + print jobString, " No reliable fit found; skipping!" fp = open(voidDir+"/NOFIT", "w") fp.write("bad ellipticity fit\n") fp.close() return else: - print "already done!" + print jobString, "already done!" # ----------------------------------------------------------------------------- From 3e5e89c8cf43f3af29a0004fb4e69cdf87c69b6e Mon Sep 17 00:00:00 2001 From: Paul Matthew Sutter Date: Wed, 1 Jan 2014 08:25:26 +0100 Subject: [PATCH 10/25] removed extraneous Done! signifier in fitting --- python_tools/void_python_tools/backend/launchers.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/python_tools/void_python_tools/backend/launchers.py b/python_tools/void_python_tools/backend/launchers.py index a615416..edbbfe2 100644 --- a/python_tools/void_python_tools/backend/launchers.py +++ b/python_tools/void_python_tools/backend/launchers.py @@ -32,6 +32,8 @@ import shutil import glob import subprocess import sys +import matplotlib +matplotlib.use('Agg') from pylab import figure from netCDF4 import Dataset from void_python_tools.backend.classes import * @@ -1192,6 +1194,7 @@ def launchFit(sample, stack, logFile=None, voidDir=None, figDir=None, figure(1).savefig(figDir+"/stackedVoid_"+sampleName+\ "_"+runSuffix+".png") + print "Done!" sys.stdout = sys.__stdout__ sys.stderr = sys.__stderr__ if jobSuccessful(logFile, "Done!\n"): From ece821de773407bbf969402b1871598fba5751df Mon Sep 17 00:00:00 2001 From: Paul Matthew Sutter Date: Wed, 1 Jan 2014 08:27:14 +0100 Subject: [PATCH 11/25] switched to a different plotting backend to better support running on headless machines From 15bf8e3cc7a9c77352dc0c892b793110e51a7931 Mon Sep 17 00:00:00 2001 From: "P.M. Sutter" Date: Wed, 1 Jan 2014 08:22:32 -0600 Subject: [PATCH 12/25] cleaned up apAnalysis script initialization From b6e9fc60c207c1c347ef81ecbe5db8741e2bd716 Mon Sep 17 00:00:00 2001 From: "P.M. Sutter" Date: Fri, 3 Jan 2014 06:57:12 -0600 Subject: [PATCH 13/25] reverted to original zobov rescaling --- c_tools/libzobov/particleInfo.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/c_tools/libzobov/particleInfo.cpp b/c_tools/libzobov/particleInfo.cpp index 1ab86f4..59d0864 100644 --- a/c_tools/libzobov/particleInfo.cpp +++ b/c_tools/libzobov/particleInfo.cpp @@ -94,24 +94,24 @@ bool loadParticleInfo(ParticleInfo& info, offset = info.ranges[0][0]; // TEST PMS NON-COBIC BOXES - mul = 1.0; - //mul = info.ranges[0][1] - info.ranges[0][0]; + //mul = 1.0; + mul = info.ranges[0][1] - info.ranges[0][0]; f.beginCheckpoint(); for (int i = 0; i < numpart; i++) info.particles[i].x = mul*f.readReal32(); f.endCheckpoint(); offset = info.ranges[1][0]; - mul = 1.0; - //mul = info.ranges[1][1] - info.ranges[1][0]; + //mul = 1.0; + mul = info.ranges[1][1] - info.ranges[1][0]; f.beginCheckpoint(); for (int i = 0; i < numpart; i++) info.particles[i].y = mul*f.readReal32(); f.endCheckpoint(); offset = info.ranges[2][0]; - mul = 1.0; - //mul = info.ranges[2][1] - info.ranges[2][0]; + //mul = 1.0; + mul = info.ranges[2][1] - info.ranges[2][0]; f.beginCheckpoint(); for (int i = 0; i < numpart; i++) info.particles[i].z = mul*f.readReal32(); From 063ea61bb7f062773ff3ada8a656e42c2765d2e6 Mon Sep 17 00:00:00 2001 From: "P.M. Sutter" Date: Fri, 3 Jan 2014 06:57:37 -0600 Subject: [PATCH 14/25] default to a larger hubble plot From 079656a8da123aae67ad37e9332aa4962dac3a02 Mon Sep 17 00:00:00 2001 From: "P.M. Sutter" Date: Fri, 3 Jan 2014 19:35:51 -0600 Subject: [PATCH 15/25] switched to more general and universal subprocess command for launching --- .../void_python_tools/backend/launchers.py | 108 +++++++++++++----- 1 file changed, 79 insertions(+), 29 deletions(-) diff --git a/python_tools/void_python_tools/backend/launchers.py b/python_tools/void_python_tools/backend/launchers.py index a615416..758912e 100644 --- a/python_tools/void_python_tools/backend/launchers.py +++ b/python_tools/void_python_tools/backend/launchers.py @@ -87,8 +87,12 @@ def launchGenerate(sample, binPath, workDir=None, inputDataDir=None, if regenerate or not (continueRun and jobSuccessful(logFile, "Done!\n")): file(parmFile, mode="w").write(conf) - cmd = "%s --configFile=%s &> %s" % (binPath,parmFile,logFile) - os.system(cmd) + arg1 = "-configFile=%s" % parmFile + log = open(logFile, 'w') + subprocess.call([binPath, arg1], stdout=log, stderr=log) + log.close() + #cmd = "%s --configFile=%s >& %s" % (binPath,parmFile,logFile) + #os.system(cmd) if jobSuccessful(logFile, "Done!\n"): print "done" else: @@ -204,10 +208,16 @@ def launchGenerate(sample, binPath, workDir=None, inputDataDir=None, file(parmFile, mode="w").write(conf) if (prevSubSample == -1): - cmd = "%s --configFile=%s &> %s" % (binPath,parmFile,logFile) + #cmd = "%s --configFile=%s &> %s" % (binPath,parmFile,logFile) + log = open(logFile, 'w') else: - cmd = "%s --configFile=%s &>> %s" % (binPath,parmFile,logFile) - os.system(cmd) + #cmd = "%s --configFile=%s &>> %s" % (binPath,parmFile,logFile) + log = open(logFile, 'a') + arg1 = "--configFile=%s" % parmFile + subprocess.call([binPath, arg1], stdout=log, stderr=log) + #subprocess.call([binPath, arg1], stdout=log, stderr=log) + log.close() + #os.system(cmd) # remove intermediate files if (prevSubSample != -1): @@ -322,24 +332,49 @@ def launchZobov(sample, binPath, zobovDir=None, logDir=None, continueRun=None, if os.access(zobovDir+"/voidDesc_"+sampleName+".out", os.F_OK): os.unlink(zobovDir+"/voidDesc_"+sampleName+".out") - cmd = "%s/vozinit %s 0.1 1.0 %g %s %g %s %s %s &> %s" % \ - (binPath, datafile, numZobovDivisions, \ - "_"+sampleName, numZobovThreads, \ - binPath, zobovDir, maskIndex, logFile) - os.system(cmd) + #cmd = "%s/vozinit %s 0.1 1.0 %g %s %g %s %s %s &> %s" % \ + # (binPath, datafile, numZobovDivisions, \ + # "_"+sampleName, numZobovThreads, \ + # binPath, zobovDir, maskIndex, logFile) + #os.system(cmd) + cmd = [binPath+"/vozinit", datafile, "0.1", "1.0", str(numZobovDivisions), \ + "_"+sampleName, str(numZobovThreads), \ + binPath, zobovDir, str(maskIndex)] + log = open(logFile, 'w') + subprocess.call(cmd, stdout=log, stderr=log) + log.close() + + #cmd = "./%s >> %s 2>&1" % (vozScript, logFile) + #os.system(cmd) + cmd = ["./%s" % vozScript] + log = open(logFile, 'a') + subprocess.call(cmd, stdout=log, stderr=log) + log.close() - cmd = "./%s >> %s 2>&1" % (vozScript, logFile) - os.system(cmd) # cmd = "%s/jozov %s %s %s %s %s %g %s >> %s 2>&1" % \ - cmd = "%s/../c_tools/zobov2/jozov2/jozov2 %s %s %s %s %s %g %s >> %s 2>&1" % \ - (binPath, \ + #cmd = "%s/../c_tools/zobov2/jozov2/jozov2 %s %s %s %s %s %g %s >> %s 2>&1" % \ + # (binPath, \ + # zobovDir+"/adj_"+sampleName+".dat", \ + # zobovDir+"/vol_"+sampleName+".dat", \ + # zobovDir+"/voidPart_"+sampleName+".dat", \ + # zobovDir+"/voidZone_"+sampleName+".dat", \ + # zobovDir+"/voidDesc_"+sampleName+".out", \ + # maxDen, maskIndex, logFile) + #os.system(cmd) + cmd = [binPath+"../c_tools/zobov2/jozov2/jozov2", \ zobovDir+"/adj_"+sampleName+".dat", \ zobovDir+"/vol_"+sampleName+".dat", \ zobovDir+"/voidPart_"+sampleName+".dat", \ zobovDir+"/voidZone_"+sampleName+".dat", \ zobovDir+"/voidDesc_"+sampleName+".out", \ - maxDen, maskIndex, logFile) - os.system(cmd) + str(maxDen), str(maskIndex)] + log = open(logFile, 'a') + subprocess.call(cmd, stdout=log, stderr=log) + log.close() + + # don't need the subbox files + for fileName in glob.glob(zobovDir+"/part._"+sampleName+".*"): + os.unlink(fileName) if jobSuccessful(logFile, "Done!\n"): print "done" @@ -412,11 +447,14 @@ def launchPrune(sample, binPath, cmd += useComovingFlag cmd += " --outputDir=" + zobovDir cmd += " --sampleName=" + str(sampleName) - cmd += " &> " + logFile - f=file("run_prune.sh",mode="w") - f.write(cmd) - f.close() - os.system(cmd) + #cmd += " &> " + logFile + #f=file("run_prune.sh",mode="w") + #f.write(cmd) + #f.close() + #os.system(cmd) + log = open(logFile, 'w') + subprocess.call(cmd, stdout=log, stderr=log, shell=True) + log.close() if jobSuccessful(logFile, "NetCDF: Not a valid ID\n") or \ jobSuccessful(logFile, "Done!\n"): @@ -485,9 +523,12 @@ def launchVoidOverlap(sample1, sample2, sample1Dir, sample2Dir, if matchMethod == "useID": cmd += " --useID" cmd += periodicLine cmd += " --outfile=" + outputFile - cmd += " &> " + logFile - open("temp.par",'w').write(cmd) - os.system(cmd) + #cmd += " &> " + logFile + #open("temp.par",'w').write(cmd) + #os.system(cmd) + log = open(logFile, 'w') + subprocess.call(cmd, stdout=log, stderr=log, shell=True) + log.close() if jobSuccessful(logFile, "Done!\n"): print "done" @@ -650,9 +691,14 @@ def launchStack(sample, stack, binPath, thisDataPortion=None, logDir=None, fp.close() if not (continueRun and jobSuccessful(logFile, "Done!\n")): - cmd = "%s --configFile=%s &> %s" % \ - (binPath, parmFile, logFile) - os.system(cmd) + #cmd = "%s --configFile=%s &> %s" % \ + # (binPath, parmFile, logFile) + #os.system(cmd) + cmd = "%s --configFile=%s" % \ + (binPath, parmFile) + log = open(logFile, 'w') + subprocess.call(cmd, stdout=log, stderr=log, shell=True) + log.close() if jobSuccessful(logFile, "Done!\n"): print "done" @@ -1721,8 +1767,12 @@ def launchVelocityStack(sample, stack, binPath, parameters="--velocityField=%s --voidCenters=%s --Rmax=%e --L0=%e --numBins=%d" % (velField_file, voidCenters, Rmax, Boxsize, numBins) if not (continueRun and jobSuccessful(logFile, "Done!\n")): - cmd = "%s %s &> %s" % (binPath,parameters,logFile) - os.system(cmd) + #cmd = "%s %s &> %s" % (binPath,parameters,logFile) + #os.system(cmd) + cmd = "%s %s" % (binPath,parameters) + log = open(logFile, 'w') + subprocess.call(cmd, stdout=log, stderr=log, shell=True) + log.close() if jobSuccessful(logFile, "Done!\n"): print "done" else: From 2ff3ff79a427d009942e74eee886fd0944da9f83 Mon Sep 17 00:00:00 2001 From: "P.M. Sutter" Date: Sun, 5 Jan 2014 16:37:23 -0600 Subject: [PATCH 16/25] more flexibile catalog matching options --- python_tools/void_python_tools/backend/launchers.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/python_tools/void_python_tools/backend/launchers.py b/python_tools/void_python_tools/backend/launchers.py index 2d72ca8..fddae0f 100644 --- a/python_tools/void_python_tools/backend/launchers.py +++ b/python_tools/void_python_tools/backend/launchers.py @@ -472,7 +472,7 @@ def launchVoidOverlap(sample1, sample2, sample1Dir, sample2Dir, binPath, thisDataPortion=None, logFile=None, workDir=None, continueRun=None, outputFile=None, - matchMethod=None): + matchMethod=None, strictMatch=False): sampleName1 = sample1.fullName sampleName2 = sample2.fullName @@ -484,6 +484,11 @@ def launchVoidOverlap(sample1, sample2, sample1Dir, sample2Dir, # periodicLine += "z" #periodicLine += "' " + if strictMatch: + matchPrefix = "" + else: + matchPrefix = "trimmed_nodencut_" + if not (continueRun and jobSuccessful(logFile, "Done!\n")): cmd = binPath cmd += " --partFile1=" + sample1Dir+"/zobov_slice_" + \ @@ -507,14 +512,14 @@ def launchVoidOverlap(sample1, sample2, sample1Dir, sample2Dir, str(sampleName2) cmd += " --volFile2=" + sample2Dir+"/vol_" + \ str(sampleName2)+".dat" - cmd += " --voidFile2=" + sample2Dir+"/trimmed_nodencut_voidDesc_" + \ + cmd += " --voidFile2=" + sample2Dir+"/"+matchPrefix+"voidDesc_" + \ thisDataPortion+"_"+str(sampleName2)+".out" cmd += " --infoFile2=" + sample2Dir+"/zobov_slice_" + \ str(sampleName2)+".par" cmd += " --centerFile2=" + sample2Dir + \ - "/trimmed_nodencut_barycenters_"+thisDataPortion+"_"+str(sampleName2)+".out" + "/"+matchPrefix+"barycenters_"+thisDataPortion+"_"+str(sampleName2)+".out" cmd += " --shapeFile2=" + sample2Dir + \ - "/trimmed_nodencut_shapes_"+thisDataPortion+"_"+str(sampleName2)+".out" + "/"+matchPrefix+"shapes_"+thisDataPortion+"_"+str(sampleName2)+".out" cmd += " --zoneFile2=" + sample2Dir+"/voidZone_" + \ str(sampleName2)+".dat" cmd += " --zonePartFile2=" + sample2Dir+"/voidPart_" + \ From 385c0e65aa113812e2d0d2e6f5ed7f68aae373d9 Mon Sep 17 00:00:00 2001 From: "P.M. Sutter" Date: Thu, 9 Jan 2014 15:05:31 -0600 Subject: [PATCH 17/25] more generic subprocess calling in preparation scripts --- .../pipeline_source/prepareCatalogs.in.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/python_tools/pipeline_source/prepareCatalogs.in.py b/python_tools/pipeline_source/prepareCatalogs.in.py index 55a8e4e..2c98c53 100644 --- a/python_tools/pipeline_source/prepareCatalogs.in.py +++ b/python_tools/pipeline_source/prepareCatalogs.in.py @@ -476,9 +476,8 @@ for iSubSample in xrange(len(subSamples)): rescale_velocity, rescale_velocity, convertedFile ) - os.system(command) - - os.system(command) + #os.system(command) + subprocess.call(command, shell=True) dataFile = convertedFile inFile = open(dataFile, 'r') @@ -670,7 +669,8 @@ if (args.halos or args.all) and haloFileBase != "": command = "%s -a 200000 %s mass ident x y z vz vy vx parent_id | awk '{if ($9==-1) print $2, $3, $4, $5, $6, $7, $8, $1}'>>%s" % (SDFcvt_PATH, dataFile, outFileName ) else: command = "%s -a 200000 %s mass ident x y z vz vy vx parent_id | awk '{if ($1>%g && $9==-1) print $2, $3, $4, $5, $6, $7, $8, $1}'>>%s" % (SDFcvt_PATH, dataFile, minHaloMass, outFileName ) - os.system(command) + #os.system(command) + subprocess.call(command, shell=True) outFile = open(outFileName, 'a') outFile.write("-99 -99 -99 -99 -99 -99 -99 -99\n") outFile.close() @@ -804,7 +804,8 @@ if (args.hod or args.all) and haloFileBase != "": outFile = haloFile+"_temp" SDFcvt_PATH = "@CMAKE_BINARY_DIR@/external/libsdf/apps/SDFcvt/SDFcvt.x86_64" command = "%s -a 200000 %s mass x y z vx vy vz parent_id | awk '{if ($8 ==-1) print $1, $2, $3, $4, $5, $6, $7}'>>%s" % (SDFcvt_PATH, inFile, outFile) - os.system(command) + #os.system(command) + subprocess.call(command, shell=True) haloFile = outFile for thisHod in hodParmList: @@ -831,8 +832,12 @@ if (args.hod or args.all) and haloFileBase != "": sampleName = getSampleName(prefix+"hod_"+thisHod['name'], redshift, False) tempFile = "./hod.out_"+sampleName - HOD_PATH = "@CMAKE_BINARY_DIR@/c_tools/hod/hod" - os.system(HOD_PATH+" "+parFileName+">& " + tempFile) + output = open(tempFile, 'w') + HOD_PATH = "/home/psutter2/projects/Voids/vide/c_tools/hod/hod" + #os.system(HOD_PATH+" "+parFileName+">& " + tempFile) + subprocess.call(HOD_PATH+" "+parFileName, stdout=output, stderr=output, shell=True) + output.close() + for line in open(tempFile): if "MLO" in line: print " (minimum halo mass = ", line.split()[1], ")" From 23871953f09e398c692c360e4ea4695f15b06a8b Mon Sep 17 00:00:00 2001 From: "P.M. Sutter" Date: Thu, 9 Jan 2014 15:50:11 -0600 Subject: [PATCH 18/25] fixed cmakelist file to include HOD code From a513603957364d94a42942bfa715cd62c6cca67c Mon Sep 17 00:00:00 2001 From: "P.M. Sutter" Date: Fri, 10 Jan 2014 10:33:08 -0600 Subject: [PATCH 19/25] unique filenames for HOD output so scripts can be run in parallel --- python_tools/pipeline_source/prepareCatalogs.in.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/python_tools/pipeline_source/prepareCatalogs.in.py b/python_tools/pipeline_source/prepareCatalogs.in.py index 2c98c53..d853ac3 100644 --- a/python_tools/pipeline_source/prepareCatalogs.in.py +++ b/python_tools/pipeline_source/prepareCatalogs.in.py @@ -737,7 +737,7 @@ RESOLUTION {numPartPerSide} BOX_SIZE {boxSize} % output -root_filename {workDir}/hod +root_filename {workDir}/hod_{sampleName} """ if (args.script or args.all) and haloFileBase != "": @@ -827,7 +827,8 @@ if (args.hod or args.all) and haloFileBase != "": haloFileFormat=dataFormat, numPartPerSide=numPart**(1/3.), boxSize=lbox, - workDir=catalogDir)) + workDir=catalogDir, + sampleName=sampleName)) parFile.close() sampleName = getSampleName(prefix+"hod_"+thisHod['name'], redshift, False) @@ -845,7 +846,7 @@ if (args.hod or args.all) and haloFileBase != "": os.unlink(tempFile) outFileName = catalogDir+"/"+sampleName+".dat" - os.system("mv %s/hod.mock %s" % (catalogDir, outFileName)) + os.system("mv %s/hod_%s.mock %s" % (catalogDir, sampleName, outFileName)) os.system("rm %s/hod.*" % catalogDir) os.system("rm ./hod.par") os.system("rm ./hod-usedvalues") From ee2a5467c801c8abf03fe3e4caf62b556649f2a3 Mon Sep 17 00:00:00 2001 From: "P.M. Sutter" Date: Mon, 13 Jan 2014 02:22:35 -0600 Subject: [PATCH 20/25] fixed barycenter periodic box wrapping for z>0 boxes --- c_tools/stacking/pruneVoids.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/c_tools/stacking/pruneVoids.cpp b/c_tools/stacking/pruneVoids.cpp index 9ac1f88..6e54cc6 100644 --- a/c_tools/stacking/pruneVoids.cpp +++ b/c_tools/stacking/pruneVoids.cpp @@ -587,21 +587,21 @@ int main(int argc, char **argv) { voids[iVoid].barycenter[2] += voids[iVoid].center[2]; if (periodicX) { - if (voids[iVoid].barycenter[0] > boxLen[0]) + if (voids[iVoid].barycenter[0] > ranges[0][1]) voids[iVoid].barycenter[0] = voids[iVoid].barycenter[0] - boxLen[0]; - if (voids[iVoid].barycenter[0] < 0) + if (voids[iVoid].barycenter[0] < ranges[0][0]) voids[iVoid].barycenter[0] = boxLen[0] + voids[iVoid].barycenter[0]; } if (periodicY) { - if (voids[iVoid].barycenter[1] > boxLen[1]) + if (voids[iVoid].barycenter[1] > ranges[1][1]) voids[iVoid].barycenter[1] = voids[iVoid].barycenter[1] - boxLen[1]; - if (voids[iVoid].barycenter[1] < 0) + if (voids[iVoid].barycenter[1] < ranges[1][0]) voids[iVoid].barycenter[1] = boxLen[1] + voids[iVoid].barycenter[1]; } if (periodicZ) { - if (voids[iVoid].barycenter[2] > boxLen[2]) + if (voids[iVoid].barycenter[2] > ranges[2][1]) voids[iVoid].barycenter[2] = voids[iVoid].barycenter[2] - boxLen[2]; - if (voids[iVoid].barycenter[2] < 0) + if (voids[iVoid].barycenter[2] < ranges[2][0]) voids[iVoid].barycenter[2] = boxLen[2] + voids[iVoid].barycenter[2]; } clock4 = clock(); @@ -850,7 +850,7 @@ int main(int argc, char **argv) { int numTooSmall = 0; printf(" Picking winners and losers...\n"); - printf(" Starting with %d voids\n", voids.size()); + printf(" Starting with %d voids\n", (int) voids.size()); for (iVoid = 0; iVoid < voids.size(); iVoid++) { voids[iVoid].accepted = 1; @@ -950,7 +950,7 @@ int main(int argc, char **argv) { } } - printf(" Number kept: %d (out of %d)\n", voids.size(), numVoids); + printf(" Number kept: %d (out of %d)\n", (int) voids.size(), numVoids); printf(" We have %d edge voids\n", numEdge); printf(" We have %d central voids\n", numCentral); printf(" We have %d too high central density\n", numHighDen); From 82dfc3bd0f23d709389d6920198ab7adf0eae2cd Mon Sep 17 00:00:00 2001 From: "P.M. Sutter" Date: Mon, 13 Jan 2014 02:38:27 -0600 Subject: [PATCH 21/25] use simulation's cosmology for predicted a-p signal --- .../void_python_tools/backend/launchers.py | 81 +++++++++++-------- 1 file changed, 49 insertions(+), 32 deletions(-) diff --git a/python_tools/void_python_tools/backend/launchers.py b/python_tools/void_python_tools/backend/launchers.py index fddae0f..32cced1 100644 --- a/python_tools/void_python_tools/backend/launchers.py +++ b/python_tools/void_python_tools/backend/launchers.py @@ -776,7 +776,7 @@ def launchStack(sample, stack, binPath, thisDataPortion=None, logDir=None, exit(-1) sys.stdout = open(logFile, 'a') - sys.stderr = open(logFile, 'a') + #sys.stderr = open(logFile, 'a') zMin = sample.zRange[0] zMax = sample.zRange[1] if not sample.volumeLimited: @@ -788,8 +788,10 @@ def launchStack(sample, stack, binPath, thisDataPortion=None, logDir=None, zMaxForVol = sample.zBoundary[1] props = vp.getSurveyProps(maskFile, zMinForVol, zMaxForVol, zMin, zMax, "all") + props = ((1.0,1.0)) + sys.stdout = sys.__stdout__ - sys.stderr = sys.__stderr__ + #sys.stderr = sys.__stderr__ boxVol = props[0] nbar = props[1] @@ -866,7 +868,7 @@ def launchCombine(sample, stack, voidDir=None, logFile=None, jobString = " "+runSuffix+":" sys.stdout = open(logFile, 'w') - sys.stderr = open(logFile, 'a') + #sys.stderr = open(logFile, 'a') if os.access(voidDir+"/num_voids.txt", os.F_OK): os.unlink(voidDir+"/num_voids.txt") @@ -1086,7 +1088,7 @@ def launchCombine(sample, stack, voidDir=None, logFile=None, print "Done!" sys.stdout = sys.__stdout__ - sys.stderr = sys.__stderr__ + #sys.stderr = sys.__stderr__ if jobSuccessful(logFile, "Done!\n"): print jobString, "Combining stacks done" @@ -1139,12 +1141,12 @@ def launchProfile(sample, stack, voidDir=None, logFile=None, continueRun=None, density = sample.profileBinSize sys.stdout = open(logFile, 'w') - sys.stderr = open(logFile, 'a') + #sys.stderr = open(logFile, 'a') vp.build_1d_profile(base_dir=voidDir, density=density, rescaleMode=stack.rescaleMode) vp.build_2d_profile(base_dir=voidDir, density=density) sys.stdout = sys.__stdout__ - sys.stderr = sys.__stderr__ + #sys.stderr = sys.__stderr__ if jobSuccessful(logFile, "Done!\n"): print jobString, "Profiling stacks done, (N_v=", numVoids,")" @@ -1205,14 +1207,16 @@ def launchFit(sample, stack, logFile=None, voidDir=None, figDir=None, runSuffix+".eps") sys.stdout = open(logFile, 'w') - sys.stderr = open(logFile, 'a') + #sys.stderr = open(logFile, 'a') badChain = True ntries = 0 maxtries = 5 while badChain: - Rexpect = (stack.rMin+stack.rMax)/2 - Rtruncate = stack.rMin*3. + 1 # TEST + ntries += 1 + + #Rexpect = (stack.rMin+stack.rMax)/2 + #Rtruncate = stack.rMin*3. + 1 # TEST #if sample.dataType == "observation": # ret,fits,args = vp.fit_ellipticity(voidDir,Rbase=Rexpect, # Niter=300000, @@ -1220,15 +1224,16 @@ def launchFit(sample, stack, logFile=None, voidDir=None, figDir=None, # Rextracut=Rtruncate) #else: # ret,fits,args = vp.fit_ellipticity(voidDir,Rbase=Rexpect, - # Niter=300000, + # Niter=500000, # Nburn=100000, - # Rextracut=Rtruncate) + # Rextracut=Rtruncate) #badChain = (args[0][0] > 0.5 or args[0][1] > stack.rMax or \ # args[0][2] > stack.rMax) and \ # (ntries < maxtries) - ret,fits,args = vp.compute_inertia(voidDir, stack.rMax, mode="symmetric", nBootstraps=500) + #ret,fits,args = vp.compute_radial_inertia(voidDir, stack.rMax, mode="symmetric", nBootstraps=5) + ret,fits,args = vp.compute_inertia(voidDir, stack.rMax, nBootstraps=100, rMaxInertia=1.0) + #ret,fits,args = vp.compute_inertia(voidDir, stack.rMax, mode="symmetric", nBootstraps=500, rMaxInertia=1.5) badChain = False - ntries += 1 #np.save(voidDir+"/chain.npy", ret) np.savetxt(voidDir+"/fits.out", fits) @@ -1259,7 +1264,7 @@ def launchFit(sample, stack, logFile=None, voidDir=None, figDir=None, "_"+runSuffix+".png") sys.stdout = sys.__stdout__ - sys.stderr = sys.__stderr__ + #sys.stderr = sys.__stderr__ if jobSuccessful(logFile, "Done!\n"): print jobString, "Fitting done (", ntries, " tries)" else: @@ -1352,7 +1357,7 @@ def launchHubble(dataPortions=None, dataSampleList=None, logDir=None, aveDist = vp.aveStretchCone(stack.zMin, stack.zMax, skyFrac = sample.skyFraction) else: - aveDist = vp.aveStretch(stack.zMin, stack.zMax) + aveDist = vp.aveStretch(stack.zMin, stack.zMax, Om=sample.omegaM) aveDistList[iZBin, 0] = stack.zMin aveDistList[iZBin, 1] = aveDist @@ -1401,7 +1406,7 @@ def launchHubble(dataPortions=None, dataSampleList=None, logDir=None, aveDist = vp.aveStretchCone(zBin.zMin, zBin.zMax, skyFrac = sample.skyFraction) else: - aveDist = vp.aveStretch(zBin.zMin, zBin.zMax) + aveDist = vp.aveStretch(zBin.zMin, zBin.zMax, Om=sample.omegaOm) expList[0, iR, iZBin, 2] = aveDist @@ -1437,7 +1442,7 @@ def launchHubble(dataPortions=None, dataSampleList=None, logDir=None, if not (continueRun and jobSuccessful(logFile, "Done!\n")): sys.stdout = open(logFile, 'w') - sys.stderr = open(logFile, 'a') + #sys.stderr = open(logFile, 'a') plotTitle = "Sample: "+sample.nickName+", "+thisDataPortion+" voids" if doPlot: #vp.do_all_obs(zbase, expList, workDir+"/avedistortion_", @@ -1453,7 +1458,7 @@ def launchHubble(dataPortions=None, dataSampleList=None, logDir=None, print "Skipping plot" print "Done!" sys.stdout = sys.__stdout__ - sys.stderr = sys.__stderr__ + #sys.stderr = sys.__stderr__ if jobSuccessful(logFile, "Done!\n"): print "done" @@ -1468,7 +1473,7 @@ def launchHubble(dataPortions=None, dataSampleList=None, logDir=None, print " For data set combined...", sys.stdout.flush() - logFile = logDir+"/hubble_combined_"+thisDataPortion+".out" + logFile = logDir+"/hubble_combined_"+sampleName+"_"+thisDataPortion+".out" if not (continueRun and jobSuccessful(logFile, "Done!\n")): @@ -1516,6 +1521,7 @@ def launchHubble(dataPortions=None, dataSampleList=None, logDir=None, aveDistList[iZ, 0] = zBin.zMin aveDistList[iZ, 1] = aveDist aveDistList[iZ, 2] = 0.00125 + if plotZmax > 1.5: plotZmax = 1.5 shortSampleNames = list() @@ -1523,7 +1529,7 @@ def launchHubble(dataPortions=None, dataSampleList=None, logDir=None, if sample.includeInHubble: shortSampleNames.append(sample.nickName) sys.stdout = open(logFile, 'w') - sys.stderr = open(logFile, 'a') + #sys.stderr = open(logFile, 'a') if doPlot: if INCOHERENT: #plotTitle = "all samples, incoherent "+\ @@ -1536,12 +1542,15 @@ def launchHubble(dataPortions=None, dataSampleList=None, logDir=None, vp.do_all_obs(zbase, allExpList, aveDistList, rlist, plotTitle=plotTitle, sampleNames=shortSampleNames, plotAve=True, mulfac = 1.0, biasLine = 1.16, - plotZmin=plotZmin, plotZmax=plotZmax+0.2) - figure(1).savefig(figDir+"/hubble_combined_"+thisDataPortion+\ + plotZmin=plotZmin, plotZmax=plotZmax) + figure(1).savefig(figDir+"/hubble_combined_"+setName+"_"+ \ + thisDataPortion+\ ".eps",bbox_inches='tight') - figure(1).savefig(figDir+"/hubble_combined_"+thisDataPortion+\ + figure(1).savefig(figDir+"/hubble_combined_"+setName+"_"+ \ + thisDataPortion+\ ".pdf",bbox_inches='tight') - figure(1).savefig(figDir+"/hubble_combined_"+thisDataPortion+\ + figure(1).savefig(figDir+"/hubble_combined_"+setName+"_"+ \ + thisDataPortion+\ ".png",bbox_inches='tight') if INCOHERENT: @@ -1554,18 +1563,21 @@ def launchHubble(dataPortions=None, dataSampleList=None, logDir=None, vp.do_all_obs(zbase, allExpList, aveDistList, rlist, plotTitle=plotTitle, sampleNames=shortSampleNames, plotAve=True, mulfac = 1.16, - plotZmin=plotZmin, plotZmax=plotZmax+0.2) - figure(1).savefig(figDir+"/hubble_combined_"+thisDataPortion+\ + plotZmin=plotZmin, plotZmax=plotZmax) + figure(1).savefig(figDir+"/hubble_combined_"+setName+"_"+\ + thisDataPortion+\ "_debiased.eps",bbox_inches='tight') - figure(1).savefig(figDir+"/hubble_combined_"+thisDataPortion+\ + figure(1).savefig(figDir+"/hubble_combined_"+setName+"_"+\ + thisDataPortion+\ "_debiased.pdf",bbox_inches='tight') - figure(1).savefig(figDir+"/hubble_combined_"+thisDataPortion+\ + figure(1).savefig(figDir+"/hubble_combined_"+setName+"_"+\ + thisDataPortion+\ "_debiased.png",bbox_inches='tight') else: print "Skipping plot" print "Done!" sys.stdout = sys.__stdout__ - sys.stderr = sys.__stderr__ + #sys.stderr = sys.__stderr__ # save all expansion data to a single file fp = file(workDir+'/calculatedExpansions_'+thisDataPortion+'.txt', @@ -1603,8 +1615,13 @@ def launchHubble(dataPortions=None, dataSampleList=None, logDir=None, voidRedshifts = np.loadtxt(centersFile) if voidRedshifts.ndim > 1: voidRedshifts = voidRedshifts[:,5] + np.savetxt(fp, voidRedshifts[None]) else: - voidRedshifts = voidRedshifts[5] + if (len(voidRedshifts) > 0): + voidRedshifts = voidRedshifts[5] + np.savetxt(fp, voidRedshifts[None]) + else: + fp.write("-1\n") #fp.write(str(len(voidRedshifts))+" ") np.savetxt(fp, voidRedshifts[None]) else: @@ -1634,7 +1651,7 @@ def launchLikelihood(dataPortions=None, logDir=None, workDir=None, if not (continueRun and jobSuccessful(logFile, "Done!\n")): sys.stdout = open(logFile, 'w') - sys.stderr = open(logFile, 'a') + #sys.stderr = open(logFile, 'a') vp.build1dLikelihood(workDir+"/calculatedExpansions_"+\ thisDataPortion+".txt", @@ -1651,7 +1668,7 @@ def launchLikelihood(dataPortions=None, logDir=None, workDir=None, useBinAve = False) sys.stdout = sys.__stdout__ - sys.stderr = sys.__stderr__ + #sys.stderr = sys.__stderr__ if jobSuccessful(logFile, "Done!\n"): print "done" From 89082b2f1e0eee3a587530c42f536f6f4621f53a Mon Sep 17 00:00:00 2001 From: Paul Matthew Sutter Date: Tue, 14 Jan 2014 11:06:29 +0100 Subject: [PATCH 22/25] merger --- c_tools/mock/generateMock.cpp | 8 ++++++++ python_tools/void_python_tools/backend/launchers.py | 9 ++++++--- zobov/jozov.c | 4 ++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/c_tools/mock/generateMock.cpp b/c_tools/mock/generateMock.cpp index 1635a05..8192f42 100644 --- a/c_tools/mock/generateMock.cpp +++ b/c_tools/mock/generateMock.cpp @@ -116,6 +116,11 @@ void metricTransform(SimuData *data, int axis, bool reshift, bool pecvel, double baseComovingDistance = LIGHT_SPEED/100.* gslIntegrate(e_computer, 0, z0, 1e-3); cout << "Comoving distance = " << baseComovingDistance << " Mpc/h" << endl; + if (cosmo_flag) cout << "Will place particles on a lightcone..." << endl; + + float minZ = 1.e99; + float maxZ = 0; + for (uint32_t i = 0; i < data->NumPart; i++) { float& x = data->Pos[x0][i]; @@ -148,8 +153,11 @@ void metricTransform(SimuData *data, int axis, bool reshift, bool pecvel, double cout << "The offending value is z=" << reduced_red << endl; abort(); } + if (z > maxZ) maxZ = z; + if (z < minZ) minZ = z; } + printf("Range of z: %.2f - %.2f\n", minZ, maxZ); } // slightly perturb particle positions diff --git a/python_tools/void_python_tools/backend/launchers.py b/python_tools/void_python_tools/backend/launchers.py index d9b2525..83873b4 100644 --- a/python_tools/void_python_tools/backend/launchers.py +++ b/python_tools/void_python_tools/backend/launchers.py @@ -1451,11 +1451,14 @@ def launchHubble(dataPortions=None, dataSampleList=None, logDir=None, #vp.do_all_obs(zbase, expList, workDir+"/avedistortion_", vp.do_all_obs(zbase, expList, aveDistList, rlist, plotTitle=plotTitle, plotAve=True) - figure(1).savefig(figDir+"/hubble_"+sampleName+"_"+thisDataPortion+\ + figure(1).savefig(figDir+"/hubble_"+setName+"_"+sampleName+"_"+\ + thisDataPortion+\ ".eps",bbox_inches='tight') - figure(1).savefig(figDir+"/hubble_"+sampleName+"_"+thisDataPortion+\ + figure(1).savefig(figDir+"/hubble_"+setName+"_"+sampleName+"_"+\ + thisDataPortion+\ ".pdf",bbox_inches='tight') - figure(1).savefig(figDir+"/hubble_"+sampleName+"_"+thisDataPortion+\ + figure(1).savefig(figDir+"/hubble_"+setName+"_"+sampleName+"_"+\ + thisDataPortion+\ ".png",bbox_inches='tight') else: print "Skipping plot" diff --git a/zobov/jozov.c b/zobov/jozov.c index a4ee12b..e2ed619 100644 --- a/zobov/jozov.c +++ b/zobov/jozov.c @@ -131,7 +131,7 @@ int main(int argc,char **argv) { printf("OVERFLOW for particle %d (pending %d). List of accepted:\n", i, j); for (q=0;q Date: Tue, 14 Jan 2014 11:36:19 +0100 Subject: [PATCH 23/25] cleaner handling of HOD errors --- .../pipeline_source/prepareCatalogs.in.py | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/python_tools/pipeline_source/prepareCatalogs.in.py b/python_tools/pipeline_source/prepareCatalogs.in.py index d853ac3..e5e6c87 100644 --- a/python_tools/pipeline_source/prepareCatalogs.in.py +++ b/python_tools/pipeline_source/prepareCatalogs.in.py @@ -812,6 +812,8 @@ if (args.hod or args.all) and haloFileBase != "": print " ", thisHod['name'] sys.stdout.flush() + sampleName = getSampleName(prefix+"hod_"+thisHod['name'], redshift, False) + parFileName = "./hod.par" parFile = open(parFileName, 'w') parFile.write(parFileText.format(omegaM=omegaM, @@ -831,19 +833,29 @@ if (args.hod or args.all) and haloFileBase != "": sampleName=sampleName)) parFile.close() - sampleName = getSampleName(prefix+"hod_"+thisHod['name'], redshift, False) tempFile = "./hod.out_"+sampleName output = open(tempFile, 'w') - HOD_PATH = "/home/psutter2/projects/Voids/vide/c_tools/hod/hod" + HOD_PATH = "@CMAKE_BINARY_DIR@/c_tools/hod/hod" + #os.system(HOD_PATH+" "+parFileName+">& " + tempFile) - subprocess.call(HOD_PATH+" "+parFileName, stdout=output, stderr=output, shell=True) + subprocess.call(HOD_PATH+" "+parFileName, stdout=output, stderr=output, + shell=True) output.close() - + + hodWorked = False for line in open(tempFile): if "MLO" in line: print " (minimum halo mass = ", line.split()[1], ")" + hodWorked = True break - os.unlink(tempFile) + + if hodWorked: + os.unlink(tempFile) + else: + print "HOD Failed! Log follows:" + for line in open(tempFile): + print line + exit(-1) outFileName = catalogDir+"/"+sampleName+".dat" os.system("mv %s/hod_%s.mock %s" % (catalogDir, sampleName, outFileName)) From 8c446d10791f45f95a8f73a1228a6057821b1b23 Mon Sep 17 00:00:00 2001 From: "P.M. Sutter" Date: Wed, 15 Jan 2014 16:02:18 -0600 Subject: [PATCH 24/25] buildSkyProjections now fully integrated into vide --- .../void_python_tools/backend/launchers.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/python_tools/void_python_tools/backend/launchers.py b/python_tools/void_python_tools/backend/launchers.py index 32cced1..addd367 100644 --- a/python_tools/void_python_tools/backend/launchers.py +++ b/python_tools/void_python_tools/backend/launchers.py @@ -87,7 +87,7 @@ def launchGenerate(sample, binPath, workDir=None, inputDataDir=None, if regenerate or not (continueRun and jobSuccessful(logFile, "Done!\n")): file(parmFile, mode="w").write(conf) - arg1 = "-configFile=%s" % parmFile + arg1 = "--configFile=%s" % parmFile log = open(logFile, 'w') subprocess.call([binPath, arg1], stdout=log, stderr=log) log.close() @@ -209,12 +209,14 @@ def launchGenerate(sample, binPath, workDir=None, inputDataDir=None, if (prevSubSample == -1): #cmd = "%s --configFile=%s &> %s" % (binPath,parmFile,logFile) + cmd = "%s --configFile=%s" % (binPath,parmFile) log = open(logFile, 'w') else: #cmd = "%s --configFile=%s &>> %s" % (binPath,parmFile,logFile) + cmd = "%s --configFile=%s" % (binPath,parmFile) log = open(logFile, 'a') arg1 = "--configFile=%s" % parmFile - subprocess.call([binPath, arg1], stdout=log, stderr=log) + subprocess.call(cmd, stdout=log, stderr=log, shell=True) #subprocess.call([binPath, arg1], stdout=log, stderr=log) log.close() #os.system(cmd) @@ -254,7 +256,7 @@ def launchGenerate(sample, binPath, workDir=None, inputDataDir=None, if sample.dataType == "observation": (boxVol, nbar) = vp.getSurveyProps(sample.maskFile, sample.zRange[0], sample.zRange[1], sample.zRange[0], sample.zRange[1], "all", - useComoving=useComoving) + useLCDM=useComoving) else: iX = float(sample.mySubvolume[0]) iY = float(sample.mySubvolume[1]) @@ -1224,15 +1226,16 @@ def launchFit(sample, stack, logFile=None, voidDir=None, figDir=None, # Rextracut=Rtruncate) #else: # ret,fits,args = vp.fit_ellipticity(voidDir,Rbase=Rexpect, - # Niter=500000, + # Niter=300000, # Nburn=100000, # Rextracut=Rtruncate) #badChain = (args[0][0] > 0.5 or args[0][1] > stack.rMax or \ # args[0][2] > stack.rMax) and \ # (ntries < maxtries) #ret,fits,args = vp.compute_radial_inertia(voidDir, stack.rMax, mode="symmetric", nBootstraps=5) - ret,fits,args = vp.compute_inertia(voidDir, stack.rMax, nBootstraps=100, rMaxInertia=1.0) - #ret,fits,args = vp.compute_inertia(voidDir, stack.rMax, mode="symmetric", nBootstraps=500, rMaxInertia=1.5) + #ret,fits,args = vp.compute_inertia(voidDir, stack.rMax, nBootstraps=100, rMaxInertia=1.0) + ret,fits,args = vp.compute_inertia(voidDir, stack.rMax, mode="2d", nBootstraps=500, rMaxInertia=0.7) + #ret,fits,args = vp.compute_inertia(voidDir, stack.rMax, mode="symmetric", nBootstraps=500, rMaxInertia=100) badChain = False #np.save(voidDir+"/chain.npy", ret) @@ -1406,7 +1409,7 @@ def launchHubble(dataPortions=None, dataSampleList=None, logDir=None, aveDist = vp.aveStretchCone(zBin.zMin, zBin.zMax, skyFrac = sample.skyFraction) else: - aveDist = vp.aveStretch(zBin.zMin, zBin.zMax, Om=sample.omegaOm) + aveDist = vp.aveStretch(zBin.zMin, zBin.zMax, Om=sample.omegaM) expList[0, iR, iZBin, 2] = aveDist From 1177313ac9d9381dfe02346fd531e74e5a7ea8ed Mon Sep 17 00:00:00 2001 From: "P.M. Sutter" Date: Wed, 15 Jan 2014 16:04:05 -0600 Subject: [PATCH 25/25] updated A-P analysis