Atomic elements

An atomic element is a single, irreducible network element with its own residual kernel — as opposed to a composite, which expands to a graph of atomics at build time. (The codebase calls them atomic; base / primitive would be synonyms.) Every element maps to one integer residual_id — the @njit dispatch key in nefes.elements.ids — and is constructed from nefes.elements.catalog.

How an element is defined

State lives on edges (intermediate flow states); an element is a node that imposes residual equations coupling its incident edges. The band-1 unknowns per edge are the mass flow \dot m, the static pressure p and the total enthalpy h_t (plus transported scalars — mixture fractions, the burnt marker). An element of degree d (its port count) contributes:

  • 1-port boundary/termination — a single row: either a mass-flux row (\dot m pinned) or an absolute-pressure row (p or p_t pinned).
  • interior element (d \ge 2) — one mass-balance row plus d-1 pressure-coupling rows (the row-kind map is nefes.elements.ids.row_kind_tags, the single source of truth).

The flow area is a property of each edge, not the element: edges are wired as (tail_node, head_node, area), so an area-change element simply reads the differing areas of its two incident edges. Every element also takes a name (a display label; sub-elements of a composite are namespaced under it).

All residual math is complex-step-safe (smooth, complex-analytic, no abs/min/max/ branches on the flow state); Jacobians come from complex-step differentiation.

Acoustic contribution. In the perturbation problem the operator is

\mathbf{A}(\omega) = \overline{\mathbf{J}} + \mathrm{i}\omega\, \mathbf{M} + \mathbf{P} + \mathbf{S}.

Most elements contribute only through \overline{\mathbf{J}} (the complex-step linearization of their mean residual). Three add blocks beyond that default: duct/pipe add the phase-propagation stamp \mathbf{P}(\omega); cavity (and a plenum junction/splitter) add the storage block \mathbf{M}; the flames carry an unsteady heat-release source \mathbf{S}(\omega) on their DynamicSource descriptor. Single-port boundaries can also carry an explicit PerturbationBC (reflection/impedance); left at None they inherit the linearization of their own mean row.

The catalogue

Element residual_id Ports Imposes (mean residual) Acoustic contribution
mass_flow_inlet MASS_FLOW_INLET (0) 1 \dot m = \dot m_\text{spec}\ge 0; feeds h_t(T_t), composition inherited (\dot m'=0)
total_pressure_inlet PT_INLET (1) 1 p_t = p_{t,\text{spec}}; feeds h_t(T_t), composition inherited
pressure_outlet P_OUTLET (2) 1 p = p_\text{spec}; backflow stream on ingestion inherited
mass_flow_outlet MASS_FLOW_OUTLET (15) 1 \dot m = \dot m_\text{spec}>0; p floats inherited (\dot m'=0)
choked_nozzle_outlet CHOKED_NOZZLE_OUTLET (16) 1 \dot m = \dot m^{*}(p_t,T_t,A^{*}) inherited (Marble–Candel)
wall WALL (11) 1 \dot m = 0 hard wall R=+1
cavity CAVITY (18) 1 \dot m = 0 (wall to mean flow) storage \mathbf{M}, C=V/(\varrho c^2)
isentropic_area_change ISEN_AREA_CHANGE (3) 2 mass + p_{t,0}=p_{t,1} across an area change default (+\mathbf{M} if length-bearing)
sudden_area_change SUDDEN_AREA_CHANGE (4) 2 mass + Borda–Carnot / vena-contracta loss default
loss LOSS (5) 2 mass + \Delta p_t = K\cdot\tfrac12\varrho u^2 default (+\mathbf{M} if length-bearing)
linear_resistance LINEAR_RESISTANCE (17) 2 mass + \Delta p_t = R\,\dot m default (+\mathbf{M} if length-bearing)
duct DUCT (8) 2 mass + equal-area p_t continuity phase \mathbf{P}(\omega)
pipe PIPE (20) 2 mass + Darcy–Weisbach K=fL/D phase \mathbf{P}(\omega)
heat_release_flame FLAME_HEAT_RELEASE (12) 2 mass + p_t continuity, \Delta h_t=\dot Q/\dot m default (+\mathbf{S}(\omega) if dynamic)
equilibrium_flame FLAME_EQUILIBRIUM (13) 2 mass + static-p + h_t + Z conserved default (+\mathbf{S}(\omega) if dynamic)
mass_source MASS_SOURCE (14) 2 mass/momentum/energy/composition injection default
junction JUNCTION (6) variable common static pressure p_i=p_0 default (+\mathbf{M} if plenum)
splitter SPLITTER (7) variable common total pressure p_{t,i}=p_{t,0} default (+\mathbf{M} if plenum)
mixer MIXER (22) variable common effective total pressure p_{t,i}^{\text{eff}}=p_{t,0}^{\text{eff}} (second law) default
forced_splitter FORCED_SPLITTER (19) variable \dot m_{\text{out},k}=\beta_k\dot m_\text{in} default
supersonic inlet/outlet (9 / 10) 1 reserved — deferred (v1 is subsonic)

Below, the parameter tables list only each element’s own arguments; every constructor also accepts name (a label). Optional acoustic hooks — perturbation_bc (1-port boundaries) and dynamic_source (flames, source) — are noted per element.

Boundaries

mass_flow_inlet(mdot, Tt, composition=None, basis="mole", marker=0.0)

Pins the edge mass rate and feeds a stream: an inflow boundary with \dot m \ge 0 (negative is rejected — use pressure_outlet for a reversing boundary).

\dot m = \dot m_\text{spec}, \qquad h_t = h_t(T_t,\ \text{composition}).

Argument Symbol Meaning Units Default / constraint
mdot \dot m_\text{spec} prescribed inflow mass rate kg/s required, \ge 0
Tt T_t feed total temperature K required
composition feed species mixture, e.g. {"O2":0.21,"N2":0.79} None (perfect-gas)
basis units of composition "mole" / "mass" "mole"
marker b injected burnt-marker (0 fresh, 1 burnt) 0.0

total_pressure_inlet(pt, Tt, composition=None, basis="mole", marker=0.0)

Pins the edge total pressure (the mass rate emerges from the interior) — the natural inlet when a reservoir total pressure is known.

p_t = p_{t,\text{spec}}, \qquad h_t = h_t(T_t,\ \text{composition}).

Argument Symbol Meaning Units Default / constraint
pt p_{t,\text{spec}} prescribed total pressure Pa required, >0
Tt T_t feed total temperature K required
composition, basis, marker as mass_flow_inlet as above

pressure_outlet(p, Tt_backflow=300.0, composition=None, basis="mole", marker=0.0)

Pins the edge static pressure. The only boundary that models ingestion / backflow: on inflow it draws the backflow stream in at T_{t,\text{back}}. Its choked/unchoked behaviour is emergent (complementarity against the prescribed back-pressure), so it is the boundary for a flow that may reverse or un-choke.

p = p_\text{spec}.

Argument Symbol Meaning Units Default / constraint
p p_\text{spec} prescribed static pressure Pa required, >0
Tt_backflow T_{t,\text{back}} total temperature of ingested backflow K 300.0
composition, basis, marker backflow stream (on ingestion) as inlet

mass_flow_outlet(mdot)

Pins the outflow rate with the static pressure floating — a metered exhaust, or the mean-flow partner of a downstream choked throat. Inherited acoustic termination \dot m'=0. Outflow only.

\dot m = \dot m_\text{spec} > 0.

Argument Symbol Meaning Units Default / constraint
mdot \dot m_\text{spec} prescribed outflow mass rate kg/s required, >0
perturbation_bc acoustic termination None\dot m'=0

choked_nozzle_outlet(throat_area)

Asserts a sonic (M=1) throat of area A^{*} just past the outlet plane: the outflow is the critical mass flux for the interior stagnation state, so p floats. For a perfect gas,

\dot m^{*} = A^{*}\, \frac{p_t}{\sqrt{T_t}}\, \sqrt{\frac{\gamma}{R}}\left(\frac{2}{\gamma+1}\right)^{\frac{\gamma+1}{2(\gamma-1)}}.

Because the nozzle is compact the application plane stays subsonic; the inherited termination is the compact choked-nozzle (Marble–Candel) reflection with entropy→acoustic coupling. A^{*} < A_\text{outlet} (a contraction) is enforced.

Argument Symbol Meaning Units Default / constraint
throat_area A^{*} sonic-throat area required, >0, <A_\text{outlet}
perturbation_bc acoustic termination None → Marble–Candel reflection

wall(perturbation_bc=None)

\dot m = 0 on its single edge — the leg behind it is stagnant (M=0); its purpose is acoustic. By default a rigid hard wall (u'=0, R=+1), identical at M=0 to the inherited \dot m'=0. Pass perturbation_bc for a liner impedance. No physics parameters.

cavity(volume)

A wall to the mean flow (\dot m = 0, no interior mean unknowns) but a compliance to acoustics: the enclosed gas compresses isentropically, giving

C = \frac{V}{\varrho c^2}

which populates the storage block \mathbf{M}. Paired with a neck inertance (a short duct off a junction) it forms a Helmholtz resonator, f_0 = \dfrac{c}{2\pi}\sqrt{\dfrac{A_\text{neck}}{V\,l_\text{eff}}}.

Argument Symbol Meaning Units Default / constraint
volume V enclosed cavity volume required, >0

Area changes and losses

Every element here takes the optional storage lengths l_up, l_down, end_correction (all default 0, in metres): the passage half-lengths on each side give acoustic compliance (\sim l_i A_i of stored gas) and inertance (series effective length l_\text{up}+l_\text{down}+\ell_\text{end}), populating \mathbf{M} while staying inert in the mean flow.

isentropic_area_change(l_up=0.0, l_down=0.0, end_correction=0.0)

A smooth, lossless area change: mass conservation plus total-pressure continuity (p_{t,0}=p_{t,1}) with the static↔︎dynamic conversion set by each port’s edge area. By default a lengthless (compact) jump.

Argument Symbol Meaning Units Default
l_up, l_down l_\text{up}, l_\text{down} passage half-lengths (port 0 / port 1) m 0.0
end_correction \ell_\text{end} added-mass length (inertance only) m 0.0

sudden_area_change(cc=1.0, eps=None, l_up=0.0, l_down=0.0, end_correction=0.0)

Mass conservation plus a direction-dependent loss. Forward flow (small → large) follows the Borda–Carnot momentum balance; reverse flow (large → small) a vena-contracta loss

\Delta p_t = K_c\left(\tfrac12\varrho u^2\right)_\text{small}, \qquad K_c = \left(\frac{1}{c_c}-1\right)^2.

The incompressible head is accurate to O(M^2); the sudden_contraction composite is the compressible upgrade.

Argument Symbol Meaning Units Default / constraint
cc c_c contraction coefficient (reverse flow) 1.0, in (0,1]
eps \varepsilon smoothing width for the direction switch kg/s None (global)
l_up, l_down, end_correction storage lengths m 0.0

loss(K, ref_port=0, eps=None, l_up=0.0, l_down=0.0, end_correction=0.0)

Conserves mass and drops total pressure by K dynamic heads, the head signed by flow direction:

p_{t,\text{in}} - p_{t,\text{out}} = K\left(\tfrac12\varrho u^2\right)_{\text{ref\_port}}.

The static state on each port is reconstructed from that port’s own area, so the loss may straddle an area change. With storage lengths it becomes an orifice impedance Z = R(u) + i\omega L_\text{eff}/A.

Argument Symbol Meaning Units Default / constraint
K K loss coefficient (dynamic heads) required
ref_port port whose \tfrac12\varrho u^2 head K references 0 (or 1)
eps \varepsilon smoothing width kg/s None
l_up, l_down, end_correction storage lengths m 0.0

linear_resistance(R, l_up=0.0, l_down=0.0, end_correction=0.0)

Drops total pressure linearly in the mass rate:

p_{t,\text{in}} - p_{t,\text{out}} = R\,\dot m.

Because it is linear (not the quadratic head), it survives the linearization with a non-zero coefficient even at zero mean flow — the acoustic resistance of a screen/perforate/damper in a quiescent network. With storage lengths, the quiescent orifice impedance Z = R + i\omega L_\text{eff}/A.

Argument Symbol Meaning Units Default / constraint
R R resistance (total-pressure drop per unit mass flow) Pa·s/kg required, \ge 0
l_up, l_down, end_correction storage lengths m 0.0

Transport

duct(length=0.0)

Equal-area total-pressure continuity in the mean (length-independent); the length is inert in the steady residual and read only by the acoustic phase stamp \mathbf{P}(\omega) (wavenumber k = \omega/c), so it propagates waves \propto e^{\pm i k L}. Its two ports share one flow area.

Argument Symbol Meaning Units Default
length L acoustic propagation length m 0.0

pipe(length, diameter, friction_factor)

The DUCT + LOSS unification (Greyvenstein–Laurie): one element that drops total pressure with the Darcy–Weisbach coefficient

K = \frac{f\,L}{D}, \qquad p_{t,\text{in}} - p_{t,\text{out}} = K\left(\tfrac12\varrho u^2\right),

and carries its length for the acoustic phase stamp \mathbf{P}(\omega). Constant area; D is the hydraulic diameter (friction term only). Chain several with the fanno_pipe composite to resolve Fanno gradients.

Argument Symbol Meaning Units Default / constraint
length L pipe length (friction and acoustic) m required, >0
diameter D hydraulic diameter m required, >0
friction_factor f Darcy friction factor required, \ge 0

Reacting elements and sources

heat_release_flame(Qdot, dynamic_source=None)

A compact constant-area flame conserving mass and total pressure (a low-Mach compact-flame idealization neglecting the O(M^2) Rayleigh loss) while raising the total enthalpy:

\Delta h_t = \frac{\dot Q}{\dot m}, \qquad \Delta T_t = \frac{\dot Q}{\dot m\, c_p}.

With \dot Q fixed the mean flame is acoustically passive; a dynamic_source (an n\tau flame transfer function) gives it the unsteady \mathbf{S}(\omega) that drives thermoacoustic instability.

Argument Symbol Meaning Units Default / constraint
Qdot \dot Q heat-release rate W required (>0 heats)
dynamic_source \mathbf{S}(\omega) unsteady heat-release response (FTF) None (passive)

equilibrium_flame(dynamic_source=None)

The headline reacting flame: conserves mass, static pressure (low-Mach compact idealization), total enthalpy (adiabatic) and elemental composition Z. “Ignition” is the per-edge closure switch — the approach edge uses the frozen (EQ_FROZEN) closure, the product edge the equilibrium (EQ_KERNEL) closure — so the temperature rise emerges from an HP-equilibrium solve at the shared (Z, h_t, p). Acoustically passive; a dynamic_source adds the lagged \mathbf{S}(\omega). No mean-flow parameters (the composition comes from the feeds).

Argument Symbol Meaning Units Default
dynamic_source \mathbf{S}(\omega) unsteady heat-release response (FTF) None (passive)

mass_source(mdot, T, composition, u_inj=0.0, basis="mole", dynamic_source=None, marker=0.0)

Injects a stream, conserving mass, momentum and energy with source terms:

\dot m_\text{out} = \dot m_\text{in} + \dot m, \qquad \left[\varrho u^2 + p\right]_\text{out} = \left[\varrho u^2 + p\right]_\text{in} + \dot m\, u_\text{inj},

with total enthalpy and composition mixed in mass-weighted. A fuel injector is this element with a fuel composition; it performs no reaction (ignition is the flame’s job).

Argument Symbol Meaning Units Default / constraint
mdot \dot m injected mass rate kg/s required, >0
T T injected stream total temperature K required
composition injected species mixture required
u_inj u_\text{inj} axial injection velocity (momentum source) m/s 0.0 (transverse)
basis units of composition "mole"
marker b burnt-marker of the injected stream 0.0

Manifolds (variable port count)

junction(volume=0.0)

Ties all incident ports to a common static pressure: a mass balance \sum_i \dot m_i = 0 plus d-1 rows p_i = p_0. A plenum volume adds the compliance C = V/(\varrho c^2) to \mathbf{M} (inert in the mean flow) — a junction with a volume is a cavity with through-flow. A branch’s neck inertance is not a manifold parameter; model it as an explicit neck duct on that branch (exactly what helmholtz_resonator assembles).

Argument Symbol Meaning Units Default / constraint
volume V chamber volume (plenum compliance) 0.0, \ge 0

splitter(volume=0.0)

As junction, but ties the ports to a common total pressure (p_{t,i} = p_{t,0}, lossless) — the idealization when the manifold recovers dynamic head. Same optional volume.

mixer(recovery=1.0)

The general merge that obeys the second law at any port Mach number. It ties the ports to a common effective total pressure p_{t,i}^{\text{eff}} = p_{t,0}^{\text{eff}}, removing from each inflow a loss \ell_k = \chi_k\big[(1-\sigma)(p_{t,k}-p_k) + \sigma(p_{t,k}-p_t^{\min})\big], where \chi_k is the smooth inflow indicator, \sigma is recovery, and p_t^{\min} is the smooth minimum of the inflow total pressures. The node total pressure never rises above the feeds, so the mass-averaged outflow entropy never falls below the feed mean (entropy production \ge 0). Use it instead of junction where a merging port is not slow: the junction would there hand a fast branch more total pressure than the feed carries (free energy, a second-law violation and often no steady solution at all). recovery sets the loss between two limits: 1 (the default) removes only each inflow’s excess over the weakest feed, so the outlet leaves at the minimum inflow total pressure, the least dissipation the second law allows; 0 is the full dump loss of a plenum (each inflow gives up its whole dynamic head), the most dissipative and best-conditioned merge. At the default \sigma = 1 the element adds no flow resistance of its own (pressure equalities only, like the splitter), so the flow split must be pinned by the network: distributing one inflow this is automatic and \sigma = 1 is the lossless (isentropic) splitter; merging, it is well posed only when every inflow’s rate is pinned by a mass_flow_inlet or a branch resistance (a loss, orifice, or pipe) – two bare total_pressure_inlet feeds on the node leave the split under-determined, the splitter’s own requirement, and the solve warns when it detects this. Lower recovery toward 0 for the robust dump when the feeds are not otherwise pinned: each inflow’s dump term is then a self-supplied resistance that pins the split unaided, so it converges on any topology and reduces to junction at low Mach. Unlike junction/splitter it carries no chamber compliance (a lengthless mixing node); model a resonating plenum with a junction or cavity volume.

Argument Symbol Meaning Units Default / constraint
recovery \sigma dynamic-head recovery: 1 = least-dissipative ideal, 0 = full dump loss 1.0, \in[0,1]

forced_splitter(fractions)

One inflow (port 0) split into N outflows at prescribed mass fractions:

\dot m_{\text{out},k} = \beta_k\, \dot m_\text{in}, \qquad \beta_N = 1 - \sum_{k} \beta_k .

You give N-1 fractions; the last (remainder) branch carries \beta_N and keeps total-pressure continuity with the inflow. The controlled branches float in pressure (a control-valve / ideal flow-divider idealization); reverse flow is not modelled. Wire the inflow edge first and the remainder outflow last.

Argument Symbol Meaning Units Default / constraint
fractions \{\beta_k\} the N-1 controlled outflow fractions each in (0,1), \sum<1

Reserved (deferred)

SUPERSONIC_INLET (9) and SUPERSONIC_OUTLET (10) are reserved dispatch ids for supersonic boundaries. v1 scope is subsonic (flowing or quiescent); supersonic / shock-seeding boundaries are deferred.

Back to top