fix: #1087 - [M5-P1] Fix NaN kernel for monodisperse particles#1090
fix: #1087 - [M5-P1] Fix NaN kernel for monodisperse particles#1090Gorkowski wants to merge 1 commit intouncscode:mainfrom
Conversation
Add a safe divide in get_diffusive_knudsen_number to avoid near-zero kinetic enhancement causing inf/NaN, using an explicit threshold and documenting the same-sign repulsion path. Add regression coverage for monodisperse same-sign kernels, opposite- sign finiteness, full kernel matrix finiteness across implementations, particle-resolved step behavior, and extreme negative kinetic limits. Closes uncscode#1087 ADW-ID: 7ef9668e
There was a problem hiding this comment.
Pull request overview
This PR fixes a critical bug in the charged coagulation kernel where monodisperse same-sign particles produced NaN values, causing crashes in the particle-resolved coagulation step. The fix introduces a numerical guard that prevents division by near-zero kinetic enhancement values, correctly driving the kernel to zero for strongly repulsive same-sign interactions.
Changes:
- Added
KINETIC_ENHANCE_MINguard constant and safe division logic indiffusive_knudsen_module.pyto prevent NaN propagation when kinetic enhancement approaches zero for extreme repulsive potentials - Created comprehensive regression test suite in
charged_kernel_bugs_test.pycovering monodisperse cases, mixed charges, multiple kernel models, and particle-resolved step behavior - Added unit test for the guard in
diffusive_knudsen_test.pyto verify extreme negative potentials yield finite near-zero values
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
particula/particles/properties/diffusive_knudsen_module.py |
Added KINETIC_ENHANCE_MIN = 1e-80 constant and guard using np.divide with where= to set denominator to infinity when kinetic enhancement is below threshold, preventing NaN from division by near-zero |
particula/particles/properties/tests/diffusive_knudsen_test.py |
Added test_near_zero_kinetic_enhancement_guard to verify extreme negative potentials (phi=-200) produce finite near-zero results instead of NaN |
particula/dynamics/coagulation/tests/charged_kernel_bugs_test.py |
New file with 6 regression tests covering monodisperse opposite/same-sign cases, parametrized kernel function tests across 5 models, kinetic limit extremes, and particle-resolved step crash/zero-merger scenarios |
particula/dynamics/condensation/tests/staggered_stability_test.py |
Removed extraneous blank line between imports (style cleanup) |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ) | ||
| denominator = sum_of_radii * continuum_enhance / kinetic_enhance | ||
| # Guard for same-sign repulsion; see coulomb_enhancement.py:83-97 and | ||
| # diffusive_knudsen_module.py:119-126 (issue #1087). |
There was a problem hiding this comment.
The line reference "diffusive_knudsen_module.py:119-126" in the comment appears to point to lines that include the numerator calculation and comment start. Consider updating to reference lines 113-119 (where kinetic_enhance is computed from coulomb_potential_ratio) for better accuracy and traceability.
| # diffusive_knudsen_module.py:119-126 (issue #1087). | |
| # diffusive_knudsen_module.py:113-119 (issue #1087). |
| from particula.util.reduced_quantity import get_reduced_self_broadcast | ||
| from particula.util.validate_inputs import validate_inputs | ||
|
|
||
| KINETIC_ENHANCE_MIN = 1e-80 |
There was a problem hiding this comment.
Consider adding a brief inline comment explaining the threshold choice, e.g., "Threshold prevents NaN/Inf from exp(phi) ≈ 0 when phi < -184 (extreme same-sign repulsion)". This would improve code maintainability by documenting the physical reasoning behind the constant value.
| KINETIC_ENHANCE_MIN = 1e-80 | |
| KINETIC_ENHANCE_MIN = 1e-80 # Minimum kinetic enhancement to avoid underflow/NaN when exp(phi) → 0 for extreme same-sign repulsion |
Target Branch:
mainFixes #1087 | Workflow:
7ef9668eSummary
Prevents NaNs in the charged coagulation kernel when kinetic enhancement collapses for same-sign monodisperse particles. Adds regression coverage to ensure repulsive pairs drive the kernel to zero while mixed/attractive cases stay finite and the particle-resolved step completes.
What Changed
New Components
particula/dynamics/coagulation/tests/charged_kernel_bugs_test.py- Regression tests covering monodisperse same/opposite-sign kernels, mixed-charge matrix finiteness, kinetic limit extreme case, and particle-resolved step behavior.Modified Components
particula/particles/properties/diffusive_knudsen_module.py- AddedKINETIC_ENHANCE_MINguard and safe divide to avoid near-zero kinetic enhancement producing NaN/Inf; documented root cause inline.particula/particles/properties/tests/diffusive_knudsen_test.py- Added regression asserting extreme negative potentials stay finite and near zero.particula/dynamics/condensation/tests/staggered_stability_test.py- Minor cleanup (remove stray blank line).Tests Added/Updated
charged_kernel_bugs_test.py- Monodisperse opposite/same-sign, mixed-charge kernel finiteness, kinetic limit extreme negative, particle-resolved step crash/zero-merger checks.diffusive_knudsen_test.py- Near-zero kinetic enhancement guard regression.How It Works
KINETIC_ENHANCE_MIN = 1e-80and usesnp.divide(..., where=kinetic_enhance >= threshold, out=inf)so repulsive same-sign interactions yield an infinite denominator, driving the diffusive Knudsen number (and kernel) toward zero instead of NaN.Implementation Notes
-Werror.Testing