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!")