Skip to content

Energy budget and heat-flow diagnostics ​

A model that leaks heat can still produce plausible temperatures, velocities and Nusselt numbers. MILEVA therefore logs a discrete energy budget with every row of diagnostics.csv, built from the same fluxes and the same time weighting the solver uses, so its residual tests conservation rather than sampling. This page defines the budget columns and the Nusselt numbers.

The budget ​

The thermal energy of the domain is

Eth=ρ0cp∑cTcVc,

with Vc the cell measure of the run's geometry (cell_areas and cell_volumes), scaled to physical walls: in the spherical annulus each column stands for 1/Nt of a full sphere, so a wall has area 4πr2; in the cylinder the budget is per unit length, 2πr. The diagnostics use cp=1250 J kg−1K−1, the value the diffusion solver uses.

Each step the main loop accumulates the energy supplied,

Ebnd+=Δt(Pin−Pout+Pint),P=θP(Tn+1)+(1−θ)P(Tn),

where Pin and Pout are the core-mantle boundary and surface powers from boundary_power(Tg, grid, cfg), θ is the diffusion solver's own implicitness (cfg.implicitTheta when useImplicitTemp, else 0), and Pint is the internal heating the solver actually applied in that call (internal_power_last(): radiogenic, latent, heat pipe and any uniform source). Between two CSV rows the residual is

budget_resid=ΔEthΔtrow−ΔEbndΔtrow⟨max(|Pout|,|Pint|)⟩row,

normalised by the larger of the surface power and the internal power, taken every step and averaged over the interval (E_out_cum in main_SphCon.jl), so an internally heated run with a small surface flux still has a meaningful denominator. A conservative scheme gives zero whatever the heating mode.

ColumnMeaning
E_th_JEth at this row
dEdt_Wmean dEth/dt since the previous row
P_supplied_Wmean supplied power since the previous row (boundaries plus internal heating)
budget_residthe residual above; the log line prints it as bud=
E_core_J, E_cmb_cum_J, budget_resid_jointthe same budget for core plus mantle, when the 2-D core cools (cmbHeatfluxMode = "parameterized"); NaN otherwise

E_cmb_cum_J restarts at zero when a run is resumed; difference it, never read it as an absolute value.

Conduction in the default shell (64×8, ALA) from a uniform 2500 K interior with 5 pW/kg of internal heating, advanced by diffuse_temperature with Crank-Nicolson steps of 20 Myr. Left: the change of thermal_energy and the energy supplied, accumulated from boundary_power and internal_power_last with the solver's θ=0.5; the two curves coincide. Right: the per-step residual of the budget formula. With the θ-weighted wall power it is about 10−12; using only the end-of-step or only the start-of-step power leaves a residual of 10−2 to 10−1 that decays only as the transient does, which is a timing error of the bookkeeping, not a leak. Script: docs/scripts/fig_numerics_energy_budget_sections.jl.

Wall fluxes and Nusselt numbers ​

The wall temperatures are held at the faces Rin and Rout through a half-cell ghost (see Temperature transport), and the reported fluxes are exactly the ones the diffusion operator uses:

qtop=−kTsurf−TNrRout−rNr,qbot=−kT1−Tcmbr1−Rin,

averaged over the wall cells. The Nusselt numbers divide them by the conductive flux of the same geometry. Steady conduction has rmkdT/dr constant, so

qcond(r)=Crm,C=Tcmb−Tsurf∫RinRoutdrrmκ(r),Nutop=|qtopqcond(Rout)|,Nubot=|qbotqcond(Rin)|,

(compute_diagnostics in utils/compute_diagnostics.jl, conductive_baseline_C in physics/compressibility.jl). Flux and baseline use the diffusivity the model transports with, which matters under ALA where κ rises toward the core. In 3-D the baseline is C/r2.

Two internal checks follow. On a conducting field Nu = 1, and at a steady state with basal heating Nutop = Nubot, because the same power crosses every shell. Neither depends on any published reference value. tests/test_nusselt_conduction.jl asserts both forms on the solver's own conducting steady state: Nu converges to 1 (error 10−3 falling to 5×10−5 with refinement) and a one-step budget residual is 2×10−15.

Left: the top of a conducting steady state on a 16-cell column. The surface temperature is held at the face Rout, half a cell above the top cell centre, and the reported flux is the slope of the red segment, k(TNr−Tsurf)/(12Δr); the open circle is the reflected ghost used by the advection schemes. Right: Nu_top and Nu_bot from compute_diagnostics while a uniform 2000 K interior relaxes to conduction (Nr=64, ALA, backward Euler). Both fall to 1 (1.000014 and 0.999950 at the end) and agree with each other once the state is steady, as the two internal checks require. Script: docs/scripts/fig_numerics_energy_budget_sections.jl.

Measured residuals ​

tests/test_marker_energy.jl pins the marker step: energy delivered equals energy computed to 3×10−15 in 2-D and 5×10−11 in 3-D.

Residuals on the Hernlund & Tackley (2008) spherical-annulus verification runs (window means; the benchmark comparison itself is documented elsewhere):

CaseNrbudget_resid
Ra = 104, isoviscous128−0.0004
Ra = 105, isoviscous128−0.001
Ra = 105, viscosity contrast 10664+0.0015
Ra = 105, isoviscous, start-up transient32+0.003 per 500-step window
Ra = 105, temperature on the grid with TVD64+0.011

diagnostics.csv of the Ra = 105 isoviscous verification run at Nr=128. Top: the change of thermal energy and the net wall power, which lie on top of each other through the start-up transient and the time-dependent state. Bottom: budget_resid, scattered between about −0.01 and +0.01.

Sources of small residuals ​

  • Reseeding. A cell that has emptied completely gets markers with temperatures interpolated from the grid; that is the one non-conservative marker operation (see Markers).

  • The delivery cap. Energy withheld by cfg.deliveryScaleMax at sparsely populated nodes appears in the residual.

  • Temperature clamps. The bounds applied after diffusion and after the hand-back remove energy only when they bind, which on a well-resolved run they do not.

  • Grid TVD advection gives a slightly larger residual, as the table shows.

The delivery cap as a residual source. Left: the factor Vc/Wc that measure-scaled delivery applies at each node of a 64×256 Boussinesq annulus, for the markers of init_markers (9 per cell) and after 600 CFL steps through one fixed two-cell Stokes flow with no reseeding. Advection widens the distribution and pushes a few nodes past deliveryScaleMax = 2. Right: row means and row maxima with depth; the cap binds mostly in single cells and in the bottom wall row. For a uniform increment the cap withholds 4.8×10−4 of the energy in this state, which then appears in budget_resid. Script: docs/scripts/fig_numerics_energy_budget_sections.jl.

3-D ​

In 3-D the row is computed on the Yin patch only (E_th "this patch only" in diagnostics_row), with the patch's own wall areas. Because the Yin patch overlaps Yang (see Markers), the 3-D budget_resid is a diagnostic of that patch rather than a global budget.

Left: the Yin patch (black rectangle) and the boundary of the Yang patch mapped into Yin's frame with yy_yang_to_yin, sampled with random points on the sphere. Each patch covers 53.0 % of the sphere and they overlap on 6.0 % (orange). Right: the 3-D budget row integrates the Yin patch only; cell_volumes gives 0.530 of the shell at Nθ=12, so the row covers about half the mantle and includes the overlap band that Yang also holds. Script: docs/scripts/fig_numerics_energy_budget_sections.jl.

Where in the code ​

TopicFileFunction
Budget accumulationmain_SphCon.jlstep (14), E_bnd_cum, E_out_cum, E_cmb_cum
Wall powersutils/diagnostics_csv.jlboundary_power
CSV row and residualutils/diagnostics_csv.jldiagnostics_row, _diag_row_common
Applied internal powersolvers/diffuse_temperature.jlinternal_power_last
Nusselt numbersutils/compute_diagnostics.jlcompute_diagnostics
Conductive baselinephysics/compressibility.jlconductive_baseline_C
Teststests/test_nusselt_conduction.jl, test_marker_energy.jl, test_conduction_conservation.jl, test_energy_consistency.jl