From 617bd07d3b12fd309fa744caa07deae05d42ab19 Mon Sep 17 00:00:00 2001 From: ezapartas Date: Thu, 15 Jan 2026 13:34:00 +0200 Subject: [PATCH 01/32] started a new branch and some pint statements --- posydon/binary_evol/DT/step_merged.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index 9f48673688..11bb09a52b 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -93,12 +93,13 @@ def __call__(self,binary): if self.verbose: print("Before Merger", binary.star_1.state, binary.star_2.state, binary.state, binary.event) - print("M1 , M2, he_core_mass1, he_core_mass2: ", + print("M1 , M2, he_core_mass1, he_core_mass2, co_core_mass1, co_core_mass2: ", binary.star_1.mass, binary.star_2.mass, - binary.star_1.he_core_mass, binary.star_2.he_core_mass) - print("star_1.center_he4, star_2.center_he4, star_1.surface_he4, " - "star_2.surface_he4: ", binary.star_1.center_he4, - binary.star_2.center_he4, binary.star_1.surface_he4, + binary.star_1.he_core_mass, binary.star_2.he_core_mass, binary.star_1.co_core_mass, binary.star_2.co_core_mass) + print("star_1.center_h1, star_2.center_h1, star_1.center_he4, star_1.center_c12, star_2.center_c12, " + "star_2.center_he4, star_1.surface_he4, star_2.surface_he4: ", + binary.star_1.center_h1, binary.star_2.center_h1, binary.star_1.center_he4, + binary.star_2.center_he4, binary.star_1.center_c12, binary.star_2.center_c12, binary.star_1.surface_he4, binary.star_2.surface_he4) if binary.state == "merged": @@ -126,10 +127,16 @@ def __call__(self,binary): if self.verbose: print("After Merger", binary.star_1.state, binary.star_2.state, binary.state, binary.event) - print("M_merged , he_core_mass merged: ", binary.star_1.mass, - binary.star_1.he_core_mass) - print("star_1.center_he4, star_1.surface_he4: ", - binary.star_1.center_he4, binary.star_1.surface_he4) + if binary.event == 'oMerging1': + print("M_merged , he_core_mass merged, co_core_mass merged: ", binary.star_1.mass, + binary.star_1.he_core_mass, binary.star_1.co_core_mass) + print("star_1.center_h1, star_1.center_he4, star_1.center_c12, star_1.surface_he4: ", + binary.star_1.center_h1, binary.star_1.center_he4, binary.star_1.center_c12, binary.star_1.surface_he4) + elif binary.event=='oMerging2': + print("M_merged , he_core_mass merged, co_core_mass merged: ", binary.star_2.mass, + binary.star_2.he_core_mass, binary.star_2.co_core_mass) + print("star_2.center_h1, star_2.center_he4, star_2.center_c12, star_2.surface_he4: ", + binary.star_2.center_h1, binary.star_2.center_he4, binary.star_2.center_c12, binary.star_2.surface_he4) super().__call__(binary) From b057d4737235c9efbca9a72a3a62e80aa05d0c56 Mon Sep 17 00:00:00 2001 From: ezapartas Date: Thu, 15 Jan 2026 14:02:06 +0200 Subject: [PATCH 02/32] started process for HMS+HMS: the mass change occurs after the mass weighted averages --- posydon/binary_evol/DT/step_merged.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index 11bb09a52b..c424faf72a 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -175,13 +175,24 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma M2 = getattr(star2, "he_core_mass") - getattr(star2, "co_core_mass") else: M2 = getattr(star2, mass_weight2) - return (A1*M1 + A2*M2 ) / (M1+M2) + + try: + mass_weighted_avg_value=(A1*M1+A2*M2)/(M1+M2) + except TypeError: + mass_weighted_avg_value= np.nan + + if self.verbose: + print(abundance_name, mass_weight1, mass_weight2) + print("A_base, M_base_abundance, A_comp, M_comp_abundanc", A1, M1, A2, M2) + print("mass_weighted_avg= ", mass_weighted_avg_value) + + return mass_weighted_avg_value # MS + MS if ( s1 in LIST_ACCEPTABLE_STATES_FOR_HMS and s2 in LIST_ACCEPTABLE_STATES_FOR_HMS): #these stellar attributes change value - merged_star.mass = (star_base.mass + comp.mass) * (1.-self.rel_mass_lost_HMS_HMS) + #TODO for key in ["center_h1", "center_he4", "center_c12", "center_n14","center_o16"]: merged_star.center_h1 = mass_weighted_avg() merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4") @@ -197,6 +208,8 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma merged_star.surface_n14 = mass_weighted_avg(abundance_name = "surface_n14") merged_star.surface_o16 = mass_weighted_avg(abundance_name = "surface_o16") + merged_star.mass = (star_base.mass + comp.mass) * (1.-self.rel_mass_lost_HMS_HMS) + for key in STARPROPERTIES: # these stellar attributes become np.nan for substring in ["log_", "lg_", "surf_", "conv_", "lambda", "profile"]: From 253fc720dd23554dadcc270752d7779ad84f6576 Mon Sep 17 00:00:00 2001 From: ezapartas Date: Thu, 15 Jan 2026 14:05:59 +0200 Subject: [PATCH 03/32] in postMS+MS merger, some central attributes do not become np.nan, they only come from the core of the postMS star --- posydon/binary_evol/DT/step_merged.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index c424faf72a..bee02f4dae 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -208,7 +208,8 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma merged_star.surface_n14 = mass_weighted_avg(abundance_name = "surface_n14") merged_star.surface_o16 = mass_weighted_avg(abundance_name = "surface_o16") - merged_star.mass = (star_base.mass + comp.mass) * (1.-self.rel_mass_lost_HMS_HMS) + # The change of masses occurs after the calculation of weighted averages + merged_star.mass = (star_base.mass + comp.mass) * (1.-self.rel_mass_lost_HMS_HMS) for key in STARPROPERTIES: # these stellar attributes become np.nan @@ -224,8 +225,6 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma elif (s1 in LIST_ACCEPTABLE_STATES_FOR_POSTMS and s2 in LIST_ACCEPTABLE_STATES_FOR_HMS): - merged_star.mass = star_base.mass + comp.mass #TODO: in step_CEE we need to eject part of the (common) envelope - # weigheted mixing on the surface abundances of the whole comp with the envelope of star_base merged_star.surface_h1 = mass_weighted_avg(abundance_name = "surface_h1", mass_weight1="H-rich_envelope_mass", mass_weight2="mass") merged_star.surface_he4 = mass_weighted_avg(abundance_name = "surface_he4", mass_weight1="H-rich_envelope_mass", mass_weight2="mass") @@ -233,13 +232,15 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma merged_star.surface_n14 = mass_weighted_avg(abundance_name = "surface_n14", mass_weight1="H-rich_envelope_mass", mass_weight2="mass") merged_star.surface_o16 = mass_weighted_avg(abundance_name = "surface_o16", mass_weight1="H-rich_envelope_mass", mass_weight2="mass") + # The change of masses occurs after the calculation of weighted averages + merged_star.mass = star_base.mass + comp.mass + for key in STARPROPERTIES: # these stellar attributes become np.nan for substring in ["log_", "lg_", "surf_", "conv_", "lambda", "profile"]: if (substring in key) : setattr(merged_star, key, np.nan) - if key in [ "c12_c12", "center_gamma", - "avg_c_in_c_core", "total_moment_of_inertia", "spin"]: + if key in [ "c12_c12", "total_moment_of_inertia", "spin"]: setattr(merged_star, key, np.nan) merged_star.log_LHe = star_base.log_LHe From c0c41f3766825132f97b1fe0347dd68e11c6a3ca Mon Sep 17 00:00:00 2001 From: ezapartas Date: Thu, 15 Jan 2026 14:37:22 +0200 Subject: [PATCH 04/32] no working with HMS+postMS mergers, where the merger is the companions (with changes) and the star_base (the HMS, star 1 probably) becomes massless remnant --- posydon/binary_evol/DT/step_merged.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index bee02f4dae..f90c67821a 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -253,7 +253,7 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma elif (s1 in LIST_ACCEPTABLE_STATES_FOR_HMS and s2 in LIST_ACCEPTABLE_STATES_FOR_POSTMS): - merged_star.mass = star_base.mass + comp.mass + merged_star = comp merged_star.surface_h1 = mass_weighted_avg(abundance_name = "surface_h1", mass_weight2="H-rich_envelope_mass", mass_weight1="mass") merged_star.surface_he4 = mass_weighted_avg(abundance_name = "surface_he4", mass_weight2="H-rich_envelope_mass", mass_weight1="mass") @@ -261,6 +261,9 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma merged_star.surface_n14 = mass_weighted_avg(abundance_name = "surface_n14", mass_weight2="H-rich_envelope_mass", mass_weight1="mass") merged_star.surface_o16 = mass_weighted_avg(abundance_name = "surface_o16", mass_weight2="H-rich_envelope_mass", mass_weight1="mass") + # The change of masses occurs after the calculation of weighted averages + merged_star.mass = star_base.mass + comp.mass + for key in STARPROPERTIES: # these stellar attributes become np.nan for substring in ["log_", "lg_", "surf_", "conv_", "lambda", "profile"]: @@ -274,7 +277,7 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma merged_star.log_LZ = comp.log_LZ merged_star.state = check_state_of_star(merged_star, star_CO=False) # TODO for sure this needs testing! - massless_remnant = convert_star_to_massless_remnant(comp) + massless_remnant = convert_star_to_massless_remnant(star_base) #postMS + postMS elif (s1 in LIST_ACCEPTABLE_STATES_FOR_POSTMS From a8ae47635211a186fd764f8094424aecfda33a15 Mon Sep 17 00:00:00 2001 From: ezapartas Date: Thu, 15 Jan 2026 14:37:56 +0200 Subject: [PATCH 05/32] also not erasing core properties --- posydon/binary_evol/DT/step_merged.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index f90c67821a..270899bafa 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -269,8 +269,7 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma for substring in ["log_", "lg_", "surf_", "conv_", "lambda", "profile"]: if (substring in key) : setattr(merged_star, key, np.nan) - if key in [ "c12_c12", "center_gamma", - "avg_c_in_c_core", "total_moment_of_inertia", "spin"]: + if key in [ "c12_c12", "total_moment_of_inertia", "spin"]: setattr(merged_star, key, np.nan) merged_star.log_LHe = comp.log_LHe From bba592a13b2e8cf5da9626c4f61b1d97da7d07b9 Mon Sep 17 00:00:00 2001 From: ezapartas Date: Thu, 15 Jan 2026 15:51:12 +0200 Subject: [PATCH 06/32] finished postMS+He stars and opposite --- posydon/binary_evol/DT/step_merged.py | 51 ++++++++++++++++----------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index 270899bafa..1668a06511 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -157,6 +157,7 @@ def merged_star_properties(self, star_base, comp): s1 = star_base.state s2 = comp.state + def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", mass_weight1="mass", mass_weight2=None): A1 = getattr(star1, abundance_name) A2 = getattr(star2, abundance_name) @@ -282,32 +283,33 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma elif (s1 in LIST_ACCEPTABLE_STATES_FOR_POSTMS and s2 in LIST_ACCEPTABLE_STATES_FOR_POSTMS): - # add total and core masses - for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: - current = getattr(star_base, key) + getattr(comp, key) - setattr(merged_star, key,current) - # weighted central abundances if merging cores. Else only from star_base if star_base.co_core_mass == 0 and comp.co_core_mass == 0: # two stars with Helium cores merged_star.center_h1 = mass_weighted_avg(mass_weight1="he_core_mass") merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4", mass_weight1="he_core_mass") merged_star.center_c12 = mass_weighted_avg(abundance_name = "center_c12", mass_weight1="he_core_mass") + merged_star.avg_c_in_c_core = mass_weighted_avg(abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") merged_star.center_n14 = mass_weighted_avg(abundance_name = "center_n14", mass_weight1="he_core_mass") merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16", mass_weight1="he_core_mass") + setattr(merged_star, "center_gamma", np.nan) elif (star_base.co_core_mass > 0 and comp.co_core_mass == 0): # star_base with CO core and the comp has a He core pass # the central abundances are kept as the ones of star_base elif (comp.co_core_mass > 0 and star_base.co_core_mass == 0): # comp with CO core and the star_base has a He core merged_star.center_h1 = comp.center_h1 merged_star.center_he4 = comp.center_he4 merged_star.center_c12 = comp.center_c12 + merged_star.avg_c_in_c_core = comp.avg_c_in_c_core merged_star.center_n14 = comp.center_n14 merged_star.center_o16 = comp.center_o16 + merged_star.center_gamma = comp.center_gamma elif (star_base.co_core_mass > 0 and comp.co_core_mass > 0): merged_star.center_h1 = mass_weighted_avg(mass_weight1="co_core_mass") #TODO : maybe he_core_mass makes more sense? merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4", mass_weight1="co_core_mass") merged_star.center_c12 = mass_weighted_avg(abundance_name = "center_c12", mass_weight1="co_core_mass") + merged_star.avg_c_in_c_core = mass_weighted_avg(abundance_name = "avg_c_in_c_core", mass_weight1="co_core_mass") merged_star.center_n14 = mass_weighted_avg(abundance_name = "center_n14", mass_weight1="co_core_mass") merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16", mass_weight1="co_core_mass") + setattr(merged_star, "center_gamma", np.nan) else: Pwarn("weird compbination of CO core masses during merging", "EvolutionWarning") @@ -318,14 +320,17 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma merged_star.surface_n14 = mass_weighted_avg(abundance_name = "surface_n14", mass_weight1="H-rich_envelope_mass", mass_weight2="H-rich_envelope_mass") merged_star.surface_o16 = mass_weighted_avg(abundance_name = "surface_o16", mass_weight1="H-rich_envelope_mass", mass_weight2="H-rich_envelope_mass") + # add total and core masses after calculations of weighter average + for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: + current = getattr(star_base, key) + getattr(comp, key) + setattr(merged_star, key,current) for key in STARPROPERTIES: # these stellar attributes become np.nan for substring in ["log_", "lg_", "surf_", "conv_", "lambda", "profile"]: if (substring in key) : setattr(merged_star, key, np.nan) - if key in [ "c12_c12", "center_gamma", - "avg_c_in_c_core", "total_moment_of_inertia", "spin"]: + if key in [ "c12_c12", "total_moment_of_inertia", "spin"]: setattr(merged_star, key, np.nan) merged_star.state = check_state_of_star(merged_star, star_CO=False) # TODO for sure this needs testing! massless_remnant = convert_star_to_massless_remnant(comp) @@ -334,30 +339,32 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma elif (s1 in LIST_ACCEPTABLE_STATES_FOR_POSTMS and s2 in LIST_ACCEPTABLE_STATES_FOR_HeMS): - # add total and core masses - for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: - current = getattr(star_base, key) + getattr(comp, key) - setattr(merged_star, key,current) - # weighted central abundances if merging cores. Else only from star_base if star_base.co_core_mass == 0 and comp.co_core_mass == 0: # two stars with only Helium cores, not CO cores merged_star.center_h1 = mass_weighted_avg(mass_weight1="he_core_mass") merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4", mass_weight1="he_core_mass") merged_star.center_c12 = mass_weighted_avg(abundance_name = "center_c12", mass_weight1="he_core_mass") + merged_star.avg_c_in_c_core = mass_weighted_avg(abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") merged_star.center_n14 = mass_weighted_avg(abundance_name = "center_n14", mass_weight1="he_core_mass") merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16", mass_weight1="he_core_mass") + setattr(merged_star, "center_gamma", np.nan) elif (star_base.co_core_mass > 0 and comp.co_core_mass == 0): # star_base with CO core and the comp has just a He core (is a HeMS star) pass # the central abundances are kept as the ones of star_base else: Pwarn("weird compbination of CO core masses during merging", "EvolutionWarning") + # surface abundances from star_base + + # add total and core masses after abundance mass weighted calculations + for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: + current = getattr(star_base, key) + getattr(comp, key) + setattr(merged_star, key,current) for key in STARPROPERTIES: # these stellar attributes become np.nan for substring in ["log_", "lg_", "surf_", "conv_", "lambda", "profile"]: if (substring in key) : setattr(merged_star, key, np.nan) - if key in [ "c12_c12", "center_gamma", - "avg_c_in_c_core", "total_moment_of_inertia", "spin"]: + if key in [ "c12_c12", "total_moment_of_inertia", "spin"]: setattr(merged_star, key, np.nan) merged_star.state = check_state_of_star(merged_star, star_CO=False) # TODO for sure this needs testing! massless_remnant = convert_star_to_massless_remnant(comp) @@ -366,12 +373,9 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma elif (s1 in LIST_ACCEPTABLE_STATES_FOR_HeMS and s2 in LIST_ACCEPTABLE_STATES_FOR_POSTMS): - # add total and core masses - for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: - current = getattr(star_base, key) + getattr(comp, key) - setattr(merged_star, key,current) + merged_star = comp - # weighted central abundances if merging cores. Else only from star_base + # weighted central abundances if merging cores. Else only from comp if star_base.co_core_mass == 0 and comp.co_core_mass == 0: # two stars with only Helium cores, not CO cores merged_star.center_h1 = mass_weighted_avg(mass_weight1="he_core_mass") merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4", mass_weight1="he_core_mass") @@ -382,14 +386,19 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma pass # the central abundances are kept as the ones of star_base else: Pwarn("weird compbination of CO core masses during merging", "EvolutionWarning") + # surface abundances from comp + + # add total and core masses after weighted averages + for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: + current = getattr(star_base, key) + getattr(comp, key) + setattr(merged_star, key,current) for key in STARPROPERTIES: # these stellar attributes become np.nan for substring in ["log_", "lg_", "surf_", "conv_", "lambda", "profile"]: if (substring in key) : setattr(merged_star, key, np.nan) - if key in [ "c12_c12", "center_gamma", - "avg_c_in_c_core", "total_moment_of_inertia", "spin"]: + if key in [ "c12_c12", "total_moment_of_inertia", "spin"]: setattr(merged_star, key, np.nan) merged_star.state = check_state_of_star(merged_star, star_CO=False) # TODO for sure this needs testing! From ed378839de9f0adcebece48b23ad7e6e1527bf7c Mon Sep 17 00:00:00 2001 From: ezapartas Date: Thu, 15 Jan 2026 15:52:53 +0200 Subject: [PATCH 07/32] now finished (issue with which star became massless) --- posydon/binary_evol/DT/step_merged.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index 1668a06511..6fb6e40ba6 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -402,7 +402,7 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma setattr(merged_star, key, np.nan) merged_star.state = check_state_of_star(merged_star, star_CO=False) # TODO for sure this needs testing! - massless_remnant = convert_star_to_massless_remnant(comp) + massless_remnant = convert_star_to_massless_remnant(star_base) #postMS + HeStar that is not in HeMS elif (s1 in LIST_ACCEPTABLE_STATES_FOR_POSTMS From e434db557b12a7d8c57ec505ddec43018b9bb55c Mon Sep 17 00:00:00 2001 From: ezapartas Date: Thu, 15 Jan 2026 15:59:39 +0200 Subject: [PATCH 08/32] finished until the beginning of He+He --- posydon/binary_evol/DT/step_merged.py | 49 ++++++++++++++++----------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index 6fb6e40ba6..6e9f439cd8 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -388,7 +388,7 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma Pwarn("weird compbination of CO core masses during merging", "EvolutionWarning") # surface abundances from comp - # add total and core masses after weighted averages + # add total and core masses after weighted averages above for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: current = getattr(star_base, key) + getattr(comp, key) setattr(merged_star, key,current) @@ -408,42 +408,47 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma elif (s1 in LIST_ACCEPTABLE_STATES_FOR_POSTMS and s2 in LIST_ACCEPTABLE_STATES_FOR_POSTHeMS): - # add total and core masses - for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: - current = getattr(star_base, key) + getattr(comp, key) - setattr(merged_star, key,current) - # weighted central abundances if merging cores. Else only from star_base if star_base.co_core_mass == 0 and comp.co_core_mass == 0: # two stars with Helium cores merged_star.center_h1 = mass_weighted_avg(mass_weight1="he_core_mass") merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4", mass_weight1="he_core_mass") merged_star.center_c12 = mass_weighted_avg(abundance_name = "center_c12", mass_weight1="he_core_mass") + merged_star.avg_c_in_c_core = mass_weighted_avg(abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") merged_star.center_n14 = mass_weighted_avg(abundance_name = "center_n14", mass_weight1="he_core_mass") merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16", mass_weight1="he_core_mass") + setattr(merged_star, "center_gamma", np.nan) elif (star_base.co_core_mass > 0 and comp.co_core_mass == 0): # star_base with CO core and the comp has a He core pass # the central abundances are kept as the ones of star_base elif (comp.co_core_mass > 0 and star_base.co_core_mass == 0): # comp with CO core and the star_base has a He core merged_star.center_h1 = comp.center_h1 merged_star.center_he4 = comp.center_he4 merged_star.center_c12 = comp.center_c12 + merged_star.avg_c_in_c_core = comp.avg_c_in_c_core merged_star.center_n14 = comp.center_n14 merged_star.center_o16 = comp.center_o16 + merged_star.center_gamma = comp.center_gamma elif (star_base.co_core_mass > 0 and comp.co_core_mass > 0): merged_star.center_h1 = mass_weighted_avg(mass_weight1="co_core_mass") merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4", mass_weight1="co_core_mass") merged_star.center_c12 = mass_weighted_avg(abundance_name = "center_c12", mass_weight1="co_core_mass") + merged_star.avg_c_in_c_core = mass_weighted_avg(abundance_name = "avg_c_in_c_core", mass_weight1="co_core_mass") merged_star.center_n14 = mass_weighted_avg(abundance_name = "center_n14", mass_weight1="co_core_mass") merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16", mass_weight1="co_core_mass") + setattr(merged_star, "center_gamma", np.nan) else: Pwarn("weird compbination of CO core masses during merging", "EvolutionWarning") + # add total and core masses + for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: + current = getattr(star_base, key) + getattr(comp, key) + setattr(merged_star, key,current) + for key in STARPROPERTIES: # these stellar attributes become np.nan for substring in ["log_", "lg_", "surf_", "conv_", "lambda", "profile"]: if (substring in key) : setattr(merged_star, key, np.nan) - if key in [ "c12_c12", "center_gamma", - "avg_c_in_c_core", "total_moment_of_inertia", "spin"]: + if key in [ "c12_c12", "total_moment_of_inertia", "spin"]: setattr(merged_star, key, np.nan) merged_star.state = check_state_of_star(merged_star, star_CO=False) # TODO for sure this needs testing! massless_remnant = convert_star_to_massless_remnant(comp) @@ -452,25 +457,25 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma elif (s1 in LIST_ACCEPTABLE_STATES_FOR_POSTHeMS and s2 in LIST_ACCEPTABLE_STATES_FOR_POSTMS): - # add total and core masses - for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: - current = getattr(star_base, key) + getattr(comp, key) - setattr(merged_star, key,current) + merged_star = comp + # weighted central abundances if merging cores. Else only from star_base if star_base.co_core_mass == 0 and comp.co_core_mass == 0: # two stars with Helium cores merged_star.center_h1 = mass_weighted_avg(mass_weight1="he_core_mass") merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4", mass_weight1="he_core_mass") merged_star.center_c12 = mass_weighted_avg(abundance_name = "center_c12", mass_weight1="he_core_mass") + merged_star.avg_c_in_c_core = mass_weighted_avg(abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") merged_star.center_n14 = mass_weighted_avg(abundance_name = "center_n14", mass_weight1="he_core_mass") merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16", mass_weight1="he_core_mass") + setattr(merged_star, "center_gamma", np.nan) elif (star_base.co_core_mass > 0 and comp.co_core_mass == 0): # star_base with CO core and the comp has a He core - pass # the central abundances are kept as the ones of star_base + merged_star.center_h1 = star_base.center_h1 + merged_star.center_he4 = star_base.center_he4 + merged_star.center_c12 = star_base.center_c12 + merged_star.center_n14 = star_base.center_n14 + merged_star.center_o16 = star_base.center_o16 elif (comp.co_core_mass > 0 and star_base.co_core_mass == 0): # comp with CO core and the star_base has a He core - merged_star.center_h1 = comp.center_h1 - merged_star.center_he4 = comp.center_he4 - merged_star.center_c12 = comp.center_c12 - merged_star.center_n14 = comp.center_n14 - merged_star.center_o16 = comp.center_o16 + pass # the central abundances are kept as the ones of comp elif (star_base.co_core_mass > 0 and comp.co_core_mass > 0): merged_star.center_h1 = mass_weighted_avg(mass_weight1="co_core_mass") merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4", mass_weight1="co_core_mass") @@ -480,13 +485,17 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma else: Pwarn("weird compbination of CO core masses during merging", "EvolutionWarning") + # add total and core masses + for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: + current = getattr(star_base, key) + getattr(comp, key) + setattr(merged_star, key,current) + for key in STARPROPERTIES: # these stellar attributes become np.nan for substring in ["log_", "lg_", "surf_", "conv_", "lambda", "profile"]: if (substring in key) : setattr(merged_star, key, np.nan) - if key in [ "c12_c12", "center_gamma", - "avg_c_in_c_core", "total_moment_of_inertia", "spin"]: + if key in [ "c12_c12", "total_moment_of_inertia", "spin"]: setattr(merged_star, key, np.nan) merged_star.state = check_state_of_star(merged_star, star_CO=False) # TODO for sure this needs testing! massless_remnant = convert_star_to_massless_remnant(comp) From 5aa56025711436cf0875088624961e93102bbc13 Mon Sep 17 00:00:00 2001 From: ezapartas Date: Thu, 15 Jan 2026 16:19:56 +0200 Subject: [PATCH 09/32] finished step_merged --- posydon/binary_evol/DT/step_merged.py | 47 +++++++++++++++++---------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index 6e9f439cd8..9dd7f46d76 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -383,7 +383,7 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma merged_star.center_n14 = mass_weighted_avg(abundance_name = "center_n14", mass_weight1="he_core_mass") merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16", mass_weight1="he_core_mass") elif (star_base.co_core_mass == 0 and comp.co_core_mass > 0): # star_base is the HeMS Star and comp has a CO core - pass # the central abundances are kept as the ones of star_base + pass # the central abundances are kept as the ones of comp else: Pwarn("weird compbination of CO core masses during merging", "EvolutionWarning") # surface abundances from comp @@ -498,41 +498,47 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma if key in [ "c12_c12", "total_moment_of_inertia", "spin"]: setattr(merged_star, key, np.nan) merged_star.state = check_state_of_star(merged_star, star_CO=False) # TODO for sure this needs testing! - massless_remnant = convert_star_to_massless_remnant(comp) + massless_remnant = convert_star_to_massless_remnant(star_base) # HeStar + HeStar elif (s1 in STAR_STATES_HE_RICH and s2 in STAR_STATES_HE_RICH): - # add total and core masses - for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: - current = getattr(star_base, key) + getattr(comp, key) - setattr(merged_star, key,current) - # weighted central abundances if merging cores. Else only from star_base if star_base.co_core_mass == 0 and comp.co_core_mass == 0: # two stars with Helium cores merged_star.center_h1 = mass_weighted_avg(mass_weight1="he_core_mass") merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4", mass_weight1="he_core_mass") merged_star.center_c12 = mass_weighted_avg(abundance_name = "center_c12", mass_weight1="he_core_mass") + merged_star.avg_c_in_c_core = mass_weighted_avg(abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") merged_star.center_n14 = mass_weighted_avg(abundance_name = "center_n14", mass_weight1="he_core_mass") merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16", mass_weight1="he_core_mass") + setattr(merged_star, "center_gamma", np.nan) elif (star_base.co_core_mass > 0 and comp.co_core_mass == 0): # star_base with CO core and the comp has a He core pass # the central abundances are kept as the ones of star_base elif (comp.co_core_mass > 0 and star_base.co_core_mass == 0): # comp with CO core and the star_base has a He core merged_star.center_h1 = comp.center_h1 merged_star.center_he4 = comp.center_he4 merged_star.center_c12 = comp.center_c12 + merged_star.avg_c_in_c_core = comp.avg_c_in_c_core merged_star.center_n14 = comp.center_n14 merged_star.center_o16 = comp.center_o16 + merged_star.center_gamma = comp.center_gamma elif (star_base.co_core_mass > 0 and comp.co_core_mass > 0): merged_star.center_h1 = mass_weighted_avg(mass_weight1="co_core_mass") merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4", mass_weight1="co_core_mass") merged_star.center_c12 = mass_weighted_avg(abundance_name = "center_c12", mass_weight1="co_core_mass") + merged_star.avg_c_in_c_core = mass_weighted_avg(abundance_name = "avg_c_in_c_core", mass_weight1="co_core_mass") merged_star.center_n14 = mass_weighted_avg(abundance_name = "center_n14", mass_weight1="co_core_mass") merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16", mass_weight1="co_core_mass") + setattr(merged_star, "center_gamma", np.nan) else: Pwarn("weird compbination of CO core masses during merging", "EvolutionWarning") + # add total and core masses + for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: + current = getattr(star_base, key) + getattr(comp, key) + setattr(merged_star, key,current) + # weigheted mixing on the surface abundances based on the He-rich envelopes of the two stars merged_star.surface_h1 = mass_weighted_avg(abundance_name = "surface_h1", mass_weight1="He-rich_envelope_mass", mass_weight2="He-rich_envelope_mass") merged_star.surface_he4 = mass_weighted_avg(abundance_name = "surface_he4", mass_weight1="He-rich_envelope_mass", mass_weight2="He-rich_envelope_mass") @@ -545,8 +551,7 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma for substring in ["log_", "lg_", "surf_", "conv_", "lambda", "profile"]: if (substring in key) : setattr(merged_star, key, np.nan) - if key in [ "c12_c12", "center_gamma", - "avg_c_in_c_core", "total_moment_of_inertia", "spin"]: + if key in [ "c12_c12", "total_moment_of_inertia", "spin"]: setattr(merged_star, key, np.nan) merged_star.state = check_state_of_star(merged_star, star_CO=False) # TODO for sure this needs testing! massless_remnant = convert_star_to_massless_remnant(comp) @@ -555,34 +560,40 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma elif (s1 in STAR_STATES_NOT_CO and s2 in ["WD"]): - #WD is considered a stripped CO core - # add total and core masses - for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: - current = getattr(star_base, key) + getattr(comp, "mass") - setattr(merged_star, key,current) + # WD is considered a stripped CO core + # WD would always be the comp, it cannot be the engulfing star (so no need to do the opposite stars case below) + # weighted central abundances if merging cores. Else only from star_base - if (comp.co_core_mass > 0 and star_base.co_core_mass == 0): # comp with CO core and the star_base has not + if (comp.co_core_mass is not None and star_base.co_core_mass == 0): # comp with CO core and the star_base has not merged_star.center_h1 = comp.center_h1 merged_star.center_he4 = comp.center_he4 merged_star.center_c12 = comp.center_c12 + merged_star.avg_c_in_c_core = comp.avg_c_in_c_core merged_star.center_n14 = comp.center_n14 merged_star.center_o16 = comp.center_o16 - elif (star_base.co_core_mass > 0 and comp.co_core_mass > 0): + merged_star.center_gamma = comp.center_gamma + elif (comp.co_core_mass is not None and star_base.co_core_mass > 0): merged_star.center_h1 = mass_weighted_avg(mass_weight1="co_core_mass") merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4", mass_weight1="co_core_mass") merged_star.center_c12 = mass_weighted_avg(abundance_name = "center_c12", mass_weight1="co_core_mass") + merged_star.avg_c_in_c_core = mass_weighted_avg(abundance_name = "avg_c_in_c_core", mass_weight1="co_core_mass") merged_star.center_n14 = mass_weighted_avg(abundance_name = "center_n14", mass_weight1="co_core_mass") merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16", mass_weight1="co_core_mass") + setattr(merged_star, "center_gamma", np.nan) else: Pwarn("weird compbination of CO core masses during merging", "EvolutionWarning") + # add total and core masses + for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: + current = getattr(star_base, key) + getattr(comp, "mass") + setattr(merged_star, key,current) + for key in STARPROPERTIES: # these stellar attributes become np.nan for substring in ["log_", "lg_", "surf_", "conv_", "lambda", "profile"]: if (substring in key) : setattr(merged_star, key, np.nan) - if key in [ "c12_c12", "center_gamma", - "avg_c_in_c_core", "total_moment_of_inertia", "spin"]: + if key in [ "c12_c12", "total_moment_of_inertia", "spin"]: setattr(merged_star, key, np.nan) merged_star.state = check_state_of_star(merged_star, star_CO=False) # TODO for sure this needs testing! massless_remnant = convert_star_to_massless_remnant(comp) From 12f97e53afba01f24425399ad9486b05e18084b0 Mon Sep 17 00:00:00 2001 From: ezapartas Date: Thu, 15 Jan 2026 16:37:36 +0200 Subject: [PATCH 10/32] added co_core_mass as a potential option in the matching criteria at track_match --- posydon/binary_evol/DT/track_match.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/posydon/binary_evol/DT/track_match.py b/posydon/binary_evol/DT/track_match.py index 07399cb708..4450163647 100644 --- a/posydon/binary_evol/DT/track_match.py +++ b/posydon/binary_evol/DT/track_match.py @@ -52,10 +52,10 @@ val_names = [" ", "mass", "log_R", "center_h1", "surface_h1", "he_core_mass", "center_he4", "surface_he4", - "center_c12"] + "center_c12", "co_core_mass"] str_fmts = ["{:>14}", "{:>9}","{:>9}", "{:>9}", "{:>10}", "{:>12}", - "{:>10}", "{:>11}", "{:>10}"] + "{:>10}", "{:>11}", "{:>10}", "{:>12}"] row_str = " ".join(str_fmts) DIVIDER_STR = "_"*len(row_str.format(*[""]*len(str_fmts))) # MAJOR.MINOR version of imported scipy package @@ -285,7 +285,8 @@ def __init__( "surface_he4", "surface_h1", "log_R", - "center_c12" + "center_c12", + "co_core_mass" ] ) @@ -743,7 +744,8 @@ def match_to_single_star(self, star): f'surface_he4 = {star.surface_he4:.4f}, ', f'surface_h1 = {star.surface_h1:.4f}, ', f'he_core_mass = {star.he_core_mass:.3f}, ', - f'center_c12 = {star.center_c12:.4f}' + f'center_c12 = {star.center_c12:.4f},', + f'co_core_mass = {star.co_core_mass:.3f}' ) # done with matching attempts From 37b64b67d9da7f6ae6f2c2e4ccbd590735f6c142 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 15 Jan 2026 14:39:13 +0000 Subject: [PATCH 11/32] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- posydon/binary_evol/DT/step_merged.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index 9dd7f46d76..1cd0b3191b 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -176,7 +176,7 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma M2 = getattr(star2, "he_core_mass") - getattr(star2, "co_core_mass") else: M2 = getattr(star2, mass_weight2) - + try: mass_weighted_avg_value=(A1*M1+A2*M2)/(M1+M2) except TypeError: @@ -193,7 +193,7 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma if ( s1 in LIST_ACCEPTABLE_STATES_FOR_HMS and s2 in LIST_ACCEPTABLE_STATES_FOR_HMS): #these stellar attributes change value - + #TODO for key in ["center_h1", "center_he4", "center_c12", "center_n14","center_o16"]: merged_star.center_h1 = mass_weighted_avg() merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4") @@ -210,7 +210,7 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma merged_star.surface_o16 = mass_weighted_avg(abundance_name = "surface_o16") # The change of masses occurs after the calculation of weighted averages - merged_star.mass = (star_base.mass + comp.mass) * (1.-self.rel_mass_lost_HMS_HMS) + merged_star.mass = (star_base.mass + comp.mass) * (1.-self.rel_mass_lost_HMS_HMS) for key in STARPROPERTIES: # these stellar attributes become np.nan @@ -234,7 +234,7 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma merged_star.surface_o16 = mass_weighted_avg(abundance_name = "surface_o16", mass_weight1="H-rich_envelope_mass", mass_weight2="mass") # The change of masses occurs after the calculation of weighted averages - merged_star.mass = star_base.mass + comp.mass + merged_star.mass = star_base.mass + comp.mass for key in STARPROPERTIES: # these stellar attributes become np.nan From dd7078a620e982efb5d7cb557ccc6b28e5804a3d Mon Sep 17 00:00:00 2001 From: ezapartas Date: Thu, 12 Feb 2026 11:07:01 +0200 Subject: [PATCH 12/32] removed old code line --- posydon/binary_evol/DT/step_merged.py | 1 - 1 file changed, 1 deletion(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index 1cd0b3191b..6663d32742 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -152,7 +152,6 @@ def merged_star_properties(self, star_base, comp): is the star that is engulfed """ #by default the stellar attributes that keep the same value from the - #merged_star = copy.copy(star_base) merged_star = star_base s1 = star_base.state From a5c4a852854b441618373ec32911d1fd81302ba1 Mon Sep 17 00:00:00 2001 From: ezapartas Date: Thu, 12 Feb 2026 11:12:26 +0200 Subject: [PATCH 13/32] ZeroDivisionError added --- posydon/binary_evol/DT/step_merged.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index 6663d32742..3d2c3caac7 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -178,7 +178,7 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma try: mass_weighted_avg_value=(A1*M1+A2*M2)/(M1+M2) - except TypeError: + except (TypeError, ZeroDivisionError): mass_weighted_avg_value= np.nan if self.verbose: From 68a57e0ca1630208ca513628658015cff2066c40 Mon Sep 17 00:00:00 2001 From: ezapartas Date: Thu, 12 Feb 2026 12:27:27 +0200 Subject: [PATCH 14/32] deleted a TODO comment --- posydon/binary_evol/DT/step_merged.py | 1 - 1 file changed, 1 deletion(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index 3d2c3caac7..6781fadc7b 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -193,7 +193,6 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma and s2 in LIST_ACCEPTABLE_STATES_FOR_HMS): #these stellar attributes change value - #TODO for key in ["center_h1", "center_he4", "center_c12", "center_n14","center_o16"]: merged_star.center_h1 = mass_weighted_avg() merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4") merged_star.center_c12 = mass_weighted_avg(abundance_name = "center_c12") From 69212308c926b88a6826e8c1e73606f2a96d4065 Mon Sep 17 00:00:00 2001 From: Max Briel Date: Sun, 1 Mar 2026 12:01:49 +0100 Subject: [PATCH 15/32] typo fix, add additional c_avg to opposite merger postMS+HeMS --- posydon/binary_evol/DT/step_merged.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index 6781fadc7b..02b5b650a3 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -176,14 +176,17 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma else: M2 = getattr(star2, mass_weight2) - try: - mass_weighted_avg_value=(A1*M1+A2*M2)/(M1+M2) - except (TypeError, ZeroDivisionError): - mass_weighted_avg_value= np.nan + den = M1 + M2 + if not (np.isfinite(A1) and np.isfinite(A2) and np.isfinite(M1) and np.isfinite(M2)): + mass_weighted_avg_value = np.nan + elif den == 0: + mass_weighted_avg_value = np.nan + else: + mass_weighted_avg_value = (A1 * M1 + A2 * M2) / den if self.verbose: print(abundance_name, mass_weight1, mass_weight2) - print("A_base, M_base_abundance, A_comp, M_comp_abundanc", A1, M1, A2, M2) + print("A_base, M_base_abundance, A_comp, M_comp_abundance", A1, M1, A2, M2) print("mass_weighted_avg= ", mass_weighted_avg_value) return mass_weighted_avg_value @@ -378,8 +381,10 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma merged_star.center_h1 = mass_weighted_avg(mass_weight1="he_core_mass") merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4", mass_weight1="he_core_mass") merged_star.center_c12 = mass_weighted_avg(abundance_name = "center_c12", mass_weight1="he_core_mass") + merged_star.avg_c_in_c_core = mass_weighted_avg(abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") merged_star.center_n14 = mass_weighted_avg(abundance_name = "center_n14", mass_weight1="he_core_mass") merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16", mass_weight1="he_core_mass") + setattr(merged_star, "center_gamma", np.nan) elif (star_base.co_core_mass == 0 and comp.co_core_mass > 0): # star_base is the HeMS Star and comp has a CO core pass # the central abundances are kept as the ones of comp else: @@ -579,7 +584,7 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16", mass_weight1="co_core_mass") setattr(merged_star, "center_gamma", np.nan) else: - Pwarn("weird compbination of CO core masses during merging", "EvolutionWarning") + Pwarn("Unexpected combination of CO core masses during merging", "EvolutionWarning") # add total and core masses for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: From 6057f8f23090d3dd654b7d75252a68fc1bf4c088 Mon Sep 17 00:00:00 2001 From: Max Briel Date: Mon, 2 Mar 2026 14:32:06 +0100 Subject: [PATCH 16/32] move mass_weighted out of other function --- posydon/binary_evol/DT/step_merged.py | 286 ++++++++++++++------------ 1 file changed, 153 insertions(+), 133 deletions(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index 02b5b650a3..3cb8cd8f42 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -140,6 +140,59 @@ def __call__(self,binary): super().__call__(binary) + def mass_weighted_avg(self, star1, star2, abundance_name, mass_weight1="mass", mass_weight2=None): + """Compute the mass-weighted average of an abundance between two stars. + + Parameters + ---------- + star1 : SingleStar + The first star (base/engulfing star). + star2 : SingleStar + The second star (companion/engulfed star). + abundance_name : str + Name of the stellar attribute to average. + mass_weight1 : str + Mass attribute to use as weight for star1. Special values + ``"H-rich_envelope_mass"`` and ``"He-rich_envelope_mass"`` are + computed on the fly; any other value is looked up directly on the + star object. + mass_weight2 : str or None + Mass attribute for star2. Defaults to ``mass_weight1`` when + ``None``. + """ + A1 = getattr(star1, abundance_name) + A2 = getattr(star2, abundance_name) + if mass_weight1 == "H-rich_envelope_mass": + M1 = getattr(star1, "mass") - getattr(star1, "he_core_mass") + elif mass_weight1 == "He-rich_envelope_mass": + M1 = getattr(star1, "he_core_mass") - getattr(star1, "co_core_mass") + else: + M1 = getattr(star1, mass_weight1) + + if mass_weight2 is None: + mass_weight2 = mass_weight1 + if mass_weight2 == "H-rich_envelope_mass": + M2 = getattr(star2, "mass") - getattr(star2, "he_core_mass") + elif mass_weight2 == "He-rich_envelope_mass": + M2 = getattr(star2, "he_core_mass") - getattr(star2, "co_core_mass") + else: + M2 = getattr(star2, mass_weight2) + + den = M1 + M2 + if not (np.isfinite(A1) and np.isfinite(A2) and np.isfinite(M1) and np.isfinite(M2)): + mass_weighted_avg_value = np.nan + elif den == 0: + mass_weighted_avg_value = np.nan + else: + mass_weighted_avg_value = (A1 * M1 + A2 * M2) / den + + if self.verbose: + print(abundance_name, mass_weight1, mass_weight2) + print("A_base, M_base_abundance, A_comp, M_comp_abundance", A1, M1, A2, M2) + print("mass_weighted_avg= ", mass_weighted_avg_value) + + return mass_weighted_avg_value + def merged_star_properties(self, star_base, comp): """ Make assumptions about the core/total mass, and abundances of the star of a merged product. @@ -151,64 +204,30 @@ def merged_star_properties(self, star_base, comp): comp: Single Star is the star that is engulfed """ - #by default the stellar attributes that keep the same value from the + #by default the stellar attributes that keep the same values from the base merged_star = star_base s1 = star_base.state s2 = comp.state - def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", mass_weight1="mass", mass_weight2=None): - A1 = getattr(star1, abundance_name) - A2 = getattr(star2, abundance_name) - if mass_weight1 == "H-rich_envelope_mass": - M1 = getattr(star1, "mass") - getattr(star1, "he_core_mass") - elif mass_weight1 == "He-rich_envelope_mass": - M1 = getattr(star1, "he_core_mass") - getattr(star1, "co_core_mass") - else: - M1 = getattr(star1, mass_weight1) - - if mass_weight2 is None: - mass_weight2 = mass_weight1 - if mass_weight2 == "H-rich_envelope_mass": - M2 = getattr(star2, "mass") - getattr(star2, "he_core_mass") - elif mass_weight2 == "He-rich_envelope_mass": - M2 = getattr(star2, "he_core_mass") - getattr(star2, "co_core_mass") - else: - M2 = getattr(star2, mass_weight2) - - den = M1 + M2 - if not (np.isfinite(A1) and np.isfinite(A2) and np.isfinite(M1) and np.isfinite(M2)): - mass_weighted_avg_value = np.nan - elif den == 0: - mass_weighted_avg_value = np.nan - else: - mass_weighted_avg_value = (A1 * M1 + A2 * M2) / den - - if self.verbose: - print(abundance_name, mass_weight1, mass_weight2) - print("A_base, M_base_abundance, A_comp, M_comp_abundance", A1, M1, A2, M2) - print("mass_weighted_avg= ", mass_weighted_avg_value) - - return mass_weighted_avg_value - # MS + MS if ( s1 in LIST_ACCEPTABLE_STATES_FOR_HMS and s2 in LIST_ACCEPTABLE_STATES_FOR_HMS): #these stellar attributes change value - merged_star.center_h1 = mass_weighted_avg() - merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4") - merged_star.center_c12 = mass_weighted_avg(abundance_name = "center_c12") - merged_star.center_n14 = mass_weighted_avg(abundance_name = "center_n14") - merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16") + merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1") + merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4") + merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12") + merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14") + merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16") #TODO: should I check if the abundaces above end up in ~1 (?) # weigheted mixing on the surface abundances - merged_star.surface_h1 = mass_weighted_avg(abundance_name = "surface_h1") - merged_star.surface_he4 = mass_weighted_avg(abundance_name = "surface_he4") - merged_star.surface_c12 = mass_weighted_avg(abundance_name = "surface_c12") - merged_star.surface_n14 = mass_weighted_avg(abundance_name = "surface_n14") - merged_star.surface_o16 = mass_weighted_avg(abundance_name = "surface_o16") + merged_star.surface_h1 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_h1") + merged_star.surface_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_he4") + merged_star.surface_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_c12") + merged_star.surface_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_n14") + merged_star.surface_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_o16") # The change of masses occurs after the calculation of weighted averages merged_star.mass = (star_base.mass + comp.mass) * (1.-self.rel_mass_lost_HMS_HMS) @@ -223,16 +242,17 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma setattr(merged_star, key, np.nan) massless_remnant = convert_star_to_massless_remnant(comp) - #postMS + MS + # postMS + MS elif (s1 in LIST_ACCEPTABLE_STATES_FOR_POSTMS and s2 in LIST_ACCEPTABLE_STATES_FOR_HMS): - # weigheted mixing on the surface abundances of the whole comp with the envelope of star_base - merged_star.surface_h1 = mass_weighted_avg(abundance_name = "surface_h1", mass_weight1="H-rich_envelope_mass", mass_weight2="mass") - merged_star.surface_he4 = mass_weighted_avg(abundance_name = "surface_he4", mass_weight1="H-rich_envelope_mass", mass_weight2="mass") - merged_star.surface_c12 = mass_weighted_avg(abundance_name = "surface_c12", mass_weight1="H-rich_envelope_mass", mass_weight2="mass") - merged_star.surface_n14 = mass_weighted_avg(abundance_name = "surface_n14", mass_weight1="H-rich_envelope_mass", mass_weight2="mass") - merged_star.surface_o16 = mass_weighted_avg(abundance_name = "surface_o16", mass_weight1="H-rich_envelope_mass", mass_weight2="mass") + # weighted mixing on the surface abundances of the whole + # companion with the envelope of star_base + merged_star.surface_h1 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_h1", mass_weight1="H-rich_envelope_mass", mass_weight2="mass") + merged_star.surface_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_he4", mass_weight1="H-rich_envelope_mass", mass_weight2="mass") + merged_star.surface_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_c12", mass_weight1="H-rich_envelope_mass", mass_weight2="mass") + merged_star.surface_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_n14", mass_weight1="H-rich_envelope_mass", mass_weight2="mass") + merged_star.surface_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_o16", mass_weight1="H-rich_envelope_mass", mass_weight2="mass") # The change of masses occurs after the calculation of weighted averages merged_star.mass = star_base.mass + comp.mass @@ -251,17 +271,17 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma merged_star.state = check_state_of_star(merged_star, star_CO=False) # TODO for sure this needs testing! massless_remnant = convert_star_to_massless_remnant(comp) - # as above but opposite stars + # MS + postMS (the opposite of above) elif (s1 in LIST_ACCEPTABLE_STATES_FOR_HMS and s2 in LIST_ACCEPTABLE_STATES_FOR_POSTMS): merged_star = comp - merged_star.surface_h1 = mass_weighted_avg(abundance_name = "surface_h1", mass_weight2="H-rich_envelope_mass", mass_weight1="mass") - merged_star.surface_he4 = mass_weighted_avg(abundance_name = "surface_he4", mass_weight2="H-rich_envelope_mass", mass_weight1="mass") - merged_star.surface_c12 = mass_weighted_avg(abundance_name = "surface_c12", mass_weight2="H-rich_envelope_mass", mass_weight1="mass") - merged_star.surface_n14 = mass_weighted_avg(abundance_name = "surface_n14", mass_weight2="H-rich_envelope_mass", mass_weight1="mass") - merged_star.surface_o16 = mass_weighted_avg(abundance_name = "surface_o16", mass_weight2="H-rich_envelope_mass", mass_weight1="mass") + merged_star.surface_h1 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_h1", mass_weight2="H-rich_envelope_mass", mass_weight1="mass") + merged_star.surface_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_he4", mass_weight2="H-rich_envelope_mass", mass_weight1="mass") + merged_star.surface_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_c12", mass_weight2="H-rich_envelope_mass", mass_weight1="mass") + merged_star.surface_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_n14", mass_weight2="H-rich_envelope_mass", mass_weight1="mass") + merged_star.surface_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_o16", mass_weight2="H-rich_envelope_mass", mass_weight1="mass") # The change of masses occurs after the calculation of weighted averages merged_star.mass = star_base.mass + comp.mass @@ -286,12 +306,12 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma # weighted central abundances if merging cores. Else only from star_base if star_base.co_core_mass == 0 and comp.co_core_mass == 0: # two stars with Helium cores - merged_star.center_h1 = mass_weighted_avg(mass_weight1="he_core_mass") - merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4", mass_weight1="he_core_mass") - merged_star.center_c12 = mass_weighted_avg(abundance_name = "center_c12", mass_weight1="he_core_mass") - merged_star.avg_c_in_c_core = mass_weighted_avg(abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") - merged_star.center_n14 = mass_weighted_avg(abundance_name = "center_n14", mass_weight1="he_core_mass") - merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16", mass_weight1="he_core_mass") + merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1", mass_weight1="he_core_mass") + merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4", mass_weight1="he_core_mass") + merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12", mass_weight1="he_core_mass") + merged_star.avg_c_in_c_core = self.mass_weighted_avg(star_base, comp, abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") + merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14", mass_weight1="he_core_mass") + merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16", mass_weight1="he_core_mass") setattr(merged_star, "center_gamma", np.nan) elif (star_base.co_core_mass > 0 and comp.co_core_mass == 0): # star_base with CO core and the comp has a He core pass # the central abundances are kept as the ones of star_base @@ -304,22 +324,22 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma merged_star.center_o16 = comp.center_o16 merged_star.center_gamma = comp.center_gamma elif (star_base.co_core_mass > 0 and comp.co_core_mass > 0): - merged_star.center_h1 = mass_weighted_avg(mass_weight1="co_core_mass") #TODO : maybe he_core_mass makes more sense? - merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4", mass_weight1="co_core_mass") - merged_star.center_c12 = mass_weighted_avg(abundance_name = "center_c12", mass_weight1="co_core_mass") - merged_star.avg_c_in_c_core = mass_weighted_avg(abundance_name = "avg_c_in_c_core", mass_weight1="co_core_mass") - merged_star.center_n14 = mass_weighted_avg(abundance_name = "center_n14", mass_weight1="co_core_mass") - merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16", mass_weight1="co_core_mass") + merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1", mass_weight1="co_core_mass") #TODO : maybe he_core_mass makes more sense? + merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4", mass_weight1="co_core_mass") + merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12", mass_weight1="co_core_mass") + merged_star.avg_c_in_c_core = self.mass_weighted_avg(star_base, comp, abundance_name = "avg_c_in_c_core", mass_weight1="co_core_mass") + merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14", mass_weight1="co_core_mass") + merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16", mass_weight1="co_core_mass") setattr(merged_star, "center_gamma", np.nan) else: Pwarn("weird compbination of CO core masses during merging", "EvolutionWarning") # weigheted mixing on the surface abundances based on the envelopes of the two stars - merged_star.surface_h1 = mass_weighted_avg(abundance_name = "surface_h1", mass_weight1="H-rich_envelope_mass", mass_weight2="H-rich_envelope_mass") - merged_star.surface_he4 = mass_weighted_avg(abundance_name = "surface_he4", mass_weight1="H-rich_envelope_mass", mass_weight2="H-rich_envelope_mass") - merged_star.surface_c12 = mass_weighted_avg(abundance_name = "surface_c12", mass_weight1="H-rich_envelope_mass", mass_weight2="H-rich_envelope_mass") - merged_star.surface_n14 = mass_weighted_avg(abundance_name = "surface_n14", mass_weight1="H-rich_envelope_mass", mass_weight2="H-rich_envelope_mass") - merged_star.surface_o16 = mass_weighted_avg(abundance_name = "surface_o16", mass_weight1="H-rich_envelope_mass", mass_weight2="H-rich_envelope_mass") + merged_star.surface_h1 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_h1", mass_weight1="H-rich_envelope_mass", mass_weight2="H-rich_envelope_mass") + merged_star.surface_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_he4", mass_weight1="H-rich_envelope_mass", mass_weight2="H-rich_envelope_mass") + merged_star.surface_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_c12", mass_weight1="H-rich_envelope_mass", mass_weight2="H-rich_envelope_mass") + merged_star.surface_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_n14", mass_weight1="H-rich_envelope_mass", mass_weight2="H-rich_envelope_mass") + merged_star.surface_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_o16", mass_weight1="H-rich_envelope_mass", mass_weight2="H-rich_envelope_mass") # add total and core masses after calculations of weighter average for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: @@ -342,12 +362,12 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma # weighted central abundances if merging cores. Else only from star_base if star_base.co_core_mass == 0 and comp.co_core_mass == 0: # two stars with only Helium cores, not CO cores - merged_star.center_h1 = mass_weighted_avg(mass_weight1="he_core_mass") - merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4", mass_weight1="he_core_mass") - merged_star.center_c12 = mass_weighted_avg(abundance_name = "center_c12", mass_weight1="he_core_mass") - merged_star.avg_c_in_c_core = mass_weighted_avg(abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") - merged_star.center_n14 = mass_weighted_avg(abundance_name = "center_n14", mass_weight1="he_core_mass") - merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16", mass_weight1="he_core_mass") + merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1", mass_weight1="he_core_mass") + merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4", mass_weight1="he_core_mass") + merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12", mass_weight1="he_core_mass") + merged_star.avg_c_in_c_core = self.mass_weighted_avg(star_base, comp, abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") + merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14", mass_weight1="he_core_mass") + merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16", mass_weight1="he_core_mass") setattr(merged_star, "center_gamma", np.nan) elif (star_base.co_core_mass > 0 and comp.co_core_mass == 0): # star_base with CO core and the comp has just a He core (is a HeMS star) pass # the central abundances are kept as the ones of star_base @@ -378,12 +398,12 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma # weighted central abundances if merging cores. Else only from comp if star_base.co_core_mass == 0 and comp.co_core_mass == 0: # two stars with only Helium cores, not CO cores - merged_star.center_h1 = mass_weighted_avg(mass_weight1="he_core_mass") - merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4", mass_weight1="he_core_mass") - merged_star.center_c12 = mass_weighted_avg(abundance_name = "center_c12", mass_weight1="he_core_mass") - merged_star.avg_c_in_c_core = mass_weighted_avg(abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") - merged_star.center_n14 = mass_weighted_avg(abundance_name = "center_n14", mass_weight1="he_core_mass") - merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16", mass_weight1="he_core_mass") + merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1", mass_weight1="he_core_mass") + merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4", mass_weight1="he_core_mass") + merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12", mass_weight1="he_core_mass") + merged_star.avg_c_in_c_core = self.mass_weighted_avg(star_base, comp, abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") + merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14", mass_weight1="he_core_mass") + merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16", mass_weight1="he_core_mass") setattr(merged_star, "center_gamma", np.nan) elif (star_base.co_core_mass == 0 and comp.co_core_mass > 0): # star_base is the HeMS Star and comp has a CO core pass # the central abundances are kept as the ones of comp @@ -413,12 +433,12 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma # weighted central abundances if merging cores. Else only from star_base if star_base.co_core_mass == 0 and comp.co_core_mass == 0: # two stars with Helium cores - merged_star.center_h1 = mass_weighted_avg(mass_weight1="he_core_mass") - merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4", mass_weight1="he_core_mass") - merged_star.center_c12 = mass_weighted_avg(abundance_name = "center_c12", mass_weight1="he_core_mass") - merged_star.avg_c_in_c_core = mass_weighted_avg(abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") - merged_star.center_n14 = mass_weighted_avg(abundance_name = "center_n14", mass_weight1="he_core_mass") - merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16", mass_weight1="he_core_mass") + merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1", mass_weight1="he_core_mass") + merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4", mass_weight1="he_core_mass") + merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12", mass_weight1="he_core_mass") + merged_star.avg_c_in_c_core = self.mass_weighted_avg(star_base, comp, abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") + merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14", mass_weight1="he_core_mass") + merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16", mass_weight1="he_core_mass") setattr(merged_star, "center_gamma", np.nan) elif (star_base.co_core_mass > 0 and comp.co_core_mass == 0): # star_base with CO core and the comp has a He core pass # the central abundances are kept as the ones of star_base @@ -431,12 +451,12 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma merged_star.center_o16 = comp.center_o16 merged_star.center_gamma = comp.center_gamma elif (star_base.co_core_mass > 0 and comp.co_core_mass > 0): - merged_star.center_h1 = mass_weighted_avg(mass_weight1="co_core_mass") - merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4", mass_weight1="co_core_mass") - merged_star.center_c12 = mass_weighted_avg(abundance_name = "center_c12", mass_weight1="co_core_mass") - merged_star.avg_c_in_c_core = mass_weighted_avg(abundance_name = "avg_c_in_c_core", mass_weight1="co_core_mass") - merged_star.center_n14 = mass_weighted_avg(abundance_name = "center_n14", mass_weight1="co_core_mass") - merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16", mass_weight1="co_core_mass") + merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1", mass_weight1="co_core_mass") + merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4", mass_weight1="co_core_mass") + merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12", mass_weight1="co_core_mass") + merged_star.avg_c_in_c_core = self.mass_weighted_avg(star_base, comp, abundance_name = "avg_c_in_c_core", mass_weight1="co_core_mass") + merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14", mass_weight1="co_core_mass") + merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16", mass_weight1="co_core_mass") setattr(merged_star, "center_gamma", np.nan) else: Pwarn("weird compbination of CO core masses during merging", "EvolutionWarning") @@ -464,12 +484,12 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma # weighted central abundances if merging cores. Else only from star_base if star_base.co_core_mass == 0 and comp.co_core_mass == 0: # two stars with Helium cores - merged_star.center_h1 = mass_weighted_avg(mass_weight1="he_core_mass") - merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4", mass_weight1="he_core_mass") - merged_star.center_c12 = mass_weighted_avg(abundance_name = "center_c12", mass_weight1="he_core_mass") - merged_star.avg_c_in_c_core = mass_weighted_avg(abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") - merged_star.center_n14 = mass_weighted_avg(abundance_name = "center_n14", mass_weight1="he_core_mass") - merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16", mass_weight1="he_core_mass") + merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1", mass_weight1="he_core_mass") + merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4", mass_weight1="he_core_mass") + merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12", mass_weight1="he_core_mass") + merged_star.avg_c_in_c_core = self.mass_weighted_avg(star_base, comp, abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") + merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14", mass_weight1="he_core_mass") + merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16", mass_weight1="he_core_mass") setattr(merged_star, "center_gamma", np.nan) elif (star_base.co_core_mass > 0 and comp.co_core_mass == 0): # star_base with CO core and the comp has a He core merged_star.center_h1 = star_base.center_h1 @@ -480,11 +500,11 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma elif (comp.co_core_mass > 0 and star_base.co_core_mass == 0): # comp with CO core and the star_base has a He core pass # the central abundances are kept as the ones of comp elif (star_base.co_core_mass > 0 and comp.co_core_mass > 0): - merged_star.center_h1 = mass_weighted_avg(mass_weight1="co_core_mass") - merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4", mass_weight1="co_core_mass") - merged_star.center_c12 = mass_weighted_avg(abundance_name = "center_c12", mass_weight1="co_core_mass") - merged_star.center_n14 = mass_weighted_avg(abundance_name = "center_n14", mass_weight1="co_core_mass") - merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16", mass_weight1="co_core_mass") + merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1", mass_weight1="co_core_mass") + merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4", mass_weight1="co_core_mass") + merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12", mass_weight1="co_core_mass") + merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14", mass_weight1="co_core_mass") + merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16", mass_weight1="co_core_mass") else: Pwarn("weird compbination of CO core masses during merging", "EvolutionWarning") @@ -509,12 +529,12 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma # weighted central abundances if merging cores. Else only from star_base if star_base.co_core_mass == 0 and comp.co_core_mass == 0: # two stars with Helium cores - merged_star.center_h1 = mass_weighted_avg(mass_weight1="he_core_mass") - merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4", mass_weight1="he_core_mass") - merged_star.center_c12 = mass_weighted_avg(abundance_name = "center_c12", mass_weight1="he_core_mass") - merged_star.avg_c_in_c_core = mass_weighted_avg(abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") - merged_star.center_n14 = mass_weighted_avg(abundance_name = "center_n14", mass_weight1="he_core_mass") - merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16", mass_weight1="he_core_mass") + merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1", mass_weight1="he_core_mass") + merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4", mass_weight1="he_core_mass") + merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12", mass_weight1="he_core_mass") + merged_star.avg_c_in_c_core = self.mass_weighted_avg(star_base, comp, abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") + merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14", mass_weight1="he_core_mass") + merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16", mass_weight1="he_core_mass") setattr(merged_star, "center_gamma", np.nan) elif (star_base.co_core_mass > 0 and comp.co_core_mass == 0): # star_base with CO core and the comp has a He core pass # the central abundances are kept as the ones of star_base @@ -527,12 +547,12 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma merged_star.center_o16 = comp.center_o16 merged_star.center_gamma = comp.center_gamma elif (star_base.co_core_mass > 0 and comp.co_core_mass > 0): - merged_star.center_h1 = mass_weighted_avg(mass_weight1="co_core_mass") - merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4", mass_weight1="co_core_mass") - merged_star.center_c12 = mass_weighted_avg(abundance_name = "center_c12", mass_weight1="co_core_mass") - merged_star.avg_c_in_c_core = mass_weighted_avg(abundance_name = "avg_c_in_c_core", mass_weight1="co_core_mass") - merged_star.center_n14 = mass_weighted_avg(abundance_name = "center_n14", mass_weight1="co_core_mass") - merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16", mass_weight1="co_core_mass") + merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1", mass_weight1="co_core_mass") + merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4", mass_weight1="co_core_mass") + merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12", mass_weight1="co_core_mass") + merged_star.avg_c_in_c_core = self.mass_weighted_avg(star_base, comp, abundance_name = "avg_c_in_c_core", mass_weight1="co_core_mass") + merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14", mass_weight1="co_core_mass") + merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16", mass_weight1="co_core_mass") setattr(merged_star, "center_gamma", np.nan) else: Pwarn("weird compbination of CO core masses during merging", "EvolutionWarning") @@ -543,11 +563,11 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma setattr(merged_star, key,current) # weigheted mixing on the surface abundances based on the He-rich envelopes of the two stars - merged_star.surface_h1 = mass_weighted_avg(abundance_name = "surface_h1", mass_weight1="He-rich_envelope_mass", mass_weight2="He-rich_envelope_mass") - merged_star.surface_he4 = mass_weighted_avg(abundance_name = "surface_he4", mass_weight1="He-rich_envelope_mass", mass_weight2="He-rich_envelope_mass") - merged_star.surface_c12 = mass_weighted_avg(abundance_name = "surface_c12", mass_weight1="He-rich_envelope_mass", mass_weight2="He-rich_envelope_mass") - merged_star.surface_n14 = mass_weighted_avg(abundance_name = "surface_n14", mass_weight1="He-rich_envelope_mass", mass_weight2="He-rich_envelope_mass") - merged_star.surface_o16 = mass_weighted_avg(abundance_name = "surface_o16", mass_weight1="He-rich_envelope_mass", mass_weight2="He-rich_envelope_mass") + merged_star.surface_h1 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_h1", mass_weight1="He-rich_envelope_mass", mass_weight2="He-rich_envelope_mass") + merged_star.surface_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_he4", mass_weight1="He-rich_envelope_mass", mass_weight2="He-rich_envelope_mass") + merged_star.surface_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_c12", mass_weight1="He-rich_envelope_mass", mass_weight2="He-rich_envelope_mass") + merged_star.surface_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_n14", mass_weight1="He-rich_envelope_mass", mass_weight2="He-rich_envelope_mass") + merged_star.surface_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_o16", mass_weight1="He-rich_envelope_mass", mass_weight2="He-rich_envelope_mass") for key in STARPROPERTIES: # these stellar attributes become np.nan @@ -576,12 +596,12 @@ def mass_weighted_avg(star1=star_base,star2=comp, abundance_name="center_h1", ma merged_star.center_o16 = comp.center_o16 merged_star.center_gamma = comp.center_gamma elif (comp.co_core_mass is not None and star_base.co_core_mass > 0): - merged_star.center_h1 = mass_weighted_avg(mass_weight1="co_core_mass") - merged_star.center_he4 = mass_weighted_avg(abundance_name = "center_he4", mass_weight1="co_core_mass") - merged_star.center_c12 = mass_weighted_avg(abundance_name = "center_c12", mass_weight1="co_core_mass") - merged_star.avg_c_in_c_core = mass_weighted_avg(abundance_name = "avg_c_in_c_core", mass_weight1="co_core_mass") - merged_star.center_n14 = mass_weighted_avg(abundance_name = "center_n14", mass_weight1="co_core_mass") - merged_star.center_o16 = mass_weighted_avg(abundance_name = "center_o16", mass_weight1="co_core_mass") + merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1", mass_weight1="co_core_mass") + merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4", mass_weight1="co_core_mass") + merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12", mass_weight1="co_core_mass") + merged_star.avg_c_in_c_core = self.mass_weighted_avg(star_base, comp, abundance_name = "avg_c_in_c_core", mass_weight1="co_core_mass") + merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14", mass_weight1="co_core_mass") + merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16", mass_weight1="co_core_mass") setattr(merged_star, "center_gamma", np.nan) else: Pwarn("Unexpected combination of CO core masses during merging", "EvolutionWarning") From 0a196d70cd12c27aed1fc17a6afb068d9923b828 Mon Sep 17 00:00:00 2001 From: Max Briel Date: Mon, 2 Mar 2026 19:58:20 +0100 Subject: [PATCH 17/32] simplify setting the parameters --- posydon/binary_evol/DT/step_merged.py | 567 ++++++++++++++------------ 1 file changed, 296 insertions(+), 271 deletions(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index 3cb8cd8f42..92e405247d 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -140,38 +140,40 @@ def __call__(self,binary): super().__call__(binary) - def mass_weighted_avg(self, star1, star2, abundance_name, mass_weight1="mass", mass_weight2=None): + def mass_weighted_avg(self, star1, star2, abundance_name, mass_weight1="mass", mass_weight2='mass'): """Compute the mass-weighted average of an abundance between two stars. Parameters ---------- star1 : SingleStar - The first star (base/engulfing star). + Primary star star2 : SingleStar - The second star (companion/engulfed star). + Companion star abundance_name : str - Name of the stellar attribute to average. + Name of the SingleStar attribute to average. mass_weight1 : str Mass attribute to use as weight for star1. Special values ``"H-rich_envelope_mass"`` and ``"He-rich_envelope_mass"`` are computed on the fly; any other value is looked up directly on the star object. mass_weight2 : str or None - Mass attribute for star2. Defaults to ``mass_weight1`` when - ``None``. + Mass attribute for star2. """ A1 = getattr(star1, abundance_name) A2 = getattr(star2, abundance_name) - if mass_weight1 == "H-rich_envelope_mass": + + if mass_weight1 == "mass": + M1 = getattr(star1, "mass") + elif mass_weight1 == "H-rich_envelope_mass": M1 = getattr(star1, "mass") - getattr(star1, "he_core_mass") elif mass_weight1 == "He-rich_envelope_mass": M1 = getattr(star1, "he_core_mass") - getattr(star1, "co_core_mass") else: M1 = getattr(star1, mass_weight1) - if mass_weight2 is None: - mass_weight2 = mass_weight1 - if mass_weight2 == "H-rich_envelope_mass": + if mass_weight2 == "mass": + M2 = getattr(star2, "mass") + elif mass_weight2 == "H-rich_envelope_mass": M2 = getattr(star2, "mass") - getattr(star2, "he_core_mass") elif mass_weight2 == "He-rich_envelope_mass": M2 = getattr(star2, "he_core_mass") - getattr(star2, "co_core_mass") @@ -193,18 +195,46 @@ def mass_weighted_avg(self, star1, star2, abundance_name, mass_weight1="mass", m return mass_weighted_avg_value - def merged_star_properties(self, star_base, comp): + def _apply_nan_attributes(self, star, extra_nan_keys=set()): + """Set to np.nan the attributes of the star that are not expected to be meaningful after a merger event. + + Parameters set to np.nan are: + - all attributes containing the substrings + {"log_", "lg_", "surf_", "conv_", "lambda", "profile"} + - all attributes in the set: + {"c12_c12", "total_moment_of_inertia", "spin",} + + Parameters + ---------- + star: SingleStar + The star for which the attributes will be set to np.nan + extra_nan_keys: set of str + Set of keys to be set to np.nan in addition to the default ones. """ - Make assumptions about the core/total mass, and abundances of the star of a merged product. + _NAN_SUBSTRINGS = ("log_", "lg_", "surf_", "conv_", "lambda", "profile") + _NAN_KEYS = set(["c12_c12", "total_moment_of_inertia", "spin"]) + + for key in STARPROPERTIES: + if any(sub in key for sub in _NAN_SUBSTRINGS) or (key in extra_nan_keys) or (key in _NAN_KEYS): + setattr(star, key, np.nan) - Similar to the table of merging in BSE + def merged_star_properties(self, star_base, comp): + """Set the properties of the merged star after a merger event. + + Generally, the Roche lobe overflowing star becomes star_base, except + when the companion is further evolved than star_base, in which + case the comp becomes the base for the merged star. + + Abundances are mass-weighted averages of the two stars, with the + weights depending on the type of merger and the abundance considered. star_base: Single Star - is our base star that engulfs its companion. The merged star will have this star as a base + The star that engulfs its companion. + (generally the base for the merged_star) comp: Single Star - is the star that is engulfed + The star that is engulfed by star_base. """ - #by default the stellar attributes that keep the same values from the base + # By default the stellar attributes are kept from star_base. merged_star = star_base s1 = star_base.state @@ -213,33 +243,25 @@ def merged_star_properties(self, star_base, comp): # MS + MS if ( s1 in LIST_ACCEPTABLE_STATES_FOR_HMS and s2 in LIST_ACCEPTABLE_STATES_FOR_HMS): - #these stellar attributes change value - - merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1") - merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4") - merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12") - merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14") - merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16") - #TODO: should I check if the abundaces above end up in ~1 (?) - - # weigheted mixing on the surface abundances - merged_star.surface_h1 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_h1") - merged_star.surface_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_he4") - merged_star.surface_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_c12") - merged_star.surface_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_n14") - merged_star.surface_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_o16") + # Mix central and surface abundances of the two stars with + # mass-weighted averages based on the total masses of the two stars. + parameters_to_mix = ["center_h1", "center_he4", "center_c12", "center_n14", "center_o16", + "surface_h1", "surface_he4", "surface_c12", "surface_n14", "surface_o16"] + + for abundance_name in parameters_to_mix: + #TODO: should I check if the abundaces above end up in ~1 (?) + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="mass", mass_weight2='mass')) # The change of masses occurs after the calculation of weighted averages merged_star.mass = (star_base.mass + comp.mass) * (1.-self.rel_mass_lost_HMS_HMS) - for key in STARPROPERTIES: - # these stellar attributes become np.nan - for substring in ["log_", "lg_", "surf_", "conv_", "lambda", "profile"]: - if (substring in key) : - setattr(merged_star, key, np.nan) - if key in [ "c12_c12", "center_gamma", - "avg_c_in_c_core", "total_moment_of_inertia", "spin", "envelope_binding_energy"]: - setattr(merged_star, key, np.nan) + # Set parameters that are not expected to be meaningful after a merger to np.nan + self._apply_nan_attributes(merged_star, + extra_nan_keys=set(["center_gamma", + "avg_c_in_c_core", + "envelope_binding_energy"])) + + # Set companion to a massless remnant. massless_remnant = convert_star_to_massless_remnant(comp) # postMS + MS @@ -248,27 +270,23 @@ def merged_star_properties(self, star_base, comp): # weighted mixing on the surface abundances of the whole # companion with the envelope of star_base - merged_star.surface_h1 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_h1", mass_weight1="H-rich_envelope_mass", mass_weight2="mass") - merged_star.surface_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_he4", mass_weight1="H-rich_envelope_mass", mass_weight2="mass") - merged_star.surface_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_c12", mass_weight1="H-rich_envelope_mass", mass_weight2="mass") - merged_star.surface_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_n14", mass_weight1="H-rich_envelope_mass", mass_weight2="mass") - merged_star.surface_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_o16", mass_weight1="H-rich_envelope_mass", mass_weight2="mass") + parameters_to_mix = ["surface_h1", "surface_he4", "surface_c12", "surface_n14", "surface_o16"] + for abundance_name in parameters_to_mix: + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="H-rich_envelope_mass", mass_weight2="mass")) # The change of masses occurs after the calculation of weighted averages + # Note that the he core mass is unchanged, which means that + # adding the mass changes the envelope mass only. merged_star.mass = star_base.mass + comp.mass - for key in STARPROPERTIES: - # these stellar attributes become np.nan - for substring in ["log_", "lg_", "surf_", "conv_", "lambda", "profile"]: - if (substring in key) : - setattr(merged_star, key, np.nan) - if key in [ "c12_c12", "total_moment_of_inertia", "spin"]: - setattr(merged_star, key, np.nan) + # Set parameters that are not expected to be meaningful after a merger to np.nan + self._apply_nan_attributes(merged_star) + # Set burning luminosities and star state. merged_star.log_LHe = star_base.log_LHe merged_star.log_LZ = star_base.log_LZ - merged_star.state = check_state_of_star(merged_star, star_CO=False) # TODO for sure this needs testing! + massless_remnant = convert_star_to_massless_remnant(comp) # MS + postMS (the opposite of above) @@ -277,285 +295,299 @@ def merged_star_properties(self, star_base, comp): merged_star = comp - merged_star.surface_h1 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_h1", mass_weight2="H-rich_envelope_mass", mass_weight1="mass") - merged_star.surface_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_he4", mass_weight2="H-rich_envelope_mass", mass_weight1="mass") - merged_star.surface_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_c12", mass_weight2="H-rich_envelope_mass", mass_weight1="mass") - merged_star.surface_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_n14", mass_weight2="H-rich_envelope_mass", mass_weight1="mass") - merged_star.surface_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_o16", mass_weight2="H-rich_envelope_mass", mass_weight1="mass") + parameters_to_mix = ["surface_h1", "surface_he4", "surface_c12", "surface_n14", "surface_o16"] + for abundance_name in parameters_to_mix: + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight2="H-rich_envelope_mass", mass_weight1="mass")) # The change of masses occurs after the calculation of weighted averages merged_star.mass = star_base.mass + comp.mass - for key in STARPROPERTIES: - # these stellar attributes become np.nan - for substring in ["log_", "lg_", "surf_", "conv_", "lambda", "profile"]: - if (substring in key) : - setattr(merged_star, key, np.nan) - if key in [ "c12_c12", "total_moment_of_inertia", "spin"]: - setattr(merged_star, key, np.nan) + # Set parameters that are not expected to be meaningful after a merger to np.nan + self._apply_nan_attributes(merged_star) + # Set burning luminosities and star state. merged_star.log_LHe = comp.log_LHe merged_star.log_LZ = comp.log_LZ + merged_star.state = check_state_of_star(merged_star, star_CO=False) - merged_star.state = check_state_of_star(merged_star, star_CO=False) # TODO for sure this needs testing! massless_remnant = convert_star_to_massless_remnant(star_base) - #postMS + postMS + # postMS + postMS elif (s1 in LIST_ACCEPTABLE_STATES_FOR_POSTMS and s2 in LIST_ACCEPTABLE_STATES_FOR_POSTMS): + # Weighted central abundances if merging cores. + + parameters_to_mix = ["center_h1", "center_he4", "center_c12", "center_n14", "center_o16", + 'avg_c_in_c_core'] + + # two stars with Helium cores + if star_base.co_core_mass == 0 and comp.co_core_mass == 0: + mass_weight1 = 'he_core_mass' + mass_weight2 = 'he_core_mass' + + for abundance_name in parameters_to_mix: + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1=mass_weight1, mass_weight2=mass_weight2)) - # weighted central abundances if merging cores. Else only from star_base - if star_base.co_core_mass == 0 and comp.co_core_mass == 0: # two stars with Helium cores - merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1", mass_weight1="he_core_mass") - merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4", mass_weight1="he_core_mass") - merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12", mass_weight1="he_core_mass") - merged_star.avg_c_in_c_core = self.mass_weighted_avg(star_base, comp, abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") - merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14", mass_weight1="he_core_mass") - merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16", mass_weight1="he_core_mass") setattr(merged_star, "center_gamma", np.nan) - elif (star_base.co_core_mass > 0 and comp.co_core_mass == 0): # star_base with CO core and the comp has a He core + + # star_base with CO core and the comp has a He core + elif (star_base.co_core_mass > 0 and comp.co_core_mass == 0): pass # the central abundances are kept as the ones of star_base - elif (comp.co_core_mass > 0 and star_base.co_core_mass == 0): # comp with CO core and the star_base has a He core - merged_star.center_h1 = comp.center_h1 - merged_star.center_he4 = comp.center_he4 - merged_star.center_c12 = comp.center_c12 - merged_star.avg_c_in_c_core = comp.avg_c_in_c_core - merged_star.center_n14 = comp.center_n14 - merged_star.center_o16 = comp.center_o16 - merged_star.center_gamma = comp.center_gamma + + # Companion with CO core and the star_base has a He core + elif (comp.co_core_mass > 0 and star_base.co_core_mass == 0): + + for abundance_name in parameters_to_mix: + setattr(merged_star, abundance_name, getattr(comp, abundance_name)) + + setattr(merged_star, "center_gamma", comp.center_gamma) + + # both stars have CO cores elif (star_base.co_core_mass > 0 and comp.co_core_mass > 0): - merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1", mass_weight1="co_core_mass") #TODO : maybe he_core_mass makes more sense? - merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4", mass_weight1="co_core_mass") - merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12", mass_weight1="co_core_mass") - merged_star.avg_c_in_c_core = self.mass_weighted_avg(star_base, comp, abundance_name = "avg_c_in_c_core", mass_weight1="co_core_mass") - merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14", mass_weight1="co_core_mass") - merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16", mass_weight1="co_core_mass") + + #TODO : maybe he_core_mass makes more sense? + mass_weight1='co_core_mass' + mass_weight2='co_core_mass' + + for abundance_name in parameters_to_mix: + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1=mass_weight1, mass_weight2=mass_weight2)) + setattr(merged_star, "center_gamma", np.nan) + else: - Pwarn("weird compbination of CO core masses during merging", "EvolutionWarning") + Pwarn("Unexpected combination of CO core masses during merging", "EvolutionWarning") - # weigheted mixing on the surface abundances based on the envelopes of the two stars - merged_star.surface_h1 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_h1", mass_weight1="H-rich_envelope_mass", mass_weight2="H-rich_envelope_mass") - merged_star.surface_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_he4", mass_weight1="H-rich_envelope_mass", mass_weight2="H-rich_envelope_mass") - merged_star.surface_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_c12", mass_weight1="H-rich_envelope_mass", mass_weight2="H-rich_envelope_mass") - merged_star.surface_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_n14", mass_weight1="H-rich_envelope_mass", mass_weight2="H-rich_envelope_mass") - merged_star.surface_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_o16", mass_weight1="H-rich_envelope_mass", mass_weight2="H-rich_envelope_mass") + additional_parameter_to_mix = ['surface_h1', 'surface_he4', 'surface_c12', 'surface_n14', 'surface_o16'] - # add total and core masses after calculations of weighter average + # Weighted mixing on the surface abundances based on the envelopes of the two stars + for abundance_name in additional_parameter_to_mix: + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="H-rich_envelope_mass", mass_weight2="H-rich_envelope_mass")) + + # Add total and core masses after calculations of weighted average for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: current = getattr(star_base, key) + getattr(comp, key) setattr(merged_star, key,current) - for key in STARPROPERTIES: - # these stellar attributes become np.nan - for substring in ["log_", "lg_", "surf_", "conv_", "lambda", "profile"]: - if (substring in key) : - setattr(merged_star, key, np.nan) - if key in [ "c12_c12", "total_moment_of_inertia", "spin"]: - setattr(merged_star, key, np.nan) - merged_star.state = check_state_of_star(merged_star, star_CO=False) # TODO for sure this needs testing! + # Set parameters that are not expected to be meaningful after a merger to np.nan + self._apply_nan_attributes(merged_star) + + # TODO for sure this needs testing! + merged_star.state = check_state_of_star(merged_star, star_CO=False) massless_remnant = convert_star_to_massless_remnant(comp) - #postMS + HeMSStar + # postMS + HeMS elif (s1 in LIST_ACCEPTABLE_STATES_FOR_POSTMS and s2 in LIST_ACCEPTABLE_STATES_FOR_HeMS): + # Keep surface abundances from star_base. + + parameters_to_mix = ["center_h1", "center_he4", "center_c12", "center_n14", "center_o16", "avg_c_in_c_core"] + + # Weighted central abundances if merging cores. + # two stars with only Helium cores, not CO cores + if star_base.co_core_mass == 0 and comp.co_core_mass == 0: + + for abundance_name in parameters_to_mix: + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="he_core_mass", mass_weight2="he_core_mass")) - # weighted central abundances if merging cores. Else only from star_base - if star_base.co_core_mass == 0 and comp.co_core_mass == 0: # two stars with only Helium cores, not CO cores - merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1", mass_weight1="he_core_mass") - merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4", mass_weight1="he_core_mass") - merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12", mass_weight1="he_core_mass") - merged_star.avg_c_in_c_core = self.mass_weighted_avg(star_base, comp, abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") - merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14", mass_weight1="he_core_mass") - merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16", mass_weight1="he_core_mass") setattr(merged_star, "center_gamma", np.nan) - elif (star_base.co_core_mass > 0 and comp.co_core_mass == 0): # star_base with CO core and the comp has just a He core (is a HeMS star) - pass # the central abundances are kept as the ones of star_base + + # star_base with CO core and the comp has just a He core (is a HeMS star) + # Keep central abundances as those from star_base. + elif (star_base.co_core_mass > 0 and comp.co_core_mass == 0): + pass + else: - Pwarn("weird compbination of CO core masses during merging", "EvolutionWarning") - # surface abundances from star_base + Pwarn("Unexpected combination of CO core masses during merging", "EvolutionWarning") # add total and core masses after abundance mass weighted calculations for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: current = getattr(star_base, key) + getattr(comp, key) setattr(merged_star, key,current) - for key in STARPROPERTIES: - # these stellar attributes become np.nan - for substring in ["log_", "lg_", "surf_", "conv_", "lambda", "profile"]: - if (substring in key) : - setattr(merged_star, key, np.nan) - if key in [ "c12_c12", "total_moment_of_inertia", "spin"]: - setattr(merged_star, key, np.nan) - merged_star.state = check_state_of_star(merged_star, star_CO=False) # TODO for sure this needs testing! + # Set parameters that are not expected to be meaningful after a merger to np.nan + self._apply_nan_attributes(merged_star) + + # TODO for sure this needs testing! + merged_star.state = check_state_of_star(merged_star, star_CO=False) massless_remnant = convert_star_to_massless_remnant(comp) - # as above but opposite stars + # HeMS + postMS (the opposite of above) elif (s1 in LIST_ACCEPTABLE_STATES_FOR_HeMS and s2 in LIST_ACCEPTABLE_STATES_FOR_POSTMS): - + # surface abundances from comp merged_star = comp + parameters_to_mix = ["center_h1", "center_he4", "center_c12", "center_n14", "center_o16", "avg_c_in_c_core"] - # weighted central abundances if merging cores. Else only from comp + # Weighted central abundances if merging cores. Else only from comp if star_base.co_core_mass == 0 and comp.co_core_mass == 0: # two stars with only Helium cores, not CO cores - merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1", mass_weight1="he_core_mass") - merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4", mass_weight1="he_core_mass") - merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12", mass_weight1="he_core_mass") - merged_star.avg_c_in_c_core = self.mass_weighted_avg(star_base, comp, abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") - merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14", mass_weight1="he_core_mass") - merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16", mass_weight1="he_core_mass") + + for abundance_name in parameters_to_mix: + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="he_core_mass", mass_weight2="he_core_mass")) + setattr(merged_star, "center_gamma", np.nan) - elif (star_base.co_core_mass == 0 and comp.co_core_mass > 0): # star_base is the HeMS Star and comp has a CO core - pass # the central abundances are kept as the ones of comp + + # star_base is the HeMS Star and comp has a CO core + # the central abundances are kept from comp + elif (star_base.co_core_mass == 0 and comp.co_core_mass > 0): + pass else: - Pwarn("weird compbination of CO core masses during merging", "EvolutionWarning") - # surface abundances from comp + Pwarn("Unexpected combination of CO core masses during merging", "EvolutionWarning") # add total and core masses after weighted averages above for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: current = getattr(star_base, key) + getattr(comp, key) setattr(merged_star, key,current) - for key in STARPROPERTIES: - # these stellar attributes become np.nan - for substring in ["log_", "lg_", "surf_", "conv_", "lambda", "profile"]: - if (substring in key) : - setattr(merged_star, key, np.nan) - if key in [ "c12_c12", "total_moment_of_inertia", "spin"]: - setattr(merged_star, key, np.nan) + # Set parameters that are not expected to be meaningful after a merger to np.nan + self._apply_nan_attributes(merged_star) - merged_star.state = check_state_of_star(merged_star, star_CO=False) # TODO for sure this needs testing! + # TODO for sure this needs testing! + merged_star.state = check_state_of_star(merged_star, star_CO=False) massless_remnant = convert_star_to_massless_remnant(star_base) - #postMS + HeStar that is not in HeMS + #postMS + PostHeMS elif (s1 in LIST_ACCEPTABLE_STATES_FOR_POSTMS and s2 in LIST_ACCEPTABLE_STATES_FOR_POSTHeMS): - # weighted central abundances if merging cores. Else only from star_base - if star_base.co_core_mass == 0 and comp.co_core_mass == 0: # two stars with Helium cores - merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1", mass_weight1="he_core_mass") - merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4", mass_weight1="he_core_mass") - merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12", mass_weight1="he_core_mass") - merged_star.avg_c_in_c_core = self.mass_weighted_avg(star_base, comp, abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") - merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14", mass_weight1="he_core_mass") - merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16", mass_weight1="he_core_mass") + parameters_to_mix = ["center_h1", "center_he4", "center_c12", "center_n14", "center_o16", "avg_c_in_c_core"] + + # Weighted central abundances if merging cores + # Two stars with Helium cores + if star_base.co_core_mass == 0 and comp.co_core_mass == 0: + + for abundance_name in parameters_to_mix: + setattr(merged_star, abundance_name, + self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="he_core_mass")) + setattr(merged_star, "center_gamma", np.nan) - elif (star_base.co_core_mass > 0 and comp.co_core_mass == 0): # star_base with CO core and the comp has a He core - pass # the central abundances are kept as the ones of star_base - elif (comp.co_core_mass > 0 and star_base.co_core_mass == 0): # comp with CO core and the star_base has a He core - merged_star.center_h1 = comp.center_h1 - merged_star.center_he4 = comp.center_he4 - merged_star.center_c12 = comp.center_c12 - merged_star.avg_c_in_c_core = comp.avg_c_in_c_core - merged_star.center_n14 = comp.center_n14 - merged_star.center_o16 = comp.center_o16 - merged_star.center_gamma = comp.center_gamma + + # Star_base with CO core and the comp has a He core + # the central abundances are kept as the ones of star_base + elif (star_base.co_core_mass > 0 and comp.co_core_mass == 0): + pass + + # comp with CO core and the star_base has a He core + elif (comp.co_core_mass > 0 and star_base.co_core_mass == 0): + + for abundance_name in parameters_to_mix: + setattr(merged_star, abundance_name, getattr(comp, abundance_name)) + + setattr(merged_star, "center_gamma", comp.center_gamma) + + # both stars have CO cores elif (star_base.co_core_mass > 0 and comp.co_core_mass > 0): - merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1", mass_weight1="co_core_mass") - merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4", mass_weight1="co_core_mass") - merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12", mass_weight1="co_core_mass") - merged_star.avg_c_in_c_core = self.mass_weighted_avg(star_base, comp, abundance_name = "avg_c_in_c_core", mass_weight1="co_core_mass") - merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14", mass_weight1="co_core_mass") - merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16", mass_weight1="co_core_mass") + + for abundance_name in parameters_to_mix: + setattr(merged_star, abundance_name, + self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="co_core_mass")) + setattr(merged_star, "center_gamma", np.nan) + else: - Pwarn("weird compbination of CO core masses during merging", "EvolutionWarning") + Pwarn("Unexpected combination of CO core masses during merging", "EvolutionWarning") # add total and core masses for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: current = getattr(star_base, key) + getattr(comp, key) setattr(merged_star, key,current) - for key in STARPROPERTIES: - # these stellar attributes become np.nan - for substring in ["log_", "lg_", "surf_", "conv_", "lambda", "profile"]: - if (substring in key) : - setattr(merged_star, key, np.nan) - if key in [ "c12_c12", "total_moment_of_inertia", "spin"]: - setattr(merged_star, key, np.nan) - merged_star.state = check_state_of_star(merged_star, star_CO=False) # TODO for sure this needs testing! + # Set parameters that are not expected to be meaningful after a merger to np.nan + self._apply_nan_attributes(merged_star) + + # TODO for sure this needs testing! + merged_star.state = check_state_of_star(merged_star, star_CO=False) massless_remnant = convert_star_to_massless_remnant(comp) - # as above but the opposite stars + # PostHeMS + postMS (the opposite of above) elif (s1 in LIST_ACCEPTABLE_STATES_FOR_POSTHeMS and s2 in LIST_ACCEPTABLE_STATES_FOR_POSTMS): merged_star = comp - # weighted central abundances if merging cores. Else only from star_base - if star_base.co_core_mass == 0 and comp.co_core_mass == 0: # two stars with Helium cores - merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1", mass_weight1="he_core_mass") - merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4", mass_weight1="he_core_mass") - merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12", mass_weight1="he_core_mass") - merged_star.avg_c_in_c_core = self.mass_weighted_avg(star_base, comp, abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") - merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14", mass_weight1="he_core_mass") - merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16", mass_weight1="he_core_mass") + parameters_to_mix = ["center_h1", "center_he4", "center_c12", "center_n14", "center_o16", "avg_c_in_c_core"] + + # weighted central abundances if merging cores + # two stars with Helium cores + if star_base.co_core_mass == 0 and comp.co_core_mass == 0: + + for abundance_name in parameters_to_mix: + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="he_core_mass", mass_weight2="he_core_mass")) + setattr(merged_star, "center_gamma", np.nan) - elif (star_base.co_core_mass > 0 and comp.co_core_mass == 0): # star_base with CO core and the comp has a He core - merged_star.center_h1 = star_base.center_h1 - merged_star.center_he4 = star_base.center_he4 - merged_star.center_c12 = star_base.center_c12 - merged_star.center_n14 = star_base.center_n14 - merged_star.center_o16 = star_base.center_o16 - elif (comp.co_core_mass > 0 and star_base.co_core_mass == 0): # comp with CO core and the star_base has a He core - pass # the central abundances are kept as the ones of comp + + # star_base with CO core and the comp has a He core + elif (star_base.co_core_mass > 0 and comp.co_core_mass == 0): + + for abundance_name in parameters_to_mix: + setattr(merged_star, abundance_name, getattr(star_base, abundance_name)) + + setattr(merged_star, "center_gamma", star_base.center_gamma) + + # comp with CO core and the star_base has a He core + # the central abundances are kept as the ones of comp + elif (comp.co_core_mass > 0 and star_base.co_core_mass == 0): + pass + + # both stars have CO cores elif (star_base.co_core_mass > 0 and comp.co_core_mass > 0): - merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1", mass_weight1="co_core_mass") - merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4", mass_weight1="co_core_mass") - merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12", mass_weight1="co_core_mass") - merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14", mass_weight1="co_core_mass") - merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16", mass_weight1="co_core_mass") + + for abundance_name in parameters_to_mix: + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="co_core_mass", mass_weight2="co_core_mass")) + + setattr(merged_star, "center_gamma", np.nan) + else: - Pwarn("weird compbination of CO core masses during merging", "EvolutionWarning") + Pwarn("Unexpected combination of CO core masses during merging", "EvolutionWarning") # add total and core masses for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: current = getattr(star_base, key) + getattr(comp, key) setattr(merged_star, key,current) - for key in STARPROPERTIES: - # these stellar attributes become np.nan - for substring in ["log_", "lg_", "surf_", "conv_", "lambda", "profile"]: - if (substring in key) : - setattr(merged_star, key, np.nan) - if key in [ "c12_c12", "total_moment_of_inertia", "spin"]: - setattr(merged_star, key, np.nan) - merged_star.state = check_state_of_star(merged_star, star_CO=False) # TODO for sure this needs testing! + # Set parameters that are not expected to be meaningful after a merger to np.nan + self._apply_nan_attributes(merged_star) + + # TODO for sure this needs testing! + merged_star.state = check_state_of_star(merged_star, star_CO=False) massless_remnant = convert_star_to_massless_remnant(star_base) # HeStar + HeStar elif (s1 in STAR_STATES_HE_RICH and s2 in STAR_STATES_HE_RICH): + parameters_to_mix = ["center_h1", "center_he4", "center_c12", "center_n14", "center_o16", "avg_c_in_c_core"] # weighted central abundances if merging cores. Else only from star_base - if star_base.co_core_mass == 0 and comp.co_core_mass == 0: # two stars with Helium cores - merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1", mass_weight1="he_core_mass") - merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4", mass_weight1="he_core_mass") - merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12", mass_weight1="he_core_mass") - merged_star.avg_c_in_c_core = self.mass_weighted_avg(star_base, comp, abundance_name = "avg_c_in_c_core", mass_weight1="he_core_mass") - merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14", mass_weight1="he_core_mass") - merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16", mass_weight1="he_core_mass") + # two stars with Helium cores + if star_base.co_core_mass == 0 and comp.co_core_mass == 0: + + for abundance_name in parameters_to_mix: + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="he_core_mass", mass_weight2="he_core_mass")) + setattr(merged_star, "center_gamma", np.nan) - elif (star_base.co_core_mass > 0 and comp.co_core_mass == 0): # star_base with CO core and the comp has a He core - pass # the central abundances are kept as the ones of star_base - elif (comp.co_core_mass > 0 and star_base.co_core_mass == 0): # comp with CO core and the star_base has a He core - merged_star.center_h1 = comp.center_h1 - merged_star.center_he4 = comp.center_he4 - merged_star.center_c12 = comp.center_c12 - merged_star.avg_c_in_c_core = comp.avg_c_in_c_core - merged_star.center_n14 = comp.center_n14 - merged_star.center_o16 = comp.center_o16 - merged_star.center_gamma = comp.center_gamma + + # star_base with CO core and the comp has a He core + # the central abundances are kept as the ones of star_base + elif (star_base.co_core_mass > 0 and comp.co_core_mass == 0): + pass + + # comp with CO core and the star_base has a He core + elif (comp.co_core_mass > 0 and star_base.co_core_mass == 0): + + for abundance_name in parameters_to_mix: + setattr(merged_star, abundance_name, getattr(comp, abundance_name)) + + setattr(merged_star, "center_gamma", comp.center_gamma) + + # both stars have CO cores elif (star_base.co_core_mass > 0 and comp.co_core_mass > 0): - merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1", mass_weight1="co_core_mass") - merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4", mass_weight1="co_core_mass") - merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12", mass_weight1="co_core_mass") - merged_star.avg_c_in_c_core = self.mass_weighted_avg(star_base, comp, abundance_name = "avg_c_in_c_core", mass_weight1="co_core_mass") - merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14", mass_weight1="co_core_mass") - merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16", mass_weight1="co_core_mass") + + for abundance_name in parameters_to_mix: + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="co_core_mass", mass_weight2="co_core_mass")) + setattr(merged_star, "center_gamma", np.nan) + else: - Pwarn("weird compbination of CO core masses during merging", "EvolutionWarning") + Pwarn("Unexpected combination of CO core masses during merging", "EvolutionWarning") # add total and core masses for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: @@ -563,46 +595,43 @@ def merged_star_properties(self, star_base, comp): setattr(merged_star, key,current) # weigheted mixing on the surface abundances based on the He-rich envelopes of the two stars - merged_star.surface_h1 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_h1", mass_weight1="He-rich_envelope_mass", mass_weight2="He-rich_envelope_mass") - merged_star.surface_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_he4", mass_weight1="He-rich_envelope_mass", mass_weight2="He-rich_envelope_mass") - merged_star.surface_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_c12", mass_weight1="He-rich_envelope_mass", mass_weight2="He-rich_envelope_mass") - merged_star.surface_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_n14", mass_weight1="He-rich_envelope_mass", mass_weight2="He-rich_envelope_mass") - merged_star.surface_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "surface_o16", mass_weight1="He-rich_envelope_mass", mass_weight2="He-rich_envelope_mass") - - for key in STARPROPERTIES: - # these stellar attributes become np.nan - for substring in ["log_", "lg_", "surf_", "conv_", "lambda", "profile"]: - if (substring in key) : - setattr(merged_star, key, np.nan) - if key in [ "c12_c12", "total_moment_of_inertia", "spin"]: - setattr(merged_star, key, np.nan) - merged_star.state = check_state_of_star(merged_star, star_CO=False) # TODO for sure this needs testing! + additional_parameter_to_mix = ['surface_h1', 'surface_he4', 'surface_c12', 'surface_n14', 'surface_o16'] + for abundance_name in additional_parameter_to_mix: + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="He-rich_envelope_mass", mass_weight2="He-rich_envelope_mass")) + + # Set parameters that are not expected to be meaningful after a merger to np.nan + self._apply_nan_attributes(merged_star) + + # TODO for sure this needs testing! + merged_star.state = check_state_of_star(merged_star, star_CO=False) massless_remnant = convert_star_to_massless_remnant(comp) # Star + WD elif (s1 in STAR_STATES_NOT_CO and s2 in ["WD"]): + parameters_to_mix = ["center_h1", "center_he4", "center_c12", "center_n14", "center_o16", "avg_c_in_c_core"] # WD is considered a stripped CO core # WD would always be the comp, it cannot be the engulfing star (so no need to do the opposite stars case below) # weighted central abundances if merging cores. Else only from star_base - if (comp.co_core_mass is not None and star_base.co_core_mass == 0): # comp with CO core and the star_base has not - merged_star.center_h1 = comp.center_h1 - merged_star.center_he4 = comp.center_he4 - merged_star.center_c12 = comp.center_c12 - merged_star.avg_c_in_c_core = comp.avg_c_in_c_core - merged_star.center_n14 = comp.center_n14 - merged_star.center_o16 = comp.center_o16 - merged_star.center_gamma = comp.center_gamma + # comp with CO core and the star_base has not + if (comp.co_core_mass is not None and star_base.co_core_mass == 0): + + for abundance_name in parameters_to_mix: + setattr(merged_star, abundance_name, getattr(comp, abundance_name)) + + setattr(merged_star, "center_gamma", comp.center_gamma) + + + # Star_base with CO core and the comp is a WD (so has a CO core) elif (comp.co_core_mass is not None and star_base.co_core_mass > 0): - merged_star.center_h1 = self.mass_weighted_avg(star_base, comp, abundance_name="center_h1", mass_weight1="co_core_mass") - merged_star.center_he4 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_he4", mass_weight1="co_core_mass") - merged_star.center_c12 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_c12", mass_weight1="co_core_mass") - merged_star.avg_c_in_c_core = self.mass_weighted_avg(star_base, comp, abundance_name = "avg_c_in_c_core", mass_weight1="co_core_mass") - merged_star.center_n14 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_n14", mass_weight1="co_core_mass") - merged_star.center_o16 = self.mass_weighted_avg(star_base, comp, abundance_name = "center_o16", mass_weight1="co_core_mass") + + for abundance_name in parameters_to_mix: + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="co_core_mass", mass_weight2="co_core_mass")) + setattr(merged_star, "center_gamma", np.nan) + else: Pwarn("Unexpected combination of CO core masses during merging", "EvolutionWarning") @@ -611,13 +640,9 @@ def merged_star_properties(self, star_base, comp): current = getattr(star_base, key) + getattr(comp, "mass") setattr(merged_star, key,current) - for key in STARPROPERTIES: - # these stellar attributes become np.nan - for substring in ["log_", "lg_", "surf_", "conv_", "lambda", "profile"]: - if (substring in key) : - setattr(merged_star, key, np.nan) - if key in [ "c12_c12", "total_moment_of_inertia", "spin"]: - setattr(merged_star, key, np.nan) + # Set parameters that are not expected to be meaningful after a merger to np.nan + self._apply_nan_attributes(merged_star) + merged_star.state = check_state_of_star(merged_star, star_CO=False) # TODO for sure this needs testing! massless_remnant = convert_star_to_massless_remnant(comp) From 47edaa456347203d7d9dd5c7c20e0c879fff3b7b Mon Sep 17 00:00:00 2001 From: Max Briel Date: Mon, 2 Mar 2026 20:02:17 +0100 Subject: [PATCH 18/32] cleanup comments --- posydon/binary_evol/DT/step_merged.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index 92e405247d..0ffaba1828 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -445,7 +445,7 @@ def merged_star_properties(self, star_base, comp): merged_star.state = check_state_of_star(merged_star, star_CO=False) massless_remnant = convert_star_to_massless_remnant(star_base) - #postMS + PostHeMS + # postMS + postHeMS elif (s1 in LIST_ACCEPTABLE_STATES_FOR_POSTMS and s2 in LIST_ACCEPTABLE_STATES_FOR_POSTHeMS): @@ -498,7 +498,7 @@ def merged_star_properties(self, star_base, comp): merged_star.state = check_state_of_star(merged_star, star_CO=False) massless_remnant = convert_star_to_massless_remnant(comp) - # PostHeMS + postMS (the opposite of above) + # postHeMS + postMS (the opposite of above) elif (s1 in LIST_ACCEPTABLE_STATES_FOR_POSTHeMS and s2 in LIST_ACCEPTABLE_STATES_FOR_POSTMS): @@ -551,7 +551,7 @@ def merged_star_properties(self, star_base, comp): merged_star.state = check_state_of_star(merged_star, star_CO=False) massless_remnant = convert_star_to_massless_remnant(star_base) - # HeStar + HeStar + # He star + He star elif (s1 in STAR_STATES_HE_RICH and s2 in STAR_STATES_HE_RICH): From fdb8344c935d9bb4f59006bfb2d151aa47612786 Mon Sep 17 00:00:00 2001 From: Max Briel Date: Fri, 13 Mar 2026 17:20:42 +0100 Subject: [PATCH 19/32] add explicity mass_weight2 to all calls --- posydon/binary_evol/DT/step_merged.py | 96 ++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 18 deletions(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index 0ffaba1828..af9c2da740 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -250,7 +250,11 @@ def merged_star_properties(self, star_base, comp): for abundance_name in parameters_to_mix: #TODO: should I check if the abundaces above end up in ~1 (?) - setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="mass", mass_weight2='mass')) + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, + comp, + abundance_name=abundance_name, + mass_weight1="mass", + mass_weight2='mass')) # The change of masses occurs after the calculation of weighted averages merged_star.mass = (star_base.mass + comp.mass) * (1.-self.rel_mass_lost_HMS_HMS) @@ -272,7 +276,11 @@ def merged_star_properties(self, star_base, comp): # companion with the envelope of star_base parameters_to_mix = ["surface_h1", "surface_he4", "surface_c12", "surface_n14", "surface_o16"] for abundance_name in parameters_to_mix: - setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="H-rich_envelope_mass", mass_weight2="mass")) + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, + comp, + abundance_name=abundance_name, + mass_weight1="H-rich_envelope_mass", + mass_weight2="mass")) # The change of masses occurs after the calculation of weighted averages # Note that the he core mass is unchanged, which means that @@ -297,7 +305,11 @@ def merged_star_properties(self, star_base, comp): parameters_to_mix = ["surface_h1", "surface_he4", "surface_c12", "surface_n14", "surface_o16"] for abundance_name in parameters_to_mix: - setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight2="H-rich_envelope_mass", mass_weight1="mass")) + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, + comp, + abundance_name=abundance_name, + mass_weight1="mass", + mass_weight2="H-rich_envelope_mass",)) # The change of masses occurs after the calculation of weighted averages merged_star.mass = star_base.mass + comp.mass @@ -326,7 +338,11 @@ def merged_star_properties(self, star_base, comp): mass_weight2 = 'he_core_mass' for abundance_name in parameters_to_mix: - setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1=mass_weight1, mass_weight2=mass_weight2)) + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, + comp, + abundance_name = abundance_name, + mass_weight1 = mass_weight1, + mass_weight2 = mass_weight2)) setattr(merged_star, "center_gamma", np.nan) @@ -350,7 +366,11 @@ def merged_star_properties(self, star_base, comp): mass_weight2='co_core_mass' for abundance_name in parameters_to_mix: - setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1=mass_weight1, mass_weight2=mass_weight2)) + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, + comp, + abundance_name=abundance_name, + mass_weight1=mass_weight1, + mass_weight2=mass_weight2)) setattr(merged_star, "center_gamma", np.nan) @@ -361,7 +381,11 @@ def merged_star_properties(self, star_base, comp): # Weighted mixing on the surface abundances based on the envelopes of the two stars for abundance_name in additional_parameter_to_mix: - setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="H-rich_envelope_mass", mass_weight2="H-rich_envelope_mass")) + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, + comp, + abundance_name=abundance_name, + mass_weight1="H-rich_envelope_mass", + mass_weight2="H-rich_envelope_mass")) # Add total and core masses after calculations of weighted average for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: @@ -387,7 +411,11 @@ def merged_star_properties(self, star_base, comp): if star_base.co_core_mass == 0 and comp.co_core_mass == 0: for abundance_name in parameters_to_mix: - setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="he_core_mass", mass_weight2="he_core_mass")) + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, + comp, + abundance_name=abundance_name, + mass_weight1="he_core_mass", + mass_weight2="he_core_mass")) setattr(merged_star, "center_gamma", np.nan) @@ -402,7 +430,7 @@ def merged_star_properties(self, star_base, comp): # add total and core masses after abundance mass weighted calculations for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: current = getattr(star_base, key) + getattr(comp, key) - setattr(merged_star, key,current) + setattr(merged_star, key, current) # Set parameters that are not expected to be meaningful after a merger to np.nan self._apply_nan_attributes(merged_star) @@ -422,7 +450,11 @@ def merged_star_properties(self, star_base, comp): if star_base.co_core_mass == 0 and comp.co_core_mass == 0: # two stars with only Helium cores, not CO cores for abundance_name in parameters_to_mix: - setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="he_core_mass", mass_weight2="he_core_mass")) + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, + comp, + abundance_name=abundance_name, + mass_weight1="he_core_mass", + mass_weight2="he_core_mass")) setattr(merged_star, "center_gamma", np.nan) @@ -436,7 +468,7 @@ def merged_star_properties(self, star_base, comp): # add total and core masses after weighted averages above for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: current = getattr(star_base, key) + getattr(comp, key) - setattr(merged_star, key,current) + setattr(merged_star, key, current) # Set parameters that are not expected to be meaningful after a merger to np.nan self._apply_nan_attributes(merged_star) @@ -457,7 +489,11 @@ def merged_star_properties(self, star_base, comp): for abundance_name in parameters_to_mix: setattr(merged_star, abundance_name, - self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="he_core_mass")) + self.mass_weighted_avg(star_base, + comp, + abundance_name=abundance_name, + mass_weight1="he_core_mass", + mass_weight2="he_core_mass")) setattr(merged_star, "center_gamma", np.nan) @@ -479,7 +515,11 @@ def merged_star_properties(self, star_base, comp): for abundance_name in parameters_to_mix: setattr(merged_star, abundance_name, - self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="co_core_mass")) + self.mass_weighted_avg(star_base, + comp, + abundance_name=abundance_name, + mass_weight1="co_core_mass", + mass_weight2="co_core_mass")) setattr(merged_star, "center_gamma", np.nan) @@ -489,7 +529,7 @@ def merged_star_properties(self, star_base, comp): # add total and core masses for key in ["mass", "he_core_mass", "c_core_mass", "o_core_mass", "co_core_mass"]: current = getattr(star_base, key) + getattr(comp, key) - setattr(merged_star, key,current) + setattr(merged_star, key, current) # Set parameters that are not expected to be meaningful after a merger to np.nan self._apply_nan_attributes(merged_star) @@ -511,7 +551,11 @@ def merged_star_properties(self, star_base, comp): if star_base.co_core_mass == 0 and comp.co_core_mass == 0: for abundance_name in parameters_to_mix: - setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="he_core_mass", mass_weight2="he_core_mass")) + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, + comp, + abundance_name=abundance_name, + mass_weight1="he_core_mass", + mass_weight2="he_core_mass")) setattr(merged_star, "center_gamma", np.nan) @@ -561,7 +605,11 @@ def merged_star_properties(self, star_base, comp): if star_base.co_core_mass == 0 and comp.co_core_mass == 0: for abundance_name in parameters_to_mix: - setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="he_core_mass", mass_weight2="he_core_mass")) + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, + comp, + abundance_name=abundance_name, + mass_weight1="he_core_mass", + mass_weight2="he_core_mass")) setattr(merged_star, "center_gamma", np.nan) @@ -582,7 +630,11 @@ def merged_star_properties(self, star_base, comp): elif (star_base.co_core_mass > 0 and comp.co_core_mass > 0): for abundance_name in parameters_to_mix: - setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="co_core_mass", mass_weight2="co_core_mass")) + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, + comp, + abundance_name=abundance_name, + mass_weight1="co_core_mass", + mass_weight2="co_core_mass")) setattr(merged_star, "center_gamma", np.nan) @@ -597,7 +649,11 @@ def merged_star_properties(self, star_base, comp): # weigheted mixing on the surface abundances based on the He-rich envelopes of the two stars additional_parameter_to_mix = ['surface_h1', 'surface_he4', 'surface_c12', 'surface_n14', 'surface_o16'] for abundance_name in additional_parameter_to_mix: - setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="He-rich_envelope_mass", mass_weight2="He-rich_envelope_mass")) + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, + comp, + abundance_name=abundance_name, + mass_weight1="He-rich_envelope_mass", + mass_weight2="He-rich_envelope_mass")) # Set parameters that are not expected to be meaningful after a merger to np.nan self._apply_nan_attributes(merged_star) @@ -628,7 +684,11 @@ def merged_star_properties(self, star_base, comp): elif (comp.co_core_mass is not None and star_base.co_core_mass > 0): for abundance_name in parameters_to_mix: - setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, comp, abundance_name=abundance_name, mass_weight1="co_core_mass", mass_weight2="co_core_mass")) + setattr(merged_star, abundance_name, self.mass_weighted_avg(star_base, + comp, + abundance_name=abundance_name, + mass_weight1="co_core_mass", + mass_weight2="co_core_mass")) setattr(merged_star, "center_gamma", np.nan) From 7f5db49c2436beeffbb8b8a482d4442a643b2080 Mon Sep 17 00:00:00 2001 From: Max Briel Date: Fri, 13 Mar 2026 17:22:04 +0100 Subject: [PATCH 20/32] move set outside of default call, since it's shared --- posydon/binary_evol/DT/step_merged.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index af9c2da740..837138a9ae 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -195,7 +195,7 @@ def mass_weighted_avg(self, star1, star2, abundance_name, mass_weight1="mass", m return mass_weighted_avg_value - def _apply_nan_attributes(self, star, extra_nan_keys=set()): + def _apply_nan_attributes(self, star, extra_nan_keys=None): """Set to np.nan the attributes of the star that are not expected to be meaningful after a merger event. Parameters set to np.nan are: @@ -211,6 +211,9 @@ def _apply_nan_attributes(self, star, extra_nan_keys=set()): extra_nan_keys: set of str Set of keys to be set to np.nan in addition to the default ones. """ + if extra_nan_keys is None: + extra_nan_keys = set() + _NAN_SUBSTRINGS = ("log_", "lg_", "surf_", "conv_", "lambda", "profile") _NAN_KEYS = set(["c12_c12", "total_moment_of_inertia", "spin"]) From 3c39ecbff58d3307aa9862c3bebe8f9a6bbcf16b Mon Sep 17 00:00:00 2001 From: Max Briel Date: Fri, 13 Mar 2026 17:35:16 +0100 Subject: [PATCH 21/32] add np.nan instead of None as default output --- posydon/binary_evol/DT/step_merged.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index 837138a9ae..ae6882af3d 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -159,8 +159,9 @@ def mass_weighted_avg(self, star1, star2, abundance_name, mass_weight1="mass", m mass_weight2 : str or None Mass attribute for star2. """ - A1 = getattr(star1, abundance_name) - A2 = getattr(star2, abundance_name) + # give NaN if the abundance is not defined for one of the stars + A1 = getattr(star1, abundance_name, np.nan) + A2 = getattr(star2, abundance_name, np.nan) if mass_weight1 == "mass": M1 = getattr(star1, "mass") From a6a5b4d93d100195b72fae8a94be7c82f68f19e7 Mon Sep 17 00:00:00 2001 From: Max Briel Date: Fri, 13 Mar 2026 19:41:21 +0100 Subject: [PATCH 22/32] add np.nan --- posydon/binary_evol/DT/step_merged.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index ae6882af3d..18742559de 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -164,22 +164,22 @@ def mass_weighted_avg(self, star1, star2, abundance_name, mass_weight1="mass", m A2 = getattr(star2, abundance_name, np.nan) if mass_weight1 == "mass": - M1 = getattr(star1, "mass") + M1 = getattr(star1, "mass", np.nan) elif mass_weight1 == "H-rich_envelope_mass": - M1 = getattr(star1, "mass") - getattr(star1, "he_core_mass") + M1 = getattr(star1, "mass", np.nan) - getattr(star1, "he_core_mass", np.nan) elif mass_weight1 == "He-rich_envelope_mass": - M1 = getattr(star1, "he_core_mass") - getattr(star1, "co_core_mass") + M1 = getattr(star1, "he_core_mass", np.nan) - getattr(star1, "co_core_mass", np.nan) else: - M1 = getattr(star1, mass_weight1) + M1 = getattr(star1, mass_weight1, np.nan) if mass_weight2 == "mass": - M2 = getattr(star2, "mass") + M2 = getattr(star2, "mass", np.nan) elif mass_weight2 == "H-rich_envelope_mass": - M2 = getattr(star2, "mass") - getattr(star2, "he_core_mass") + M2 = getattr(star2, "mass", np.nan) - getattr(star2, "he_core_mass", np.nan) elif mass_weight2 == "He-rich_envelope_mass": - M2 = getattr(star2, "he_core_mass") - getattr(star2, "co_core_mass") + M2 = getattr(star2, "he_core_mass", np.nan) - getattr(star2, "co_core_mass", np.nan) else: - M2 = getattr(star2, mass_weight2) + M2 = getattr(star2, mass_weight2, np.nan) den = M1 + M2 if not (np.isfinite(A1) and np.isfinite(A2) and np.isfinite(M1) and np.isfinite(M2)): From f4433c51430783e2d1c6ddcc3e0008e7bb469916 Mon Sep 17 00:00:00 2001 From: Max Briel Date: Fri, 13 Mar 2026 19:43:40 +0100 Subject: [PATCH 23/32] add additional checks for A1, A2, M1, and M2 --- posydon/binary_evol/DT/step_merged.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index 18742559de..0c09a63398 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -162,6 +162,10 @@ def mass_weighted_avg(self, star1, star2, abundance_name, mass_weight1="mass", m # give NaN if the abundance is not defined for one of the stars A1 = getattr(star1, abundance_name, np.nan) A2 = getattr(star2, abundance_name, np.nan) + if A1 is None: + A1 = np.nan + if A2 is None: + A2 = np.nan if mass_weight1 == "mass": M1 = getattr(star1, "mass", np.nan) @@ -172,6 +176,9 @@ def mass_weighted_avg(self, star1, star2, abundance_name, mass_weight1="mass", m else: M1 = getattr(star1, mass_weight1, np.nan) + if M1 is None: + M1 = np.nan + if mass_weight2 == "mass": M2 = getattr(star2, "mass", np.nan) elif mass_weight2 == "H-rich_envelope_mass": @@ -181,6 +188,9 @@ def mass_weighted_avg(self, star1, star2, abundance_name, mass_weight1="mass", m else: M2 = getattr(star2, mass_weight2, np.nan) + if M2 is None: + M2 = np.nan + den = M1 + M2 if not (np.isfinite(A1) and np.isfinite(A2) and np.isfinite(M1) and np.isfinite(M2)): mass_weighted_avg_value = np.nan From 4bfdd770b266278a34ce6c759dc2181410b5e07d Mon Sep 17 00:00:00 2001 From: Seth Gossage Date: Fri, 20 Mar 2026 11:15:27 -0500 Subject: [PATCH 24/32] Update posydon/binary_evol/DT/step_merged.py --- posydon/binary_evol/DT/step_merged.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index 0c09a63398..a74aefd4a8 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -133,10 +133,13 @@ def __call__(self,binary): print("star_1.center_h1, star_1.center_he4, star_1.center_c12, star_1.surface_he4: ", binary.star_1.center_h1, binary.star_1.center_he4, binary.star_1.center_c12, binary.star_1.surface_he4) elif binary.event=='oMerging2': - print("M_merged , he_core_mass merged, co_core_mass merged: ", binary.star_2.mass, - binary.star_2.he_core_mass, binary.star_2.co_core_mass) - print("star_2.center_h1, star_2.center_he4, star_2.center_c12, star_2.surface_he4: ", - binary.star_2.center_h1, binary.star_2.center_he4, binary.star_2.center_c12, binary.star_2.surface_he4) + print(f"M_merged = {binary.star_2.mass}\n" + f"he_core_mass merged = {binary.star_2.he_core_mass}\n" + f"co_core_mass merged = {binary.star_2.co_core_mass}\n") + print(f"star_2.center_h1 = {binary.star_2.center_h1}\n" + f"star_2.center_he4 = {binary.star_2.center_he4}\n" + f"star_2.center_c12 = {binary.star_2.center_c12}\n" + f"star_2.surface_he4 = {binary.star_2.surface_he4}\n") super().__call__(binary) From c1dfa1994eb5d7d0c793f183a873d18c5346773f Mon Sep 17 00:00:00 2001 From: Seth Gossage Date: Fri, 20 Mar 2026 11:15:42 -0500 Subject: [PATCH 25/32] Update posydon/binary_evol/DT/step_merged.py --- posydon/binary_evol/DT/step_merged.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index a74aefd4a8..dc6678ea05 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -128,10 +128,13 @@ def __call__(self,binary): print("After Merger", binary.star_1.state, binary.star_2.state, binary.state, binary.event) if binary.event == 'oMerging1': - print("M_merged , he_core_mass merged, co_core_mass merged: ", binary.star_1.mass, - binary.star_1.he_core_mass, binary.star_1.co_core_mass) - print("star_1.center_h1, star_1.center_he4, star_1.center_c12, star_1.surface_he4: ", - binary.star_1.center_h1, binary.star_1.center_he4, binary.star_1.center_c12, binary.star_1.surface_he4) + print(f"M_merged = {binary.star_1.mass}\n" + f"he_core_mass merged = {binary.star_1.he_core_mass}\n" + f"co_core_mass merged = {binary.star_1.co_core_mass}\n") + print(f"star_1.center_h1 = {binary.star_1.center_h1}\n" + f"star_1.center_he4 = {binary.star_1.center_he4}\n" + f"star_1.center_c12 = {binary.star_1.center_c12}\n" + f"star_1.surface_he4 = {binary.star_1.surface_he4}\n") elif binary.event=='oMerging2': print(f"M_merged = {binary.star_2.mass}\n" f"he_core_mass merged = {binary.star_2.he_core_mass}\n" From 5530ed75f7f1317d167f8c3663e3b961e06b55da Mon Sep 17 00:00:00 2001 From: Seth Gossage Date: Fri, 20 Mar 2026 11:16:02 -0500 Subject: [PATCH 26/32] Update posydon/binary_evol/DT/step_merged.py --- posydon/binary_evol/DT/step_merged.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index dc6678ea05..6acfa05347 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -125,8 +125,12 @@ def __call__(self,binary): binary.event = None if self.verbose: - print("After Merger", binary.star_1.state, binary.star_2.state, - binary.state, binary.event) + print("After Merger:\n" + f"_____________\n" + f"star_1.state = {binary.star_1.state}\n" + f"star_2.state = {binary.star_2.state}\n" + f"binary.state = {binary.state}\n" + f"binary.event = {binary.event}\n") if binary.event == 'oMerging1': print(f"M_merged = {binary.star_1.mass}\n" f"he_core_mass merged = {binary.star_1.he_core_mass}\n" From 10af496a74483da3a14655b44ab2b5167f634ef6 Mon Sep 17 00:00:00 2001 From: Seth Gossage Date: Fri, 20 Mar 2026 11:16:18 -0500 Subject: [PATCH 27/32] Update posydon/binary_evol/DT/step_merged.py --- posydon/binary_evol/DT/step_merged.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index 6acfa05347..8521eb240f 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -96,11 +96,15 @@ def __call__(self,binary): print("M1 , M2, he_core_mass1, he_core_mass2, co_core_mass1, co_core_mass2: ", binary.star_1.mass, binary.star_2.mass, binary.star_1.he_core_mass, binary.star_2.he_core_mass, binary.star_1.co_core_mass, binary.star_2.co_core_mass) - print("star_1.center_h1, star_2.center_h1, star_1.center_he4, star_1.center_c12, star_2.center_c12, " - "star_2.center_he4, star_1.surface_he4, star_2.surface_he4: ", - binary.star_1.center_h1, binary.star_2.center_h1, binary.star_1.center_he4, - binary.star_2.center_he4, binary.star_1.center_c12, binary.star_2.center_c12, binary.star_1.surface_he4, - binary.star_2.surface_he4) + print(f"star_1.center_h1 = {binary.star_1.center_h1}\n" + f"star_2.center_h1 = {binary.star_2.center_h1}\n" + f"star_1.center_he4 = {binary.star_1.center_he4}\n" + f"star_2.center_he4 = {binary.star_2.center_he4}\n" + f"star_1.center_c12 = {binary.star_1.center_c12}\n" + f"star_2.center_c12 = {binary.star_2.center_c12}\n" + f"star_1.surface_he4 = {binary.star_1.surface_he4}\n" + f"star_2.surface_he4 = {binary.star_2.surface_he4}\n" + f"_____________\n") if binary.state == "merged": if binary.event == 'oMerging1': From 6f265ce3d263785df8f9146dd365468cbdbe47d5 Mon Sep 17 00:00:00 2001 From: Seth Gossage Date: Fri, 20 Mar 2026 11:16:29 -0500 Subject: [PATCH 28/32] Update posydon/binary_evol/DT/step_merged.py --- posydon/binary_evol/DT/step_merged.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index 8521eb240f..3ae190ee95 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -91,8 +91,12 @@ def __call__(self,binary): merged_star_properties = self.merged_star_properties if self.verbose: - print("Before Merger", binary.star_1.state, binary.star_2.state, - binary.state, binary.event) + print("Before Merger:\n" + f"_____________\n" + f"star_1.state = {binary.star_1.state}\n" + f"star_2.state = {binary.star_2.state}\n" + f"binary.state = {binary.state}\n" + f"binary.event = {binary.event}\n") print("M1 , M2, he_core_mass1, he_core_mass2, co_core_mass1, co_core_mass2: ", binary.star_1.mass, binary.star_2.mass, binary.star_1.he_core_mass, binary.star_2.he_core_mass, binary.star_1.co_core_mass, binary.star_2.co_core_mass) From 9b3aa9fd6c4328217dbe982fab808f26f0e251d4 Mon Sep 17 00:00:00 2001 From: Seth Gossage Date: Fri, 20 Mar 2026 11:16:54 -0500 Subject: [PATCH 29/32] Update posydon/binary_evol/DT/step_merged.py --- posydon/binary_evol/DT/step_merged.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index 3ae190ee95..adc4a6af90 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -93,13 +93,12 @@ def __call__(self,binary): if self.verbose: print("Before Merger:\n" f"_____________\n" - f"star_1.state = {binary.star_1.state}\n" - f"star_2.state = {binary.star_2.state}\n" - f"binary.state = {binary.state}\n" - f"binary.event = {binary.event}\n") - print("M1 , M2, he_core_mass1, he_core_mass2, co_core_mass1, co_core_mass2: ", - binary.star_1.mass, binary.star_2.mass, - binary.star_1.he_core_mass, binary.star_2.he_core_mass, binary.star_1.co_core_mass, binary.star_2.co_core_mass) + print(f"M1 = {binary.star_1.mass}\n" + f"M2 = {binary.star_2.mass}\n" + f"he_core_mass1 = {binary.star_1.he_core_mass}\n" + f"he_core_mass2 = {binary.star_2.he_core_mass}\n" + f"co_core_mass1 = {binary.star_1.co_core_mass}\n" + f"co_core_mass2 = {binary.star_2.co_core_mass}\n") print(f"star_1.center_h1 = {binary.star_1.center_h1}\n" f"star_2.center_h1 = {binary.star_2.center_h1}\n" f"star_1.center_he4 = {binary.star_1.center_he4}\n" From c0976d8871db9499683eae1935456671ffebb4eb Mon Sep 17 00:00:00 2001 From: Seth Gossage Date: Fri, 20 Mar 2026 11:17:10 -0500 Subject: [PATCH 30/32] Update posydon/binary_evol/DT/step_merged.py --- posydon/binary_evol/DT/step_merged.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index adc4a6af90..62e5c7eba3 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -217,9 +217,14 @@ def mass_weighted_avg(self, star1, star2, abundance_name, mass_weight1="mass", m mass_weighted_avg_value = (A1 * M1 + A2 * M2) / den if self.verbose: - print(abundance_name, mass_weight1, mass_weight2) - print("A_base, M_base_abundance, A_comp, M_comp_abundance", A1, M1, A2, M2) - print("mass_weighted_avg= ", mass_weighted_avg_value) + print(f"Mass weighted average for {abundance_name}:\n" + f"weight 1: {mass_weight1}\n" + f"weight 2: {mass_weight2}\n" + f"A_base = {A1}\n" + f"M_base_abundance = {M1}\n" + f"A_comp = {A2}\n" + f"M_comp_abundance = {M2}\n" + f"mass_weighted_avg = {mass_weighted_avg_value}\n") return mass_weighted_avg_value From f013d561ff220ba761b9bfe9b07e7df7bb1bf4be Mon Sep 17 00:00:00 2001 From: Seth Gossage Date: Fri, 20 Mar 2026 11:30:27 -0500 Subject: [PATCH 31/32] close parentheses --- posydon/binary_evol/DT/step_merged.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index 62e5c7eba3..f426f31cfb 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -92,7 +92,7 @@ def __call__(self,binary): if self.verbose: print("Before Merger:\n" - f"_____________\n" + f"_____________\n") print(f"M1 = {binary.star_1.mass}\n" f"M2 = {binary.star_2.mass}\n" f"he_core_mass1 = {binary.star_1.he_core_mass}\n" From d019ef48df930ff7d9087754268a004fd25e58ce Mon Sep 17 00:00:00 2001 From: Seth Gossage Date: Fri, 20 Mar 2026 23:47:15 -0500 Subject: [PATCH 32/32] commenting out binary.event = None --- posydon/binary_evol/DT/step_merged.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/posydon/binary_evol/DT/step_merged.py b/posydon/binary_evol/DT/step_merged.py index f426f31cfb..d3c32bee3a 100644 --- a/posydon/binary_evol/DT/step_merged.py +++ b/posydon/binary_evol/DT/step_merged.py @@ -129,7 +129,7 @@ def __call__(self,binary): else: raise ValueError("step_merged initiated but binary is not in valid merging state!") - binary.event = None + #binary.event = None if self.verbose: print("After Merger:\n"