Heat transport
The energy equation is solved implicitly on the FE grid (src/physics/Heat.jl, driven by solve_heat_step! in src/time_stepping/Driver.jl) with sources assembled in src/physics/HeatSources.jl. Temperature advection is, by default, handled in the Lagrangian frame by the markers (PIC pattern below), so the grid solve is a pure diffusion + source step.
Strong form and backward-Euler discretization
where
Testing with build_heat_forms):
Temperature uses Q1 elements (fe_order_T = 1). The system is solved with a cached MUMPS factorization (CachedMumps in state.heat_solver_cache) — the sparsity pattern is constant across steps, so only the numeric factorization repeats.
Density convention: the heat equation uses the constant Boussinesq reference density, rho_ref_heat formulation = "tala" the reference density rho_ref_heat (heat_density), in the heat solve, in the subgrid
Thermal conductivity
Each marker's conductivity is (marker_conductivity, src/materials/Density.jl)
with thermal_conductivity (k_T_exponent (k_P_coeff (k_radiative (
about 0.05 W/m/K at 735 K and 0.32 at 1700 K (coefficients as quoted by McKenzie et al. 2005). Cell conductivity is the harmonic mean over the markers in the cell.
Xu, Y., Shankland, T. J., Linhardt, S., Rubie, D. C., Langenhorst, F., & Klasinski, K. (2004). Thermal diffusivity and conductivity of olivine, wadsleyite and ringwoodite to 20 GPa and 1373 K. Phys. Earth Planet. Inter., 143–144, 321–336. doi:10.1016/j.pepi.2004.03.005
Hofmeister, A. M. (1999). Mantle values of thermal conductivity and the geotherm from phonon lifetimes. Science, 283, 1699–1706.
McKenzie, D., Jackson, J., & Priestley, K. (2005). Thermal structure of oceanic and continental lithosphere. Earth Planet. Sci. Lett., 233, 337–349.
Stabilized FE advection (optional)
With do_supg_heat = true (or heat_stabilisation = "supg"), the FE field advects temperature directly and the cell-Péclet > 1 regime is stabilized by SUPG: the test function is augmented
with the Codina (2000) parameter
so
heat_stabilisation = "entropy" instead adds residual-driven artificial diffusion (Guermond–Pasquetti–Popov 2011; entropy_viscosity in src/physics/EntropyViscosity.jl):
with solve_heat_step!). Default is heat_stabilisation = "none" (PIC advection, diffusion-only FE operator).
Boundary conditions
Configured per wall in [boundary_temperature] (build_heat_flux_bcs in Heat.jl; Dirichlet values in src/boundary_conditions/Temperature.jl):
bcT_surface / bcT_deep | Weak-form contribution | Keys |
|---|---|---|
"dirichlet" (default) | strong, via the FE space: T_top (surface), T_bot (deep) | T_top, T_bot |
"flux" | q_surface, q_deep (W/m²) | |
"robin" | h_robin, T_amb | |
"insulating" | natural zero-flux Neumann, no contribution | — |
Lateral walls are insulating by default.
Heat sources
build_heat_source (src/physics/HeatSources.jl) assembles CellField expressions that track the current FE solution:
Radiogenic (
do_radiogenic = true): per-cell marker mean of the per-rockradiogenic_heating(W/m³; typical continental crust, oceanic crust, mantle), held in state.ht_c.Constant / functional:
H_constadds a uniform W/m³ everywhere;cfg.H_fn(set programmatically, not from TOML) evaluatesat cell centres — used by prescribed-source benchmarks. Shear heating (
do_shear_heating = true): viscous dissipation; with MILET's invariant convention this is built from the cell fields
eta_c(the effective, so only the visco-plastic part dissipates) and eii_c.Adiabatic (
do_adiabatic = falseby default):with the hydrostatic simplification : positive for downward flow (
in the y-down convention — sinking material heats). Implemented with a representative K⁻¹, rho_ref_heat,gy. Underformulation = "tala"this term isand is always on; do_adiabaticis not used.Latent (phase change + melting):
, accumulated on markers by apply_marker_phase_and_melt!and passed in as the per-cell vectorH_marker_c. Marker contributions are averaged per cell, not summed, so dense marker packing cannot inflate the source. Sign convention:endothermic. See Phase changes and Melting.
PIC temperature pattern
Markers carry temperature; how they exchange it with the grid is set by marker_T_mode ([temperature], default "pic_increment" in cases/_defaults.toml). The per-step sequence in src/time_stepping/Driver.jl is:
pic_incrementonly — project markerto cell means ( project_marker_T_to_cells) and L2-fit the piecewise-constant field onto Q1 (_project_cellfield_to_T, bound-preserving: the projection is clamped to the marker-data range widened to the Dirichlet endpoints), stamping the post-advection marker temperature intostate.Th.Optional subgrid diffusion (below); its gridded change is subtracted from the grid increment in step 4.
FE heat solve (
solve_heat_step!) →with diffusion + sources. Marker update (
update_marker_temperatures!insrc/particles/Projection.jl):
mode = :pic_increment:(minus the gridded subgrid change, when subgrid diffusion is on) — the I2ELVIS/PIC pattern: markers keep their advected temperature identity and absorb only the diffusion + source increment. Required for vigorous convection (Blankenbach-class) and for cold slabs that must not lose their thermal identity. mode = :overwrite:— markers track the FE field entirely. Caveat: combined with the default diffusion-only heat operator, temperature then does not advect at all; use overwriteonly deliberately, e.g. together withdo_supg_heat = trueso the FE operator supplies the advection.
Subgrid diffusion (Gerya & Yuen 2003)
With do_subgrid_diffusion = true, apply_subgrid_diffusion! (src/particles/Projection.jl) relaxes each marker toward the grid-interpolated temperature
with subgrid_d (default 1.0). This suppresses the marker–grid temperature inconsistency that otherwise accumulates in PIC thermal convection and stalls it at fine grids. The correction only acts in pic_increment mode and is restricted to uniform Cartesian meshes.
The relaxed change
(subgrid_scheme = "gerya_yuen", the default). The grid field built from cell means is slightly biased by where markers sit inside their cells; the subtraction cancels that systematic part, so only genuine sub-cell deviations relax. The earlier implementation instead re-projected the relaxed markers and diffused that field (subgrid_scheme = "reproject", kept only to reproduce old runs). It re-applied the projection bias every step, which accumulated as a slow artificial drift: 20–57 K of lateral temperature spread in a static stagnant lid, where the full scheme gives 0.1 K, and Blankenbach 1a at 65×65 off by −5.9 % in Nu and +4.6 % in
Bound-preserving clamp
Galerkin/BE produces small over/undershoots near sharp gradients (sticky-air interface, slab tips) that compound over many PIC steps. _heat_clamp_bounds (src/time_stepping/Driver.jl) computes per-step bounds from the pre-solve field range united with the Dirichlet endpoints, widened by a 5 % slack:
The rationale: by the maximum principle, pure BE diffusion cannot exceed the pre-solve range; the slack admits legitimate source-driven growth (shear/radiogenic/latent heating) per step. The same bounds are applied to the FE dofs after the solve and to the marker temperatures in update_marker_temperatures!, so grid and markers stay consistent. (Clamping to the Dirichlet endpoints alone — an earlier scheme — flattened internal anomalies hotter than the boundary range.)
Time-step interaction
compute_dt (src/time_stepping/CFL.jl) limits
Key reference
| Config key | Default | Meaning |
|---|---|---|
do_heat | true | solve the energy equation |
T_top, T_bot | 273, 1623 K | Dirichlet surface / bottom temperature |
rho_ref_heat | 3300 | constant |
marker_T_mode | "pic_increment" | pic_increment (ΔT → markers) or overwrite (FE → markers) |
heat_stabilisation | "none" | none (PIC) | supg | entropy |
do_supg_heat | false | legacy alias for SUPG-stabilized FE advection |
do_subgrid_diffusion, subgrid_d | false, 1.0 | Gerya–Yuen marker-grid relaxation |
subgrid_scheme | "gerya_yuen" | "gerya_yuen" (subgrid change subtracted from the grid increment) or "reproject" (legacy, drifts) |
do_radiogenic, do_shear_heating, do_adiabatic | true, true, false | source toggles |
H_const | 0.0 | uniform extra source (W/m³) |
bcT_surface, bcT_deep | "dirichlet" | dirichlet | flux | insulating | robin |
q_surface, q_deep, h_robin, T_amb | 0, 0, 0, 298.15 | flux / Robin BC data |
radiogenic_heating (per [[rock]]) | — | |
specific_heat, thermal_conductivity (per [[rock]]) | — | |
k_T_exponent, k_P_coeff, k_radiative (per [[rock]]) | 0, 0, 0 |