Skip to content

Boundary interior module#668

Draft
rdc49 wants to merge 6 commits intomainfrom
boundary_interior_module
Draft

Boundary interior module#668
rdc49 wants to merge 6 commits intomainfrom
boundary_interior_module

Conversation

@rdc49
Copy link
Copy Markdown
Contributor

@rdc49 rdc49 commented Apr 14, 2026

This pull request is for the current iteration of the boundary interior module. This is a 0D, parameterised mantle evolution model, based on the model in Schaefer et. al. (2016). The key differences between this model and the Schaefer model are as follows:

-The viscosity treatment from Bower et. al. (2018) is used instead of that in the Schaefer paper.
-The radius of solidification (r_s) and rate of change of r_s are determined analytically assuming r_s is simply a function of the melt fraction.
-The second term on the LHS of equation 14 is corrected to use the heat capacity of the boundary layer (r_p^3-(r_-delta)^3).

The module currently works with the dummy atmosphere module (without radiogenic heating). The main issue it has when trying to operate alongside AGNI is time-stepping: large atmospheric fluxes result in too steep a decrease in surface temperature for a given time step. In theory, this could be overcome by playing with the adaptive time-stepping parameters, but this is fiddly, and results in the model taking a very long time to run.

I also need to update the module to work alongside Zalmoxis: currently the mass and radius need to be passed manually.

Copilot AI review requested due to automatic review settings April 14, 2026 14:29
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “boundary” interior option (0D parameterised mantle evolution) and wires it into the PROTEUS coupler/interior wrapper, alongside a broad set of example/config updates intended to exercise updated stellar-spectrum and condensation settings.

Changes:

  • Introduces src/proteus/interior/boundary.py and adds interior.module = "boundary" support in the interior wrapper/config.
  • Adjusts atmosphere wrapper logic so T_surf can be driven by the boundary interior module.
  • Updates many example planet/demo/CHILI/ensemble TOMLs (stellar spectrum fields, condensation/rainout naming, and various parameter tweaks).

Reviewed changes

Copilot reviewed 35 out of 35 changed files in this pull request and generated 24 comments.

Show a summary per file
File Description
src/proteus/proteus.py Adds boundary-specific first-loop initialization/outgassing before interior evolution.
src/proteus/interior/wrapper.py Adds boundary module routing, structure-handling special cases, and atmos_o parameter.
src/proteus/interior/boundary.py New boundary-layer interior evolution implementation (ODE integration + diagnostics).
src/proteus/config/_interior.py Adds InteriorBoundary config section and extends interior.module allowed values.
src/proteus/atmos_clim/wrapper.py Skips T_surf update when boundary interior is responsible for surface temperature.
src/proteus/atmos_clim/dummy.py Uses hf_row["T_surf"] for dummy atmosphere when boundary interior is enabled.
input/planets/trappist1c.toml Updates stellar spectrum settings and AGNI options.
input/planets/toi6255.toml Updates stellar spectrum settings.
input/planets/l9859d.toml Updates stellar spectrum settings and AGNI condensation/rainout option naming.
input/planets/l9859c.toml Updates stellar spectrum settings and AGNI condensation/rainout option naming.
input/planets/l9859b.toml Updates stellar spectrum settings and AGNI condensation/rainout option naming.
input/planets/hd63433d.toml Updates stellar spectrum settings and AGNI condensation/rainout option naming.
input/planets/gj9827d.toml Updates stellar spectrum settings and AGNI condensation/rainout option naming.
input/planets/fiducial_sub_Neptune.toml Updates stellar spectrum settings, AGNI condensation/rainout naming, and other parameters.
input/planets/earth.toml Updates timestep params and changes stellar spectrum + AGNI condensation/rainout naming.
input/planets/GDSP_fiducial.toml Adds a new fiducial planet config used by new ensemble grids.
input/minimal.toml Updates minimal config stellar spectrum field.
input/ensembles/stellar_spectra_test_mors.toml Adds a new ensemble config intended to sweep stellar spectra for MORS.
input/ensembles/stellar_spectra_test_bb.toml Adds a new ensemble config sweeping dummy-star Teff (blackbody-like).
input/ensembles/solubility_test.toml Adds a new outgassing solubility toggle ensemble.
input/ensembles/ocean_formation_grid.toml Adds a new ensemble config for initial-inventory sweeps.
input/ensembles/example.infer.toml Updates example inference settings/targets and BO hyperparameters.
input/ensembles/boundary_interior_test.toml Adds a new ensemble config intended to exercise the boundary interior with dummy atmosphere.
input/ensembles/SNS_0.5%_sweep.toml Adds a new ensemble config for parameter sweeps.
input/ensembles/SNS_0.5%_sanity_check.toml Adds a new ensemble config for sanity checks across instellation.
input/ensembles/GDSP_initial_grid_2.toml Adds another GDSP initial grid ensemble config.
input/demos/sat_physical.toml Updates AGNI condensation/rainout option naming.
input/demos/escape.toml Updates stellar spectrum field and AGNI condensation/rainout option naming.
input/demos/aragog.toml Updates AGNI condensation/rainout option naming.
input/chili/readme.md Removes an outdated CHILI GitHub link line.
input/chili/protocol/tr1b.toml Updates stellar spectrum field and AGNI condensation/rainout option naming; adds several extra tables.
input/chili/protocol/earth.toml Updates stellar spectrum field and AGNI condensation/rainout option naming; adds several extra tables.
input/chili/intercomp/_base.toml Updates stellar spectrum field, AGNI condensation/rainout naming, and several parameter defaults.
input/chili/intercomp/_base.grid.toml Updates grid settings and sampled values for CHILI intercomparison runs.
input/all_options.toml Adds an [interior.boundary] example block and tweaks various comment/option defaults.

solution_rtol = 1e-1 # solver relative tolerance
overlap_method = "ee" # gas overlap method
rainout = true # volatile condensation
condensation = true # volatile condensation
Comment thread input/demos/escape.toml
solution_rtol = 0.13
overlap_method = "ee"
rainout = false
condensation = false
Comment on lines +457 to +460
# Set up CSV logging for step diagnostics.
output_dir = dirs.get('output', '.')
csv_log_file = f"{output_dir}/boundary_solver_debug.csv"
self._run_solver_call_count = self.iteration
Comment on lines +393 to +401
phi = self.melt_fraction(T_p)
q_m_val = self.q_m(T_p, T_surf, phi)

delta = self.thermal_conductivity * (T_p - T_surf) / q_m_val

numerator = 4 * np.pi * self.planet_radius**2 * (q_m_val - self.f_atm)
denominator = self.atmosphere_heat_capacity * self.m_atm + \
(4/3) * np.pi * self.silicate_heat_capacity * self.bulk_density * (self.planet_radius**3 - (self.planet_radius-delta)**3)

Comment on lines +49 to +76
class BoundaryRunner():

def __init__(self, config: Config, dirs: dict, hf_row: dict, hf_all:
pd.DataFrame, interior_o: Interior_t, atmos_o: Atmos_t):

self.curr_time = hf_row["Time"] * secs_per_year
self.dt = self.compute_time_step(config, dirs, hf_row, hf_all, interior_o) * secs_per_year
self.iteration = 1 if hf_all is None else len(hf_all)

self.planet_radius = hf_row["R_int"]
self.planet_mass = config.struct.mass_tot * M_earth
self.core_mass = hf_row["M_core"]
self.m_atm = hf_row["M_atm"]
self.f_atm = hf_row["F_atm"]

cp_layer = getattr(getattr(atmos_o, "_atm", None), "layer_cp", None)
if cp_layer is not None and len(cp_layer) > 2 and not pd.isna(cp_layer[2]):
self.atmosphere_heat_capacity = cp_layer[2] # J/kg/K
else:
self.atmosphere_heat_capacity = 1.7e4 # J/kg/K for H2 at 2000K

self.core_radius = config.struct.corefrac * self.planet_radius

self.mantle_radius = self.planet_radius - self.core_radius
self.mantle_volume = (4/3) * np.pi * (self.planet_radius**3 - self.core_radius**3)
self.mantle_mass = (self.planet_mass - self.core_mass)
self.bulk_density = self.mantle_mass / self.mantle_volume

symlink = ""

# Path to base (reference) config file relative to PROTEUS root folder
ref_config = "input/planets/nogit_fiducial_sub_Neptune_MORS.toml"
Comment on lines +148 to +153
else:
# *** will change this once interior module works with zalmoxis ***
hf_row["R_int"] = R_earth
hf_row["M_tot"] = M_target
calculate_core_mass(hf_row, config)
hf_row["gravity"] = 9.81
Comment on lines +245 to +253
K_term = self.K_abun * K_heat_production * np.exp(
K_decay_constant * (self.radio_tref * secs_per_year - t)
)
Ur_term = self.U_abun * Ur_heat_production * np.exp(
Ur_decay_constant * (self.radio_tref * secs_per_year - t)
)
Th_term = self.Th_abun * Th_heat_production * np.exp(
Th_decay_constant * (self.radio_tref * secs_per_year - t)
)
Comment on lines +534 to +538
"F_int": q_m_final,
"Phi_global": phi_final,
"Phi_global_vol": phi_final,
"F_radio": f_radio_final/(4*np.pi*self.planet_radius**2),
"RF_depth": r_s_final/self.planet_radius,
Comment thread input/minimal.toml
age_now = 4.567 # Current age of star used for scaling [Gyr]
star_name = "sun"
spectrum_source = "solar"
spec = "stellar_spectra/Named/sun.txt" # Stellar spectrum
@codecov
Copy link
Copy Markdown

codecov bot commented Apr 14, 2026

Codecov Report

❌ Patch coverage is 14.13043% with 237 lines in your changes missing coverage. Please review.
✅ Project coverage is 68.07%. Comparing base (6fb36f6) to head (e986c34).

Files with missing lines Patch % Lines
src/proteus/interior/boundary.py 0.00% 198 Missing ⚠️
src/proteus/interior/wrapper.py 30.43% 11 Missing and 5 partials ⚠️
src/proteus/config/_interior.py 76.31% 8 Missing and 1 partial ⚠️
src/proteus/atmos_clim/wrapper.py 0.00% 4 Missing and 2 partials ⚠️
src/proteus/proteus.py 14.28% 5 Missing and 1 partial ⚠️
src/proteus/atmos_clim/dummy.py 50.00% 1 Missing and 1 partial ⚠️

❌ Your patch check has failed because the patch coverage (14.13%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #668      +/-   ##
==========================================
- Coverage   69.12%   68.07%   -1.05%     
==========================================
  Files          98       99       +1     
  Lines       10214    10469     +255     
  Branches     1422     1448      +26     
==========================================
+ Hits         7060     7127      +67     
- Misses       2814     3025     +211     
+ Partials      340      317      -23     
Flag Coverage Δ
unit-tests 56.26% <14.13%> (-1.19%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@nichollsh nichollsh self-requested a review April 15, 2026 12:14
@nichollsh
Copy link
Copy Markdown
Member

nichollsh commented Apr 15, 2026

The main issue it has when trying to operate alongside AGNI is time-stepping: large atmospheric fluxes result in too steep a decrease in surface temperature for a given time step. In theory, this could be overcome by playing with the adaptive time-stepping parameters, but this is fiddly, and results in the model taking a very long time to run.

As mentioned earlier today, @rdc49, one potential option to avoid taking too-large timesteps is to incorporate 'callback' events. We already do this in SPIDER and Aragog, where the time-integration of the interior is stopped prematurely if the $T_s$ or $\Phi$ change more than a set threshold during a single iteration.

You can do this with solve_ivp by setting events=[event_tsurf, event_phi] where event_tsurf and event_phi are functions that return a float. The return should switch from >0 to <0 when the 'event' occurs, so e.g. event_tsurf would return tsurf_old - tsurf_maxdiff - tsurf_new.

https://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.solve_ivp.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants