Skip to content

Operator-split integration for the condensed-phase reactive burn - #1831

Open
sbryngelson wants to merge 2 commits into
MFlowCode:masterfrom
sbryngelson:feat/reactive-burn-substeps
Open

Operator-split integration for the condensed-phase reactive burn#1831
sbryngelson wants to merge 2 commits into
MFlowCode:masterfrom
sbryngelson:feat/reactive-burn-substeps

Conversation

@sbryngelson

Copy link
Copy Markdown
Member

Added to the flow RHS, the condensed-phase burn ties the reaction time scale to the acoustic CFL: a fast burn forces a smaller step for the entire simulation, even where nothing is reacting.

This adds rburn%substeps. Above zero, the flow is frozen and the burn ODE is integrated across the step in equal sub-steps, with the mixture pressure re-evaluated from the frozen internal energy each sub-step so the rate feels its own feedback as reactant becomes product. rburn%substeps = 0 is the default and leaves the source in the flow RHS exactly as before.

Two details worth review:

  • Completion. A sub-step longer than the reaction time would carry the progress variable past one. It stops at one and hands over the reactant's remaining mass in the same sub-step. Capping the volume-fraction and mass increments independently strands reactant mass at zero reactant volume, and the mixture EOS divides one by the other.
  • One rate law. s_burn_rate now states the pressure drive, the (1 - lambda) factor and the optional Arrhenius term once; both integrators call it. Previously the new path would have carried a second copy that had to stay in step forever.

Testing

  • 1D -> Reactive Burn -> Condensed Programmed Detonation -> substeps (86893F55), substeps = 10 on 2 ranks. Two ranks deliberately: substeps is the only integer among the rburn members, and the broadcast kind is now registry-driven, so a wrong kind leaves rank 1 sub-stepping a garbage count — invisible to a single-rank golden.
  • The new golden differs from the RHS-path golden in 45.5% of values, largest relative difference 3.2e-3 in the progress variable, so the case exercises the split integrator rather than reproducing the old answer.
  • The four existing reactive-burn goldens pass unchanged on both CPU and GPU, confirming the rate-law extraction altered no behaviour.

…ubsteps > 0

Added to the flow RHS, the burn ties the reaction time scale to the acoustic CFL: a fast burn forces a smaller step for the whole simulation. With rburn%substeps > 0 the flow is frozen and the ODE is integrated over the step in equal sub-steps, re-evaluating the mixture pressure from the frozen internal energy each one so the rate feels the coefficients moving as reactant becomes product. rburn%substeps = 0, the default, keeps the source in the RHS unchanged. Completing a sub-step hands over the reactant's remaining mass along with the last of its volume fraction; capping the two separately strands mass at zero volume, which the EOS then divides by. The rate law is now stated once and called by both integrators.
Copilot AI lite review requested due to automatic review settings September 6, 2026 00:29

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Pull request overview

Adds an operator-split path for condensed-phase reactive burn by introducing rburn%substeps, allowing the burn ODE to be integrated in post-flow substeps so fast chemistry doesn’t globally constrain the acoustic CFL time step.

Changes:

  • Register/validate new parameter rburn%substeps and ensure its MPI broadcast uses the correct MPI datatype (integer vs real).
  • Integrate reactive burn via operator splitting after the flow update when rburn%substeps > 0, leaving the existing RHS source path for substeps == 0.
  • Add a new 2-rank golden test case to exercise the new substepping path and catch broadcast-kind issues.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
toolchain/mfc/test/cases.py Adds a new reactive-burn test case with rburn%substeps=10 on 2 MPI ranks.
toolchain/mfc/params/generators/fortran_gen.py Updates generated MPI_BCAST code to pick MPI type per rburn member (supports new INT member).
toolchain/mfc/params/definitions.py Registers rburn%substeps as an INT reactive-burn parameter.
toolchain/mfc/case_validator.py Validates rburn%substeps >= 0 with an explanatory error message.
src/simulation/m_time_steppers.fpp Calls s_reactive_burn_substep after the flow update when substeps > 0.
src/simulation/m_rhs.fpp Skips adding burn source to RHS when substeps > 0 (operator-split path instead).
src/simulation/m_reactive_burn.fpp Factors out s_burn_rate and implements operator-split substep integrator.
src/common/m_global_parameters_common.fpp Initializes rburn%substeps default to 0.
src/common/m_derived_types.fpp Extends reactive burn parameter type with integer substeps.
tests/86893F55/golden.txt Adds new golden outputs for the new substepping test case.
tests/86893F55/golden-metadata.txt Adds metadata for the new golden generation.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/simulation/m_reactive_burn.fpp Outdated
! Optional Arrhenius dependence on the reactant phasic temperature from the stiffened-gas
! EOS. rburn%ta = 0, the default, leaves the pure pressure-driven rate unchanged.
if (rburn%ta > 0._wp) then
rate = rate*exp(-rburn%ta/f_sg_thermal(pres, alpha_rho_react/alpha_react, isentrope_n(1), isentrope_B(1), cvs(1)))

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in ed51f33 — the divisor is now max(alpha_react, sgm_eps), matching the form the Riemann solvers already use for phasic densities.

Worth noting it is reachable: completing a sub-step sets the reactant volume fraction to exactly zero, and the lambda < 1 test only covers the same iteration while the volume fractions still sum to one, which the six-equation model does not guarantee.

alpha_rho(i) = q_cons_vf(i + eqn_idx%cont%beg - 1)%sf(x, y, z)
alpha(i) = q_cons_vf(i + eqn_idx%adv%beg - 1)%sf(x, y, z)
end do
rho = alpha_rho(1) + alpha_rho(2)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The second alternative already holds: case_validator.py:1932 enforces reactive_burn requires num_fluids = 2 (reactant then product), so fluids 1 and 2 are the whole mixture here. s_compute_reactive_burn computes rho the same way for the same reason. Leaving as is.

Comment on lines +1963 to +1967
rsub = self.get("rburn%substeps")
self.prohibit(
self._is_numeric(rsub) and rsub < 0,
"reactive_burn requires rburn%substeps >= 0 (operator-split sub-steps per time step; 0 adds the source to the flow RHS)",
)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving this lower-bounded only, for consistency with the sibling parameter: chem_params%reaction_substeps drives the identical operator-split pattern for chemistry and is likewise validated as >= 0 with no ceiling. Adding a bound to one and not the other would be the surprising choice, and a defensible upper limit is case-dependent rather than universal.

Completing a sub-step drives the reactant volume fraction to exactly zero, and the lambda >= 1 test only covers the same iteration if the volume fractions still sum to one, which the six-equation model does not guarantee. Use the max(alpha, sgm_eps) form the Riemann solvers already use for this.
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown

Lines of Code

File Lines Diff
src/simulation/m_reactive_burn.fpp 111 +70
src/simulation/m_time_steppers.fpp 833 +6
src/common/m_derived_types.fpp 441 +1
src/common/m_global_parameters_common.fpp 240 +1
Directory Lines Diff
common 9948 +2
simulation 27744 +76
total 45549 +78

@codecov

codecov Bot commented Sep 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.78261% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 62.35%. Comparing base (70589fd) to head (ed51f33).

Files with missing lines Patch % Lines
src/simulation/m_reactive_burn.fpp 82.50% 2 Missing and 5 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1831      +/-   ##
==========================================
+ Coverage   62.30%   62.35%   +0.04%     
==========================================
  Files          84       84              
  Lines       21583    21622      +39     
  Branches     3195     3199       +4     
==========================================
+ Hits        13448    13483      +35     
- Misses       5937     5939       +2     
- Partials     2198     2200       +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

2 participants