Maintainer triage (June 29, 2026)
- Status: Verified bug against the current
master source in this fork.
- Severity: High.
- Area labels: area:kinetics, area:crystallizers.
- 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: logic | Location: Kinetics.py lines 838-839, 850-858, 884-885
What's wrong
For sup_sat_type='ratio', sup_sat = (c-csat)/csat + 1 = c/csat, which is >0 even under undersaturation (0<S<1). The dissolution/growth switch keys off the sign of this same sup_sat (line 853 if sup_sat >= 0), so dissolution can never trigger under 'ratio', and the growth driving force differs from the 'relative' case.
Verification: 2/2 adversarial reviewers confirmed (refuted: 0).
Maintainer triage (June 29, 2026)
mastersource in this fork.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: logic | Location:
Kinetics.pylines 838-839, 850-858, 884-885What's wrong
For sup_sat_type='ratio', sup_sat = (c-csat)/csat + 1 = c/csat, which is >0 even under undersaturation (0<S<1). The dissolution/growth switch keys off the sign of this same sup_sat (line 853
if sup_sat >= 0), so dissolution can never trigger under 'ratio', and the growth driving force differs from the 'relative' case.Verification: 2/2 adversarial reviewers confirmed (refuted: 0).