fix(photochem): exclude flux from VODE convergence; hard-code atol for DTypeFront; add docs#1956
Conversation
Replace 1e-10 atol defaults with values grounded in the physical scales of the problem: atol_spec = 1e-3 cm^-3 (1e-4 × n_H negligibility floor) and atol_rad_num = 1e-2 cm^-3 (below the photoionization-rate significance threshold of ~0.8 cm^-3). These prevent the solver from pursuing spurious precision on trace species and negligible photon densities. All three physics checks continue to pass. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
atol_rad_num = 1e-2 allowed VODE to step the photon number density into negative values (N_gamma starts at ~1e-89 cm^-3, far below the tolerance floor), reversing the photoionization term sign and causing Newton-iteration failures. Reduce to 1e-5, which is safely below the empirical failure threshold (~3e-4) while remaining five decades more relaxed than the original default of 1e-10. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- photochemistry.hpp: pass N_gamma_eff = max(Erad - Erad_floor, 0) / E_photon to VODE so dark cells (with only floor radiation) see N_gamma = 0 and take one trivial step; add Erad_floor_ back in write-back for energy conservation - actual_rhs.H: clamp n_gamma = max(rn[0], 0) in RHS and Jacobian to prevent sign reversal if VODE steps N_gamma slightly below zero within tolerance - testDTypeFront.cpp: set Erad_floor = a_rad * (10 K)^4 as a physically motivated radiation floor (vs the former 1e-99) - DTypeFront.toml: relax atol_rad_num from 1e-5 to 1e-2 (floor subtraction eliminates the sign-reversal numerical stability constraint); set radiation_failure_tolerance = 0.1 so VODE dipping N_gamma to -atol_rad_num does not abort the burn Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…floor subtraction Erad_floor = a_rad * (1 K)^4 gives N_gamma_floor ~ 3.5e-4 cm^-3, which is: - below atol_rad_num = 0.01, so VODE returns in one step (absolute control) - small enough that cumulative ionization over 10 steps is ~3.5e-3 cm^-3 per cell, leaving x_HI > 99.99% in dark cells (neutral temperature check passes) - physically motivated vs the arbitrary 1e-99 Floor subtraction in photochemistry.hpp is reverted — not needed when the floor is chosen correctly. The Erad_floor value itself ensures dark cells see negligible N_gamma without any special handling in the burner. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
for more information, see https://pre-commit.ci
There was a problem hiding this comment.
Code Review
This pull request adjusts resolution and integrator tolerance parameters in DTypeFront.toml, clamps n_gamma to zero in actual_rhs.H to prevent negative values from VODE steps, and updates Erad_floor in testDTypeFront.cpp. The review feedback suggests ensuring mathematical consistency in the Jacobian by updating derivatives with respect to state.rn[0] to account for the clamped n_gamma, and updating the hardcoded initial radiation energy density in testDTypeFront.cpp to use the new Erad_floor value.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
Erad_floor = a_rad*(0.1K)^4 gives N_gamma_floor = 3.5e-8 cm^-3, six orders of magnitude below atol_rad_num = 0.01, so VODE returns in one BDF step in dark cells regardless of the number of timesteps. The equilibrium ionisation from floor photons is x_HII_eq ~ 0.002%, well below the 0.01% neutral-temperature test threshold, making the strategy robust for arbitrarily long (e.g. 1M step) production runs without needing floor subtraction in the photochemistry solver. Remove the 10-step hard cap; stop_time now governs (~15 CFL steps). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ical parameters Users now specify integrator.typical_n_H, integrator.desired_accuracy_on_T_at_typical_n_H, and integrator.typical_minimal_radiation_T instead of hand-tuning integrator.atol_spec / atol_enuc / atol_rad_num / atol_rad_flux. SetAtolFromPhysics<problem_t>() injects derived values into ParmParse before init_extern_parameters() reads them, leaving the Microphysics submodule untouched. The new keys and existing integrator.atol_* keys are mutually exclusive. Neither present is a backward-compatible no-op. Erad_floor (the M1 radiation floor) remains a compile-time constexpr in each problem's RadSystem_Traits; typical_minimal_radiation_T only sets the VODE tolerance, not Erad_floor. DTypeFront.toml updated to demonstrate the interface. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…d_floor to 0.01K radiation_failure_tolerance is a physical guard (max allowed negative photon count per cm^3), not a numerical tolerance — defaulting to 0.01 cm^-3 avoids false burn failures in near-vacuum cells regardless of how tight atol_rad_num becomes. Erad_floor lowered from a_rad*(0.1K)^4 to a_rad*(0.01K)^4 so that typical_minimal_radiation_T=10K still gives atol_rad_num/N_gamma_floor ~ 1e4, ensuring dark cells converge in one BDF step. Add docs/markdown/photoionization.md documenting atol/rtol parameter choices. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
VODE's built-in defaults (~1e-10) are unusably tight for photochemistry and will cause the integrator to stall. Require either typical_* (recommended) or atol_* parameters to be present. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
E_photon cancels, so the user only needs T_min and T_floor: 1e-6 × (T_min / T_floor)⁴ ≥ 10⁴ ↔ T_floor ≤ T_min / 316 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Physical constants section defining a_rad, k_B, m_p, c_v, E_photon - Introduce T_min, T_floor, N_gamma_floor with explicit definitions - Fix incorrect ratio in Relationship example (was 10^4, now 10^6) - Add missing rtol_rad_flux to the rtol description - Make step 4 actionable with "if this fails" guidance - Tighten prose throughout Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
for more information, see https://pre-commit.ci
Co-Authored-By: Claude <noreply@anthropic.com>
Temporary change for GPU validation — revert before merging. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Temporary change for GPU validation — revert before merging. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
/azp run |
|
@BenWibking Thanks for the detailed review! I've addressed your comments: Microphysics (new branch
Could you take another look when you have a moment? Generated by Claude Code |
|
/azp run quick |
|
/azp run rocm-quick |
|
Azure Pipelines could not run because the pipeline triggers exclude this branch/path. |
1 similar comment
|
Azure Pipelines could not run because the pipeline triggers exclude this branch/path. |
…view atol_rad_num = 1.0e-2 cm^-3 matches atol_spec = 1.0e-2 cm^-3, making the photon number density tolerance comparable to the electron number density tolerance. radiation_failure_tolerance = 0.1 (10x atol_rad_num) follows the same pattern as DTypeFront. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Per Ben's review: both tolerances now describe primary (internal substep rejection) and secondary (final interpolated state at 1.5x) uses. Removed "physical guard" / "maximum allowed" language in favor of precise VODE mechanism descriptions. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
/azp run quick |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
/azp run rocm-quick |
|
Azure Pipelines successfully started running 1 pipeline(s). |
BenWibking
left a comment
There was a problem hiding this comment.
I think your description of the cooling is still grammatically confusing. I have suggested two rewordings below.
|
OK, comments addressed. Ready for review again. @BenWibking |
Description
Add hard-coded VODE absolute tolerances for the DTypeFront photoionization problem, and exclude radiation flux from VODE convergence checks.
docs/markdown/photoionization.mdnow has complete documentation for the photoionization module: governing equations (M1 radiative transfer, hydrogen thermochemistry, on-the-spot approximation), numerical scheme (operator splitting with VODE), and the full VODE tolerance design rationale.docs/markdown/parameters.mdhas the completeintegrator.*parameter reference.The
SetAtolFromPhysicsmachinery (automatic atol derivation from physical scales) has been moved to PR #1980.Summary of changes
src/problems/DTypeFront/testDTypeFront.cppErad_floor = a_rad * (0.01 K)^4with documentation of the relationship toatol_rad_numinputs/DTypeFront.tomlintegrator.atol_*values with documentationsrc/networks/photoionization/actual_rhs.HN_gamma >= 0in RHS and Jacobian to prevent sign reversal when photons are fully absorbeddocs/markdown/photoionization.mddocs/markdown/parameters.mdintegrator.*parametersextern/Microphysics/.../vode_dvode.Hextern/Microphysics/.../vode_dvnlsd.Hextern/Microphysics/.../vode_dvstep.Hextern/Microphysics/.../vode_dvhin.HKey design decisions
atol_spec = 1.4e-3 cm^-3,atol_enuc = 1.24e8 erg/g,atol_rad_num = 5e-2 cm^-3,radiation_failure_tolerance = 0.5 cm^-3.atol_specandatol_enuccorrespond to a negligibility floor of 1e-5 × n_H and a 1 K temperature accuracy at n_H = 139.9 cm^-3.atol_rad_num = 5e-2is the performance plateau for this problem (see Performance below).atol_rad_numandradiation_failure_toleranceare coupled —radiation_failure_tolerancemust exceed the maximum negative excursion that the BDF predictor-corrector produces at the ionization front before converging (~0.05–0.2 cm^-3 for DTypeFront). Settingradiation_failure_tolerance = 0.5provides a safe margin. Note: Microphysics commit47696e49introduced a 1.5× final-state factor for species (vode_final_state_species_failure_tolerance_factor), which allowsspecies_failure_tolerance = atol_specwithout manual inflation — but no equivalent factor exists for radiation, soradiation_failure_tolerancerequires its own margin.Erad_flooris separate fromatol_rad_num— the former is a compile-timeconstexprinRadSystem_Traitscontrolling the M1 hyperbolic floor; the latter is the VODE tolerance. They must satisfyN_gamma_floor << atol_rad_numso dark cells return in one BDF step.dF/dtdepends onn_HIbut flux does not feed back into species, energy, or N_gamma). N_gamma has an additional isotropic source term (stellar emission) that flux lacks, so flux is not analytically determined by N_gamma — but it remains a diagnostic quantity whose convergence should not drive the timestep.Performance
All benchmarks: ROCm GPU (64^3, AMD GPU on moth.anu.edu.au).
vs.
developmentbranch (64^3,stop_time = 2.895e12≈ 3 t_s):developmentEffect of
atol_rad_numtuning within this PR (64^3,stop_time = 1.93e13= 20 t_s):atol_rad_numwas swept from 1.25e-6 to 0.2 cm^-3. Performance plateaus at ~5e-2 cm^-3: below this VODE spends extra steps in dark cells; above it the step-rejection loop (N_gamma overshooting near −radiation_failure_toleranceat the ionization front) erodes the gain.atol_rad_numRelated issues
N/A
Checklist
/azp run.