diff --git a/bin/cosmic-pop b/bin/cosmic-pop index 0f0c9f17..bd2649ea 100755 --- a/bin/cosmic-pop +++ b/bin/cosmic-pop @@ -270,6 +270,9 @@ if __name__ == '__main__': # save configuration settings and COSMIC version to output file with h5.File(dat_store_fname, 'a') as f: + # if config already exists, we need to overwrite it + if "config" in f: + del f["config"] f["config"] = json.dumps({'BSEDict' : BSEDict, 'filters' : filters, 'convergence' : convergence, 'sampling' : sampling, 'rand_seed': seed_int}) f.attrs['COSMIC_version'] = __version__ @@ -287,11 +290,12 @@ if __name__ == '__main__': # Warn about qmin and m2_min if (hasattr(args, 'qmin')) & (hasattr(args, 'm2_min')): - warnings.warn(f"You have specified both qmin and m2_min. COSMIC will use qmin={args.qmin} to " - "determine the secondary masses in the initial sample.") + if args.qmin is not None and args.m2_min is not None: + warnings.warn(f"You have specified both qmin and m2_min. COSMIC will use qmin={args.qmin} to " + "determine the secondary masses in the initial sample.") - log_file.write("You have specified both qmin and m2_min.\n") - log_file.write("COSMIC will use qmin={} to determine the secondary masses in the initial sample.\n".format(args.qmin)) + log_file.write("You have specified both qmin and m2_min.\n") + log_file.write("COSMIC will use qmin={} to determine the secondary masses in the initial sample.\n".format(args.qmin)) while (Nstep < args.Niter) & (np.max(match) > convergence['match']) & ((time.time() - start_time) < args.max_wall_time): # Set random seed such that each iteration gets a unique, determinable seed @@ -301,7 +305,8 @@ if __name__ == '__main__': # Select the initial binary sample method from user input if sampling['sampling_method'] == 'independent': if hasattr(args,'qmin') and hasattr(args,'m2_min'): - raise ValueError("You cannot specify both qmin and m2_min in the inifile if you are using the independent sampler. Please choose one or the other.") + if args.qmin != 0.0 and args.m2_min is not None: + raise ValueError("You cannot specify both qmin and m2_min in the inifile if you are using the independent sampler. Please choose one or the other.") # If qmin is specified, use it to sample the initial binary table if hasattr(args,'qmin'): init_samp_list = InitialBinaryTable.sampler(format_ = sampling['sampling_method'], diff --git a/examples/Params.ini b/examples/Params.ini index 4327a588..900992d5 100644 --- a/examples/Params.ini +++ b/examples/Params.ini @@ -52,6 +52,7 @@ primary_model = kroupa01 ; renzo19 - Uses ``sana12`` for massive binaries (\(m_1 > 15 {\rm M_{\odot}}\)) and flat in log otherwise (following Renzo+19). ; raghavan10 - Sample log normal orbital periods in days with mean_logP = 4.9 and sigma_logP = 2.3 between \(0 Raghavan+2010 ; moe19 - As ``raghavan10`` but with different close binary fractions following Moe+2019 +; martinez26 - Uses sana12 for massive binaries (\(m_1 ≥ 8 {\rm M_{\odot}}\)) with upper limit at 3000 days and raghavan10 for low-mass binaries. Used in Martinez+2026. ; custom - Sample from a custom power law. The user provides a dictionary of min, max and slope values for the power law. ; Default: sana12 porb_model = sana12 @@ -69,17 +70,17 @@ ecc_model = sana12 ; qmin ; Minimum mass ratio for sampling the secondary mass *[Only used when ``sampling_method = independent``]* -; The assumed mass ratio distribution is flat in \(q \equiv m_2 / m_1\). NOTE: only one of ``qmin`` and ``m2_min`` should be specified. +; The assumed mass ratio distribution is flat in \(q \equiv m_2 / m_1\). NOTE: only one of ``qmin`` and ``m2_min`` should be specified as something other than None or 0 respectively. ; Options: -; values in [0, 1] - Sets the minimum mass ratio +; range [0, 1] - Sets the minimum mass ratio ; -1 - Set the minimum mass ratio such that the pre-MS lifetime of the secondary is not longer than the full lifetime of the primary if it were to evolve as a single star +; 0 - Ignore qmin, use m2_min instead ; Default: -1 qmin = -1 ; m2_min ; Minimum secondary mass for sampling *[Only used when ``sampling_method = independent``]* -; NOTE: When running cosmic-pop, either ``qmin`` or ``m2_min`` will need to be commented out, or an error will appear if using the independent sampler. -; NOTE: only one of ``qmin`` and ``m2_min`` should be specified. +; NOTE: only one of ``qmin`` and ``m2_min`` should be specified as something other than None or 0 respectively. ; Options: ; positive values - Sample the secondary mass uniformly between ``m2_min`` and ``mass_1`` ; None - Default value (ignore, use ``qmin``) @@ -92,7 +93,7 @@ m2_min = None ; Options: ; values between [0, 1] - Fixed binary fraction ; vanHaaften - Primary mass dependent binary fraction following van Haaften+05 -; offner22 - Primary mass dependent binary fraction following Offner+22 +; offner23 - Primary mass dependent binary fraction following Offner+23 ; 0.5 - Default value ; Default: 0.5 binfrac_model = 0.5 @@ -125,15 +126,14 @@ SF_duration = 0.0 ; Default: 0.02 metallicity = 0.02 - ; keep_singles -; Sets whether or not to keep the singles when using cosmic-pop -; Necessary to have in the sampling section, or cosmic-pop will produce an error -; Options: -; True = single stars will be kept -; False = single stars will not be kept -; Default: True -keep_singles = True +; Sets whether to keep single stars in the sampled population +; +; Options: +; True - Keep single stars in the sampled population +; False - Do not keep single stars in the sampled population +; Default: False +keep_singles = False [convergence] @@ -299,7 +299,7 @@ bwind = 0.0 ; Helium star mass loss parameter ; \( 10^{-13} {\rm \ \texttt{hewind} \ } L^{2/3}\) gives He star mass-loss. Equivalent to \(1 - \mu\) in the last equation on Hurley+2000, page 19. ; Options: -; positive values - Sets the helium star mass loss parameter +; range [0, 1] - Sets the helium star mass loss parameter ; 0.5 - Default value ; Default: 0.5 hewind = 0.5 @@ -318,7 +318,7 @@ beta = 0.125 ; Wind accretion efficiency factor, which gives the fraction of angular momentum lost via winds from the primary that transfers to the spin angular momentum of the companion. ; Corresponds to \(\mu_w\) in Hurley+2002, Eq. 11 ; Options: -; positive values - Sets the wind accretion efficiency factor +; range [0, 1] - Sets the wind accretion efficiency factor ; 0.5 - Default value ; Default: 0.5 xi = 0.5 @@ -353,7 +353,7 @@ alpha1 = 1.0 ; Options: ; positive values - uses variable lambda prescription detailed in appendix of Claeys+2014 where lambdaf is the fraction of the ionization energy that can go into ejecting the envelope; to use this prescription without extra ionization energy, set lambdaf = 0 ; 0.0 - As above, this is the default choice -; -1.0 - Uses a fixed value (i.e. fixes \( \lambda \) to a value of -lambdaf) +; negative values - Uses a fixed value (i.e. fixes \( \lambda \) to a value of -lambdaf) ; Default: 0.0 lambdaf = 0.0 @@ -432,14 +432,21 @@ qcrit_array = [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0] ; 5 - Follows the same prescription as 1, but uses the kick prescription described in Disberg & Mandel 2025 for CCSN. ; 6 - Follows Mandel & Mueller 2020, where the kick velocity is drawn based on the mass of the formed NS or BH, with scaling parameters that are set with 'mm_mu_ns' and 'mm_mu_bh'. ; negative values - Same as above settings but using the old Kiel & Hurley 2009 prescription for changing the orbital configuration of the binary, available for reproducibility purposes but not recommended for new work -; Default: 1 -kickflag = 1 +; -1 - As 1, but using the old Kiel & Hurley 2009 prescription for changing the orbital configuration of the binary, available for reproducibility purposes but not recommended for new work +; -2 - As 2, but using the old Kiel & Hurley 2009 prescription for changing the orbital configuration of the binary, available for reproducibility purposes but not recommended for new work +; -3 - As 3, but using the old Kiel & Hurley 2009 prescription for changing the orbital configuration of the binary, available for reproducibility purposes but not recommended for new work +; -4 - As 4, but using the old Kiel & Hurley 2009 prescription for changing the orbital configuration of the binary, available for reproducibility purposes but not recommended for new work +; -5 - As 5, but using the old Kiel & Hurley 2009 prescription for changing the orbital configuration of the binary, available for reproducibility purposes but not recommended for new work +; -6 - As 6, but using the old Kiel & Hurley 2009 prescription for changing the orbital configuration of the binary, available for reproducibility purposes but not recommended for new work +; Default: 5 +kickflag = 5 ; sigma ; Sets the dispersion in the Maxwellian for the SN kick velocity in km/s ; ; Options: ; positive values - Sets the dispersion in the Maxwellian for the SN kick velocity in km/s +; 0.0 - No natal kicks for core-collapse when using Hobbs kicks ; 265.0 - Default choice ; Default: 265.0 sigma = 265.0 @@ -459,7 +466,7 @@ bhflag = 1 ; Sets a fractional modification which scales down sigma for BHs. This works in addition to whatever is chosen for bhflag, and is applied to sigma before the bhflag prescriptions are applied ; ; Options: -; values between [0, 1] - reduces sigma by bhsigmafrac for BHs +; range (0, 1] - reduces sigma by bhsigmafrac for BHs ; 1.0 - Default choice ; Default: 1.0 bhsigmafrac = 1.0 @@ -489,6 +496,7 @@ ecsn = 2.25 ; ; Options: ; positive values - sets maximum He-star mass for ECSN; BSE (Hurley+2002) uses ecsn_mlow = 1.6, StarTrack (Belczynski+2008) uses ecsn_mlow = 1.85, Podsiadlowksi+2004 argues that binarity can decrease this to ecsn_mlow = 1.4 +; 0.0 - no lower limit on He-star mass for ECSN ; 1.6 - Default choice ; Default: 1.6 ecsn_mlow = 1.6 @@ -527,7 +535,7 @@ pisn = -2 ; Sets the opening angle of the SN kick relative to the pole of the exploding star ; ; Options: -; values between [0, 90] - Sets the opening angle of the SN kick relative to the pole of the exploding star +; range [0, 90] - Sets the opening angle of the SN kick relative to the pole of the exploding star ; 0.0 - Strictly polar kicks ; 90.0 - Fully isotropic kicks (default choice) ; Default: 90.0 @@ -597,7 +605,7 @@ mxns = 3.0 ; ; Options: ; positive values - sets the maximum amount of mass loss, which should be about 10% of the maximum mass of an iron core (\({\sim 5 \mathrm{M}_\odot}\) Fryer, private communication) -; values in [-1, 0) - assumes that proto-compact objects lose a constant fraction of their baryonic mass when collapsing to a black hole, such that \(M_{\rm rem} = (1 + \texttt{rembar\_massloss}) M_{\rm rem}\) (e.g., rembar_massloss = -0.1 gives the black hole a gravitational mass that is 90% of the proto-compact object's baryonic mass) +; range [-1, 0] - assumes that proto-compact objects lose a constant fraction of their baryonic mass when collapsing to a black hole, such that \(M_{\rm rem} = (1 + \texttt{rembar\_massloss}) M_{\rm rem}\) (e.g., rembar_massloss = -0.1 gives the black hole a gravitational mass that is 90% of the proto-compact object's baryonic mass) ; 0.5 - Default choice ; Default: 0.5 rembar_massloss = 0.5 @@ -618,23 +626,23 @@ wd_mass_lim = 1 ; 0 - Extrapolate Maltsev+25 fits to the full range of metallicities ; 1 - Extrapolate Maltsev+25 fits only within Z/Zsun = [1/50, 1], use boundary values outside this range ; 2 - No extrapolation: use Maltsev+25 fits only within Z/Zsun = [1/10, 1], use boundary values outside this range -; Default: 1 -maltsev_mode = 1 +; Default: 0 +maltsev_mode = 0 ; maltsev_fallback -; Sets the fallback fraction for partial fallback in the Maltsev remnant mass prescription (only relevant if remnantflag = 6) +; Sets the fallback fraction for partial fallback in the Maltsev remnant mass prescription (only relevant if remnantflag = 6). This fallback fraction, \(f_{\rm fallback}\), is used to calculate the remnant mass by calculating \(M_{\rm rem} = M_{\rm NS} + f_{\rm fallback} (M_{\rm core, total} - M_{\rm NS})\), where this prescription assumes that \(M_{\rm NS} = 1.4 \, \mathrm{M}_\odot\). ; ; Options: -; values in [0, 1] - Sets the fallback fraction for partial fallback in the Maltsev remnant mass prescription +; range [0, 1] - Sets the fallback fraction for partial fallback in the Maltsev remnant mass prescription ; 0.5 - Default choice ; Default: 0.5 maltsev_fallback = 0.5 ; maltsev_pf_prob -; Sets the probability of partial fallback leading to BH formation in the Maltsev remnant mass prescription +; Sets the probability of partial fallback leading to BH formation occurring in the Maltsev remnant mass prescription when the CO core mass is in the partial fallback regime of \(M_2 \le M_{\rm CO} \le M_3\) (only relevant if remnantflag = 6) ; ; Options: -; values in [0, 1] - Sets the probability of partial fallback leading to BH formation in the Maltsev remnant mass prescription +; range [0, 1] - Sets the probability of partial fallback leading to BH formation in the Maltsev remnant mass prescription ; 0.1 - Default choice ; Default: 0.1 maltsev_pf_prob = 0.1 @@ -658,7 +666,7 @@ bhspinflag = 0 ; Sets either the spin of all BHs or the upper limit of the uniform distribution for BH spins (see bhspinflag) ; ; Options: -; positive values - Sets either the spin of all BHs or the upper limit of the uniform distribution for BH spins (see bhspinflag) +; range [0, 1] - Sets either the spin of all BHs or the upper limit of the uniform distribution for BH spins (see bhspinflag) ; 0.0 - Default choice ; Default: 0.0 bhspinmag = 0.0 @@ -686,9 +694,9 @@ grflag = 1 ; Eddington limit factor for mass transfer. ; ; Options: +; positive values - restrict accretion limit to fraction of Eddington (sub- or super-Eddington accretion) +; 0 - no mass transfer onto compact objects ; 1 - mass transfer rate is limited by the Eddington rate following Equation 67 in Hurley+2002 -; values > 1 - permit super-Eddington accretion up to value ``eddfac`` -; values in [0, 1] - restrict accretion limit to fraction of Eddington (sub-Eddington accretion) ; 10 - mass transfer rate is limited to 10x the Eddington rate ; Default: 10 eddfac = 10 @@ -701,6 +709,7 @@ eddfac = 10 ; -2 - assumes material is lost from the system as if it is a wind from the secondary ; -3 - assumes mass is lost through the outer Lagrangian point, forming a circumbinary disk. See Zapartas+17 Eq. 9 and Artymowicz & Lubow (1994). ; positive values - assumes that the lost material takes away a fraction ``gamma`` of the orbital angular momentum +; 0.0 - no angular momentum loss from the system due to mass loss ; Default: -2 gamma = -2 @@ -721,7 +730,8 @@ don_lim = -1 ; -2 - limited to 1x the thermal rate of the accretor for MS/HG/CHeB and unlimited for GB/EAGB/AGB stars ; -3 - limited to 10x the thermal rate of the accretor for all stars ; -4 - limited to 1x the thermal rate of the accretor for all stars -; >= 0 - sets overall fraction of donor material that is accreted, with the rest being lost from the system (``acc_lim = 0.5`` assumes 50% accretion efficiency as in Belczynski+2008) +; positive values - sets overall fraction of donor material that is accreted, with the rest being lost from the system (``acc_lim = 0.5`` assumes 50% accretion efficiency as in Belczynski+2008) +; 0.0 - assume all mass is lost from the system (fully nonconservative) ; Default: -1 acc_lim = -1 @@ -784,7 +794,7 @@ wdflag = 1 ; Fraction of accreted matter retained in a nova eruption. This is relevant for accretion onto degenerate objects; see Section 2.6.6.2 in Hurley+2002. ; ; Options: -; positive values - Retains epsnov fraction of accreted matter +; range [0, 1] - Retains epsnov fraction of accreted matter ; 0.001 - Default choice ; Default: 0.001 epsnov = 0.001 @@ -830,7 +840,7 @@ ck = 1000 ; Sets the mixing factor in main sequence star collisions. This is hard coded to 0.1 in the original BSE release and in Equation 80 of Hurley+2002 but can lead to extended main sequence lifetimes in some cases. ; ; Options: -; positive values - sets the mixing factor in main sequence star collisions +; range [0, 1] - sets the mixing factor in main sequence star collisions ; 1.0 - Default choice ; Default: 1.0 rejuv_fac = 1.0 diff --git a/src/cosmic/data/cosmic-settings.json b/src/cosmic/data/cosmic-settings.json index ca26a700..fdfeae37 100644 --- a/src/cosmic/data/cosmic-settings.json +++ b/src/cosmic/data/cosmic-settings.json @@ -160,7 +160,7 @@ "name": "qmin", "description": "Minimum mass ratio for sampling the secondary mass
[Only used when sampling_method = independent]", "type": "number", - "options-preface": "The assumed mass ratio distribution is flat in \\(q \\equiv m_2 / m_1\\). NOTE: only one of qmin and m2_min should be specified.", + "options-preface": "The assumed mass ratio distribution is flat in \\(q \\equiv m_2 / m_1\\). NOTE: only one of qmin and m2_min should be specified as something other than None or 0 respectively.", "options": [ { "name": "range [0, 1]", @@ -170,14 +170,18 @@ "name": -1, "description": "Set the minimum mass ratio such that the pre-MS lifetime of the secondary is not longer than the full lifetime of the primary if it were to evolve as a single star", "default": true + }, + { + "name": 0, + "description": "Ignore qmin, use m2_min instead" } ] }, { "name": "m2_min", "description": "Minimum secondary mass for sampling
[Only used when sampling_method = independent]", - "type": "string", - "options-preface": "NOTE: only one of qmin and m2_min should be specified.", + "type": "number", + "options-preface": "NOTE: only one of qmin and m2_min should be specified as something other than None or 0 respectively.", "options": [ { "name": "positive values", @@ -270,6 +274,23 @@ "default": true } ] + }, + { + "name": "keep_singles", + "description": "Sets whether to keep single stars in the sampled population", + "type": "dropdown", + "options-preface": "", + "options": [ + { + "name": "True", + "description": "Keep single stars in the sampled population" + }, + { + "name": "False", + "description": "Do not keep single stars in the sampled population", + "default": true + } + ] } ] }, @@ -339,7 +360,7 @@ "default": true }, { - "name": "{'mass_1' : [5, 10], 'sep' : [0, 10]}", + "name": "{\"mass_1\" : [5, 10], \"sep\" : [0, 10]}", "description": "For example, this specifies that the primary mass must be between 5 and 10 solar masses, and the separation must be between 0 and 10 Rsun." } ] @@ -1297,7 +1318,7 @@ }, { "name": "maltsev_pf_prob", - "description": "Sets the probability of partial fallback leading to BH formation occurring in the Maltsev remnant mass prescription when the CO core mass is in the 'partial fallback' regime of \\(M_2 \\le M_{\\rm CO} < M_3\\) (only relevant if remnantflag = 6)", + "description": "Sets the probability of partial fallback leading to BH formation occurring in the Maltsev remnant mass prescription when the CO core mass is in the partial fallback regime of \\(M_2 \\le M_{\\rm CO} \\le M_3\\) (only relevant if remnantflag = 6)", "type": "number", "options-preface": "", "options": [ diff --git a/src/cosmic/sample/sampler/independent.py b/src/cosmic/sample/sampler/independent.py index d025f8bc..c135d5fe 100644 --- a/src/cosmic/sample/sampler/independent.py +++ b/src/cosmic/sample/sampler/independent.py @@ -182,7 +182,8 @@ def get_independent_sampler( # don't allow users to specify both a qmin and m2_min if "qmin" in kwargs and "m2_min" in kwargs: - raise ValueError("You cannot specify both qmin and m2_min, please choose one or the other") + if kwargs["qmin"] != 0.0 and kwargs["m2_min"] is not None: + raise ValueError("You cannot specify both qmin and m2_min, please choose one or the other") final_kstar1 = [final_kstar1] if isinstance(final_kstar1, (int, float)) else final_kstar1 final_kstar2 = [final_kstar2] if isinstance(final_kstar2, (int, float)) else final_kstar2 diff --git a/src/cosmic/tests/test_sample.py b/src/cosmic/tests/test_sample.py index d0fb6b8d..a782a840 100644 --- a/src/cosmic/tests/test_sample.py +++ b/src/cosmic/tests/test_sample.py @@ -539,6 +539,46 @@ def test_sampling_targets_mass_trimmed(self): trim_extra_samples=True) self.assertLessEqual(abs(samples[1] + samples[2] - mass), 300) + def test_m2min_qmin(self): + # ensure you can't sample with both qmin and m2_min + it_fails = False + try: + InitialBinaryTable.sampler('independent', np.arange(16), np.arange(16), + primary_model='kroupa01', ecc_model='thermal', + porb_model='sana12', binfrac_model=0.5, + SF_start=10.0, SF_duration=0.0, met=0.02, + size=1000, + qmin=0.1, m2_min=0.08) + except ValueError: + it_fails = True + self.assertTrue(it_fails) + + # but it works if m2_min is None + it_fails = False + try: + InitialBinaryTable.sampler('independent', np.arange(16), np.arange(16), + primary_model='kroupa01', ecc_model='thermal', + porb_model='sana12', binfrac_model=0.5, + SF_start=10.0, SF_duration=0.0, met=0.02, + size=1000, + qmin=0.1, m2_min=None) + except ValueError: + it_fails = True + self.assertFalse(it_fails) + + # and vice versa + it_fails = False + try: + InitialBinaryTable.sampler('independent', np.arange(16), np.arange(16), + primary_model='kroupa01', ecc_model='thermal', + porb_model='sana12', binfrac_model=0.5, + SF_start=10.0, SF_duration=0.0, met=0.02, + size=1000, + qmin=0, m2_min=0.08) + except FileNotFoundError: + it_fails = True + self.assertFalse(it_fails) + class TestCMCSample(unittest.TestCase): def test_plummer_profile(self): np.random.seed(2) diff --git a/src/cosmic/utils.py b/src/cosmic/utils.py index aa4a72b7..3aaf10ed 100644 --- a/src/cosmic/utils.py +++ b/src/cosmic/utils.py @@ -594,7 +594,7 @@ def mass_min_max_select(kstar_1, kstar_2, **kwargs): secondary_max = kwargs["m_max"] if "m_max" in kwargs.keys() else 150.0 primary_min = kwargs["m1_min"] if "m1_min" in kwargs.keys() else 0.08 - secondary_min = kwargs["m2_min"] if "m2_min" in kwargs.keys() else 0.08 + secondary_min = kwargs["m2_min"] if ("m2_min" in kwargs.keys() and kwargs["m2_min"] is not None) else 0.08 if ((primary_min < 0.08) | (secondary_min < 0.08)): warnings.warn("Tread carefully, BSE is not equipped to handle stellar masses less than 0.08 Msun!")