Skip to content

High: [Kinetics] Reversible-reaction analytical Jacobian ignores the equilibrium reverse term #23

Description

@bernalde

Maintainer triage (June 29, 2026)

  • Status: Verified bug against the current master source in this fork.
  • Severity: High.
  • Area labels: area:kinetics.
  • Tackle batch: P4 - high-impact numerical/model correctness.

The source review confirmed that the cited code path and failure mode are still present. The original audit details are preserved below for reproduction notes and suggested fixes.


Original audit details

Part of the model-correctness audit — see #17.

Severity: high | Category: kinetics | Location: PharmaPy/Kinetics.py lines 564-598, 603-609

What's wrong

get_rxn_rates computes net rates with the reverse term when keq_params is not None: f_terms = equilibrium_model(conc, temp, delta_hrxn) which returns f_term - r_term (lines 606-607, 529). However, when jac=True (line 596-598) it calls derivatives(conc, temp), and derivatives ALWAYS uses self.kinetic_model (= elem_f_model, forward only) and self.df_dstates (= elem_df_dstates, forward only) at lines 566-571. The reverse contribution -d/dC[ prod(C_prod^beta)/Keq ] is never added to the Jacobian.

Why it's incorrect

The net rate is r = kfprod(C_react^alpha) - (kf/Keq)prod(C_prod^beta). Its derivative wrt concentrations must include the reverse term: dr/dC_k = kfalpha_kf/C_k - (kf/Keq)beta_kg/C_k. The code returns only the first (forward) part, so the analytical state Jacobian disagrees with the actual rate model for any reversible (keq) reaction. Any implicit/Newton integrator or sensitivity analysis using this Jacobian gets an inconsistent (wrong) derivative, degrading convergence and giving incorrect sensitivities.

Suggested regression test

For a reversible reaction A<->B with finite Keq, compare derivatives(conc,temp) against a finite-difference Jacobian of get_rxn_rates(conc,temp,overall_rates=True). They will differ by the omitted reverse-term derivative whenever the reverse rate is nonzero.


Verification: 2/2 adversarial reviewers confirmed (refuted: 0).

Metadata

Metadata

Assignees

Labels

area:kineticsReaction and crystallization kineticsbugSomething isn't workingcorrectnessModel/numerical correctness defectseverity:highConfirmed bug with major correctness impact or broken documented workflowstatus:verifiedSource-reviewed against the current codebase

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions