Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion docs/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ constant-volume batch reactor.

**Features demonstrated:**

- `CanteraConstantUV` adapter — closed adiabatic constant-V batch
- `CanteraConstantUV` adapter — closed adiabatic constant-V batch (same `IdealGasReactor` as a shock tube post-reflected-shock state). For IDT-specific sensitivity analysis use `CanteraIDT` instead.
- Dilute mixture in argon (`balance: true` on Ar, `reactive: false`)
- `global_observables: ['IDT']` — IDT is the primary measurement of a shock tube
- Short `termination_time` in milliseconds, matching typical IDT magnitudes
Expand Down Expand Up @@ -208,6 +208,23 @@ Demonstrates a liquid-phase simulation with a solvent species.
- Liquid-phase specific species constraints


## IDT with experimental comparison

**Directory:** `examples/idt_with_experiment/`

Demonstrates running IDT-focused sensitivity analysis with experimental data
comparison. T3 computes predicted IDTs and compares them against experimental
measurements, reporting per-point log-errors and RMSE.

**Features demonstrated:**

- `global_observables: ['IDT']` for IDT-based SA
- `idt_criterion: max_dOHdt` (configurable: `max_dTdt`, `max_radical_dt`)
- `idt_sa_method: adjoint` (`brute_force` or `adjoint` for Cantera built-in SA)
- `experimental_idt_path` pointing to a YAML file with experimental data
- Experimental YAML format with citation, T/P/phi/idt fields


## Input reference

For a comprehensive reference showing **every** available input argument with
Expand Down
4 changes: 2 additions & 2 deletions docs/how_to.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ adapter that reproduces its idealized chemistry:

| Experimental setup | Adapter | Notes |
|---|---|---|
| Shock tube (reflected shock) | `CanteraConstantUV` | Standard treatment: closed, adiabatic, constant-volume batch reactor. Use `IDT` as a global observable for ignition delay measurements. |
| Rapid compression machine (RCM) | `CanteraConstantUV` | Same idealization as a reflected shock once the piston is at top-dead-center. Heat loss is not modeled. |
| Shock tube (reflected shock) | `CanteraConstantUV` or `CanteraIDT` | Standard treatment: closed, adiabatic, constant-volume batch reactor (`IdealGasReactor`). Use `CanteraConstantUV` for general simulations, or `CanteraIDT` when you need IDT-specific sensitivity analysis (brute-force or adjoint). Use `IDT` as a global observable for ignition delay measurements. |
| Rapid compression machine (RCM) | `CanteraConstantUV` or `CanteraRCM` | Same physics but at constant pressure (`IdealGasConstPressureReactor`). Use `CanteraRCM` when you need IDT-specific sensitivity analysis. Heat loss is not modeled. |
| Constant-volume bomb | `CanteraConstantUV` | Adiabatic version. |
| Flow reactor (isothermal) | `CanteraPFR` | Lagrangian PFR: a parcel of gas advected at constant T, P. |
| Flow reactor with measured wall temperature | `CanteraPFRTProfile` | Lagrangian PFR with a hard-coded axial temperature profile `T(z)` (energy equation off). The geometry, the breakpoints, and the profile shape are set by module-level constants in `t3/simulate/cantera_pfr_t_profile.py` (defaults to an 80 cm reactor: a 20 cm raised-cosine ramp 300 → 900 K, a 40 cm 900 K plateau, and a 20 cm raised-cosine ramp 900 → 500 K). Pressure stays at the inlet value; density evolves with `T`. Supports SA -- the SA coefficients are returned as a function of axial position `z` (the reactor is steady-state in the lab frame), via an extra `'distance'` key in the `sa_dict`. |
Expand Down
58 changes: 57 additions & 1 deletion docs/input_reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ t3:
adapter: CanteraConstantTP # *required* (this is how SA is requested)
# Available adapters: 'CanteraConstantTP', 'CanteraConstantHP',
# 'CanteraConstantUV', 'CanteraPFR', 'CanteraPFRTProfile',
# 'CanteraJSR', 'RMGConstantTP'
# 'CanteraJSR', 'CanteraIDT', 'CanteraRCM', 'RMGConstantTP'
atol: 1e-6 # optional, default: 1e-6
rtol: 1e-4 # optional, default: 1e-4
global_observables: ['IDT', 'ESR', 'SL'] # optional, only implemented in Cantera adapters,
Expand All @@ -79,11 +79,31 @@ t3:
top_SA_species: 10 # optional, used per observable to determine thermo to calculate, default: 10
top_SA_reactions: 10 # optional, used per observable to determine rates to calculate as well as
# thermo of species participating in these reactions, default: 10
max_sa_workers: 24 # optional, max worker processes for brute-force SA in the Cantera IDT
# adapter (one perturbation per worker), default: 24
T_list: [800, 1000, 1200] # optional, explicit temperature list for SA runs (overrides
# range-based generation), Units: K, default: None
P_list: [1, 10] # optional, explicit pressure list for SA runs (overrides range-based
# generation), Units: bar, default: None

# IDT-specific SA options (only apply when adapter is CanteraIDT or CanteraRCM):
idt_criterion: max_dOHdt # optional, how to define the ignition delay time.
# 'max_dOHdt' (default): time of max d[OH]/dt (falls back to d[H]/dt
# if OH is absent from the mechanism)
# 'max_dTdt': time of max dT/dt
# 'max_radical_dt': auto-detect highest-conc radical, use max d[radical]/dt
idt_sa_method: brute_force # optional, SA method for IDT.
# 'brute_force' (default): perturb each parameter, re-simulate
# 'adjoint': Cantera built-in adjoint SA (faster, single sim per condition)
delta_h: 0.1 # optional, enthalpy perturbation for brute-force thermo SA, Units: kJ/mol, default: 0.1
delta_k: 0.05 # optional, fractional rate perturbation for brute-force kinetics SA, default: 0.05
adaptive_perturbation: false # optional, enable adaptive perturbation sizing. When true,
# delta_h scales relative to |H298| and failed workers retry with
# halved perturbation. default: false
experimental_idt_path: null # optional, path to a YAML file with experimental IDT data for
# comparison (not optimization). See examples/idt_with_experiment/.
# default: null

# uncertainty analysis (optional block, T3 can run w/o UA)
# either local or global UA type must be specified to execute an UA
uncertainty:
Expand Down Expand Up @@ -157,6 +177,39 @@ rmg:
# note: 'constant' is only allowed in liquid phase simulations
# note: 'solvent' is only allowed in liquid phase simulations

# fuel / oxidizer / diluent roles (used by the IDT adapter and the equivalence-ratio sweep)
# When 'role' is set, the species concentrations are recomputed per phi from the fuel
# concentration, the oxidizer's stoichiometric demand, and the diluent_to_oxidizer_ratio.
# Exactly one species must carry role='fuel'. Multiple oxidizers / diluents are allowed;
# oxidizer_fraction must sum to 1 across oxidizers when more than one oxidizer is given.
#
# Role-specific field restrictions (setting a field on the wrong role raises a validation error):
# equivalence_ratios — only on role='fuel' (required for fuel)
# oxidizer_fraction — only on role='oxidizer'
# diluent_to_oxidizer_ratio — only on role='diluent'
# Example below: an NH3 fuel in an O2/N2O oxidizer diluted with N2:
#
# species:
# - label: NH3
# smiles: 'N'
# concentration: 1.0
# role: fuel
# equivalence_ratios: [0.5, 1.0, 1.5] # required on the fuel, drives the phi sweep
# - label: O2
# smiles: '[O][O]'
# role: oxidizer
# oxidizer_fraction: 0.8 # fraction of total oxidizer demand carried by this oxidizer
# - label: N2O
# smiles: 'N#[N+][O-]'
# role: oxidizer
# oxidizer_fraction: 0.2
# - label: N2
# adjlist: |
# 1 N u0 p1 c0 {2,T}
# 2 N u0 p1 c0 {1,T}
# role: diluent
# diluent_to_oxidizer_ratio: 3.76 # default 3.76 (air-like); set to 0 for an undiluted mixture

# reactors (List[dict]) (a required block)
# reactor type: 'gas batch constant T P' or 'liquid batch constant T V'
# at least one termination criterion must be given per reactor
Expand All @@ -171,6 +224,9 @@ rmg:
termination_time: [5, 's'] # allowed units: 'micro-s', 'ms', 's', 'hours', 'days'
termination_rate_ratio: 0.01
conditions_per_iteration: 12 # optional, default: 12 (nSims in RMG)
idt_mode: matrix # optional, only used by the Cantera IDT adapter, default: 'matrix'
# 'matrix' = full T_list x P_list x phi_list cartesian product
# 'row' = zip(T_list, P_list, phi_list) (lists must be same length)

# model (a required block)
model:
Expand Down
23 changes: 23 additions & 0 deletions examples/idt_with_experiment/experimental_idt.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Experimental ignition delay time data for H2/O2 in Ar
# Replace with real data and citation for your system.
citation: "Placeholder et al., Combustion and Flame 250 (2023) 112600"
fuel: H2
oxidizer: O2
diluent: Ar
data:
# T in K, P in bar (post-reflected-shock conditions), idt in seconds
- {T: 1000, P: 2, phi: 1.0, idt: 3.2e-3}
- {T: 1050, P: 2, phi: 1.0, idt: 1.8e-3}
- {T: 1100, P: 2, phi: 1.0, idt: 9.5e-4}
- {T: 1150, P: 2, phi: 1.0, idt: 5.1e-4}
- {T: 1200, P: 2, phi: 1.0, idt: 2.7e-4}
- {T: 1300, P: 2, phi: 1.0, idt: 8.3e-5}
- {T: 1400, P: 2, phi: 1.0, idt: 2.9e-5}
- {T: 1000, P: 10, phi: 1.0, idt: 2.1e-3}
- {T: 1100, P: 10, phi: 1.0, idt: 6.2e-4}
- {T: 1200, P: 10, phi: 1.0, idt: 1.8e-4}
- {T: 1300, P: 10, phi: 1.0, idt: 5.5e-5}
- {T: 1400, P: 10, phi: 1.0, idt: 1.9e-5}
- {T: 1000, P: 2, phi: 0.5, idt: 4.5e-3}
- {T: 1200, P: 2, phi: 0.5, idt: 3.8e-4}
- {T: 1400, P: 2, phi: 0.5, idt: 4.1e-5}
69 changes: 69 additions & 0 deletions examples/idt_with_experiment/input.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Shock tube IDT with experimental comparison
#
# This example demonstrates how to run an IDT-focused T3 iteration
# and compare the predicted ignition delay times against experimental data.
# The experimental comparison is for tracking model quality per iteration;
# T3 does NOT optimize to match experiments.

project: idt_with_experiment_example

t3:
options:
max_T3_iterations: 5
max_RMG_walltime: '00:00:10:00'
sensitivity:
adapter: CanteraConstantUV
atol: 1e-6
rtol: 1e-4
SA_threshold: 0.01
global_observables: ['IDT']
top_SA_species: 10
top_SA_reactions: 10
idt_criterion: max_dOHdt # or 'max_dTdt' or 'max_radical_dt'
idt_sa_method: brute_force # or 'adjoint' for Cantera built-in SA
experimental_idt_path: examples/idt_with_experiment/experimental_idt.yaml

rmg:
database:
thermo_libraries:
- primaryThermoLibrary
- BurkeH2O2
kinetics_libraries:
- BurkeH2O2inN2
species:
- label: H2
smiles: '[H][H]'
concentration: 0.04
- label: O2
smiles: '[O][O]'
concentration: 0.02
- label: Ar
smiles: '[Ar]'
concentration: 0.94
reactive: false
balance: true
- label: OH
smiles: '[OH]'
SA_observable: true
- label: H
smiles: '[H]'
SA_observable: true
reactors:
- type: gas batch constant T P
T: [1000, 1400] # range: T3 will expand to ~25 points in 1/T space
P: [2, 10] # range: T3 will expand logarithmically
termination_conversion:
H2: 0.9
termination_time: [10, 'ms']
model:
core_tolerance: [0.01, 0.005, 0.001]

qm:
adapter: ARC
level_of_theory: b3lyp/6-31g(d,p)
job_types:
rotors: false
fine: false
freq: true
opt: true
sp: true
Loading
Loading