Residual layer
The pure-residual surface underneath solve: a ProblemDef is an immutable problem description, a Workspace holds the mutable buffers, and residual! evaluates the semi-discrete right-hand side. This is the layer to target for custom solver loops; see the User Guide's solver-configuration chapter.
Problem definition and workspaces
Pyrolysis.Problem.SimulationMode — Type
SimulationMode{Mesh, Rad, Trans, Chi}Bundled trait carrying all four orthogonal axes as type parameters. The residual takes SimulationMode as a single parameter so adding new axes does not multiply method-table size.
Pyrolysis.Problem.StateLayout — Type
StateLayout — unified state-vector descriptor.
Describes the packing of the state vector u in terms of the bundled SimulationMode. Block layout (T, then ξ, then optional z, then optional χ) is the single source of truth for every pack / unpack / view operation in the package.
Block presence is strictly determined by SimulationMode:
- T and ξ blocks are always present.
- z block is present iff
mesh_mode(mode) isa ALE. - χ block is present iff
chi_mode(mode) isa WithChi.
Type Parameters
NC: number of componentsMode <: SimulationMode: bundled trait
Block-major offsets (1-based, with n = n_cells)
- T:
1 .. n - ξ:
n + (j-1)*n + (1..n)forj ∈ 1:NC - z:
n*(1+NC) + (1..n_nodes)(ALE only) - χ: trailing block of length
n(only ifWithChi)
Pyrolysis.Problem.ProblemDef — Type
ProblemDef — immutable problem definition.
A ProblemDef carries the unchanging contract of a pyrolysis problem: material, topology, boundary conditions, simulation mode and runtime options. Every mutable cache lives in Workspace instead.
This split makes the residual a pure function of (du, u, def, t, ws), so parameter sweeps, sensitivity analysis and the Jacobian backends share one problem definition.
Field access is direct: read def.material, def.topology, def.bcs, def.mode, def.options. The single helper is get_option for fallback semantics on the runtime-options NamedTuple.
Type Parameters
M: Material typeTop: MeshTopology typeB: BoundaryConditionSet typeMode: bundled SimulationMode typeOpts: NamedTuple of runtime options
Pyrolysis.Problem.Workspace — Type
Workspace — mutable container that owns every per-step cache and work array used by the unified residual.
The Workspace is the only place where mutable per-step state lives. Material, boundary conditions, and the radiation model are read from def::ProblemDef (the immutable side); the workspace does not duplicate them.
Every cache is parameterized so that Nothing can appear as a concrete type parameter rather than as a Union{Nothing, T}. Trait dispatch on the type — not runtime isnothing checks — decides whether to touch a cache.
Type Parameters
NC: number of componentsMode: bundledSimulationMode(matches the parentProblemDef)Tu: scalar eltype carried by the live state (Float64for the canonical workspace;ForwardDiff.Dual{Tag, Float64, N}for the AD workspace allocated by an AD Jacobian backend)MeshT: Reference to the mutableMesh1Dcarrying connectivity and per-step geometry. The mesh is read-only during residual / Jacobian assembly; writes happen only between integrator-accepted steps viaStepUpdateCallback. Kernels only read connectivity (cell IDs, face IDs, neighbor lookups, boundary tags) off the mesh; live state and state-derived geometry live instate_cache.GeomT:MeshGeometry(built from the mesh at construction, not updated afterwards; not read by the 1D residual)LayoutT:StateLayoutdescriptorRadCacheT:Properties.RadiationCachefor P1;NothingotherwiseStateCacheT:StateCache{NC, Tu, Mode}— typed mirror of the live state populated at every residual entryDryIdxT:NTupleof the dry-pyrolysis-gas component indicesDarcyT: thePropertyCache's Darcy sub-cache type (Nothingfor Fickian transport)
Pyrolysis.Problem.to_problem_def — Function
to_problem_def(problem::PyrolysisProblem; use_ale=false,
radiation_model=NO_RADIATION,
radiation_intensity=0.0,
radiation_kirchhoff=true) -> ProblemDefLift a user-facing PyrolysisProblem into the immutable ProblemDef. The returned object shares the underlying material/BC data with the input and carries no mutable mesh state.
radiation_kirchhoff records the surface-transmissivity convention for the Beer–Lambert injection: true (the default) means radiation_intensity is the bare incident flux and the live surface-cell ε_eff is applied at injection (Kirchhoff α = ε); false means the RadiativeFluxBC's explicit absorptivity is already folded into the intensity. solve() derives it from the top thermal BC.
The effect of outgassing on convective exchange is a property of each ConvectiveBC (its blowing model), not a solve option: the surface balance feeds every convective member the outward gas mass flux at its face and the model returns the coefficient ratio. This modifies the convective coefficient, not the gas enthalpy accounting, which stays with the volumetric source S_conv. See Discretization.blowing_state.
Pyrolysis.Problem.build_workspace — Function
build_workspace(problem::PyrolysisProblem, def::ProblemDef) -> WorkspaceBuild the Float64 Workspace that owns every per-step cache and work array used by the unified residual. Each cache is sized to the current mesh and component count. AD Jacobian backends allocate a Dual-typed twin with build_ad_workspace.
The mesh carried by the workspace is the same mutable Mesh1D referenced by problem. The mesh is read-only during residual / Jacobian assembly; live state lives in ws.state_cache and is written back to the mesh only between accepted timesteps via StepUpdateCallback.
Pyrolysis.Problem.build_ad_workspace — Function
build_ad_workspace(def::ProblemDef, ws::Workspace, ::Type{Tu}) -> WorkspaceBuild a parallel Workspace{NC, Mode, Tu} whose state cache, property cache, RHS cache, and physics work arrays carry scalar eltype Tu (typically ForwardDiff.Dual{Tag, Float64, N}), sharing the canonical workspace's mesh, layout, boundary IDs, and runtime settings.
Used by AD Jacobian backends to keep a Dual-typed workspace alongside the Float64 one — the residual then dispatches on eltype(ws.dT_work) == Tu end-to-end without per-call reallocation.
The mesh is shared (same identity), reflecting the read-only mesh contract during residual / Jacobian assembly.
Pyrolysis.Residual.residual! — Function
Unified ODE right-hand side for the pyrolysis package.
function residual!(du, u, def::ProblemDef, t, ws::Workspace) -> nothingThis is the single RHS for all non-P1 simulations. The trait dispatch chain is:
residual!(du, u, def, t, ws)
→ _residual!(du, u, def, t, ws, mesh_mode(def.mode))
::Eulerian → Eulerian path
::ALE → ALE pathInside each path, the gas transport law follows the property cache (a Darcy sub-cache exists only in DarcyFick mode) and the χ block is included iff chi_mode(def.mode) isa WithChi.
P1 radiation has its own residual in Pyrolysis.Experimental.RadiationP1 and is not routed through this entry point.
Contract
defis immutable — safe to share across threads / sweep workers.wsis mutable — one per worker.tis a plainReal; the kernel must accept whatever scalar typedu/ucarry (Float64,ForwardDiff.Dual, …).
State-vector layout and accessors
Pyrolysis.Problem.state_length — Function
state_length(l::StateLayout) -> IntReturn the total length of the state vector encoded by this layout.
Pyrolysis.Problem.create_state_vector — Function
create_state_vector(layout::StateLayout, mesh) -> Vector{Float64}Allocate a fresh state vector sized to layout and pack the current mesh state into it.
Packs the mesh as-is: it does not consult the problem's initial-condition callables or populate mesh.m_dry_solid_initial. For building u0, use initialize_state (the canonical path, which solve() also takes) or call apply_initial_conditions!(problem) first — otherwise u0 silently carries the mesh constructor's placeholder state.
Pyrolysis.Problem.pack_state! — Function
pack_state!(u, mesh, layout::StateLayout) -> uPack the mesh's cell_states (and node positions when ALE; χ when WithChi) into the flat ODE state vector u. Mode is read from the layout's type parameter.
Pyrolysis.Problem.update_mesh_from_state! — Function
update_mesh_from_state!(mesh, u::AbstractVector{Float64}, layout::StateLayout) -> meshMirror an integrator-accepted Float64 state vector into the mutable mesh. Called by StepUpdateCallback between timesteps so AMR, depletion checks, and post-processing read a consistent mesh.
This function is not invoked during residual / Jacobian assembly — those are pure functions of u and the typed state_cache. The mesh is read-only during assembly.
Pyrolysis.Problem.block_view — Function
block_view(u, l::StateLayout, ::Val{:T}) -> view of T block
block_view(u, l::StateLayout, ::Val{:ξ}, j::Int) -> view of component j
block_view(u, l::StateLayout, ::Val{:z}) -> view of node-position block (ALE)
block_view(u, l::StateLayout, ::Val{:χ}) -> view of pyrolysis-progress block (WithChi)Compile-time-dispatched view into the named block of u. Returns an empty view when the block does not exist for the layout's mode.
Pyrolysis.Problem.get_temperature — Function
get_temperature(u, layout, i) -> RealPyrolysis.Problem.get_concentration — Function
get_concentration(u, layout, i, j) -> RealPyrolysis.Problem.get_node_position — Function
get_node_position(u, layout, i) -> RealOnly valid for ALE layouts.
Pyrolysis.Problem.get_node_positions — Function
get_node_positions(u, layout) -> viewView of node positions for ALE layouts.
Pyrolysis.Problem.get_thickness_from_state — Function
get_thickness_from_state(u, layout) -> RealCompute current domain thickness z_top - z_bottom from the ALE state. Returns 0 for Eulerian layouts.
Pyrolysis.Residual.column_chi_bar_from_state — Function
column_chi_bar_from_state(u, layout, mesh) -> RealMass-weighted column-averaged χ̄. AD-Dual safe (numerator carries duals, denominator from the immutable m_dry_solid_initial). Thin wrapper over the single implementation _chi_bar_from_state, which also returns the column dry-solid mass used by update_cross_section_area!.
Pyrolysis.Residual.cross_section_area_from_state — Function
cross_section_area_from_state(mesh, material, u, layout) -> RealCurrent column cross-sectional area implied by the χ block. Returns mesh.cross_section_area_initial for identity-law materials.