Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion src/stellar.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,11 +269,13 @@ void ReadXUVModel(BODY *body, CONTROL *control, FILES *files, OPTIONS *options,
body[iFile - 1].iXUVModel = STELLAR_MODEL_ENGLE24EARLY;
} else if (!memcmp(sLower(cTmp), "engle24m", 8)) {
body[iFile - 1].iXUVModel = STELLAR_MODEL_ENGLE24MIDLATE;
} else if (!memcmp(sLower(cTmp), "engle24a", 8)) {
body[iFile - 1].iXUVModel = STELLAR_MODEL_ENGLE24AUTO;
} else {
if (control->Io.iVerbose >= VERBERR) {
fprintf(stderr,
"ERROR: Unknown argument to %s: %s. Options are RIBAS, REINERS, "
"ENGLE24EARLY, ENGLE24MIDLATE, or NONE.\n",
"ENGLE24EARLY, ENGLE24MIDLATE, ENGLE24AUTO, or NONE.\n",
options->cName, cTmp);
}
LineExit(files->Infile[iFile].cIn, lTmp);
Expand Down Expand Up @@ -1677,6 +1679,17 @@ void fnPropsAuxStellar(BODY *body, EVOLVE *evolve, IO *io, UPDATE *update,
body[iBody].dLXUV = fdLXUVEngle(
body, body[iBody].dXUVEngleMidLateA, body[iBody].dXUVEngleMidLateB,
body[iBody].dXUVEngleMidLateC, body[iBody].dXUVEngleMidLateD, iBody);
} else if (body[iBody].iXUVModel == STELLAR_MODEL_ENGLE24AUTO) {
/* Per-timestep dispatch on stellar mass. Boundary at 0.4 Msun. */
if (body[iBody].dMass >= 0.4 * MSUN) {
body[iBody].dLXUV = fdLXUVEngle(
body, body[iBody].dXUVEngleEarlyA, body[iBody].dXUVEngleEarlyB,
body[iBody].dXUVEngleEarlyC, body[iBody].dXUVEngleEarlyD, iBody);
} else {
body[iBody].dLXUV = fdLXUVEngle(
body, body[iBody].dXUVEngleMidLateA, body[iBody].dXUVEngleMidLateB,
body[iBody].dXUVEngleMidLateC, body[iBody].dXUVEngleMidLateD, iBody);
}
} else {

// Constant XUV fraction
Expand Down Expand Up @@ -1904,12 +1917,29 @@ void VerifyXUVEngleMidLate(BODY *body, CONTROL *control, FILES *files,
OPT_XUVMODEL, OPT_XUVENGLEEARLYD, iBody);
}

void VerifyXUVEngleAuto(BODY *body, CONTROL *control, FILES *files,
OPTIONS *options, int iBody) {
/* Engle24Auto: pick Early or MidLate per-timestep based on dMass. Allow
up to 25% extrapolation outside the calibrated union range
[0.1, 0.6] M_sun, but exit for masses more than 25% out of bounds. */
char cModel[LINE] = "ENGLE24AUTO XUV";
double dMinSafe = 0.075;
double dMaxSafe = 0.750;

VerifyEngleMassSpectralType(body, control, files, options, cModel,
dMaxSafe, dMinSafe, OPT_XUVMODEL, iBody);
/* No VerifyTwoEngleOptionsNotSet calls — Auto requires BOTH Early
and MidLate coefficient blocks to be present in star.in. */
}

void VerifyXUVEngle(BODY *body, CONTROL *control, FILES *files,
OPTIONS *options, int iBody) {
if (body[iBody].iXUVModel == STELLAR_MODEL_ENGLE24EARLY) {
VerifyXUVEngleEarly(body, control, files, options, iBody);
} else if (body[iBody].iXUVModel == STELLAR_MODEL_ENGLE24MIDLATE) {
VerifyXUVEngleMidLate(body, control, files, options, iBody);
} else if (body[iBody].iXUVModel == STELLAR_MODEL_ENGLE24AUTO) {
VerifyXUVEngleAuto(body, control, files, options, iBody);
}
}

Expand Down
5 changes: 5 additions & 0 deletions src/stellar.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@
7 /**< XUV evolution from Engle (2024) for M0-M2 dwarfs */
#define STELLAR_MODEL_ENGLE24MIDLATE \
8 /**< XUV evolution from Engle (2024) for M2.6-M6.5 dwarfs */
#define STELLAR_MODEL_ENGLE24AUTO \
9 /**< XUV evolution from Engle (2024) with per-timestep model selection \
based on stellar mass. Both Early and MidLate coefficient sets must \
be provided in star.in; dispatch uses Early for dMass >= 0.4 Msun, \
MidLate otherwise. Mass safety bound: 0.075 < dMass < 0.75 Msun. */

#define STELLAR_DJDT_NONE \
0 /**< No stellar angular momentum loss via magnetic braking */
Expand Down
30 changes: 30 additions & 0 deletions tests/Stellar/EngleAutoEarly/star.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Engle24Auto -- Early dispatch test fixture (M = 0.5 Msun).
# At M = 0.5 > 0.40 Msun, Auto-mode dispatch must select the Early
# coefficient set. Companion fixture `star_early.in` runs the same setup
# with sXUVModel = Engle24Early directly; the test asserts the resulting
# .log files agree, proving dispatch correctness in the Early regime.

sName star
saModules stellar

dMass 0.5
dRotPeriod -10
dAge 1e9

sStellarModel baraffe
sXUVModel Engle24Auto
sMagBrakingModel reiners

# Engle (2024) Early coefficients (active for M = 0.5 >= 0.4)
dXUVEngleEarlyA -0.4896
dXUVEngleEarlyB -3.2128
dXUVEngleEarlyC -0.4469
dXUVEngleEarlyD -0.2985

# Engle (2024) MidLate coefficients (present but unused for M=0.5)
dXUVEngleMidLateA -0.1456
dXUVEngleMidLateB -2.8876
dXUVEngleMidLateC -1.8187
dXUVEngleMidLateD 0.3545

saOutputOrder Time -Luminosity -LXUVStellar -LXUVTot
78 changes: 78 additions & 0 deletions tests/Stellar/EngleAutoEarly/test_EngleAutoEarly.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
from benchmark import Benchmark, benchmark
import astropy.units as u

@benchmark(
{
"log.initial.system.Age": {"value": 3.155760e+16, "unit": u.sec},
"log.initial.system.Time": {"value": 0.000000, "unit": u.sec},
"log.initial.system.TotAngMom": {"value": 1.316702e+41, "unit": (u.kg * u.m ** 2) / u.sec},
"log.initial.system.TotEnergy": {"value": -1.236883e+41, "unit": u.Joule},
"log.initial.system.PotEnergy": {"value": -1.236888e+41, "unit": u.Joule},
"log.initial.system.KinEnergy": {"value": 4.787665e+35, "unit": u.Joule},
"log.initial.system.DeltaTime": {"value": 0.000000, "unit": u.sec},
"log.initial.star.Mass": {"value": 9.942080e+29, "unit": u.kg},
"log.initial.star.Radius": {"value": 3.200220e+08, "unit": u.m},
"log.initial.star.RadGyra": {"value": 0.421689},
"log.initial.star.RotAngMom": {"value": 1.316702e+41, "unit": (u.kg * u.m ** 2) / u.sec},
"log.initial.star.RotVel": {"value": 2327.265658, "unit": u.m / u.sec},
"log.initial.star.BodyType": {"value": 0.000000},
"log.initial.star.RotRate": {"value": 7.272205e-06, "unit": 1 / u.sec},
"log.initial.star.RotPer": {"value": 8.640000e+05, "unit": u.sec},
"log.initial.star.Density": {"value": 7241.843562, "unit": u.kg / u.m ** 3},
"log.initial.star.HZLimitDryRunaway": {"value": 2.534228e+10, "unit": u.m},
"log.initial.star.HZLimRecVenus": {"value": 2.247260e+10, "unit": u.m},
"log.initial.star.HZLimRunaway": {"value": 2.975872e+10, "unit": u.m},
"log.initial.star.HZLimMoistGreenhouse": {"value": 2.973489e+10, "unit": u.m},
"log.initial.star.HZLimMaxGreenhouse": {"value": 5.547642e+10, "unit": u.m},
"log.initial.star.HZLimEarlyMars": {"value": 6.050631e+10, "unit": u.m},
"log.initial.star.Instellation": {"value": -1.000000, "unit": u.kg / u.sec ** 3},
"log.initial.star.CriticalSemiMajorAxis": {"value": -1.000000, "unit": u.m},
"log.initial.star.LXUVTot": {"value": 1.569641e-05, "unit": u.LSUN},
"log.initial.star.LostEnergy": {"value": 5.562685e-309, "unit": u.Joule},
"log.initial.star.LostAngMom": {"value": 5.562685e-309, "unit": (u.kg * u.m ** 2) / u.sec},
"log.initial.star.EscapeVelocity": {"value": 6.439704e+05, "unit": u.m / u.sec},
"log.initial.star.Luminosity": {"value": 0.034834, "unit": u.LSUN},
"log.initial.star.LXUVStellar": {"value": 1.569641e-05, "unit": u.LSUN},
"log.initial.star.Temperature": {"value": 3680.001536, "unit": u.K},
"log.initial.star.LXUVFrac": {"value": 0.000451},
"log.initial.star.RossbyNumber": {"value": 0.209553},
"log.initial.star.DRotPerDtStellar": {"value": 7.073788e-11},
"log.initial.star.WindTorque": {"value": 1.078018e+25},
"log.final.system.Age": {"value": 3.098080e+17, "unit": u.sec, "rtol": 1e-4},
"log.final.system.Time": {"value": 2.782504e+17, "unit": u.sec, "rtol": 1e-4},
"log.final.system.TotAngMom": {"value": 1.317902e+41, "unit": (u.kg * u.m ** 2) / u.sec, "rtol": 1e-4},
"log.final.system.TotEnergy": {"value": -1.235338e+41, "unit": u.Joule, "rtol": 1e-4},
"log.final.system.PotEnergy": {"value": -1.208001e+41, "unit": u.Joule, "rtol": 1e-4},
"log.final.system.KinEnergy": {"value": 4.875508e+34, "unit": u.Joule, "rtol": 1e-4},
"log.final.star.Mass": {"value": 9.942080e+29, "unit": u.kg, "rtol": 1e-4},
"log.final.star.Radius": {"value": 3.276747e+08, "unit": u.m, "rtol": 1e-4},
"log.final.star.RadGyra": {"value": 0.418088, "rtol": 1e-4},
"log.final.star.RotAngMom": {"value": 4.265542e+40, "unit": (u.kg * u.m ** 2) / u.sec, "rtol": 1e-4},
"log.final.star.RotVel": {"value": 749.063438, "unit": u.m / u.sec, "rtol": 1e-4},
"log.final.star.BodyType": {"value": 0.000000, "rtol": 1e-4},
"log.final.star.RotRate": {"value": 2.285997e-06, "unit": 1 / u.sec, "rtol": 1e-4},
"log.final.star.RotPer": {"value": 2.748553e+06, "unit": u.sec, "rtol": 1e-4},
"log.final.star.Density": {"value": 6746.210879, "unit": u.kg / u.m ** 3, "rtol": 1e-4},
"log.final.star.HZLimitDryRunaway": {"value": 2.609042e+10, "unit": u.m, "rtol": 1e-4},
"log.final.star.HZLimRecVenus": {"value": 2.313092e+10, "unit": u.m, "rtol": 1e-4},
"log.final.star.HZLimRunaway": {"value": 3.063255e+10, "unit": u.m, "rtol": 1e-4},
"log.final.star.HZLimMoistGreenhouse": {"value": 3.060595e+10, "unit": u.m, "rtol": 1e-4},
"log.final.star.HZLimMaxGreenhouse": {"value": 5.708049e+10, "unit": u.m, "rtol": 1e-4},
"log.final.star.HZLimEarlyMars": {"value": 6.225591e+10, "unit": u.m, "rtol": 1e-4},
"log.final.star.Instellation": {"value": -1.000000, "unit": u.kg / u.sec ** 3, "rtol": 1e-4},
"log.final.star.CriticalSemiMajorAxis": {"value": -1.000000, "unit": u.m, "rtol": 1e-4},
"log.final.star.LXUVTot": {"value": 1.959178e-06, "unit": u.LSUN, "rtol": 1e-4},
"log.final.star.LostEnergy": {"value": -2.733782e+39, "unit": u.Joule, "rtol": 1e-4},
"log.final.star.LostAngMom": {"value": 8.913482e+40, "unit": (u.kg * u.m ** 2) / u.sec, "rtol": 1e-4},
"log.final.star.EscapeVelocity": {"value": 6.364062e+05, "unit": u.m / u.sec, "rtol": 1e-4},
"log.final.star.Luminosity": {"value": 0.036921, "unit": u.LSUN, "rtol": 1e-4},
"log.final.star.LXUVStellar": {"value": 1.959178e-06, "unit": u.LSUN, "rtol": 1e-4},
"log.final.star.Temperature": {"value": 3689.002929, "unit": u.K, "rtol": 1e-4},
"log.final.star.LXUVFrac": {"value": 5.306436e-05, "rtol": 1e-4},
"log.final.star.RossbyNumber": {"value": 0.669712, "rtol": 1e-4},
"log.final.star.DRotPerDtStellar": {"value": 2.418466e-12, "rtol": 1e-4},
"log.final.star.WindTorque": {"value": 3.753272e+22, "rtol": 1e-4},
}
)
class Test_EngleAutoEarly(Benchmark):
pass
20 changes: 20 additions & 0 deletions tests/Stellar/EngleAutoEarly/vpl.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
sSystemName star
iVerbose 0
bOverwrite 1

saBodyFiles star.in

sUnitMass solar
sUnitLength AU
sUnitTime YEARS
sUnitAngle d

bDoLog 1
iDigits 6
dMinValue 1e-10

bDoForward 1
bVarDt 1
dEta 0.01
dStopTime 1e10
dOutputTime 1e9
31 changes: 31 additions & 0 deletions tests/Stellar/EngleAutoMidLate/star.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Engle24Auto XUV model — MidLate dispatch test.
# Same physical setup as tests/Stellar/EngleXUV (M=0.181, P_rot=-122d) but
# with sXUVModel = Engle24Auto. Because M < 0.40 Msun, Auto-mode dispatch
# must select the MidLate coefficient set; numerical results should be
# bit-identical to the EngleXUV benchmark. Engle24Early coefficients are
# also present (required by Auto mode) but should not influence the result.

sName star
saModules stellar

dMass 0.181
dRotPeriod -122
dAge 1e9

sStellarModel baraffe
sXUVModel Engle24Auto
sMagBrakingModel reiners

# Engle (2024) Early coefficients (unused for M=0.181 < 0.4)
dXUVEngleEarlyA -0.4896
dXUVEngleEarlyB -3.2128
dXUVEngleEarlyC -0.4469
dXUVEngleEarlyD -0.2985

# Engle (2024) MidLate coefficients (active for M=0.181 < 0.4)
dXUVEngleMidLateA -0.1456
dXUVEngleMidLateB -2.8876
dXUVEngleMidLateC -1.8187
dXUVEngleMidLateD 0.3545

saOutputOrder Time -Luminosity -LXUVStellar -LXUVTot
78 changes: 78 additions & 0 deletions tests/Stellar/EngleAutoMidLate/test_EngleAutoMidLate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
from benchmark import Benchmark, benchmark
import astropy.units as u

@benchmark(
{
"log.initial.system.Age": {"value": 3.155760e+16, "unit": u.sec},
"log.initial.system.Time": {"value": 0.000000, "unit": u.sec},
"log.initial.system.TotAngMom": {"value": 8.694238e+38, "unit": (u.kg * u.m ** 2) / u.sec},
"log.initial.system.TotEnergy": {"value": -3.754922e+40, "unit": u.Joule},
"log.initial.system.PotEnergy": {"value": -3.754922e+40, "unit": u.Joule},
"log.initial.system.KinEnergy": {"value": 2.591241e+32, "unit": u.Joule},
"log.initial.system.DeltaTime": {"value": 0.000000, "unit": u.sec},
"log.initial.star.Mass": {"value": 3.599033e+29, "unit": u.kg},
"log.initial.star.Radius": {"value": 1.381422e+08, "unit": u.m},
"log.initial.star.RadGyra": {"value": 0.460833},
"log.initial.star.RotAngMom": {"value": 8.694238e+38, "unit": (u.kg * u.m ** 2) / u.sec},
"log.initial.star.RotVel": {"value": 82.344140, "unit": u.m / u.sec},
"log.initial.star.BodyType": {"value": 0.000000},
"log.initial.star.RotRate": {"value": 5.960824e-07, "unit": 1 / u.sec},
"log.initial.star.RotPer": {"value": 1.054080e+07, "unit": u.sec},
"log.initial.star.Density": {"value": 3.259252e+04, "unit": u.kg / u.m ** 3},
"log.initial.star.HZLimitDryRunaway": {"value": 8.356400e+09, "unit": u.m},
"log.initial.star.HZLimRecVenus": {"value": 7.485986e+09, "unit": u.m},
"log.initial.star.HZLimRunaway": {"value": 9.873134e+09, "unit": u.m},
"log.initial.star.HZLimMoistGreenhouse": {"value": 9.905190e+09, "unit": u.m},
"log.initial.star.HZLimMaxGreenhouse": {"value": 1.882335e+10, "unit": u.m},
"log.initial.star.HZLimEarlyMars": {"value": 2.052890e+10, "unit": u.m},
"log.initial.star.Instellation": {"value": -1.000000, "unit": u.kg / u.sec ** 3},
"log.initial.star.CriticalSemiMajorAxis": {"value": -1.000000, "unit": u.m},
"log.initial.star.LXUVTot": {"value": 4.906221e-06, "unit": u.LSUN},
"log.initial.star.LostEnergy": {"value": 5.562685e-309, "unit": u.Joule},
"log.initial.star.LostAngMom": {"value": 5.562685e-309, "unit": (u.kg * u.m ** 2) / u.sec},
"log.initial.star.EscapeVelocity": {"value": 5.897214e+05, "unit": u.m / u.sec},
"log.initial.star.Luminosity": {"value": 0.003787, "unit": u.LSUN},
"log.initial.star.LXUVStellar": {"value": 4.906221e-06, "unit": u.LSUN},
"log.initial.star.Temperature": {"value": 3212.579977, "unit": u.K},
"log.initial.star.LXUVFrac": {"value": 0.001295},
"log.initial.star.RossbyNumber": {"value": 2.012152},
"log.initial.star.DRotPerDtStellar": {"value": 5.277006e-12},
"log.initial.star.WindTorque": {"value": 4.352568e+20},
"log.final.system.Age": {"value": 3.108426e+17, "unit": u.sec, "rtol": 1e-4},
"log.final.system.Time": {"value": 2.792850e+17, "unit": u.sec, "rtol": 1e-4},
"log.final.system.TotAngMom": {"value": 8.931191e+38, "unit": (u.kg * u.m ** 2) / u.sec, "rtol": 1e-4},
"log.final.system.TotEnergy": {"value": -3.698928e+40, "unit": u.Joule, "rtol": 1e-4},
"log.final.system.PotEnergy": {"value": -3.674712e+40, "unit": u.Joule, "rtol": 1e-4},
"log.final.system.KinEnergy": {"value": 2.108611e+32, "unit": u.Joule, "rtol": 1e-4},
"log.final.star.Mass": {"value": 3.599033e+29, "unit": u.kg, "rtol": 1e-4},
"log.final.star.Radius": {"value": 1.411575e+08, "unit": u.m, "rtol": 1e-4},
"log.final.star.RadGyra": {"value": 0.460733, "rtol": 1e-4},
"log.final.star.RotAngMom": {"value": 8.012348e+38, "unit": (u.kg * u.m ** 2) / u.sec, "rtol": 1e-4},
"log.final.star.RotVel": {"value": 74.296896, "unit": u.m / u.sec, "rtol": 1e-4},
"log.final.star.BodyType": {"value": 0.000000, "rtol": 1e-4},
"log.final.star.RotRate": {"value": 5.263403e-07, "unit": 1 / u.sec, "rtol": 1e-4},
"log.final.star.RotPer": {"value": 1.193750e+07, "unit": u.sec, "rtol": 1e-4},
"log.final.star.Density": {"value": 3.054816e+04, "unit": u.kg / u.m ** 3, "rtol": 1e-4},
"log.final.star.HZLimitDryRunaway": {"value": 8.540511e+09, "unit": u.m, "rtol": 1e-4},
"log.final.star.HZLimRecVenus": {"value": 7.649893e+09, "unit": u.m, "rtol": 1e-4},
"log.final.star.HZLimRunaway": {"value": 1.008994e+10, "unit": u.m, "rtol": 1e-4},
"log.final.star.HZLimMoistGreenhouse": {"value": 1.012207e+10, "unit": u.m, "rtol": 1e-4},
"log.final.star.HZLimMaxGreenhouse": {"value": 1.923039e+10, "unit": u.m, "rtol": 1e-4},
"log.final.star.HZLimEarlyMars": {"value": 2.097284e+10, "unit": u.m, "rtol": 1e-4},
"log.final.star.Instellation": {"value": -1.000000, "unit": u.kg / u.sec ** 3, "rtol": 1e-4},
"log.final.star.CriticalSemiMajorAxis": {"value": -1.000000, "unit": u.m, "rtol": 1e-4},
"log.final.star.LXUVTot": {"value": 2.529287e-07, "unit": u.LSUN, "rtol": 1e-4},
"log.final.star.LostEnergy": {"value": -2.421681e+38, "unit": u.Joule, "rtol": 1e-4},
"log.final.star.LostAngMom": {"value": 9.188425e+37, "unit": (u.kg * u.m ** 2) / u.sec, "rtol": 1e-4},
"log.final.star.EscapeVelocity": {"value": 5.833888e+05, "unit": u.m / u.sec, "rtol": 1e-4},
"log.final.star.Luminosity": {"value": 0.003956, "unit": u.LSUN, "rtol": 1e-4},
"log.final.star.LXUVStellar": {"value": 2.529287e-07, "unit": u.LSUN, "rtol": 1e-4},
"log.final.star.Temperature": {"value": 3219.534123, "unit": u.K, "rtol": 1e-4},
"log.final.star.LXUVFrac": {"value": 6.393251e-05, "rtol": 1e-4},
"log.final.star.RossbyNumber": {"value": 2.286901, "rtol": 1e-4},
"log.final.star.DRotPerDtStellar": {"value": 3.905842e-12, "rtol": 1e-4},
"log.final.star.WindTorque": {"value": 2.621569e+20, "rtol": 1e-4},
}
)
class Test_EngleAutoMidLate(Benchmark):
pass
20 changes: 20 additions & 0 deletions tests/Stellar/EngleAutoMidLate/vpl.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
sSystemName star
iVerbose 0
bOverwrite 1

saBodyFiles star.in

sUnitMass solar
sUnitLength AU
sUnitTime YEARS
sUnitAngle d

bDoLog 1
iDigits 6
dMinValue 1e-10

bDoForward 1
bVarDt 1
dEta 0.01
dStopTime 1e10
dOutputTime 1e9
Loading