Repository navigation
IBM: ib_flux_wall for fixed no-slip inert bodies, and trace species no longer starve the reacting flux wall - #2213
Conversation
The positivity factor theta of a fluid cell caps all of its wall fluxes so that they take at most 0.9 of any consumed species in one forward-Euler step. A species with a negligible share of the consumption that the cell holds almost none of (OH: rho Y ~ 1e-46 against a wall rate ~ 1e-45 per step) set theta ~ 0 and starved the whole wall. Species carrying less than 1e-6 of the cell's wall consumption no longer set theta. On a 48 x 48 grid the reacting-cylinder test starved from step ~27 and the burn rate fell 12 % by 2e-5 s; the 24 x 24 Flux Wall test is unaffected (theta stays 1), so its golden does not change. Adds the 48 x 48 case as a test and updates the flux-wall columns of the mass-budget example table.
ib_flux_wall now also covers fixed, no-slip, non-blowing inert bodies (surface_reaction = 0): their wall faces keep a zero source, so they carry no mass or species, only conduction, pressure and viscous stresses. This removes the ghost-cell gas exchange across the staircase faces that makes the gas mass of a closed periodic box with fixed isothermal inert bodies drift. An inert body that slips or blows keeps the ghost-state wall. The option stays opt-in (default F); results with it off do not change. The case validator accepts the option with such inert bodies (it still needs at least one reacting or no-slip, non-blowing body, and every body fixed). Adds two inert flux-wall tests: the reacting cylinder example with surface_reaction = 0, and a closed periodic box.
|
Claude Code Review Head SHA: 1b0d007 Files changed:
Findings: |
f_wall_face_sum built per-thread arrays h(3) and c(3), which the amdflang OpenMP-offload build placed in scratch memory. It now sums the neighbour terms through f_wall_face_term, so only the order of the floating-point additions changes. MI300A (amdflang AFAR, 96 cells/D, 100 steps, rocprofv3): s_ib_flux_wall_prepare took 3.69 ms per call (1107 ms of the 1950 ms of kernel time) before and 0.030 ms per call (9.0 ms in total) after. ib_flux_wall step cost went from +80% (9.6 -> 17.4 ns/gp/eq/rhs) to within run-to-run noise (10.7 on vs 9.7 and 11.6 off).
Lines of Code
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #2213 +/- ##
==========================================
+ Coverage 65.15% 65.16% +0.01%
==========================================
Files 110 110
Lines 29555 29559 +4
Branches 4476 4476
==========================================
+ Hits 19256 19263 +7
+ Misses 6743 6742 -1
+ Partials 3556 3554 -2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
…s ghost temperature also moves 8B2A7F3E, FAF04D7A and 3F5FE078 (MFlowCode#2213 inert and trace-species flux walls) and F8D466BD and C02C399E (MFlowCode#2200 thermostat, goldens regenerated for MFlowCode#2205) were generated on master without the isothermal ghost change.
Two commits on
origin/master80997da, each with its own tests and goldens. The option stays opt-in (ib_flux_walldefaultF); with it off nothing changes (no existing golden moved on either vendor, see Tests).Summary
m_ibm.fpp,s_ib_flux_wall_prepare). The positivity factorthetaof a fluid cell caps all of its wall faces so that they take at most 0.9 of any consumed species in one forward-Euler step. A species with a negligible share of the wall consumption that the cell holds almost none of settheta~ 0 for every species. Species carrying less than 1e-6 of the cell's wall consumption no longer settheta(they are not limited;rhoYof such a species can in principle go slightly negative, which no run here showed).m_ibm.fpp,s_ib_flux_wall_setup, validator, docs).ib_flux_wallalso covers fixed, no-slip, non-blowing bodies withsurface_reaction = 0. Their wall faces keep a zero source: no mass or species, only conduction, pressure and viscous stresses. This removes the ghost-cell gas exchange across the staircase faces that makes the gas mass of a closed periodic box with fixed isothermal inert bodies drift. An inert body that slips or blows keeps the ghost-state wall. The validator accepts the option with such bodies (it still needs every body fixed and at least one reacting or no-slip, non-blowing body). In a case that mixes reacting and inert bodies withib_flux_wall = T, the inert bodies now get the zero-flux wall.No case sets
ib_flux_wallby default, and no toolchain default is touched.Evidence
Machines: A100: NVIDIA A100 80GB PCIe, nvfortran 25.11, OpenACC (
--gpu acc), 1 rank unless stated. MI300A: AMD MI300A (gfx942), amdflang (AFAR 24.3.0), OpenMP offload (--gpu mp), 1 rank. "master" is a build oforigin/master80997da; "branch" is this PR. The MI300A runs below used the branch with the option off, which is bit-identical to master (see Tests); they reproduce the A100 master numbers to all printed digits.1. Trace species (commit 1)
Mass-budget example (
examples/2D_ibm_wall_mass_budget, reacting carbon cylinder in a closed box, 16 cells/D,--flux_wall, A100). Gasified mass is the time integral of the surface records, as inmass_budget.py; the fix is the only difference.The gas budget closes to 0.3% or better after 60 us in both. That the shortfall on master is trace-species starvation is inferred from the next table; I did not print
thetafor this case.The 48 x 48 reacting-cylinder case (the new test; the 24 x 24
Flux Walltest never hastheta< 1). Gasification rate of the body (ib_heat_wrtcolumn 3), A100:A CPU build with a print in
s_ib_flux_wall_prepareshows species 9 (OH) as the limiting species in those cells (consumption ~ 7e-46 againstrhoY~ 2e-46 kg/m^3 per step). Fields at 2e-5 s differ between the two builds by up to 1e-4 relative in the mixture density and 1e-3 in the energy and x-momentum, far above the 1e-6 test tolerance, so the new test fails on master.2. Inert flux wall (commit 2)
Periodic square array of fixed isothermal inert cylinders (area fraction 0.2), carbon-gas mechanism of
examples/2D_ibm_reacting_surfacewith reactions off,thermal_bc = 1, no-slip, body-force driven (bf_x), Re_m = 100 and Mach 0.3 at the start (u_mean 110-190 m/s as the gas heats; the Mach number drifts between about 0.2 and 0.4), 10 nominal flow-throughs (L/U0), WENO5 + HLLC + RK3, A100, 16/24/32/48 cells per diameter. Drag is the x-force on the body and Q the heat rate into the body (ib_force_wrt,ib_heat_wrt), both averaged over the last 5 flow-throughs (the flow is unsteady: the drag standard deviation is 3-4% of its mean, Q about 15%). Errors are relative to the 48 cells/D run with the option; master at 48 cells/D is within 0.3% (drag) and 1.8% (Q) of it, so that reference is not an artifact of the option.Cold wall (gas 600 K, wall 300 K):
The drift is the mean over the 10 flow-throughs; on master at 16 cells/D it is +2.1% in the first and +0.9% in the last. With the option the gas mass is constant to round-off. Absolute values at 48 cells/D with the option: drag 0.1821 N/m, Q 54.98 W/m.
Neutral wall (gas 300 K, wall 300 K, heated only by dissipation):
3D (periodic cubic array of spheres, volume fraction 0.2, cold wall, 8 flow-throughs, A100):
(Two resolutions only, so no convergence statement for 3D; WENO5 needs 26 or more cells per direction, so 16 cells/D does not run.)
What this shows, and what it does not:
s_ib_flux_wall_prepare) uses no per-thread arrays, (removing the arrays is what changed it; I assume the amdflang OpenMP-offload build put them in scratch memory, I did not inspect the generated code): on the MI300A at 96 cells/D it takes 0.030 ms per call (9.0 ms of 100 steps, 1.0% of kernel time) against 3.69 ms per call (1107 ms, 57%) with the arrays, where the option cost +80% per step (9.6 -> 17.4 ns/gp/eq/rhs, two repeats). With the kernel as committed the option is within run-to-run noise on the MI300A (10.66 and 10.70 on; 9.66 and 11.59 off ns/gp/eq/rhs). On the A100 (nvfortran 25.11, GPU 0 otherwise idle, 96 cells/D, 100 fixed steps, three repeats each, interleaved) it is +10.5%: 5.30 (5.29-5.31) off, 5.85 (5.81-5.89) on ns/gp/eq/rhs. The earlier A100 sweep at 16-48 cells/D, with other jobs on the same GPUs (indicative only), gave 173/141, 72.8/60.9, 38.3/36.9, 18.5/16.1 ns/gp/eq/rhs (branch/master), i.e. +4% to +23%.Tests
New (all
Chemistrylabel,override_tol = 1e-6for the cross-vendor single-precision output, goldens generated on the MI300A):2D -> Chemistry -> IBM Reacting Surface -> Flux Wall -> Trace Species(3F5FE078): the reacting cylinder on 48 x 48.2D -> Chemistry -> IBM Inert Surface -> Flux Wall(8B2A7F3E): the same cylinder withsurface_reaction = 0in the freestream.2D -> Chemistry -> IBM Inert Surface -> Flux Wall -> Closed Box(FAF04D7A): inert cylinder in the periodic box of2D_ibm_wall_mass_budget.test_case_validator.py: inert no-slip bodies accepted; slip and blowing inert bodies alone rejected.Results at the head of this branch (
./mfc.sh test --only ..., one rank):--gpu mp)--gpu acc)ChemistryIBMChemistryandIBMtogetherFlux Wall(C1F0BCB1), final tolerancesNo existing golden was regenerated or changed on either vendor.
./mfc.sh formatleaves everything unchanged and./mfc.sh precheckpasses.Limitations
--single,--mixed. The A100 binaries were built before a comment and whitespace reformat ofm_ibm.fppandm_chemistry.fpp(the code is the same; I did not rebuild). Commit 1 on its own was not built or tested separately; itsm_ibm.fppis the theta hunk of the final file.igr, cylindrical coordinates andib_cutvol(rejected as before). Only one mechanism (the carbon/air one) was used; 3D has one sphere configuration;ib_wall_order = 2andib_ip_interp = 2were not combined with the new wall.thetathere.2D_ibm_wall_mass_budgetREADME table are updated to the numbers measured here (defect). Its N2-leak column is not updated: I measure -4e-9 to -5e-9 of the gasified mass for it on both master and branch, against the 1e-10 listed, and did not find why.This PR was made with Claude Code (AI).