Generate a population the COSMIC way
Beyond providing a simple interface and several updates to BSE (Hurley+2002), COSMIC is designed to adapt the number of systems simulated to each binary evolution model a user selects. This is done by iteratively simulating binaries initialized with ZAMS binary parameters and a star formation history until the distributions of binary parameters specified by the user converge. This process is carried out by cosmic-pop
. Once this population is simulated, an astrophysical population can be sampled from the output of cosmic-pop
.
cosmic-pop
The fixed population is the output of cosmic-pop
and is designed to fully describe the distribution of binary parameters that results from a user specified star formation history (SFH) and binary evolution model (BSEDict, specified in an inifile). The fixed population is only simulated once and only contains information about the intrinsic properties of the binary (e.g. masses, semimajor axes, metallicities, etc.) Information about the location and orientation of each binary is not contained in the fixed population. The arguments necessary to run the cosmic-pop
executable can be found using the help command:
cosmic-pop -h
usage: cosmic-pop [-h] [--inifile FILE] --final-kstar1 FINAL_KSTAR1
[FINAL_KSTAR1 ...] --final-kstar2 FINAL_KSTAR2
[FINAL_KSTAR2 ...] [--Niter NITER] [--Nstep NSTEP]
[--max-wall-time MAX_WALL_TIME]
[--binary_state BINARY_STATE [BINARY_STATE ...]]
[--sampling_method SAMPLING_METHOD]
[--primary_model PRIMARY_MODEL]
[--binfrac_model BINFRAC_MODEL] [--ecc_model ECC_MODEL]
[--porb_model PORB_MODEL] [--SF_start SF_START]
[--SF_duration SF_DURATION] [--metallicity METALLICITY]
[--convergence_params CONVERGENCE_PARAMS [CONVERGENCE_PARAMS ...]]
[--convergence_limits CONVERGENCE_LIMITS]
[--pop_select POP_SELECT] [--match MATCH]
[--apply_convergence_limits [APPLY_CONVERGENCE_LIMITS]]
[--seed SEED] [--verbose] [--complib COMPLIB]
[--complevel COMPLEVEL] [-n NPROC | --mpi]
options:
-h, --help show this help message and exit
--inifile FILE Name of ini file of params
--final-kstar1 FINAL_KSTAR1 [FINAL_KSTAR1 ...]
Specify the final condition of kstar1 , you want
systems to end at for your samples
--final-kstar2 FINAL_KSTAR2 [FINAL_KSTAR2 ...]
Specify the final condition of kstar2, you want
systems to end at for your samples
--Niter NITER Number of iterations of binaries to try, will check
ever Nstep for convergence
--Nstep NSTEP Number of binaries to try before checking for
convergence, it will check ever Nstep binaries until
it reach Niter binaries
--max-wall-time MAX_WALL_TIME
Maximum wall time (seconds) for sampling binaries
--binary_state BINARY_STATE [BINARY_STATE ...]
--sampling_method SAMPLING_METHOD
--primary_model PRIMARY_MODEL
Chooses the initial primary mass function from:
salpeter55, kroupa93, kroupa01
--binfrac_model BINFRAC_MODEL
Chooses the binary fraction model from: a float
between [0,1], vanHaaften, and offner22
--ecc_model ECC_MODEL
Chooses the initial eccentricity distribution model
from: thermal, uniform, and sana12
--porb_model PORB_MODEL
Chooses the initial orbital period distribution model
from: log_uniform and sana12
--SF_start SF_START Sets the time in the past when star formation
initiates in Myr
--SF_duration SF_DURATION
Sets the duration of constant star formation in Myr
--metallicity METALLICITY
--convergence_params CONVERGENCE_PARAMS [CONVERGENCE_PARAMS ...]
specifies the list of parameters for which you would
like to track the distribution shapes for convergence
--convergence_limits CONVERGENCE_LIMITS
dictionary that can contain limits for convergence
params
--pop_select POP_SELECT
Used in combination with the specified final_kstar1
and final_kstar2 values to select the subpopulation of
interest from the evolved population
--match MATCH provides the tolerance for the convergence calculation
--apply_convergence_limits [APPLY_CONVERGENCE_LIMITS]
filters the evolved binary population to contain only
the binaries that satsify the convergence limits
--seed SEED
--verbose Run in Verbose Mode
--complib COMPLIB HDFStore compression library
--complevel COMPLEVEL
HDFStore compression level
-n NPROC, --nproc NPROC
number of processors
--mpi Run with MPI.
Inputs
Params.ini
PLEASE SEE Configuration files for COSMIC for detailed information about the inifile and how it is constructed
The inifile contains five subsections: filters
, convergence
, rand_seed
, and bse
.
The filters
subsection allows you to specify how you would like to filter the binary population. See the inifile for a description of each flag.
The convergence
subsection allows you to specify a particular region of parameter space where you would like the convergence of each binary parameter distribution to be tested. The only implemented convergence filter is for LISA binaries, where the convergence is computed only for binaries with orbital period less than 5000 s. This allows for low probability, but high signal to noise binaries with very short orbital periods to be fully accounted for.
The rand_seed
subsections allows you to initialize the population with a random seed for reproduceability. Note that for each simulated binary, COSMIC also returns the initial conditions, including a random seed that will reproduce that exact binary. The random seed produced in the rand_seed subsection allows full populations to be reproduced. This is particularly useful when comparing two popuations, e.g. binary black holes and binary neutron stars, which should be simulated separately, but using the same rand_seed value.
The sampling
subsection allows you to control how you sample and achieve the initial binaries that you evolve.
The bse
subsection is where all the BSE flags are specified.
Sample command line
Below is an example command line call for cosmic-pop
with multiprocessing (i.e. shared memory on a single computer):
cosmic-pop --final-kstar1 13 14 --final-kstar2 13 14 --inifile Params.ini --Nstep 1000 --Niter 1000000000 -n 2
Below is an example command line call for cosmic-pop
with MPI (i.e. across many computers):
mpiexec -n 2 python PATHTOEXECTUABLEDIRECTORY/cosmic-pop --final-kstar1 13 14 --final-kstar2 13 14 --inifile Params.ini --Nstep 1000 --Niter 1000000000
A breakdown of each argument follows:
--final-kstar1 13 14 --final-kstar2 13 14
: this tells COSMIC to keep all systems where the primary star is a BH or NS and the secondary star is also a BH or NS.--inifile Params.ini
: this tells COSMIC where to look for the BSE flags that set the binary evolution model; in this case, the inifile is assumed to be in the same directory that the command line call is made--Nstep 5000 --Niter 10000000 -n 2
: this tells COSMIC to use 2 processors (or in the MPI case, MPI tasks) to evolve a maximum of 1e7 systems and check in every 5000 systems to track how the shape of the distributions of the parameters specified in convergence-params change
Stopping conditions
There are two stopping conditions for cosmic-pop
:
The shape of the parameter distributions for the parameters specified in convergence_params section of the inifile file converge to a shape, regardless of adding new binaries to the evolved population. This is quantified by the match criteria detailed in Breivik+2020
The number of binaries sampled exceeds
--Niter
.
Output of cosmic-pop
PLEASE SEE Describing the output of COSMIC/BSE: Columns names/Values/Units for more information about the output data frames including what each column means and the units.
The output of cosmic-pop
is the fixed population, an hdf5 file with a naming scheme that tells you the Galactic component and final kstars of the population; the data file created by the cosmic-pop
call above is: dat_DeltaBurst_13_14_13_14.h5.
The fixed population contains several pandas DataFrames accessed by the following keys:
conv
: The converged population whose parameters are sepcified by theconvergence
subsection of the inifilebpp
: The evolutionary history of binaries which satisfy the user-specified final kstars and filter in theconvergence
subsectionbcm
: The final state of binaries in the bcm array which satisfy the user-specified final kstars and filter in theconvergence
subsectionkick_info
: The magnitude and direction of natal kicks, three dimensional systemic velocity changes, total tilt of orbital plane, and azimuthal angle of orbital angular momentum axis with respect to spinsinitCond
: The initial conditions for each binary which satisfies the user-specified final kstars and filter in theconvergence
subsectionidx
: An integer that keeps track of the total number of simulated binaries to maintain proper indexing across several runs ofcosmic-pop
match
: Tracks the convergence where match = Log 10 (1-convergence)mass_binaries
: Tracks the total mass of binaries needed to create the fixed populationmass_singles
: Tracks the total mass of single stars needed to create the fixed population; if the binary fraction is 100%, the mass in singles will be zeromass_stars
: Tracks the total mass of all stars, including binaries and singles, needed to create the fixed populationn_binaries
: Tracks the total number of binaries needed to create the fixed populationn_singles
: Tracks the total number of single stars needed to create the fixed populationn_stars
: Tracks the total number of stars, where n_stars = n_singles + 2*n_binaries, needed to create the fixed population
The conv
, bpp
, bcm
, and initCond
DataFrames share a common column called bin_num
which is used to index the population across the DataFrames.
scaling to an astrophysical population
Once the fixed population is simulated, you can scale the simulation to an astrophysical population by resampling the conv
DataFrame.
First, we need to load the data which is saved in the same directory where` cosmic-pop
is called:
In [1]: import pandas
In [2]: import numpy
In [3]: conv = pandas.read_hdf('fixedpop/dat_DeltaBurst_13_14_13_14.h5', key='conv')
In [4]: total_mass = pandas.read_hdf('fixedpop/dat_DeltaBurst_13_14_13_14.h5', key='mass_stars')
In [5]: N_stars = pandas.read_hdf('fixedpop/dat_DeltaBurst_13_14_13_14.h5', key='n_stars')
Note
The masses and numbers of stars/binaries is saved at each iteration, so you’ll need to take the maximum mass/number:
In [6]: print(N_stars)
0
0 9832994
0 19664494
0 29497317
0 39329473
0 49161732
0 58992422
0 68823776
0 78655686
0 88189369
0 98023296
0 107858668
0 117692244
0 127524814
0 136830882
0 146137733
0 155970005
0 165803742
0 175636330
0 185467780
0 195300614
0 205131835
0 214964373
0 224798029
0 234631004
0 244464116
In [7]: total_mass = max(numpy.array(total_mass))[0]
In [8]: N_stars = max(numpy.array(N_stars))[0]
In [9]: print(total_mass, N_stars)
99434460.72687817 244464116
Since COSMIC tracks both the total number and total mass of stars formed, you can either scale by number or mass.
To scale by number, multiply the number of systems in the conv array by the ratio of the total number of stars in the astrophysical population to the total number of stars used to generate the population:
In [10]: N_astro = 1e10
In [11]: N_13_14_13_14_astro = int(len(conv)*N_astro/N_stars)
In [12]: print(N_13_14_13_14_astro)
64590
Instead, if you want to scale by mass, you can choose between supplying your own mass or using the built in COSMIC models. The process for a user-supplied mass is nearly identical to scaling by number:
In [13]: M_astro = 1e11
In [14]: N_13_14_13_14_astro = int(len(conv)*M_astro/total_mass)
In [15]: print(N_13_14_13_14_astro)
1587980
Now we can generate the astrophysical population:
In [16]: pop_astro = conv.sample(N_13_14_13_14_astro, replace=True)
If you specified a star formation history in the inifile for the cosmic-pop
call (i.e. by setting SF_start
and SF_duration
to follow a star formation history of your choice), the data in the resampled population will also be consistent with that star formation history. If you assigned the same SF_start
to all binaries in the cosmic-pop
call, you can assign birth times in post processing. As an example, we can assign a uniform birth time, assuming that the age of the population is 10 Gyr:
In [17]: pop_astro['tbirth'] = np.random.uniform(0, 10000, N_13_14_13_14_astro)
Since we are interested in NSs/BHs that form before the present, we can filter out anything that has a formation time after 10 Gyr:
In [18]: pop_astro = pop_astro.loc[pop_astro.tbirth + pop_astro.tphys < 10000]
This leaves us with a population of NSs/BHs at formation where the formation time is the sum of the birth time and tphys in the conv
array.