nx_ferment_kinetics.nx
buildroot/runtime/nx_ferment_kinetics.nx
about
nx_ferment_kinetics.nx -- R3 science rung: predictive fermentation model.
"All the science": predict a ferment's acidification curve pH(t) from
first principles -- culture population growth + temperature-scaled
lactic-acid production -- so a recipe can be SIMULATED before a drop
of milk is warmed, and so the generative rung (R5) can predict whether
a NOVEL ferment will reach a safe pH.
THE MODEL (fixed-point, integer-exact, deterministic):
1. Population N(t): logistic growth dN = r*N*(K-N)/K
r = r_base * temp_factor(T) -- warmer culture grows faster
2. Acid A(t): produced in proportion to population AND metabolic
rate dA = acid_yield * temp_factor(T) * N/K
(the lactose -> lactic-acid flux; warmer bacteria metabolise
faster, so the temperature effect COMPOUNDS through both N and A)
3. pH(t) = pH0 - A (acid accumulation drops pH from milk's 6.5)
TEMPERATURE -> RATE via the biological Q10 coefficient (van't Hoff):
rate(T) / rate(T_ref) = Q10 ^ ((T - T_ref)/10)
computed as exp( ln(Q10)/10 * (T - T_ref) ) using the canonical
nx_exp substrate. Q10 ~ 2.5 for lactic-acid bacteria.
NOTE: nx_arrhenius's reciprocal-of-Kelvin form was evaluated and is
UNUSABLE here -- 1/T in its Q10(1024) fixed-point rounds a 13 C span
to delta 0 (1048576/310426 = 3). The biological-Q10 exponential is
both the correct microbiology model for this range AND precision-
safe, so we compose nx_exp directly.
The measured exceed: a $40 yogurt maker holds 43 C but PREDICTS
nothing. This rung predicts the set-time curve and proves, by
construction, that warmer ferments (within range) acidify faster --
the quantitative Q10 claim, gate-checked, not asserted.
genealogy_id: vant_hoff_1884_q10 + verhulst_1838_logistic
+ monod_1949_growth + nishi_exp_q10_substrate_2026
dependencies 1 imports · 8 importers
imports: nx_exp.nx
imported by: nx_ferment_flavor.nxnx_ferment_flavor_test.nxnx_ferment_invent.nxnx_ferment_invent_test.nxnx_ferment_kinetics_test.nxnx_vessel_geometry_test.nxnx_vessel_twin.nxnx_vessel_twin_test.nx
structs
| none |
consts
| 39 | const NX_FKIN_K: i64 = 1000000 // carrying capacity (relative pop x1e6) |
| 40 | const NX_FKIN_N0: i64 = 1000 // inoculum |
| 41 | const NX_FKIN_R_BASE_MILLI: i64 = 300 // growth rate 0.300/hr at T_ref |
| 42 | const NX_FKIN_ACID_YIELD_MILLI:i64 = 150 // acid flux at full pop, T_ref (milli-pH/hr) |
| 43 | const NX_FKIN_T_REF_C: i64 = 30 // reference temperature (C) |
| 44 | const NX_FKIN_Q10_K_Q10: i64 = 94 // ln(2.5)/10 * 1024 (LAB Q10 ~ 2.5) |
| 45 | const NX_FKIN_PH0_MILLI: i64 = 6500 // milk pH 6.5 |
| 46 | const NX_FKIN_PH_FLOOR_MILLI: i64 = 3900 // practical ferment floor ~3.9 |
| 47 | const NX_FKIN_SET_PH_MILLI: i64 = 4600 // "set"/safe acidification target |
| 48 | const NX_FKIN_MAX_HOURS: i64 = 600 // simulation horizon |
| 49 | const NX_FKIN_Q10_ONE: i64 = 1024 |
functions
| 53 | func nx_ferment_kinetics_temp_factor_q10(t_c: i64) -> i64 |
| 62 | func nx_ferment_kinetics_set_time(t_c: i64) -> i64 called by 4: nx_ferment_inventmainnx_vessel_twin_certifymain calls 1: nx_ferment_kinetics_temp_factor_q10 |
| 85 | func nx_ferment_kinetics_ph_at(t_c: i64, target_hour: i64) -> i64 |
| 108 | func nx_ferment_kinetics_pop_at(t_c: i64, target_hour: i64) -> i64 calls 1: nx_ferment_kinetics_temp_factor_q10 |