Skip to content

ReactionBuilder

ReactionBuilder

ReactionBuilder()

Bases: Builder[Reaction]

Builder for creating REAC namelists.

Provides convenient methods for defining combustion reactions using either predefined fuels from the database or custom fuel compositions.

Examples:

>>> # Use predefined fuel
>>> reac = ReactionBuilder() \
...     .fuel('PROPANE') \
...     .soot_yield(0.015) \
...     .build()
>>> # Custom fuel with heat of combustion
>>> reac = ReactionBuilder() \
...     .fuel('CUSTOM_FUEL') \
...     .heat_of_combustion(44600) \
...     .soot_yield(0.01) \
...     .co_yield(0.02) \
...     .radiative_fraction(0.33) \
...     .build()
>>> # Complex fuel with all parameters
>>> reac = ReactionBuilder() \
...     .fuel('POLYURETHANE') \
...     .yields(soot=0.10, co=0.02) \
...     .radiative_fraction(0.30) \
...     .auto_ignition_temperature(350) \
...     .build()

Initialize the ReactionBuilder.

Source code in src/pyfds/builders/reaction.py
def __init__(self) -> None:
    """Initialize the ReactionBuilder."""
    super().__init__()
    self._fuel_name: str | None = None
    self._c: float | None = None
    self._h: float | None = None
    self._o: float | None = None
    self._n: float | None = None
    self._hoc: float | None = None
    self._soot_yield: float | None = None
    self._co_yield: float | None = None
    self._radiative_fraction: float | None = None
    self._ramp_chi_r: str | None = None
    self._auto_ignition_temp: float | None = None

    # Extinction parameters
    self._extinction_model: str | None = None
    self._critical_flame_temp: float | None = None
    self._lower_oxygen_limit: float | None = None
    self._ideal: bool | None = None

    # Species stoichiometry
    self._spec_id_nu: list[str] | None = None
    self._nu: list[float] | None = None

    # Advanced combustion parameters
    self._id: str | None = None
    self._hcn_yield: float | None = None
    self._epumo2: float | None = None
    self._hoc_complete: float | None = None
    self._n_simple_chemistry_reactions: int | None = None
    self._fuel_c_to_co_fraction: float | None = None
    self._fuel_n_to_hcn_fraction: float | None = None
    self._fuel_h_to_h2_fraction: float | None = None
    self._fuel_radcal_id: str | None = None
    self._check_atom_balance: bool | None = None
    self._reac_atom_error: float | None = None
    self._reac_mass_error: float | None = None

    # Auto-ignition exclusion zones
    self._ait_exclusion_zone: list[tuple[float, float, float, float, float, float]] | None = (
        None
    )
    self._ait_exclusion_zone_temperature: list[float] | None = None
    self._ait_exclusion_zone_devc_id: list[str] | None = None
    self._ait_exclusion_zone_ctrl_id: list[str] | None = None

    # Finite-rate kinetics
    self._a: float | None = None
    self._e: float | None = None
    self._n_t: float | None = None
    self._spec_id_n_s: list[str] | None = None
    self._n_s: list[float] | None = None
    self._equation: str | None = None
    self._reactype: str | None = None
    self._priority: int | None = None
    self._reverse: bool | None = None

    # Falloff parameters
    self._a_low_pr: float | None = None
    self._e_low_pr: float | None = None
    self._a_troe: float | None = None
    self._t1_troe: float | None = None
    self._t2_troe: float | None = None
    self._t3_troe: float | None = None

    # Third body
    self._third_body: bool | None = None
    self._third_eff: list[float] | None = None
    self._third_eff_id: list[str] | None = None

Functions

fuel

fuel(name)

Use a predefined fuel from the database.

PARAMETER DESCRIPTION
name

Name of the fuel (case-insensitive)

TYPE: str

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

RAISES DESCRIPTION
ValueError

If fuel name is not in the database

Examples:

>>> reac = ReactionBuilder().fuel('PROPANE').build()
Notes

Available fuels: METHANE, ETHANE, PROPANE, BUTANE, HYDROGEN, N-HEPTANE, N-HEXANE, GASOLINE, ACETONE, METHANOL, ETHANOL, POLYURETHANE, WOOD, PMMA, POLYSTYRENE, POLYETHYLENE, POLYPROPYLENE

Source code in src/pyfds/builders/reaction.py
def fuel(self, name: str) -> "ReactionBuilder":
    """
    Use a predefined fuel from the database.

    Parameters
    ----------
    name : str
        Name of the fuel (case-insensitive)

    Returns
    -------
    ReactionBuilder
        Self for method chaining

    Raises
    ------
    ValueError
        If fuel name is not in the database

    Examples
    --------
    >>> reac = ReactionBuilder().fuel('PROPANE').build()

    Notes
    -----
    Available fuels: METHANE, ETHANE, PROPANE, BUTANE, HYDROGEN,
    N-HEPTANE, N-HEXANE, GASOLINE, ACETONE, METHANOL, ETHANOL,
    POLYURETHANE, WOOD, PMMA, POLYSTYRENE, POLYETHYLENE, POLYPROPYLENE
    """
    fuel_key = name.upper()
    if fuel_key not in FUEL_DATABASE:
        available = ", ".join(sorted(FUEL_DATABASE.keys()))
        raise ValueError(f"Unknown fuel '{name}'. Available fuels:\n{available}")

    fuel_data = FUEL_DATABASE[fuel_key]
    self._fuel_name = fuel_key

    # Get fuel composition from database
    if "c" in fuel_data:
        self._c = float(fuel_data["c"])
    if "h" in fuel_data:
        self._h = float(fuel_data["h"])
    if "o" in fuel_data:
        self._o = float(fuel_data["o"])
    if "n" in fuel_data:
        self._n = float(fuel_data["n"])
    # Get heat of combustion from database
    if "hoc" in fuel_data:
        self._hoc = float(fuel_data["hoc"])
    # Use database soot yield as default, can be overridden
    if "soot_yield" in fuel_data:
        self._soot_yield = float(fuel_data["soot_yield"])
    # Use database co_yield if available
    if "co_yield" in fuel_data:
        self._co_yield = float(fuel_data["co_yield"])

    return self

predefined_fuel

predefined_fuel(name)

Use a predefined fuel from the database.

This is an alias for fuel() method.

PARAMETER DESCRIPTION
name

Name of the fuel (case-insensitive)

TYPE: str

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

Source code in src/pyfds/builders/reaction.py
def predefined_fuel(self, name: str) -> "ReactionBuilder":
    """
    Use a predefined fuel from the database.

    This is an alias for fuel() method.

    Parameters
    ----------
    name : str
        Name of the fuel (case-insensitive)

    Returns
    -------
    ReactionBuilder
        Self for method chaining
    """
    return self.fuel(name)

custom_fuel

custom_fuel(
    c=None, h=None, o=None, n=None, heat_of_combustion=None
)

Define a custom fuel composition.

For simple chemistry, you can specify the fuel composition using the atom counts C, H, O, N. If using a predefined fuel, you can just specify heat_of_combustion to override the default.

PARAMETER DESCRIPTION
c

Number of carbon atoms in fuel molecule

TYPE: float DEFAULT: None

h

Number of hydrogen atoms in fuel molecule

TYPE: float DEFAULT: None

o

Number of oxygen atoms in fuel molecule

TYPE: float DEFAULT: None

n

Number of nitrogen atoms in fuel molecule

TYPE: float DEFAULT: None

heat_of_combustion

Heat of combustion in kJ/kg

TYPE: float DEFAULT: None

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

Examples:

>>> # Define heptane-like fuel
>>> reac = ReactionBuilder() \
...     .custom_fuel(c=7, h=16, heat_of_combustion=44600) \
...     .build()
>>> # Override heat of combustion for predefined fuel
>>> reac = ReactionBuilder() \
...     .predefined_fuel('HEPTANE') \
...     .custom_fuel(heat_of_combustion=44000) \
...     .build()
Source code in src/pyfds/builders/reaction.py
def custom_fuel(
    self,
    c: float | None = None,
    h: float | None = None,
    o: float | None = None,
    n: float | None = None,
    heat_of_combustion: float | None = None,
) -> "ReactionBuilder":
    """
    Define a custom fuel composition.

    For simple chemistry, you can specify the fuel composition
    using the atom counts C, H, O, N. If using a predefined fuel,
    you can just specify heat_of_combustion to override the default.

    Parameters
    ----------
    c : float, optional
        Number of carbon atoms in fuel molecule
    h : float, optional
        Number of hydrogen atoms in fuel molecule
    o : float, optional
        Number of oxygen atoms in fuel molecule
    n : float, optional
        Number of nitrogen atoms in fuel molecule
    heat_of_combustion : float, optional
        Heat of combustion in kJ/kg

    Returns
    -------
    ReactionBuilder
        Self for method chaining

    Examples
    --------
    >>> # Define heptane-like fuel
    >>> reac = ReactionBuilder() \\
    ...     .custom_fuel(c=7, h=16, heat_of_combustion=44600) \\
    ...     .build()

    >>> # Override heat of combustion for predefined fuel
    >>> reac = ReactionBuilder() \\
    ...     .predefined_fuel('HEPTANE') \\
    ...     .custom_fuel(heat_of_combustion=44000) \\
    ...     .build()
    """
    if c is not None:
        self._c = c
    if h is not None:
        self._h = h
    if o is not None:
        self._o = o
    if n is not None:
        self._n = n
    if heat_of_combustion is not None:
        self._hoc = heat_of_combustion
    return self

heat_of_combustion

heat_of_combustion(value)

Set heat of combustion.

PARAMETER DESCRIPTION
value

Heat of combustion in kJ/kg

TYPE: float

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

Source code in src/pyfds/builders/reaction.py
def heat_of_combustion(self, value: float) -> "ReactionBuilder":
    """
    Set heat of combustion.

    Parameters
    ----------
    value : float
        Heat of combustion in kJ/kg

    Returns
    -------
    ReactionBuilder
        Self for method chaining
    """
    self._hoc = value
    return self

soot_yield

soot_yield(value)

Set soot yield.

PARAMETER DESCRIPTION
value

Soot yield in kg soot per kg fuel, range [0, 1]

TYPE: float

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

Source code in src/pyfds/builders/reaction.py
def soot_yield(self, value: float) -> "ReactionBuilder":
    """
    Set soot yield.

    Parameters
    ----------
    value : float
        Soot yield in kg soot per kg fuel, range [0, 1]

    Returns
    -------
    ReactionBuilder
        Self for method chaining
    """
    self._soot_yield = value
    return self

co_yield

co_yield(value)

Set CO yield.

PARAMETER DESCRIPTION
value

CO yield in kg CO per kg fuel, range [0, 1]

TYPE: float

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

Source code in src/pyfds/builders/reaction.py
def co_yield(self, value: float) -> "ReactionBuilder":
    """
    Set CO yield.

    Parameters
    ----------
    value : float
        CO yield in kg CO per kg fuel, range [0, 1]

    Returns
    -------
    ReactionBuilder
        Self for method chaining
    """
    self._co_yield = value
    return self

yields

yields(soot=0.0, co=0.0)

Set both soot and CO yields.

PARAMETER DESCRIPTION
soot

Soot yield, default: 0.0

TYPE: float DEFAULT: 0.0

co

CO yield, default: 0.0

TYPE: float DEFAULT: 0.0

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

Examples:

>>> reac = ReactionBuilder() \
...     .fuel('PROPANE') \
...     .yields(soot=0.015, co=0.02) \
...     .build()
Source code in src/pyfds/builders/reaction.py
def yields(self, soot: float = 0.0, co: float = 0.0) -> "ReactionBuilder":
    """
    Set both soot and CO yields.

    Parameters
    ----------
    soot : float, optional
        Soot yield, default: 0.0
    co : float, optional
        CO yield, default: 0.0

    Returns
    -------
    ReactionBuilder
        Self for method chaining

    Examples
    --------
    >>> reac = ReactionBuilder() \\
    ...     .fuel('PROPANE') \\
    ...     .yields(soot=0.015, co=0.02) \\
    ...     .build()
    """
    self._soot_yield = soot
    self._co_yield = co
    return self

radiative_fraction

radiative_fraction(value)

Set radiative fraction.

PARAMETER DESCRIPTION
value

Fraction of energy radiated, range [0, 1] Typical values: 0.3-0.4 for most fuels

TYPE: float

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

Source code in src/pyfds/builders/reaction.py
def radiative_fraction(self, value: float) -> "ReactionBuilder":
    """
    Set radiative fraction.

    Parameters
    ----------
    value : float
        Fraction of energy radiated, range [0, 1]
        Typical values: 0.3-0.4 for most fuels

    Returns
    -------
    ReactionBuilder
        Self for method chaining
    """
    self._radiative_fraction = value
    return self

ramp_chi_r

ramp_chi_r(ramp_id)

Set ramp for time-varying radiative fraction.

PARAMETER DESCRIPTION
ramp_id

Ramp ID for radiative fraction

TYPE: str

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

Source code in src/pyfds/builders/reaction.py
def ramp_chi_r(self, ramp_id: str) -> "ReactionBuilder":
    """
    Set ramp for time-varying radiative fraction.

    Parameters
    ----------
    ramp_id : str
        Ramp ID for radiative fraction

    Returns
    -------
    ReactionBuilder
        Self for method chaining
    """
    self._ramp_chi_r = ramp_id
    return self

auto_ignition_temperature

auto_ignition_temperature(temp)

Set auto-ignition temperature.

PARAMETER DESCRIPTION
temp

Auto-ignition temperature in °C

TYPE: float

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

Source code in src/pyfds/builders/reaction.py
def auto_ignition_temperature(self, temp: float) -> "ReactionBuilder":
    """
    Set auto-ignition temperature.

    Parameters
    ----------
    temp : float
        Auto-ignition temperature in °C

    Returns
    -------
    ReactionBuilder
        Self for method chaining
    """
    self._auto_ignition_temp = temp
    return self

with_extinction

with_extinction(model=None, critical_temp=None)

Configure extinction parameters.

Note: The extinction MODEL (EXTINCTION ½) is set on MISC namelist, not REAC. This method sets the CRITICAL_FLAME_TEMPERATURE on REAC.

PARAMETER DESCRIPTION
model

Extinction model: 'EXTINCTION 1' or 'EXTINCTION 2'. Note: This is informational only - set on MISC.

TYPE: str DEFAULT: None

critical_temp

Critical flame temperature for extinction (°C)

TYPE: float DEFAULT: None

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

Examples:

>>> reac = ReactionBuilder() \
...     .fuel('PROPANE') \
...     .with_extinction(critical_temp=1200.0) \
...     .build()
Source code in src/pyfds/builders/reaction.py
def with_extinction(
    self, model: str | None = None, critical_temp: float | None = None
) -> "ReactionBuilder":
    """
    Configure extinction parameters.

    Note: The extinction MODEL (EXTINCTION 1/2) is set on MISC namelist, not REAC.
    This method sets the CRITICAL_FLAME_TEMPERATURE on REAC.

    Parameters
    ----------
    model : str, optional
        Extinction model: 'EXTINCTION 1' or 'EXTINCTION 2'.
        Note: This is informational only - set on MISC.
    critical_temp : float, optional
        Critical flame temperature for extinction (°C)

    Returns
    -------
    ReactionBuilder
        Self for method chaining

    Examples
    --------
    >>> reac = ReactionBuilder() \\
    ...     .fuel('PROPANE') \\
    ...     .with_extinction(critical_temp=1200.0) \\
    ...     .build()
    """
    # Note: extinction_model is a MISC parameter, not REAC
    # We store it for documentation but don't pass to Reaction
    if model is not None:
        self._extinction_model = model.upper()
    if critical_temp is not None:
        self._critical_flame_temp = critical_temp
    return self

with_species_stoichiometry

with_species_stoichiometry(species, coefficients)

Set species stoichiometry.

PARAMETER DESCRIPTION
species

List of species IDs

TYPE: list[str]

coefficients

List of stoichiometric coefficients

TYPE: list[float]

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

Examples:

>>> reac = ReactionBuilder() \
...     .fuel('METHANE') \
...     .with_species_stoichiometry(['CO2', 'H2O'], [1.0, 2.0]) \
...     .build()
Source code in src/pyfds/builders/reaction.py
def with_species_stoichiometry(
    self, species: list[str], coefficients: list[float]
) -> "ReactionBuilder":
    """
    Set species stoichiometry.

    Parameters
    ----------
    species : list[str]
        List of species IDs
    coefficients : list[float]
        List of stoichiometric coefficients

    Returns
    -------
    ReactionBuilder
        Self for method chaining

    Examples
    --------
    >>> reac = ReactionBuilder() \\
    ...     .fuel('METHANE') \\
    ...     .with_species_stoichiometry(['CO2', 'H2O'], [1.0, 2.0]) \\
    ...     .build()
    """
    self._spec_id_nu = species
    self._nu = coefficients
    return self

use_non_ideal_hoc

use_non_ideal_hoc()

Use non-ideal heat of combustion.

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

Examples:

>>> reac = ReactionBuilder() \
...     .fuel('PROPANE') \
...     .use_non_ideal_hoc() \
...     .build()
Source code in src/pyfds/builders/reaction.py
def use_non_ideal_hoc(self) -> "ReactionBuilder":
    """
    Use non-ideal heat of combustion.

    Returns
    -------
    ReactionBuilder
        Self for method chaining

    Examples
    --------
    >>> reac = ReactionBuilder() \\
    ...     .fuel('PROPANE') \\
    ...     .use_non_ideal_hoc() \\
    ...     .build()
    """
    self._ideal = False
    return self

reaction_id

reaction_id(id)

Set reaction identifier.

PARAMETER DESCRIPTION
id

Reaction identifier

TYPE: str

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

Source code in src/pyfds/builders/reaction.py
def reaction_id(self, id: str) -> "ReactionBuilder":
    """
    Set reaction identifier.

    Parameters
    ----------
    id : str
        Reaction identifier

    Returns
    -------
    ReactionBuilder
        Self for method chaining
    """
    self._id = id
    return self

hcn_yield

hcn_yield(value)

Set HCN yield.

PARAMETER DESCRIPTION
value

HCN yield in kg HCN per kg fuel, range [0, 1]

TYPE: float

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

Source code in src/pyfds/builders/reaction.py
def hcn_yield(self, value: float) -> "ReactionBuilder":
    """
    Set HCN yield.

    Parameters
    ----------
    value : float
        HCN yield in kg HCN per kg fuel, range [0, 1]

    Returns
    -------
    ReactionBuilder
        Self for method chaining
    """
    self._hcn_yield = value
    return self

energy_per_o2

energy_per_o2(epumo2)

Set energy per unit mass of O2 consumed.

PARAMETER DESCRIPTION
epumo2

Energy per unit mass of O2 [kJ/kg]

TYPE: float

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

Source code in src/pyfds/builders/reaction.py
def energy_per_o2(self, epumo2: float) -> "ReactionBuilder":
    """
    Set energy per unit mass of O2 consumed.

    Parameters
    ----------
    epumo2 : float
        Energy per unit mass of O2 [kJ/kg]

    Returns
    -------
    ReactionBuilder
        Self for method chaining
    """
    self._epumo2 = epumo2
    return self

complete_heat_of_combustion

complete_heat_of_combustion(hoc_complete)

Set complete heat of combustion.

PARAMETER DESCRIPTION
hoc_complete

Complete heat of combustion [kJ/kg]

TYPE: float

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

Source code in src/pyfds/builders/reaction.py
def complete_heat_of_combustion(self, hoc_complete: float) -> "ReactionBuilder":
    """
    Set complete heat of combustion.

    Parameters
    ----------
    hoc_complete : float
        Complete heat of combustion [kJ/kg]

    Returns
    -------
    ReactionBuilder
        Self for method chaining
    """
    self._hoc_complete = hoc_complete
    return self

with_two_step_chemistry

with_two_step_chemistry(
    co_fraction=0.1, hcn_fraction=0.0, h2_fraction=0.0
)

Enable two-step chemistry model.

PARAMETER DESCRIPTION
co_fraction

Fraction of fuel carbon converted to CO, default: 0.1

TYPE: float DEFAULT: 0.1

hcn_fraction

Fraction of fuel nitrogen converted to HCN, default: 0.0

TYPE: float DEFAULT: 0.0

h2_fraction

Fraction of fuel hydrogen converted to H2, default: 0.0

TYPE: float DEFAULT: 0.0

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

Examples:

>>> reac = ReactionBuilder() \
...     .fuel('WOOD') \
...     .with_two_step_chemistry(co_fraction=0.15, hcn_fraction=0.001) \
...     .build()
Source code in src/pyfds/builders/reaction.py
def with_two_step_chemistry(
    self, co_fraction: float = 0.1, hcn_fraction: float = 0.0, h2_fraction: float = 0.0
) -> "ReactionBuilder":
    """
    Enable two-step chemistry model.

    Parameters
    ----------
    co_fraction : float, optional
        Fraction of fuel carbon converted to CO, default: 0.1
    hcn_fraction : float, optional
        Fraction of fuel nitrogen converted to HCN, default: 0.0
    h2_fraction : float, optional
        Fraction of fuel hydrogen converted to H2, default: 0.0

    Returns
    -------
    ReactionBuilder
        Self for method chaining

    Examples
    --------
    >>> reac = ReactionBuilder() \\
    ...     .fuel('WOOD') \\
    ...     .with_two_step_chemistry(co_fraction=0.15, hcn_fraction=0.001) \\
    ...     .build()
    """
    self._n_simple_chemistry_reactions = 2
    self._fuel_c_to_co_fraction = co_fraction
    self._fuel_n_to_hcn_fraction = hcn_fraction
    self._fuel_h_to_h2_fraction = h2_fraction
    return self

yields_all

yields_all(soot=0.0, co=0.0, hcn=0.0)

Set all product yields.

PARAMETER DESCRIPTION
soot

Soot yield, default: 0.0

TYPE: float DEFAULT: 0.0

co

CO yield, default: 0.0

TYPE: float DEFAULT: 0.0

hcn

HCN yield, default: 0.0

TYPE: float DEFAULT: 0.0

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

Examples:

>>> reac = ReactionBuilder() \
...     .fuel('POLYURETHANE') \
...     .yields_all(soot=0.10, co=0.02, hcn=0.001) \
...     .build()
Source code in src/pyfds/builders/reaction.py
def yields_all(self, soot: float = 0.0, co: float = 0.0, hcn: float = 0.0) -> "ReactionBuilder":
    """
    Set all product yields.

    Parameters
    ----------
    soot : float, optional
        Soot yield, default: 0.0
    co : float, optional
        CO yield, default: 0.0
    hcn : float, optional
        HCN yield, default: 0.0

    Returns
    -------
    ReactionBuilder
        Self for method chaining

    Examples
    --------
    >>> reac = ReactionBuilder() \\
    ...     .fuel('POLYURETHANE') \\
    ...     .yields_all(soot=0.10, co=0.02, hcn=0.001) \\
    ...     .build()
    """
    self._soot_yield = soot
    self._co_yield = co
    self._hcn_yield = hcn
    return self

with_extinction_limit

with_extinction_limit(lower_o2)

Set lower oxygen limit for extinction.

PARAMETER DESCRIPTION
lower_o2

Lower oxygen index for extinction, range [0, 1]

TYPE: float

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

Source code in src/pyfds/builders/reaction.py
def with_extinction_limit(self, lower_o2: float) -> "ReactionBuilder":
    """
    Set lower oxygen limit for extinction.

    Parameters
    ----------
    lower_o2 : float
        Lower oxygen index for extinction, range [0, 1]

    Returns
    -------
    ReactionBuilder
        Self for method chaining
    """
    self._lower_oxygen_limit = lower_o2
    return self

with_auto_ignition_exclusion

with_auto_ignition_exclusion(
    zone_bounds,
    temperature=None,
    device_id=None,
    control_id=None,
)

Add an auto-ignition exclusion zone.

PARAMETER DESCRIPTION
zone_bounds

XB bounds for exclusion zone (6 values)

TYPE: tuple[float, ...]

temperature

Temperature above which ignition is allowed [°C]

TYPE: float DEFAULT: None

device_id

Device to control exclusion zone

TYPE: str DEFAULT: None

control_id

Control logic for exclusion zone

TYPE: str DEFAULT: None

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

Examples:

>>> reac = ReactionBuilder() \
...     .fuel('PROPANE') \
...     .with_auto_ignition_exclusion(
...         zone_bounds=(0, 1, 0, 1, 0, 1),
...         temperature=300.0
...     ) \
...     .build()
Source code in src/pyfds/builders/reaction.py
def with_auto_ignition_exclusion(
    self,
    zone_bounds: tuple[float, float, float, float, float, float],
    temperature: float | None = None,
    device_id: str | None = None,
    control_id: str | None = None,
) -> "ReactionBuilder":
    """
    Add an auto-ignition exclusion zone.

    Parameters
    ----------
    zone_bounds : tuple[float, ...]
        XB bounds for exclusion zone (6 values)
    temperature : float, optional
        Temperature above which ignition is allowed [°C]
    device_id : str, optional
        Device to control exclusion zone
    control_id : str, optional
        Control logic for exclusion zone

    Returns
    -------
    ReactionBuilder
        Self for method chaining

    Examples
    --------
    >>> reac = ReactionBuilder() \\
    ...     .fuel('PROPANE') \\
    ...     .with_auto_ignition_exclusion(
    ...         zone_bounds=(0, 1, 0, 1, 0, 1),
    ...         temperature=300.0
    ...     ) \\
    ...     .build()
    """
    if self._ait_exclusion_zone is None:
        self._ait_exclusion_zone = []
    if self._ait_exclusion_zone_temperature is None:
        self._ait_exclusion_zone_temperature = []
    if self._ait_exclusion_zone_devc_id is None:
        self._ait_exclusion_zone_devc_id = []
    if self._ait_exclusion_zone_ctrl_id is None:
        self._ait_exclusion_zone_ctrl_id = []

    self._ait_exclusion_zone.append(zone_bounds)
    if temperature is not None:
        self._ait_exclusion_zone_temperature.append(temperature)
    if device_id is not None:
        self._ait_exclusion_zone_devc_id.append(device_id)
    if control_id is not None:
        self._ait_exclusion_zone_ctrl_id.append(control_id)
    return self

disable_atom_balance_check

disable_atom_balance_check()

Disable atom balance checking.

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

Source code in src/pyfds/builders/reaction.py
def disable_atom_balance_check(self) -> "ReactionBuilder":
    """
    Disable atom balance checking.

    Returns
    -------
    ReactionBuilder
        Self for method chaining
    """
    self._check_atom_balance = False
    return self

with_finite_rate_kinetics

with_finite_rate_kinetics(
    a, e, n_t=0.0, species=None, exponents=None
)

Configure finite-rate Arrhenius kinetics.

PARAMETER DESCRIPTION
a

Pre-exponential factor

TYPE: float

e

Activation energy [J/mol]

TYPE: float

n_t

Temperature exponent, default: 0.0

TYPE: float DEFAULT: 0.0

species

Species IDs for concentration exponents

TYPE: list[str] DEFAULT: None

exponents

Concentration exponents for each species

TYPE: list[float] DEFAULT: None

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

Source code in src/pyfds/builders/reaction.py
def with_finite_rate_kinetics(
    self,
    a: float,
    e: float,
    n_t: float = 0.0,
    species: list[str] | None = None,
    exponents: list[float] | None = None,
) -> "ReactionBuilder":
    """
    Configure finite-rate Arrhenius kinetics.

    Parameters
    ----------
    a : float
        Pre-exponential factor
    e : float
        Activation energy [J/mol]
    n_t : float, optional
        Temperature exponent, default: 0.0
    species : list[str], optional
        Species IDs for concentration exponents
    exponents : list[float], optional
        Concentration exponents for each species

    Returns
    -------
    ReactionBuilder
        Self for method chaining
    """
    self._a = a
    self._e = e
    self._n_t = n_t
    if species is not None:
        self._spec_id_n_s = species
    if exponents is not None:
        self._n_s = exponents
    return self

with_third_body

with_third_body(efficiencies=None, species=None)

Enable third body reaction.

PARAMETER DESCRIPTION
efficiencies

Third body efficiencies

TYPE: list[float] DEFAULT: None

species

Species IDs for third body efficiencies

TYPE: list[str] DEFAULT: None

RETURNS DESCRIPTION
ReactionBuilder

Self for method chaining

Source code in src/pyfds/builders/reaction.py
def with_third_body(
    self, efficiencies: list[float] | None = None, species: list[str] | None = None
) -> "ReactionBuilder":
    """
    Enable third body reaction.

    Parameters
    ----------
    efficiencies : list[float], optional
        Third body efficiencies
    species : list[str], optional
        Species IDs for third body efficiencies

    Returns
    -------
    ReactionBuilder
        Self for method chaining
    """
    self._third_body = True
    if efficiencies is not None:
        self._third_eff = efficiencies
    if species is not None:
        self._third_eff_id = species
    return self

list_fuels classmethod

list_fuels()

List all available predefined fuels.

RETURNS DESCRIPTION
list[str]

Sorted list of fuel names

Examples:

>>> fuels = ReactionBuilder.list_fuels()
>>> print(fuels)
['ACETONE', 'BUTANE', 'ETHANE', ...]
Source code in src/pyfds/builders/reaction.py
@classmethod
def list_fuels(cls) -> list[str]:
    """
    List all available predefined fuels.

    Returns
    -------
    list[str]
        Sorted list of fuel names

    Examples
    --------
    >>> fuels = ReactionBuilder.list_fuels()
    >>> print(fuels)
    ['ACETONE', 'BUTANE', 'ETHANE', ...]
    """
    return list_fuels()

get_fuel_info classmethod

get_fuel_info(name)

Get information about a predefined fuel.

PARAMETER DESCRIPTION
name

Name of the fuel (case-insensitive)

TYPE: str

RETURNS DESCRIPTION
FuelData

Dictionary with fuel composition and properties

RAISES DESCRIPTION
ValueError

If fuel name is not in the database

Examples:

>>> info = ReactionBuilder.get_fuel_info('PROPANE')
>>> print(info)
{'c': 3, 'h': 8, 'o': 0, 'n': 0, 'hoc': 46000, 'soot_yield': 0.010, ...}
Source code in src/pyfds/builders/reaction.py
@classmethod
def get_fuel_info(cls, name: str) -> FuelData:
    """
    Get information about a predefined fuel.

    Parameters
    ----------
    name : str
        Name of the fuel (case-insensitive)

    Returns
    -------
    FuelData
        Dictionary with fuel composition and properties

    Raises
    ------
    ValueError
        If fuel name is not in the database

    Examples
    --------
    >>> info = ReactionBuilder.get_fuel_info('PROPANE')
    >>> print(info)
    {'c': 3, 'h': 8, 'o': 0, 'n': 0, 'hoc': 46000, 'soot_yield': 0.010, ...}
    """
    return get_fuel_info(name)

Overview

ReactionBuilder creates combustion reaction definitions (&REAC namelists) using predefined fuels or custom compositions.

Key Features

  • Fuel Database: 17 predefined fuels (gases, liquids, solids)
  • Custom Fuels: Define C/H/O/N composition
  • Product Yields: Soot, CO, radiative fraction
  • Auto-Ignition: Temperature specification

Quick Examples

Predefined Fuel

from pyfds.builders import ReactionBuilder

# Use predefined fuel from database
reac = (
    ReactionBuilder()
    .fuel('PROPANE')
    .yields(soot=0.015, co=0.02)
    .radiative_fraction(0.33)
    .build()
)

Custom Fuel Composition

# Define custom fuel
reac = (
    ReactionBuilder()
    .custom_fuel(
        c=7,                         # Carbon atoms
        h=16,                        # Hydrogen atoms
        heat_of_combustion=44600     # kJ/kg
    )
    .yields(soot=0.01, co=0.02)
    .build()
)

# With oxygen and nitrogen
reac = (
    ReactionBuilder()
    .custom_fuel(
        c=3.52,
        h=5.48,
        o=0.88,
        n=0.32,
        heat_of_combustion=23200
    )
    .build()
)

Complete Configuration

reac = (
    ReactionBuilder()
    .fuel('POLYURETHANE')
    .soot_yield(0.10)
    .co_yield(0.03)
    .radiative_fraction(0.30)
    .auto_ignition_temperature(350)
    .build()
)

Fuel Database

PyFDS includes 17 predefined fuels:

Gases

Fuel Formula HOC (kJ/kg) Soot Yield CO Yield
METHANE CH₄ 50000 0.001 0.001
ETHANE C₂H₆ 47500 0.005 0.003
PROPANE C₃H₈ 46000 0.010 0.004
BUTANE C₄H₁₀ 45700 0.015 0.005
HYDROGEN H₂ 120000 0.000 0.000

Liquids

Fuel Formula HOC (kJ/kg) Soot Yield CO Yield
N-HEPTANE C₇H₁₆ 44600 0.037 0.010
N-HEXANE C₆H₁₄ 44750 0.033 0.009
GASOLINE ~C₇H₁₄ 43700 0.059 0.014
ACETONE C₃H₆O 25800 0.014 0.004
METHANOL CH₃OH 19900 0.001 0.003
ETHANOL C₂H₅OH 26800 0.005 0.003

Solids

Fuel Approx. Formula HOC (kJ/kg) Soot Yield CO Yield
POLYURETHANE C₃.₅₂H₅.₄₈O₀.₈₈N₀.₃₂ 23200 0.131 0.042
WOOD C₃.₄H₆.₂O₂.₅ 12400 0.015 0.004
PMMA C₅H₈O₂ 24900 0.022 0.004
POLYSTYRENE C₈H₈ 39200 0.060 0.010
POLYETHYLENE C₂H₄ 43600 0.060 0.024
POLYPROPYLENE C₃H₆ 43300 0.059 0.024

Querying the Database

# List all available fuels
fuels = ReactionBuilder.list_fuels()
print(fuels)
# ['ACETONE', 'BUTANE', 'ETHANE', 'ETHANOL', 'GASOLINE', ...]

# Get detailed info about a fuel
info = ReactionBuilder.get_fuel_info('PROPANE')
print(info)
# {
#     'c': 3,
#     'h': 8,
#     'o': 0,
#     'n': 0,
#     'hoc': 46000,
#     'soot_yield': 0.010,
#     'co_yield': 0.004,
#     'description': 'Propane gas'
# }

# Case-insensitive lookup
info = ReactionBuilder.get_fuel_info('propane')  # Works

Usage in Simulations

Simple Fire

from pyfds import Simulation
from pyfds.builders import ReactionBuilder

sim = Simulation('propane_fire')

# Add reaction
reac = ReactionBuilder().fuel('PROPANE').build()
sim.add_reaction(reac)

# Create fire surface
sim.add(Surface(id='FIRE', hrrpua=1000.0, color='RED'))
sim.add(Obstruction(xb=Bounds3D.of(4.5, 5.5, 4.5, 5.5, 0, 0.1), surf_id='FIRE'))

With Pyrolysis

# Pyrolyzing material
polymer = (
    MaterialBuilder('POLYMER')
    .density(40)
    .add_pyrolysis_reaction(
        a=1e10,
        e=80000,
        product_species='FUEL_VAPOR'
    )
    .build()
)
sim.add_material(polymer)

# Reaction for fuel vapor
reac = ReactionBuilder().fuel('POLYURETHANE').build()
sim.add_reaction(reac)

# Surface with pyrolysis
sim.add(Surface(id='FOAM', matl_id='POLYMER', thickness=0.05))

Custom Fuel with Species

# Define custom fuel species
sim.spec(id='MY_FUEL', mw=114)  # C₇H₁₆ molecular weight

# Custom fuel for that species
reac = (
    ReactionBuilder()
    .custom_fuel(c=7, h=16, heat_of_combustion=44600)
    .fuel_id('MY_FUEL')
    .yields(soot=0.037, co=0.010)
    .build()
)
sim.add_reaction(reac)

Product Yields

Soot Yield

Fraction of fuel mass converted to soot:

reac = ReactionBuilder().fuel('PROPANE').soot_yield(0.015).build()

Typical values: - Clean burning gases (methane, hydrogen): 0.000-0.005 - Gasoline/alkanes: 0.010-0.040 - Aromatics/plastics: 0.040-0.130

CO Yield

Fraction of fuel mass converted to CO:

reac = ReactionBuilder().fuel('PROPANE').co_yield(0.02).build()

Typical values: - Complete combustion: 0.001-0.005 - Well-ventilated: 0.004-0.010 - Under-ventilated: 0.010-0.050

Setting Both

reac = (
    ReactionBuilder()
    .fuel('PROPANE')
    .yields(soot=0.015, co=0.02)
    .build()
)

Radiative Fraction

Fraction of heat release radiated:

reac = (
    ReactionBuilder()
    .fuel('PROPANE')
    .radiative_fraction(0.33)  # 33% radiated
    .build()
)

Typical values: - Small/clean fires: 0.30-0.35 - Sooty fires: 0.25-0.30 - Large pool fires: 0.20-0.30

Auto-Ignition

Set auto-ignition temperature:

reac = (
    ReactionBuilder()
    .fuel('PROPANE')
    .auto_ignition_temperature(450)  # °C
    .build()
)

Common auto-ignition temperatures: - Propane: 450-500°C - Methane: 540°C - Gasoline: 280-450°C - Wood: 300-400°C

Overriding Database Values

Database values are defaults that can be overridden:

# Database default: soot_yield=0.010
reac = ReactionBuilder().fuel('PROPANE').build()
assert reac.soot_yield == 0.010

# Override with custom value
reac = ReactionBuilder().fuel('PROPANE').soot_yield(0.020).build()
assert reac.soot_yield == 0.020

Validation

The builder validates:

  • Fuel specified: Either .fuel() or .custom_fuel() required
  • Valid fuel name: Fuel must exist in database
  • Positive values: HOC, yields must be non-negative

Chemical Background

Combustion Equation

General hydrocarbon combustion:

\[ \text{C}_n\text{H}_m + \left(n + \frac{m}{4}\right) \text{O}_2 \rightarrow n \text{CO}_2 + \frac{m}{2} \text{H}_2\text{O} \]

With nitrogen and oxygen in fuel:

\[ \text{C}_a\text{H}_b\text{O}_c\text{N}_d + x \text{O}_2 \rightarrow a \text{CO}_2 + \frac{b}{2} \text{H}_2\text{O} + \frac{d}{2} \text{N}_2 \]

where:

\[ x = a + \frac{b}{4} - \frac{c}{2} \]

Heat of Combustion

Lower heating value (LHV) ranges:

  • Gases: 45,000-50,000 kJ/kg
  • Liquids: 40,000-45,000 kJ/kg
  • Solid fuels: 15,000-45,000 kJ/kg

Best Practices

Use Database Fuels

# Good: Use predefined fuel
reac = ReactionBuilder().fuel('PROPANE').build()

# Avoid: Manually entering known fuel
reac = ReactionBuilder().custom_fuel(c=3, h=8, heat_of_combustion=46000).build()

Realistic Yields

# Good: Reasonable yields based on literature
reac = ReactionBuilder().fuel('GASOLINE').yields(soot=0.059, co=0.014).build()

# Avoid: Unrealistic yields
reac = ReactionBuilder().fuel('METHANE').yields(soot=0.5, co=0.9).build()

Override When Needed

# Good: Override for specific scenario
reac = (
    ReactionBuilder()
    .fuel('PROPANE')
    .soot_yield(0.030)  # Higher soot for under-ventilated
    .build()
)

See Also