Skip to content

Commit 3ad655b

Browse files
authored
Merge pull request #1401 from brcekadam/CHE_and_merger_fixes
Fixes to CHE and MS mergers with BRCEK core mass prescription
2 parents c12800a + 5ab3409 commit 3ad655b

File tree

11 files changed

+54
-25
lines changed

11 files changed

+54
-25
lines changed

src/BaseBinaryStar.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1778,15 +1778,14 @@ void BaseBinaryStar::ResolveMainSequenceMerger() {
17781778
(utils::Compare(m_Star1->MZAMS(), BRCEK_LOWER_MASS_LIMIT) >= 0) &&
17791779
(utils::Compare(m_Star2->MZAMS(), BRCEK_LOWER_MASS_LIMIT) >= 0)) {
17801780

1781-
double coreMass1 = m_Star1->MainSequenceCoreMass();
1782-
double coreMass2 = m_Star2->MainSequenceCoreMass();
1781+
// total hydrogen masses (from the core, envelope, and the intermediate region between the core and envelope)
1782+
double hydrogenMass1 = m_Star1->HydrogenAbundanceCore() * m_Star1->MainSequenceCoreMass() + (m_Star1->HydrogenAbundanceCore() + m_Star1->HydrogenAbundanceSurface()) * (std::min(m_Star1->InitialMainSequenceCoreMass(), m_Star1->Mass()) - m_Star1->MainSequenceCoreMass()) / 2.0 + m_Star1->HydrogenAbundanceSurface() * std::max(m_Star1->Mass() - m_Star1->InitialMainSequenceCoreMass(), 0.0);
1783+
double hydrogenMass2 = m_Star2->HydrogenAbundanceCore() * m_Star2->MainSequenceCoreMass() + (m_Star2->HydrogenAbundanceCore() + m_Star2->HydrogenAbundanceSurface()) * (std::min(m_Star2->InitialMainSequenceCoreMass(), m_Star2->Mass()) - m_Star2->MainSequenceCoreMass()) / 2.0 + m_Star2->HydrogenAbundanceSurface() * std::max(m_Star2->Mass() - m_Star2->InitialMainSequenceCoreMass(), 0.0);
17831784

1784-
double coreHeliumMass1 = m_Star1->HeliumAbundanceCore() * coreMass1;
1785-
double coreHeliumMass2 = m_Star2->HeliumAbundanceCore() * coreMass2;
1786-
1787-
finalHydrogenMass = finalMass * initialHydrogenFraction - coreHeliumMass1 - coreHeliumMass2;
1785+
// final hydrogen mass in the merger product, assuming that the lost mass comes from the envelope of the star with higher surface hydrogen abundance
1786+
finalHydrogenMass = hydrogenMass1 + hydrogenMass2 - (m_Star1->Mass() + m_Star2->Mass() - finalMass) * std::max(m_Star1->HydrogenAbundanceSurface(), m_Star2->HydrogenAbundanceSurface());
17881787
}
1789-
else finalHydrogenMass = finalMass * initialHydrogenFraction - tau1 * TAMSCoreMass1 * initialHydrogenFraction - tau2 * TAMSCoreMass2 * initialHydrogenFraction;
1788+
else finalHydrogenMass = finalMass * initialHydrogenFraction - tau1 * TAMSCoreMass1 * initialHydrogenFraction - tau2 * TAMSCoreMass2 * initialHydrogenFraction;
17901789

17911790
m_SemiMajorAxis = std::numeric_limits<float>::infinity(); // set separation to infinity to avoid subsequent fake interactions with a massless companion (RLOF, CE, etc.)
17921791

src/BaseStar.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ BaseStar::BaseStar(const unsigned long int p_RandomSeed,
107107
// initialise remaining member variables
108108

109109
// Zero age main sequence parameters
110+
m_InitialMainSequenceCoreMass = DEFAULT_INITIAL_DOUBLE_VALUE; // initialised in MS_gt_07 class if BRCEK core mass prescription is used
110111
m_RZAMS = CalculateRadiusAtZAMS(m_MZAMS);
111112
m_LZAMS = CalculateLuminosityAtZAMS(m_MZAMS);
112113
m_TZAMS = CalculateTemperatureOnPhase_Static(m_LZAMS, m_RZAMS);

src/BaseStar.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ class BaseStar {
106106
double HydrogenAbundanceSurface() const { return m_HydrogenAbundanceSurface; }
107107
double InitialHeliumAbundance() const { return m_InitialHeliumAbundance; }
108108
double InitialHydrogenAbundance() const { return m_InitialHydrogenAbundance; }
109+
double InitialMainSequenceCoreMass() const { return m_InitialMainSequenceCoreMass; }
109110
bool IsAIC() const { return (m_SupernovaDetails.events.current & SN_EVENT::AIC) == SN_EVENT::AIC; }
110111
bool IsCCSN() const { return (m_SupernovaDetails.events.current & SN_EVENT::CCSN) == SN_EVENT::CCSN; }
111112
bool IsHeSD() const { return (m_SupernovaDetails.events.current & SN_EVENT::HeSD) == SN_EVENT::HeSD; }
@@ -404,6 +405,7 @@ class BaseStar {
404405
// Zero Age Main Sequence
405406
double m_InitialHeliumAbundance; // Initial helium abundance (Y)
406407
double m_InitialHydrogenAbundance; // Initial hydrogen abundance (X)
408+
double m_InitialMainSequenceCoreMass; // Initial main sequence core mass (used in BRCEK core mass prescription)
407409
double m_LZAMS; // ZAMS Luminosity
408410
double m_MZAMS; // ZAMS Mass
409411
double m_OmegaZAMS; // ZAMS Angular Frequency

src/CH.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,10 @@ STELLAR_TYPE CH::EvolveToNextPhase() {
423423
if (m_Age < m_Timescales[static_cast<int>(TIMESCALE::tMS)]) { // evolving off because of age?
424424
stellarType = STELLAR_TYPE::MS_GT_07; // no - must have spun down - evolve as MS star now
425425
m_CHE = false; // evolved CH->MS
426+
427+
// if BRCEK core mass calculations enabled, initialise the core mass based on current mass and central helium fraction
428+
if ((OPTIONS->MainSequenceCoreMassPrescription() == CORE_MASS_PRESCRIPTION::BRCEK) && (utils::Compare(m_MZAMS, BRCEK_LOWER_MASS_LIMIT) >= 0))
429+
m_MainSequenceCoreMass = MainSequence::CalculateInitialMainSequenceCoreMass(m_Mass, m_HeliumAbundanceCore);
426430
}
427431
else { // yes
428432
stellarType = STELLAR_TYPE::NAKED_HELIUM_STAR_MS; // evolve as HeMS star now

src/CH.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ class CH: virtual public BaseStar, public MS_gt_07 {
8989
bool ShouldEvolveOnPhase() const { return m_Age < m_Timescales[static_cast<int>(TIMESCALE::tMS)] && (OPTIONS->OptimisticCHE() || Omega() >= m_OmegaCHE); } // Evolve on CHE phase if age in MS timescale and spinning at least as fast as CHE threshold
9090

9191
void UpdateAgeAfterMassLoss();
92+
93+
void UpdateMainSequenceCoreMass(const double p_Dt, const double p_TotalMassLossRate) { }; // Do not use core mass calculations during CHE phase
9294

9395
};
9496

src/MS_gt_07.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ class MS_gt_07: virtual public BaseStar, public MainSequence {
4848
utils::Compare(m_MZAMS, BRCEK_LOWER_MASS_LIMIT) >= 0 && // ZAMS mass >= BRCEK_LOWER_MASS_LIMIT?
4949
m_Time <= 0.0) { // star not yet aged past creation?
5050
// yes - initialise
51-
m_InitialMainSequenceCoreMass = MainSequence::CalculateInitialMainSequenceCoreMass(m_MZAMS);
51+
m_InitialMainSequenceCoreMass = MainSequence::CalculateInitialMainSequenceCoreMass(m_MZAMS, m_InitialHeliumAbundance);
5252
m_MainSequenceCoreMass = m_InitialMainSequenceCoreMass;
5353
m_Luminosity = MainSequence::CalculateLuminosityOnPhase(m_Age, m_Mass0, m_LZAMS0);
5454
m_Radius = MainSequence::CalculateRadiusOnPhase(m_Mass, m_Tau, m_RZAMS0);

src/MainSequence.cpp

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -289,8 +289,9 @@ double MainSequence::CalculateLuminosityOnPhase(const double p_Time, const doubl
289289
#define timescales(x) m_Timescales[static_cast<int>(TIMESCALE::x)] // for convenience and readability - undefined at end of function
290290

291291
// If BRCEK core prescription is used, return luminosity from Shikauchi et al. (2024) during core hydrogen burning (valid for MZAMS >= 15 Msol) or
292-
// luminosity that smoothly connects MS and HG during MS hook (valid for MZAMS >= BRCEK_LOWER_MASS_LIMIT)
293-
if ((OPTIONS->MainSequenceCoreMassPrescription() == CORE_MASS_PRESCRIPTION::BRCEK) && (utils::Compare(m_MZAMS, BRCEK_LOWER_MASS_LIMIT) >= 0)) {
292+
// luminosity that smoothly connects MS and HG during MS hook (valid for MZAMS >= BRCEK_LOWER_MASS_LIMIT); do not use Shikauchi luminosity
293+
// prescription during CHE
294+
if ((OPTIONS->MainSequenceCoreMassPrescription() == CORE_MASS_PRESCRIPTION::BRCEK) && (utils::Compare(m_MZAMS, BRCEK_LOWER_MASS_LIMIT) >= 0) && !m_CHE) {
294295
if (utils::Compare(p_Time, 0.99 * timescales(tMS)) > 0) // star in MS hook?
295296
return CalculateLuminosityTransitionToHG(p_Mass, p_Time, p_LZAMS);
296297
else {
@@ -826,18 +827,30 @@ DBL_DBL MainSequence::CalculateMainSequenceCoreMassBrcek(const double p_Dt, cons
826827

827828

828829
/*
829-
* Calculate the initial convective core mass of a main sequence star using Equation (A3) from Shikauchi et al. (2024),
830-
* also used for calculating core mass after MS merger
830+
* Calculate the initial convective core mass of a main sequence star at ZAMS using Equation (A3) from Shikauchi+ (2024),
831+
* or after full mixing (due to merger or CHE) for an arbitrary central helium fraction using the approach
832+
* described in Brcek+ (2025)
831833
*
832-
* double CalculateInitialMainSequenceCoreMass(const double p_MZAMS)
834+
* double CalculateInitialMainSequenceCoreMass(const double p_Mass, const double p_HeliumAbundanceCore)
833835
*
834-
* @param [IN] p_MZAMS Mass at ZAMS or after merger in Msol
836+
* @param [IN] p_Mass Mass at ZAMS, after merger or after spin down of CH star in Msol
837+
* @param [IN] p_HeliumAbundanceCore Central helium fraction
835838
* @return Mass of the convective core at ZAMS or after merger in Msol
836839
*/
837-
double MainSequence::CalculateInitialMainSequenceCoreMass(const double p_MZAMS) const {
838-
DBL_VECTOR fmixCoefficients = std::get<1>(SHIKAUCHI_COEFFICIENTS);
839-
double fmix = fmixCoefficients[0] + fmixCoefficients[1] * std::exp(-p_MZAMS / fmixCoefficients[2]);
840-
return fmix * p_MZAMS;
840+
double MainSequence::CalculateInitialMainSequenceCoreMass(const double p_Mass, const double p_HeliumAbundanceCore) const {
841+
842+
double fmix = 0.0;
843+
// At ZAMS, use the approach from Shikauchi+ (2024)
844+
if (utils::Compare(p_HeliumAbundanceCore, m_InitialHeliumAbundance) == 0) {
845+
DBL_VECTOR fmixCoefficients = std::get<1>(SHIKAUCHI_COEFFICIENTS);
846+
fmix = fmixCoefficients[0] + fmixCoefficients[1] * std::exp(-p_Mass / fmixCoefficients[2]);
847+
}
848+
// After full mixing not at ZAMS, use the approach from Brcek+ (2025)
849+
else {
850+
double h = PPOW(10.0, p_HeliumAbundanceCore * (p_HeliumAbundanceCore + 2.0) / 4.0);
851+
fmix = BRCEK_FMIX_COEFFICIENTS[0] + BRCEK_FMIX_COEFFICIENTS[1] * std::exp(-p_Mass * h / BRCEK_FMIX_COEFFICIENTS[2]) * PPOW(1.0 - BRCEK_FMIX_COEFFICIENTS[4] / (p_Mass * h), BRCEK_FMIX_COEFFICIENTS[3]);
852+
}
853+
return fmix * p_Mass;
841854
}
842855

843856

@@ -1142,12 +1155,14 @@ void MainSequence::UpdateAfterMerger(double p_Mass, double p_HydrogenMass) {
11421155
m_Age = m_Tau * timescales(tMS);
11431156

11441157
m_HeliumAbundanceCore = 1.0 - m_Metallicity - p_HydrogenMass / p_Mass;
1145-
11461158
m_HydrogenAbundanceCore = 1.0 - m_Metallicity - m_HeliumAbundanceCore;
11471159

1160+
m_HeliumAbundanceSurface = m_HeliumAbundanceCore; // abundances are the same throughout the star, assuming uniform mixing after merger
1161+
m_HydrogenAbundanceSurface = m_HydrogenAbundanceCore;
1162+
11481163
if ((OPTIONS->MainSequenceCoreMassPrescription() == CORE_MASS_PRESCRIPTION::BRCEK) && (utils::Compare(m_MZAMS, BRCEK_LOWER_MASS_LIMIT) >= 0)) {
1149-
m_InitialMainSequenceCoreMass = CalculateInitialMainSequenceCoreMass(p_Mass); // update initial mixing core mass
1150-
m_MainSequenceCoreMass = m_InitialMainSequenceCoreMass; // update core mass
1164+
m_InitialMainSequenceCoreMass = CalculateInitialMainSequenceCoreMass(p_Mass, m_HeliumAbundanceCore); // update initial mixing core mass
1165+
m_MainSequenceCoreMass = m_InitialMainSequenceCoreMass; // update core mass
11511166
}
11521167

11531168
UpdateAttributesAndAgeOneTimestep(0.0, 0.0, 0.0, true);

src/MainSequence.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@ class MainSequence: virtual public BaseStar {
2525
protected:
2626

2727
// member variables
28-
2928
double m_HeliumAbundanceCoreOut = m_InitialHeliumAbundance; // Helium abundance just outside the core, used for rejuvenation calculations
30-
double m_InitialMainSequenceCoreMass = 0.0; // Initial mass of the mixing core is initialised in MS_gt_07 class
3129

3230
// member functions - alphabetically
3331
double CalculateAlphaL(const double p_Mass) const;
@@ -78,7 +76,7 @@ class MainSequence: virtual public BaseStar {
7876
double CalculateLuminosityShikauchi(const double p_CoreMass, const double p_HeliumAbundanceCore) const;
7977
double CalculateLuminosityTransitionToHG(const double p_Mass, const double p_Age, double const p_LZAMS) const;
8078
DBL_DBL CalculateMainSequenceCoreMassBrcek(const double p_Dt, const double p_MassLossRate);
81-
double CalculateInitialMainSequenceCoreMass(const double p_MZAMS) const;
79+
double CalculateInitialMainSequenceCoreMass(const double p_Mass, const double p_HeliumAbundanceCore) const;
8280
double CalculateMomentOfInertia() const { return (0.1 * (m_Mass) * m_Radius * m_Radius); } // k2 = 0.1 as defined in Hurley et al. 2000, after eq 109
8381

8482
double CalculatePerturbationMu() const { return 5.0; } // mu(MS) = 5.0 (Hurley et al. 2000, eqs 97 & 98)

src/Star.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ class Star {
9797
double HydrogenAbundanceSurface() const { return m_Star->HydrogenAbundanceSurface(); }
9898
double InitialHeliumAbundance() const { return m_Star->InitialHeliumAbundance(); }
9999
double InitialHydrogenAbundance() const { return m_Star->InitialHydrogenAbundance(); }
100+
double InitialMainSequenceCoreMass() const { return m_Star->InitialMainSequenceCoreMass(); }
100101
bool IsAIC() const { return m_Star->IsAIC(); }
101102
bool IsCCSN() const { return m_Star->IsCCSN(); }
102103
bool IsDegenerate() const { return m_Star->IsDegenerate(); }

src/changelog.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1583,8 +1583,11 @@
15831583
// - TPAGB stars should no longer experience supernovae if SN conditions are not satisfied, rather than defaulting to CCSN (corrects the partial fix in 03.10.02)
15841584
// - Added new parameter (threshold mass, generally expected to be MCH or MECS) to CalculateCoreMassAtSupernova_Static()
15851585
// - Removed McSN from GBParams, instead computed on the fly when needed
1586+
// 03.20.04 AB - Jun 23, 2025 - Defect repair, enhancement:
1587+
// - Fixes to MS mergers and CHE when BRCEK core mass prescription is used -- MS core mass is now correctly initialised after full mixing in MS
1588+
// mergers and CH stars that spun down
15861589

1587-
const std::string VERSION_STRING = "03.20.03";
1590+
const std::string VERSION_STRING = "03.20.04";
15881591

15891592

15901593
# endif // __changelog_h__

0 commit comments

Comments
 (0)