ADM Models
ADToolbox exposes two anaerobic digestion models:
| CLI command | Model | Parameter folder | Stoichiometric builder | ODE system |
|---|---|---|---|---|
adtoolbox ADM adm1 |
ADM1 | adm1 |
adm.build_adm1_stoichiometric_matrix |
adm.adm1_ode_sys |
adtoolbox ADM e-adm |
e-ADM | e_adm |
adm.build_e_adm_stoichiometric_matrix |
adm.e_adm_ode_sys |
The CLI and public API use only the names ADM1 and e-ADM. The preferred parameter format is one models.json file containing all models, keyed by model name.
Model Inputs
The canonical model input is a single JSON file with one top-level key per model:
{
"adm1": {
"species": [],
"reactions": [],
"model_parameters": {},
"base_parameters": {},
"initial_conditions": {},
"inlet_conditions": {}
},
"e_adm": {
"species": [],
"reactions": [],
"model_parameters": {},
"base_parameters": {},
"initial_conditions": {},
"inlet_conditions": {}
}
}
The first layer is always the model key. The second layer is the complete model payload used to instantiate adm.Model.
| Top-level key | Public model | CLI command |
|---|---|---|
adm1 |
ADM1 | adtoolbox ADM adm1 --models-json models.json |
e_adm |
e-ADM | adtoolbox ADM e-adm --models-json models.json |
The older six-file layout is still supported as a compatibility path, either by passing --parameters-dir or by passing each file explicitly.
| Input file | ADM1 name | e-ADM name | Description |
|---|---|---|---|
| Model parameters | adm1_model_parameters.json |
e_adm_model_parameters.json |
Kinetic, equilibrium, inhibition, gas transfer, and yield parameters used in reaction rates and acid/base calculations. |
| Base parameters | adm1_base_parameters.json |
e_adm_base_parameters.json |
Reactor-level constants such as liquid volume, gas volume, influent flow, gas transfer constants, pressure, temperature, and gas constants. |
| Initial conditions | adm1_initial_conditions.json |
e_adm_initial_conditions.json |
Initial concentration of every model state. Keys must match the species list. |
| Inlet conditions | adm1_inlet_conditions.json |
e_adm_inlet_conditions.json |
Influent concentration of every model state, using the same species names with _in appended. |
| Reactions | adm1_reactions.json |
e_adm_reactions.json |
Ordered reaction names. This order defines the columns of the stoichiometric matrix and the reaction-rate vector. |
| Species | adm1_species.json |
e_adm_species.json |
Ordered state names. This order defines the rows of the stoichiometric matrix and the concentration vector. |
The CLI also accepts:
| Option | Applies to | Description |
|---|---|---|
--models-json |
ADM1, e-ADM | Preferred input. JSON file containing all models keyed by model name. |
--parameters-dir |
ADM1, e-ADM | Directory containing the six JSON files for the selected model. |
--model-parameters, --base-parameters, --initial-conditions, --inlet-conditions, --reactions, --species |
ADM1, e-ADM | Override individual JSON file paths. |
--report |
ADM1, e-ADM | Output mode. Use csv to write a report or dash to open the interactive app. If omitted, the model is solved without creating an output view. |
--control-states |
e-ADM | JSON object of states to hold constant. By default, e-ADM holds S_H_ion at 10^-6.5. |
ADM1 Input Contract
| Input object | Required shape | Required naming rule | How it is used |
|---|---|---|---|
species |
list of 38 strings | Names must match every key in initial_conditions; each inlet key must be species_name + "_in". |
Defines the order of the state vector c. |
reactions |
list of 28 strings | Names must match the reaction names used in build_adm1_stoichiometric_matrix and adm1_ode_sys. |
Defines the order of the reaction vector v and the columns of S. |
initial_conditions |
object with 38 numeric values | Keys are exactly the ADM1 species names. | Converted to y0, the initial state passed to solve_ivp. |
inlet_conditions |
object with 38 numeric values | Keys are exactly the ADM1 species names with _in appended. |
Converted to c_in, used in the liquid and gas flow terms. |
base_parameters |
object with reactor constants | Must include q_in, V_liq, V_gas, R, T_op, T_base, P_atm, and K_W or equivalent water-equilibrium value used by the model. |
Controls hydraulic dilution, gas headspace scaling, and gas partial pressures. |
model_parameters |
object with kinetic, yield, fraction, acid/base, inhibition, and gas-transfer constants | Must include all keys referenced by ADM1 rates and stoichiometry, such as k_dis, k_hyd_*, k_m_*, K_S_*, Y_*, f_*, C_*, N_*, K_a_*, K_pH_*, K_I_*, k_L_a, K_H_*, and k_p. |
Controls reaction rates, stoichiometric coefficients, inhibition factors, acid/base rates, and gas transfer. |
e-ADM Input Contract
| Input object | Required shape | Required naming rule | How it is used |
|---|---|---|---|
species |
list of 49 strings | Names must match every key in initial_conditions; each inlet key must be species_name + "_in". |
Defines the order of the state vector c. |
reactions |
list of 45 strings | Names must match the reaction names used in build_e_adm_stoichiometric_matrix and e_adm_ode_sys. |
Defines the order of the reaction vector v and the columns of S. |
initial_conditions |
object with 49 numeric values | Keys are exactly the e-ADM species names. | Converted to y0, after applying any control_state overrides. |
inlet_conditions |
object with 49 numeric values | Keys are exactly the e-ADM species names with _in appended. |
Converted to c_in, used in the liquid and gas flow terms. |
base_parameters |
object with reactor constants | Must include q_in, V_liq, V_gas, R, T_op, T_base, P_atm, and K_W. |
Controls hydraulic dilution, gas headspace scaling, and gas partial pressures. |
model_parameters |
object with kinetic, yield, fraction, acid/base, inhibition, and gas-transfer constants | Must include all keys referenced by e-ADM rates and stoichiometry, including Y_su, Y_aa, Y_fa, Y_ac_et, Y_ac_lac, Y_pro_et, Y_pro_lac, Y_bu_et, Y_bu_lac, Y_va, Y_cap, Y_bu, Y_Me_ac, Y_Me_CO2, Y_ac_et_ox, and Y_pro_lac_ox. |
Controls reaction rates, stoichiometric coefficients, inhibition factors, acid/base rates, and gas transfer. |
control_state |
optional object | Keys must be valid species names. | Overrides initial conditions and forces selected derivatives to zero. The CLI sets S_H_ion = 10^-6.5 by default for e-ADM. |
Other Keyed Database Files
The same first-layer-key pattern should be used for other structured databases. For example, feeds can live in one feeds.json file:
{
"food_waste": {
"name": "food_waste",
"carbohydrates": 10,
"proteins": 20,
"lipids": 20,
"si": 30,
"xi": 50,
"tss": 80
},
"manure": {
"name": "manure",
"carbohydrates": 5,
"proteins": 15,
"lipids": 5,
"si": 20,
"xi": 55,
"tss": 70
}
}
That keeps the rule consistent: one file per database type, one top-level key per named item.
Model Outputs
| Output | Source | Description |
|---|---|---|
| Concentration trajectories | Model.solve_model(...) |
Returns a SciPy OdeResult. sol.t contains time points and sol.y contains species concentrations ordered exactly like model.species. |
| CSV report | --report csv or Model.csv_report(...) |
Writes <model.name>_Report.csv. Rows are species and columns are simulated time points. |
| Interactive dashboard | --report dash or Model.dash_app(...) |
Opens a Dash app with concentration plots and model tables. |
| Reaction fluxes | model.info["Fluxes"] |
The most recent reaction-rate vector v, ordered exactly like model.reactions. |
| Stoichiometric matrix | model.s |
Matrix S with shape number_of_species x number_of_reactions. Entry S[i, j] is the coefficient for species i in reaction j. |
ADM1 has 38 species and 28 reactions. e-ADM has 49 species and 45 reactions.
Output Shapes
| Output | ADM1 shape | e-ADM shape | Notes |
|---|---|---|---|
sol.t |
(n_time_points,) |
(n_time_points,) |
Time is in days in the default examples. The CLI uses np.linspace(0, 30, 10000). |
sol.y |
(38, n_time_points) |
(49, n_time_points) |
Rows follow model.species; columns follow sol.t. |
model.s |
(38, 28) |
(49, 45) |
Rows follow species; columns follow reactions. |
model.info["Fluxes"] |
(28, 1) |
(45, 1) |
Stores the most recent flux calculation from the ODE function. |
| CSV report | 38 rows plus header | 49 rows plus header | The first column is the species index. Remaining columns are simulated time points. |
The solver returns a fallback solution filled with 1e10 if integration fails. That is a failure sentinel, not a physical concentration.
Mathematical Setup
The JSON files describe the state names, reaction names, and parameter values. The Python model converts them into a dynamic system by building a stoichiometric matrix and evaluating reaction rates at every time step.
| Step | Formula | Meaning |
|---|---|---|
| Species vector | c(t) = [c_1(t), ..., c_n(t)]^T |
Concentrations are ordered by the species JSON file. |
| Reaction-rate vector | v(c, theta) = [v_1, ..., v_m]^T |
Fluxes are ordered by the reactions JSON file and are calculated from concentrations and parameters. |
| Stoichiometric matrix | S in R^(n x m) |
Rows are species, columns are reactions. S[i, j] converts reaction j into the concentration change of species i. |
| Reaction contribution | r(c, theta) = S v(c, theta) |
Net production or consumption of every species from biochemical, acid/base, and gas-transfer reactions. |
| Liquid flow contribution | (q_in / V_liq) * (c_in - c) |
Continuous stirred tank dilution or influent loading for liquid-phase states. |
| Gas flow contribution | (q_gas / V_gas) * (c_gas,in - c_gas) |
Headspace gas outflow for gas states. |
| Gas flow rate | q_gas = max(0, k_p * (P_gas - P_atm)) |
Gas leaves only when calculated gas pressure exceeds atmospheric pressure. |
| Final derivative | dc/dt = S v(c, theta) + flow terms |
This is the vector returned to scipy.integrate.solve_ivp. |
The implemented derivative can be written as:
c = current state vector
c_in = inlet state vector
S = stoichiometric matrix
v = reaction-rate vector
r = S @ v
for liquid states:
dc_liq/dt = r_liq + (q_in / V_liq) * (c_in,liq - c_liq)
for gas states:
dc_gas/dt = r_gas + (q_gas / V_gas) * (c_in,gas - c_gas)
The gas states are the final three species in both models:
S_gas_h2, S_gas_ch4, S_gas_co2
The gas pressure and gas outflow equations are:
p_gas_h2 = S_gas_h2 * R * T_op / 16
p_gas_ch4 = S_gas_ch4 * R * T_op / 64
p_gas_co2 = S_gas_co2 * R * T_op
p_gas_h2o = 0.0313 * exp(5290 * (1 / T_base - 1 / T_op))
P_gas = p_gas_h2 + p_gas_ch4 + p_gas_co2 + p_gas_h2o
q_gas = max(0, k_p * (P_gas - P_atm))
For any reaction j, the instantaneous contribution to species i is:
dc_i/dt from reaction j = S[i, j] * v_j
This is why reaction and species names are used to build S: the equations are much easier to audit than when the matrix is filled with positional numbers.
Reaction Rate Forms
| Reaction type | Formula pattern | Used for |
|---|---|---|
| First-order conversion | v_j = k * X |
Disintegration, hydrolysis, and decay reactions. |
| Single-substrate uptake | v_j = k_m * S_a / (K_S + S_a) * X * I |
Sugar, amino acid, LCFA, acetate, hydrogen, ethanol, lactate, and VFA uptake reactions. |
| Competitive ADM1 C4 uptake | v_j = k_m * S_a / (K_S + S_a) * X_c4 * S_a / (S_va + S_bu + eps) * I |
ADM1 valerate and butyrate uptake. |
| Two-substrate uptake | v_j = k_m * S_a * S_b / (K_a * S_a + K_b * S_b + S_a * S_b + eps) * X * I |
e-ADM syntrophic reactions that require paired substrates. |
| Inhibition or limitation | I = product(I_pH, I_H2, I_NH3, I_IN, ...) |
Multiplies uptake rates to suppress a reaction under limiting or inhibitory conditions. |
| Acid/base kinetic form | v_AB = k_AB * (S_ion * (K_a + S_H) - K_a * S_total) |
Kinetic acid/base reactions when the state is not solved algebraically. |
| DAE acid/base update | S_ion = K_a / (K_a + S_H) * S_total |
Algebraic speciation used when model.switch == "DAE". |
| Gas transfer | v_gas = k_La * (S_liq - H * p_gas) |
Transfer between dissolved gas states and headspace gas states. |
Acid/Base Equations
ADM1 and e-ADM both calculate kinetic acid/base rates, then set selected acid/base derivatives to zero in DAE mode. The kinetic form is:
v_AB,acid = k_A_B,acid * (S_ion * (K_a,acid + S_H) - K_a,acid * S_total)
For carbonate and inorganic nitrogen:
v_AB,co2 = k_A_B_co2 * (S_hco3_ion * (K_a_co2 + S_H) - K_a_co2 * S_IC)
v_AB,IN = k_A_B_IN * (S_nh3 * (K_a_IN + S_H) - K_a_IN * S_IN)
In DAE mode, ionized species are updated algebraically. e-ADM explicitly updates:
S_va_ion = K_a_va / (K_a_va + S_H) * S_va
S_bu_ion = K_a_bu / (K_a_bu + S_H) * S_bu
S_pro_ion = K_a_pro / (K_a_pro + S_H) * S_pro
S_cap_ion = K_a_cap / (K_a_cap + S_H) * S_cap
S_ac_ion = K_a_ac / (K_a_ac + S_H) * S_ac
S_lac_ion = K_a_lac / (K_a_lac + S_H) * S_lac
S_hco3_ion = S_IC - S_co2
Hydrogen ion concentration is calculated from electroneutrality unless it is controlled:
S_H = -phi / 2 + 0.5 * sqrt(phi^2 + 4 * K_w)
When S_H_ion is included in control_state, the controlled value is used and dS_H_ion/dt = 0.
Inhibition Equations
The pH inhibition terms use Hill-type functions:
I_pH_x = K_pH_x^n_x / (S_H^n_x + K_pH_x^n_x)
Nitrogen limitation is a Monod term:
I_IN_lim = S_IN / (K_S_IN + S_IN + eps)
Hydrogen and ammonia inhibition terms use:
I_h2_x = 1 / (1 + S_h2 / (K_I_h2_x + eps))
I_nh3 = 1 / (1 + S_nh3 / (K_I_nh3 + eps))
ADM1 uses the same conceptual forms, with its original I_IN_lim = 1 / (1 + K_S_IN / S_IN) expression.
ADM1 Reactions
The ADM1 reactions follow the Batstone ADM1 structure: disintegration, hydrolysis, soluble-substrate uptake, biomass decay, acid/base speciation, and gas transfer.
ADM1 Stoichiometric Coefficients
ADM1 uses yield coefficients Y_*, product fractions f_*, carbon contents C_*, and nitrogen contents N_* to fill S. Nitrogen limitation sets selected yields to zero before S is built.
For the main carbon-balance terms:
Y_su = 0 if nitrogen_limited else Y_su
Y_aa = 0 if nitrogen_limited else Y_aa
Y_fa = 0 if nitrogen_limited else Y_fa
s_1 = -C_xc + f_sI_xc*C_sI + f_ch_xc*C_ch + f_pr_xc*C_pr + f_li_xc*C_li + f_xI_xc*C_xI
s_2 = -C_ch + C_su
s_3 = -C_pr + C_aa
s_4 = -C_li + (1 - f_fa_li)*C_su + f_fa_li*C_fa
s_5 = -C_su + (1 - Y_su)*(f_bu_su*C_bu + f_pro_su*C_pro + f_ac_su*C_ac) + Y_su*C_bac
s_6 = -C_aa + (1 - Y_aa)*(f_va_aa*C_va + f_bu_aa*C_bu + f_pro_aa*C_pro + f_ac_aa*C_ac) + Y_aa*C_bac
s_7 = -C_fa + (1 - Y_fa)*0.7*C_ac + Y_fa*C_bac
s_8 = -C_va + (1 - Y_c4)*0.54*C_pro + (1 - Y_c4)*0.31*C_ac + Y_c4*C_bac
s_9 = -C_bu + (1 - Y_c4)*0.8*C_ac + Y_c4*C_bac
s_10 = -C_pro + (1 - Y_pro)*0.57*C_ac + Y_pro*C_bac
s_11 = -C_ac + (1 - Y_ac)*C_ch4 + Y_ac*C_bac
s_12 = (1 - Y_h2)*C_ch4 + Y_h2*C_bac
s_13 = -C_bac + C_xc
These terms are inserted into the S_IC row with negative signs for conversion reactions and positive return through decay. For example:
S[S_IC, Uptake of sugars] = -s_5
S[S_IC, Uptake of acetate] = -s_11
S[S_IC, Decay of Xsu] = -s_13
Nitrogen stoichiometry follows the same pattern:
S[S_IN, Uptake of sugars] = -Y_su * N_bac
S[S_IN, Uptake of amino acids] = N_aa - Y_aa * N_bac
S[S_IN, Uptake of acetate] = -Y_ac * N_bac
S[S_IN, Decay of Xsu] = N_bac - N_xc
| Reaction | Rate expression | Main conversion represented in S |
|---|---|---|
Disintegration |
k_dis * X_xc |
Composite particulate matter X_xc is split into carbohydrates X_ch, proteins X_pr, lipids X_li, soluble inert S_I, particulate inert X_I, inorganic carbon S_IC, and inorganic nitrogen S_IN. |
Hydrolysis carbohydrates |
k_hyd_ch * X_ch |
Particulate carbohydrates become soluble sugars S_su, with carbon correction through S_IC. |
Hydrolysis of proteins |
k_hyd_pr * X_pr |
Particulate proteins become amino acids S_aa, with carbon correction through S_IC. |
Hydrolysis of lipids |
k_hyd_li * X_li |
Lipids split into LCFA S_fa and sugars S_su, with carbon correction through S_IC. |
Uptake of sugars |
k_m_su * S_su / (K_S_su + S_su) * X_su * I5 |
Sugars are consumed to grow X_su and produce butyrate S_bu, propionate S_pro, acetate S_ac, hydrogen S_h2, inorganic carbon, and nitrogen demand. |
Uptake of amino acids |
k_m_aa * S_aa / (K_S_aa + S_aa) * X_aa * I6 |
Amino acids are consumed to grow X_aa and produce valerate S_va, butyrate, propionate, acetate, hydrogen, inorganic carbon, and inorganic nitrogen. |
Uptake of LCFA |
k_m_fa * S_fa / (K_S_fa + S_fa) * X_fa * I7 |
LCFA are consumed to grow X_fa and produce acetate, hydrogen, inorganic carbon, and nitrogen demand. |
Uptake of valerate |
k_m_c4 * S_va / (K_S_c4 + S_va) * X_c4 * S_va / (S_va + S_bu + eps) * I8 |
Valerate is consumed by X_c4, producing propionate, acetate, hydrogen, biomass, carbon, and nitrogen demand. |
Uptake of butyrate |
k_m_c4 * S_bu / (K_S_c4 + S_bu) * X_c4 * S_bu / (S_bu + S_va + eps) * I9 |
Butyrate is consumed by X_c4, producing acetate, hydrogen, biomass, carbon, and nitrogen demand. |
Uptake of propionate |
k_m_pr * S_pro / (K_S_pro + S_pro) * X_pro * I10 |
Propionate is consumed to grow X_pro and produce acetate, hydrogen, carbon, and nitrogen demand. |
Uptake of acetate |
k_m_ac * S_ac / (K_S_ac + S_ac) * X_ac * I11 |
Acetate is consumed by acetoclastic methanogens, producing methane S_ch4, X_ac, carbon correction, and nitrogen demand. |
Uptake of Hydrogen |
k_m_h2 * S_h2 / (K_S_h2 + S_h2) * X_h2 * I12 |
Hydrogen is consumed by hydrogenotrophic methanogens, producing methane S_ch4, X_h2, carbon correction, and nitrogen demand. |
Decay of Xsu |
k_dec_X_su * X_su |
Sugar degraders decay back to composite particulate matter X_xc, with carbon and nitrogen returned through S_IC and S_IN. |
Decay of Xaa |
k_dec_X_aa * X_aa |
Amino acid degraders decay to X_xc, with carbon and nitrogen returned. |
Decay of Xfa |
k_dec_X_fa * X_fa |
LCFA degraders decay to X_xc, with carbon and nitrogen returned. |
Decay of Xc4 |
k_dec_X_c4 * X_c4 |
C4 degraders decay to X_xc, with carbon and nitrogen returned. |
Decay of Xpro |
k_dec_X_pro * X_pro |
Propionate degraders decay to X_xc, with carbon and nitrogen returned. |
Decay of Xac |
k_dec_X_ac * X_ac |
Acetoclastic methanogens decay to X_xc, with carbon and nitrogen returned. |
Decay of Xh2 |
k_dec_X_h2 * X_h2 |
Hydrogenotrophic methanogens decay to X_xc, with carbon and nitrogen returned. |
Acid Base Equilibrium (Va) |
k_A_B_va * (S_va_ion * (K_a_va + S_H) - K_a_va * S_va) |
Valerate speciation between total valerate S_va and ionized valerate S_va_ion. |
Acid Base Equilibrium (Bu) |
k_A_B_bu * (S_bu_ion * (K_a_bu + S_H) - K_a_bu * S_bu) |
Butyrate speciation between S_bu and S_bu_ion. |
Acid Base Equilibrium (Pro) |
k_A_B_pro * (S_pro_ion * (K_a_pro + S_H) - K_a_pro * S_pro) |
Propionate speciation between S_pro and S_pro_ion. |
Acid Base Equilibrium (Ac) |
k_A_B_ac * (S_ac_ion * (K_a_ac + S_H) - K_a_ac * S_ac) |
Acetate speciation between S_ac and S_ac_ion. |
Acid Base Equilibrium (CO2) |
k_A_B_co2 * (S_hco3_ion * (K_a_co2 + S_H) - K_a_co2 * S_IC) |
Carbonate speciation through bicarbonate S_hco3_ion and inorganic carbon S_IC. |
Acid Base Equilibrium (In) |
k_A_B_IN * (S_nh3 * (K_a_IN + S_H) - K_a_IN * S_IN) |
Nitrogen speciation between ammonia S_nh3, ammonium S_nh4_ion, and total inorganic nitrogen S_IN. |
Gas Transfer H2 |
k_L_a * (S_h2 - 16 * K_H_h2 * p_gas_h2) |
Dissolved hydrogen leaves the liquid and enters S_gas_h2 with V_liq / V_gas scaling. |
Gas Transfer CH4 |
k_L_a * (S_ch4 - 64 * K_H_ch4 * p_gas_ch4) |
Dissolved methane leaves the liquid and enters S_gas_ch4 with V_liq / V_gas scaling. |
Gas Transfer CO2 |
k_L_a * (S_co2 - K_H_co2 * p_gas_co2) |
Dissolved carbon dioxide leaves the liquid and enters S_gas_co2 with V_liq / V_gas scaling. |
ADM1 Inhibition Factors
| Factor | Formula pattern | Applied to |
|---|---|---|
I5 |
I_pH_aa * I_IN_lim |
Sugar uptake. |
I6 |
I5 |
Amino acid uptake. |
I7 |
I_pH_aa * I_IN_lim * I_h2_fa |
LCFA uptake. |
I8, I9 |
I_pH_aa * I_IN_lim * I_h2_c4 |
Valerate and butyrate uptake. |
I10 |
I_pH_aa * I_IN_lim * I_h2_pro |
Propionate uptake. |
I11 |
I_pH_ac * I_IN_lim * I_nh3 |
Acetate uptake. |
I12 |
I_pH_h2 * I_IN_lim |
Hydrogen uptake. |
e-ADM Reactions
e-ADM keeps the same dynamic structure but expands the soluble fermentation network. It separates ethanol-linked and lactate-linked routes, adds caproate, lactate, ethanol, explicit TSS/TDS disintegration, and two methanogenesis routes.
e-ADM Stoichiometric Coefficients
e-ADM uses the same matrix logic as ADM1, but most soluble conversions are written as explicit product fractions plus a carbon-balance residual. Selected yields are set to zero under nitrogen limitation.
For sugar, amino acid, and LCFA uptake:
Y_su = 0 if nitrogen_limited else Y_su
Y_aa = 0 if nitrogen_limited else Y_aa
Y_fa = 0 if nitrogen_limited else Y_fa
f_ac_su = 1 - f_pro_su - f_et_su - f_lac_su
f_ac_aa = 1 - f_pro_aa - f_et_aa - f_lac_aa
f_ac_fa = 1 - f_pro_fa - f_et_fa - f_lac_fa
f_IC_su = -(-C_su + (1-Y_su)*f_pro_su*C_pro + (1-Y_su)*f_et_su*C_et
+ (1-Y_su)*f_lac_su*C_lac + (1-Y_su)*f_ac_su*C_ac + Y_su*C_bac)
f_IC_aa = -(-C_aa + (1-Y_aa)*f_pro_aa*C_pro + (1-Y_aa)*f_et_aa*C_et
+ (1-Y_aa)*f_lac_aa*C_lac + (1-Y_aa)*f_ac_aa*C_ac + Y_aa*C_bac)
f_IC_fa = -(-C_fa + (1-Y_fa)*f_pro_fa*C_pro + (1-Y_fa)*f_et_fa*C_et
+ (1-Y_fa)*f_lac_fa*C_lac + (1-Y_fa)*f_ac_fa*C_ac + Y_fa*C_bac)
For chain elongation and VFA conversion, e-ADM uses paired substrate routes:
f_IC_ac_et = -(-C_ac + f_et_ac*C_et + (1-f_et_ac-Y_ac_et)*f_bu_ac*C_bu + Y_ac_et*C_bac)
f_IC_ac_lac = -(-C_ac + f_lac_ac*C_lac + (1-f_lac_ac-Y_ac_lac)*f_bu_ac*C_bu + Y_ac_lac*C_bac)
f_IC_pro_et = -(-C_pro + f_et_pro*C_et + (1-f_et_pro-Y_pro_et)*f_va_pro*C_va + Y_pro_et*C_bac)
f_IC_pro_lac = -(-C_pro + f_lac_pro*C_lac + (1-f_lac_pro-Y_pro_lac)*f_va_pro*C_va + Y_pro_lac*C_bac)
f_IC_bu_et = -(-C_bu + f_et_bu*C_et + (1-f_et_bu-Y_bu_et)*f_cap_bu*C_cap + Y_bu_et*C_bac)
f_IC_bu_lac = -(-C_bu + f_lac_bu*C_lac + (1-f_lac_bu-Y_bu_lac)*f_cap_bu*C_cap + Y_bu_lac*C_bac)
Methanogenesis and oxidation use:
f_IC_Me_ach2 = -(f_ac_h2*C_ac + (1 - Y_Me_ac)*C_ch4 + Y_Me_ac*C_bac)
f_IC_et_ox = -(-C_et + (1-Y_ac_et_ox)*C_bac + Y_ac_et_ox*C_ac)
f_IC_lac_ox = -(-C_lac + (1-Y_pro_lac_ox)*C_bac + Y_pro_lac_ox*C_pro)
The stoichiometric matrix then combines these residuals with explicit product coefficients. For example:
S[S_su, Uptake of sugars] = -1
S[S_pro, Uptake of sugars] = (1 - Y_su) * f_pro_su
S[S_et, Uptake of sugars] = (1 - Y_su) * f_et_su
S[S_lac, Uptake of sugars] = (1 - Y_su) * f_lac_su
S[S_ac, Uptake of sugars] = (1 - Y_su) * f_ac_su
S[S_IN, Uptake of sugars] = -Y_su * N_bac
S[S_IC, Uptake of sugars] = f_IC_su
S[X_su, Uptake of sugars] = Y_su
| Reaction | Rate expression | Main conversion represented in S |
|---|---|---|
TSS_Disintegration |
k_dis_TSS * TSS |
Total suspended solids are split into X_ch, X_pr, X_li, and inert particulate biomass X_I using feed fractions. |
TDS_Disintegration |
k_dis_TDS * TDS |
Total dissolved solids are split into X_ch, X_pr, X_li, and soluble inert S_I using feed fractions. |
Hydrolysis carbohydrates |
k_hyd_ch * X_ch |
Particulate carbohydrate is hydrolyzed to soluble sugar S_su. |
Hydrolysis proteins |
k_hyd_pr * X_pr |
Particulate protein is hydrolyzed to amino acids S_aa. |
Hydrolysis lipids |
k_hyd_li * X_li |
Particulate lipids are hydrolyzed to LCFA S_fa. |
Uptake of sugars |
k_m_su * S_su / (K_S_su + S_su) * X_su * I5 |
Sugars are consumed to grow X_su and form propionate, ethanol, lactate, acetate, carbon, and nitrogen demand. |
Uptake of amino acids |
k_m_aa * S_aa / (K_S_aa + S_aa) * X_aa * I6 |
Amino acids are consumed to grow X_aa and form propionate, ethanol, lactate, acetate, inorganic carbon, and inorganic nitrogen. |
Uptake of LCFA |
k_m_fa * S_fa / (K_S_fa + S_fa) * X_fa * I7 |
LCFA are consumed to grow X_fa and form propionate, ethanol, lactate, acetate, carbon, and nitrogen demand. |
Uptake of acetate_et |
k_m_ac * S_ac * S_et / (K_S_ac*S_ac + K_S_ac_et*S_et + S_ac*S_et + eps) * X_ac_et * I11 |
Acetate and ethanol are converted by X_ac_et, producing butyrate, hydrogen, carbon correction, and new biomass. |
Uptake of acetate_lac |
k_m_ac * S_ac * S_lac / (K_S_ac*S_ac + K_S_ac_lac*S_lac + S_ac*S_lac + eps) * X_ac_lac * I11 |
Acetate and lactate are converted by X_ac_lac, producing butyrate, hydrogen, carbon correction, and new biomass. |
Uptake of propionate_et |
k_m_pro * S_pro * S_et / (K_S_pro*S_pro + K_S_pro_et*S_et + S_pro*S_et + eps) * X_chain_et * I10 |
Propionate and ethanol are converted by chain-elongating biomass, producing valerate, hydrogen, carbon correction, and X_chain_et. |
Uptake of propionate_lac |
k_m_pro * S_pro * S_lac / (K_S_pro*S_pro + K_S_pro_lac*S_lac + S_pro*S_lac + eps) * X_chain_lac * I10 |
Propionate and lactate are converted by chain-elongating biomass, producing valerate, hydrogen, carbon correction, and X_chain_lac. |
Uptake of butyrate_et |
k_m_bu * S_bu * S_et / (K_S_bu*S_bu + K_S_bu_et*S_et + S_bu*S_et + eps) * X_chain_et * I14 |
Butyrate and ethanol are converted to caproate, hydrogen, carbon correction, and X_chain_et. |
Uptake of butyrate_lac |
k_m_bu * S_bu * S_lac / (K_S_bu*S_bu + K_S_bu_lac*S_lac + S_bu*S_lac + eps) * X_chain_lac * I14 |
Butyrate and lactate are converted to caproate, hydrogen, carbon correction, and X_chain_lac. |
Uptake of valerate |
k_m_va * S_va / (K_S_va + S_va) * X_VFA_deg * I15 |
Valerate is degraded to propionate and X_VFA_deg. |
Uptake of caproate |
k_m_cap * S_cap / (K_S_cap + S_cap) * X_VFA_deg * I13 |
Caproate is degraded to acetate and X_VFA_deg. |
Uptake of butyrate |
k_m_bu_deg * S_bu / (K_S_bu + S_bu) * X_VFA_deg * I13 |
Butyrate is degraded to acetate and X_VFA_deg. |
Methanogenessis from acetate and h2 |
k_m_h2_Me_ac * S_gas_h2 * S_ac / (K_S_h2_Me_ac*S_gas_h2 + K_S_ac_Me*S_ac + S_ac*S_gas_h2 + eps) * X_Me_ac * I12 |
Acetate and gas-phase hydrogen are converted to dissolved methane S_ch4, methanogenic biomass X_Me_ac, carbon correction, and nitrogen demand. |
Methanogenessis from CO2 and h2 |
k_m_h2_Me_CO2 * S_gas_h2 * S_gas_co2 / (K_S_h2_Me_CO2*S_gas_h2 + K_S_CO2_Me*S_gas_co2 + S_gas_co2*S_gas_h2 + eps) * X_Me_CO2 * I12 |
Gas-phase hydrogen and carbon dioxide are converted to gas-phase methane S_gas_ch4, X_Me_CO2, gas-phase carbon dioxide change, and nitrogen demand. |
Uptake of ethanol |
k_m_et * S_et / (K_S_et + S_et) * X_et * I16 |
Ethanol is oxidized to acetate, inorganic carbon, and X_et. |
Uptake of lactate |
k_m_lac * S_lac / (K_S_lac + S_lac) * X_lac * I16 |
Lactate is oxidized to propionate, inorganic carbon, and X_lac. |
Decay of Xsu |
k_dec_X_su * X_su |
Sugar degraders decay to TSS, returning biomass carbon and nitrogen. |
Decay of Xaa |
k_dec_X_aa * X_aa |
Amino acid degraders decay to TSS, returning biomass carbon and nitrogen. |
Decay of Xfa |
k_dec_X_fa * X_fa |
LCFA degraders decay to TSS, returning biomass carbon and nitrogen. |
Decay of X_ac_et |
k_dec_X_ac * X_ac_et |
Acetate-ethanol consumers decay to TSS, returning biomass carbon and nitrogen. |
Decay of X_ac_lac |
k_dec_X_ac * X_ac_lac |
Acetate-lactate consumers decay to TSS, returning biomass carbon and nitrogen. |
Decay of Xpro |
Not currently assigned in e_adm_ode_sys |
Listed in the reaction set but not given a rate in the current ODE block. If kept, it behaves as zero-flux unless populated elsewhere. |
Decay of X_chain_et |
k_dec_X_chain_et * X_chain_et |
Ethanol-linked chain elongators decay to TSS, returning biomass carbon and nitrogen. |
Decay of X_chain_lac |
k_dec_X_chain_lac * X_chain_lac |
Lactate-linked chain elongators decay to TSS, returning biomass carbon and nitrogen. |
Decay of X_VFA_deg |
k_dec_X_VFA_deg * X_VFA_deg |
VFA degraders decay to TSS, returning biomass carbon and nitrogen. |
Decay of X_Me_ac |
k_dec_X_Me_ac * X_Me_ac |
Acetate/hydrogen methanogens decay to TSS, returning biomass carbon and nitrogen. |
Decay of X_Me_CO2 |
k_dec_X_Me_CO2 * X_Me_CO2 |
CO2/hydrogen methanogens decay to TSS, returning biomass carbon and nitrogen. |
Decay of Xet |
k_dec_X_et * X_et |
Ethanol oxidizers decay. This rate is present in the ODE; the current stoichiometric builder should be checked if this flux is expected to affect states. |
Decay of Xlac |
k_dec_X_lac * X_lac |
Lactate oxidizers decay. This rate is present in the ODE; the current stoichiometric builder should be checked if this flux is expected to affect states. |
Acid Base Equilibrium (Va) |
k_A_B_va * (S_va_ion * (K_a_va + S_H) - K_a_va * S_va) |
Valerate speciation between S_va and S_va_ion. |
Acid Base Equilibrium (Bu) |
k_A_B_bu * (S_bu_ion * (K_a_bu + S_H) - K_a_bu * S_bu) |
Butyrate speciation between S_bu and S_bu_ion. |
Acid Base Equilibrium (Pro) |
k_A_B_pro * (S_pro_ion * (K_a_pro + S_H) - K_a_pro * S_pro) |
Propionate speciation between S_pro and S_pro_ion. |
Acid Base Equilibrium (Cap) |
k_A_B_cap * (S_cap_ion * (K_a_cap + S_H) - K_a_cap * S_cap) |
Caproate speciation between S_cap and S_cap_ion. |
Acid Base Equilibrium (Lac) |
k_A_B_lac * (S_lac_ion * (K_a_lac + S_H) - K_a_lac * S_lac) |
Lactate speciation between S_lac and S_lac_ion. |
Acid Base Equilibrium (Ac) |
k_A_B_ac * (S_ac_ion * (K_a_ac + S_H) - K_a_ac * S_ac) |
Acetate speciation between S_ac and S_ac_ion. |
Acid Base Equilibrium (CO2) |
k_A_B_co2 * (S_hco3_ion * (K_a_co2 + S_H) - K_a_co2 * S_IC) |
Carbonate speciation through bicarbonate S_hco3_ion and inorganic carbon S_IC. |
Acid Base Equilibrium (In) |
k_A_B_IN * (S_nh3 * (K_a_IN + S_H) - K_a_IN * S_IN) |
Nitrogen speciation between ammonia S_nh3, ammonium S_nh4_ion, and total inorganic nitrogen S_IN. |
Gas Transfer H2 |
max(0, k_L_a * (S_h2 - 16 * K_H_h2 * p_gas_h2)) |
Dissolved hydrogen leaves the liquid and enters S_gas_h2 with V_liq / V_gas scaling. |
Gas Transfer CH4 |
max(0, k_L_a * (S_ch4 - 64 * K_H_ch4 * p_gas_ch4)) |
Dissolved methane leaves the liquid and enters S_gas_ch4 with V_liq / V_gas scaling. |
Gas Transfer CO2 |
max(0, k_L_a * (S_co2 - K_H_co2 * p_gas_co2)) |
Dissolved carbon dioxide leaves the liquid and enters S_gas_co2 with V_liq / V_gas scaling. |
e-ADM Inhibition Factors
| Factor | Formula pattern | Applied to |
|---|---|---|
I5 |
I_pH_aa * I_IN_lim |
Sugar uptake. |
I6 |
I5 |
Amino acid uptake. |
I7 |
I_pH_aa * I_IN_lim * I_h2_fa |
LCFA uptake. |
I10 |
I_pH_pro * I_IN_lim * I_h2_pro |
Propionate plus ethanol or lactate uptake. |
I11 |
I_pH_ac * I_IN_lim * I_nh3 |
Acetate plus ethanol or lactate uptake. |
I12 |
I_pH_h2 * I_IN_lim |
Methanogenesis. |
I13 |
I_pH_cap * I_IN_lim * I_h2_c4 |
Caproate uptake and direct butyrate degradation. |
I14 |
I_pH_bu * I_IN_lim * I_h2_c4 |
Butyrate plus ethanol or lactate uptake. |
I15 |
I_pH_va * I_IN_lim * I_h2_c4 |
Valerate uptake. |
I16 |
I_IN_lim * I_nh3 * I_pH_aa * I_h2_oxidation |
Ethanol and lactate oxidation. |
Methane-Producing Reactions
| Model | Methane-producing reactions |
|---|---|
| ADM1 | Uptake of acetate, Uptake of Hydrogen |
| e-ADM | Methanogenessis from acetate and h2, Methanogenessis from CO2 and h2 |
Gas Transfer CH4 does not create methane. It moves methane between dissolved S_ch4 and gas-phase S_gas_ch4.
State Vectors
ADM1 Species
S_su, S_aa, S_fa, S_va, S_bu, S_pro, S_ac, S_h2, S_ch4, S_IC, S_IN, S_I, X_xc, X_ch, X_pr, X_li, X_su, X_aa, X_fa, X_c4, X_pro, X_ac, X_h2, X_I, S_cation, S_anion, S_H_ion, S_va_ion, S_bu_ion, S_pro_ion, S_ac_ion, S_hco3_ion, S_co2, S_nh3, S_nh4_ion, S_gas_h2, S_gas_ch4, S_gas_co2
e-ADM Species
S_su, S_aa, S_fa, S_va, S_bu, S_pro, S_et, S_lac, S_cap, S_ac, S_h2, S_ch4, S_IC, S_IN, S_I, TSS, TDS, X_ch, X_pr, X_li, X_su, X_aa, X_ac_et, X_ac_lac, X_fa, X_VFA_deg, X_et, X_lac, X_chain_et, X_chain_lac, X_Me_ac, X_Me_CO2, X_I, S_cation, S_anion, S_H_ion, S_va_ion, S_bu_ion, S_pro_ion, S_cap_ion, S_lac_ion, S_ac_ion, S_hco3_ion, S_co2, S_nh3, S_nh4_ion, S_gas_h2, S_gas_ch4, S_gas_co2
Minimal CLI Run
adtoolbox ADM adm1 --models-json /path/to/ADToolbox/models.json --report csv
adtoolbox ADM e-adm --models-json /path/to/ADToolbox/models.json --report csv