One-Dimensional Reacting Flows#

Domain1D

Wrapper around a single Cantera 1-D domain (a boundary such as an inlet/outlet, or a flow region). Domains are normally created and managed by a FreeFlame; the accessors here let you inspect and set profiles on an individual domain. Domains borrow the gas Solution handle and are freed together with the owning simulation.

n_points(d::Domain1D)

Number of solution points (grid nodes) in the domain.

n_points(flame::FreeFlame)

Number of grid points in the flow domain.

domain_type(d::Domain1D)

Domain type string (e.g. “free-flow”, “inlet”, “outlet”).

grid(d::Domain1D)

Grid points of the domain [m].

grid(flame::FreeFlame)

Grid points of the flow (flame) domain [m].

value(d::Domain1D, component::AbstractString)

Scalar value of component in a boundary domain (a single-point domain).

solution_profile(d::Domain1D, component::AbstractString)

Per-point profile of component across the domain grid.

solution_profile(flame::FreeFlame, component::AbstractString)

Per-point profile of component in the flow domain.

set_profile!(domain, component, positions, values)

Set the profile of component over normalized positions positions (in [0, 1], spanning the domain) with the given values.

set_flat_profile!(d::Domain1D, component::AbstractString, value)

Set a spatially uniform value of component across the whole domain.

setup_uniform_grid!(d::Domain1D, points::Integer, length::Real, start::Real)

Set a uniform grid of points nodes spanning [start, start+length] [m].

setup_grid!(d::Domain1D, z)

Set an explicit grid from a vector of positions [m].

FreeFlame(gas; width=0.03)

Assemble a freely-propagating premixed flame from the current state of gas, mirroring Python’s cantera.FreeFlame. The unburned mixture state (temperature, pressure, composition) is taken from gas at construction time.

The flame consists of three domains in solver order: an inlet boundary, a free-flow region of the given width [m], and an outlet boundary. The flow domain starts on the same non-uniform grid Python uses, which solve! then regrids and refines, so the node count is not a constructor option. Call solve! to compute the solution; the laminar flame speed is then available from flame_speed.

set_refine_criteria!(flame; ratio=10.0, slope=0.8, curve=0.8, prune=0.0)

Set the grid-refinement criteria on the flow domain (domain index 1). Defaults match Python’s FlameBase.set_refine_criteria.

set_refine_criteria!(flame::BurnerFlame; ratio=10.0, slope=0.8, curve=0.8,
prune=0.0)

Set the grid-refinement criteria on the flow domain (domain index 1).

set_inlet!(flame; T=nothing, X=nothing, mdot=nothing)

Update the inlet (reactants) boundary temperature, composition and/or mass flux.

set_fixed_temperature!(flame::FreeFlame, T::Real)

Fix the flame temperature at T [K], as used by the free-flame eigenvalue solve.

solve!(flame; loglevel=0, refine_grid=true, auto=true)

Solve the flame.

With auto=true (the default) this follows Python’s FreeFlame.solve(auto=True): an internal staged multi-grid schedule wrapped in a domain-widening loop. After each staged solve the temperature gradients at the domain edges are checked; if the flame is too close to a boundary the grid is doubled (and refined) and the staged solve is repeated, up to 12 times.

!!! note Python additionally installs the width check as a steady-state callback inside the C++ solver, so it can abort and widen mid-solve. The CLib does not expose steady callbacks, so here the identical width criterion is applied after each completed staged solve instead. This is the one piece of the reference algorithm that is emulated externally rather than in-solver; the final converged result is unaffected for the usual case.

With auto=false a single sim1D_solve(loglevel, refine_grid) is issued using the current refine criteria (advanced use).

solve!(flame::BurnerFlame; loglevel=0, refine_grid=true, auto=true)

Solve the burner-stabilized flame. With auto=true a staged multi-grid schedule is used; with auto=false a single sim1D_solve is issued using the current refine criteria. Unlike a free flame there is no flame-speed eigenvalue or fixed-temperature anchor; the burner mass flux is a fixed input.

flame_T(flame::FreeFlame)

Temperature profile across the flame [K].

flame_velocity(flame::FreeFlame)

Axial velocity profile across the flame [m/s].

flame_X(flame::FreeFlame, species::AbstractString)

Mole-fraction profile of species across the flame.

flame_speed(flame) -> Float64

Laminar flame speed [m/s]: the inlet (unburned) axial velocity. For a freely propagating flame the inlet mass flux is an eigenvalue updated by the solver, so this reads the current inlet mdot and divides by the unburned density.

BurnerFlame(gas; width=0.03, mdot=nothing)

Assemble a burner-stabilized flat flame from the current state of gas, mirroring Python’s cantera.BurnerFlame. The unburned mixture state (temperature, pressure, composition) is taken from gas at construction time.

Unlike a FreeFlame, the burner inlet has a user-prescribed mass flux mdot [kg/m^2/s]; there is no flame-speed eigenvalue and no fixed-temperature anchor. If mdot is not given it defaults to 0.4 * ρ_unburned.

The flame consists of three domains in solver order: a burner (inlet) boundary, an unstrained-flow region of the given width [m], and an outlet boundary. Call solve! to compute the solution. Use set_burner! to change the burner temperature, composition, or mass flux.

set_burner!(flame; T=nothing, X=nothing, mdot=nothing)

Update the burner (reactants) boundary temperature, composition and/or mass flux [kg/m^2/s].

burner_mdot(flame::BurnerFlame)

Prescribed burner mass flux [kg/m^2/s].