Skip to content

IBM: force of a moving body in the body frame (subtract the wall-normal momentum carried across the moving face) - #2208

Open
sbryngelson wants to merge 7 commits into
MFlowCode:masterfrom
sbryngelson:fix/ib-force-moving-body
Open

sbryngelson wants to merge 7 commits into
MFlowCode:masterfrom
sbryngelson:fix/ib-force-moving-body

Conversation

@sbryngelson

@sbryngelson sbryngelson commented Nov 12, 2026 •

Copy link
Copy Markdown
Member

Four commits: the code and goldens of the first version, the merge of master (after #2206, the dual-pass hypoelastic force), and a rework of the correction with its regenerated goldens (below).

Summary

The force and torque an immersed boundary receives (ib_force_wrt, two-way coupling) are summed from the fluid-body face fluxes. Those faces are fixed in the grid. When the body moves (moving_ibm > 0), the lab-frame momentum flux rho u_i u_n through a face is not the flux through the moving wall, rho u_i (u_n - V_n), with V_n the wall's normal velocity at the face (V_b = V + omega x r). The force then depends on the body's velocity through the grid, by a term of order M^2.

s_accumulate_ib_face_fluxes now takes q_cons_vf and, for moving_ibm > 0, subtracts V_n times the momentum density of the face (the mean of its fluid cell and its body cell) from the momentum flux used for the force and torque. This is a state, not a flux. An earlier version of this PR subtracted V_b f_m with f_m the discrete face mass flux; that is zero for a rigid translation only if the staircase ghost-cell fill leaks no mass, which it does not, so it was off right after an impulsive start (1.3% in a hypoelastic HLLD case at V = 10, 35% at V = 100, 42% for plain HLLC at V = 50, at step 1) while the unmodified flux was within 1e-3 there. Pressure and viscous terms are unchanged. Fixed bodies (moving_ibm = 0) take the old path. The energy and mass fluxes of the lumped-body heat (ib_heat_wrt) are not changed.

Test changes: two new tests (IBM -> Translating Circle and IBM -> Translating Spinning Circle -> Body-Frame Force) record ib_forces.dat of a prescribed translating (and turning) circle. Five goldens move because forces change (listed under Tests). The docs paragraph on the force history says what the force now is.

AI disclosure: made with Claude Code.

Verification: Galilean twins

A body translating at U through gas at rest must feel the same force as the same body held in a uniform flow -U. Setup A/B: same grid and domain, case A has moving_ibm = 1, vel(1) = U, gas at rest; twin B has the gas at -U and the body held (moving_ibm = 0; for the spin cases moving_ibm = 1, vel = 0 and the same spin). Metric rel = rms(F_A - F_B) / rms(F_B) over all steps. "master" has no correction, "merged" is this PR with the V_b f_m correction (master with #2206 merged), "fixed" is the present change. NVIDIA A100 node, nvfortran 25.11, --gpu acc, 1 rank, all three built from source and run on the same node.

Developed flow: 2D periodic unit box, circle R = 0.1 at x = 0.8 (it crosses the periodic boundary at t = 0.4), rho = 1, p = 1/1.4 (c = 1), HLLC, WENO5, RK3, dt = 0.2 dx, to t = 1, no-slip, inviscid, 200 cells per unit length unless stated.

case master merged fixed
Fx, M = 0.1 2.05e-2 1.92e-2 1.72e-2
Fx, M = 0.5 2.21e-1 4.23e-2 3.91e-2
Fx, M = 0.9 7.24e-1 5.74e-2 3.84e-2
Fx, M = 0.5, 100 cells 2.12e-1 6.00e-2 6.24e-2
Fx, M = 0.5, 400 cells 2.15e-1 6.35e-2 5.01e-2
Fx, M = 0.5, slip wall 2.53e-1 2.28e-1 5.51e-2

Translation plus spin 3 rad/s, M = 0.5, 200 cells (twin: same spin, body held):

case master merged fixed
Fx, inviscid 2.23e-1 3.99e-2 5.58e-2
Fy, inviscid 2.23 4.84e-1 3.18e-1
Tz, inviscid 2.13 3.85e-1 4.42e-1
Fx, viscous (Re_D = 200) 1.73e-1 3.92e-2 3.13e-2
Fy, viscous 1.59 1.21e-1 5.51e-2
Tz, viscous 8.98e-1 2.51e-1 1.95e-1

Two-way bodies (moving_ibm = 2, mass 5 times the displaced gas, M = 0.5; the twin is also two-way, starting from rest in gas moving at -U). Force mismatch, and the velocity gained at t = 1 (v_A - U against v_B):

case master merged fixed
Fx rel, inviscid, 200 cells 1.45e-1 5.40e-2 4.42e-2
Fx rel, viscous, 100 cells 1.20e-1 6.80e-2 5.64e-2
gained velocity, inviscid (A / B) -0.1942 / -0.1909 -0.1829 / -0.1893 -0.1889 / -0.1865
gained velocity, viscous (A / B) -0.2036 / -0.1999 -0.1896 / -0.1983 -0.1969 / -0.1951

The Mach-dependent error stays removed (M = 0.9: 72% to 3.8%), and the slip-wall error, the largest limitation of the previous version, falls from 23% to 5.5% because the state carries the slip velocity. Fixed does not beat merged in every row: Fx and Tz of the inviscid spinning case are 5.6e-2 and 4.4e-1 against 4.0e-2 and 3.9e-1, and 100 cells at M = 0.5 is equal (6.2e-2 against 6.0e-2). The floor of 2-6% that is present in all three builds at M = 0.1 is not removed.

Impulsive start: 64 x 32 periodic box, circle r = 0.2, BA59123E fluid parameters (two fluids, pressure 1e5, dt = 1e-6) on a uniform state with G = 1e6 for the hypoelastic cases, 30 steps. Relative difference of Fx of A (body at V in gas at rest) from B (body fixed in gas at -V), (A - B)/B:

case step master merged fixed
hypoelastic HLLD dual pass, V = 10 1 -3.5e-6 +1.26e-2 +6.3e-6
29 -3.4e-3 +1.26e-2 -1.5e-3
hypoelastic HLLD dual pass, V = 100 1 -2.1e-4 +3.50e-1 +3.1e-4
29 -8.7e-2 +4.01e-1 -1.4e-2
plain HLLC, V = 50 1 -1.9e-4 +4.18e-1 +1.4e-4
29 +2.2e-2 +4.59e-1 +2.1e-2

Over the 30 steps the rms difference is 2.0e-3 / 1.3e-2 / 8.6e-4 (V = 10), 4.9e-2 / 3.9e-1 / 2.7e-2 (V = 100) and 5.0e-2 / 4.4e-1 / 3.2e-2 (plain, V = 50) for master / merged / fixed. At step 1 the fixed force matches the held body to the level of master (about 1e-4 to 1e-6); the later difference is not a force-correction error but the moving body crossing cells while the twin's does not. For plain HLLC at V = 50 the fixed step-29 difference equals master's (2.1e-2 against 2.2e-2) and the rms is 3.2e-2 against master's 5.0e-2.

Limitations

  • The twin floor (2-6% in the developed flow, from the body moving through the grid) is not removed and does not shrink with resolution.
  • The face momentum is the mean of the fluid and body cell; the body cell is the ghost-filled cell. Using the fluid cell alone gave 6.7e-2 (M = 0.5) and 9.2e-2 (100 cells), and a no-slip wall state rho V_n V_b gave 1.97e-1 on the slip wall, so the mean was kept. I did not study a more principled face state.
  • The spin-case torque (inviscid) is 44% of the twin's own torque. It is a small quantity and the relative measure is harsh, but it is worse than the previous version's 39%.
  • Verified in 2D, one body, one rank. No 3D twin and no multi-rank twin was run.

Fixed bodies unchanged

Fixed-body twins (moving_ibm = 0; inviscid no-slip at 100 and 400 cells and slip at 200 cells), master against this branch on the same GPU: all 10 conservative-variable files of each run are byte-identical (cmp).

Tests

./mfc.sh test --no-chemistry with the existing goldens, A100 node, nvfortran 25.11, --gpu acc --mpi:

label passed / failed failures
IBM (101 tests) 94 / 7 09FDDC81, 997E2B0E, 540C72F1 (goldens move); B7A370B8, 5173E637, 49893269 stopped with pre_process exit code 132 and pass on a rerun (3 / 3)
Hypoelasticity (65 tests) 64 / 1 BA59123E (golden moves)
IBM Examples with moving bodies 3 / 1 AA49A8BC mibm_sphere_head_on_collision (golden moves); mibm_cylinder_in_cross_flow, mibm_shock_cylinder, mibm_particle_cloud pass

The five goldens that move, regenerated on an MI300A node (flang 24.0.0, --gpu mp), and why:

UUID test change
997E2B0E IBM -> Translating Circle first Fx -0.605 to -0.725 (14% of the largest entry over the run): the force just after the impulsive start, where the old correction was wrong
540C72F1 IBM -> Translating Spinning Circle -> Body-Frame Force first Fx -0.665 to -0.825 (6% over the run), same cause
09FDDC81 IBM -> Adaptive dt (two-way circle) 4 of 10 files, up to 6.2e-4 of the file maximum
BA59123E Hypoelasticity -> HLLD -> IBM -> Two-way Circle 101 of 111 files, up to 3.2e-2 of the file maximum; first Fx 171458 to 171882 (0.25%)
AA49A8BC Example mibm_sphere_head_on_collision 5 of 12 files, up to 1.0e-1 (energy) of the file maximum

The two-way tests (09FDDC81, BA59123E, AA49A8BC) move because the body's acceleration is the corrected force; the two new tests move because their first entries are the impulsive-start force. I did not separate how much of each two-way move comes from the start and how much from later steps.

machine compiler what result
A100 node nvfortran 25.11, --gpu acc the five regenerated goldens 5 / 5 pass
MI300A node flang 24.0.0, --gpu mp the five regenerated goldens and the three moving-body Examples that do not move 8 / 8 pass

CI covers Frontier (Cray CCE); I did not run it by hand. The new force tests stay skipped under --single.

This PR was made with Claude Code (AI).

The lab-frame momentum flux through a grid face also carries the momentum of
the gas crossing it. For a body with moving_ibm > 0, subtract V_b f_m (wall
velocity V + omega x r at the face times the face mass flux) from the
momentum flux used for the force and torque, so the force no longer depends
on the body's velocity through the grid. Fixed bodies are unchanged.

Add two prescribed-translation tests that record ib_forces.dat.
Regenerated on Tuolumne (--gpu mp): 09FDDC81 (Adaptive dt) and AA49A8BC
(mibm_sphere_head_on_collision), whose two-way bodies feel the corrected
force. New: 997E2B0E and 540C72F1, a prescribed translating and a translating
spinning circle with ib_force_wrt.
@github-actions

github-actions Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

Claude Code Review

Head SHA: f50674f

Files changed:

  • 4
  • docs/documentation/case.md
  • src/simulation/m_ibm.fpp
  • toolchain/mfc/test/cases.py
  • toolchain/mfc/test/test.py

Findings:
No issues found. Checked m_ibm.fpp (s_accumulate_ib_face_fluxes), cases.py and test.py hunks against their surroundings.

@sbryngelson
sbryngelson marked this pull request as ready for review November 12, 2026 15:36
@sbryngelson
sbryngelson requested a review from a team as a code owner November 12, 2026 15:36
@sbryngelson
sbryngelson requested review from wilfonba and removed request for a team November 12, 2026 15:36
@codecov

codecov Bot commented Nov 12, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 80.00000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 64.90%. Comparing base (9649d50) to head (55092f4).
⚠️ Report is 7 commits behind head on master.

Files with missing lines Patch % Lines
src/simulation/m_ibm.fpp 80.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2208      +/-   ##
==========================================
+ Coverage   63.71%   64.90%   +1.19%     
==========================================
  Files          90      110      +20     
  Lines       24569    29485    +4916     
  Branches     3584     4467     +883     
==========================================
+ Hits        15653    19138    +3485     
- Misses       6135     6809     +674     
- Partials     2781     3538     +757     

☔ 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.

… velocity (not V_b times the face mass flux)

A moving wall's force is the momentum flux through a face moving with it, (rho u_i)(u_n - V_n) + p n_i. The lab flux carries rho u_i u_n, so remove the face momentum density (mean of the fluid and body cell) times the wall normal velocity V_n. The previous V_b f_m used the discrete mass flux, which is not zero at a staircase wall, so it was wrong at low Mach and right after an impulsive start (1 to 35 percent at step 1).
…59123E, 09FDDC81, 997E2B0E, 540C72F1, AA49A8BC)

Regenerated on MI300A (flang, --gpu mp); the A100 build (nvfortran, --gpu acc) passes them at the tests' tolerance.
@sbryngelson sbryngelson changed the title IBM: force of a moving body in the body frame (subtract V_b f_m from the face momentum flux) IBM: force of a moving body in the body frame (subtract the wall-normal momentum carried across the moving face) Nov 14, 2026
@github-actions

Copy link
Copy Markdown

Lines of Code

File Lines Diff
src/simulation/m_ibm.fpp 2880 +9
Directory Lines Diff
simulation 39389 +9
total 59355 +9

This branch has not been deployed

No deployments
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.

1 participant