Repository navigation
Fix the immersed-boundary moment of inertia: NaN for non-analytic shapes, grid-dependent cell sum, rectangle factor of 2 - #2105
Closed
ruru25254649 wants to merge 3 commits into
Conversation
Three errors in how a moving IB's moment of inertia is set: - s_ibm_setup computed it before the IB markers were filled. Geometries without a closed form (airfoil, STL, cuboid, cylinder, ...) sum over the body's marked cells, found none, and stored 0/0 = NaN. In 2D that is the only time the moment is computed; in 3D the time stepper reads it before recomputing it. A two-way-coupled airfoil, or a cuboid started with a nonzero angular velocity, went NaN. It is now computed once the markers and the centre-of-mass offsets are in place. - The cell sum divided by count*cell_volume. With patch%mass the total mass, each of the count cells carries mass/count, so the moment is mass*sum(r^2)/count; the extra 1/cell_volume made it grid dependent (MFlowCode#1994). - The rectangle used m*(lx^2 + ly^2)/6. length_x and length_y are full side lengths (f_is_inside_cuboid tests |x| <= length_x/2), so the moment about the centroid is m*(lx^2 + ly^2)/12, the same convention the ellipse branch already uses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WPhkY8p1EHhGY7jScizJmC
ruru25254649
requested review from
danieljvickers
and removed request for
a team
October 25, 2026 07:04
|
Claude Code Review Head SHA: cae2acb Files changed:
Findings:
|
ruru25254649
marked this pull request as draft
October 25, 2026 07:19
Same guard and dummy value as MFlowCode#1992 (the non-rotating case already returns 1), so the two changes agree on this block. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WPhkY8p1EHhGY7jScizJmC
In 3D the time stepper passes the angular momentum as the axis. Comparing its norm with sgm_eps = 1e-16 is a dimensional threshold. A two-way-coupled cuboid with I = 6e-14 kg m^2 spinning at 1e-3 rad/s has L = 6e-17, so the first RK stage gets the dummy moment 1. The next stage multiplies the blended angular velocity by that dummy and divides by the real moment again: omega_z goes from 1e-3 to 8.3e9 rad/s in one step and the run stops on ICFL. Only the exact zero vector now returns the dummy value. The axis is scaled by its largest component before normalising, so a small one does not underflow. The same case keeps omega_z = 1.000e-3 for 20 steps. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WPhkY8p1EHhGY7jScizJmC
Lines of Code
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
s_compute_moment_of_inertiasetspatch_ib%moment, which the two-way-coupled (moving_ibm = 2) update divides the angular momentum by. It has three independent errors.1. It runs before the body's cells are marked, so non-analytic shapes get NaN.
s_ibm_setupcalls it in the first loop, befores_apply_ib_patchesfillsib_markers. Shapes without a closed form are:For these the routine sums
r²over the cells marked with the patch id. At that point it finds none and stores0/0 = NaN.s_propagate_immersed_boundariesmultiplies by the stored moment before it recomputes it, so a body started with a nonzero angular velocity goes NaN on the first stage.The call now runs after the markers and the centre-of-mass offsets (
s_compute_centroid_offset) are in place. The rotation-matrix and prescribed-kinematics setup it was grouped with stay where they were, because the markers depend on them.2. The cell sum divides by
count*cell_volume(#1994).patch%massis the body's total mass. It is used asforce/massandaccel_bf*mass, and the analytic branches use it as0.4*mass*r². Each of thecountcells therefore carriesmass/count, and the moment ismass*Σr²/count. The extra1/cell_volumegives units of mass/length (mass/length² in 2D) and makes the moment scale with the grid.3. The rectangle uses
m(lx² + ly²)/6.length_xandlength_yare full side lengths:f_is_inside_cuboidtests|x| ≤ length_x/2.0.5*sqrt(lx² + ly²).m(lx² + ly²)/16, already uses that convention.The polar moment of a rectangle about its centroid is
m(lx² + ly²)/12, so the old value was twice too large.Verification
I printed
patch_ib(1)%momentat the end ofs_ibm_setup(a temporary print, not part of the PR). The build was GNU 13.4 + Open MPI, run on 1 rank. All three cases usemass = 1e-6and are derived fromexamples/2D_mibm_cylinder_in_cross_flowandexamples/2D_ibm_airfoil, withmoving_ibm = 2:angular_vel(3) = 1icfl = NaN)NaN(s) in timestep output,MPI_ABORT)After the fix, the cell sum agrees with the closed forms. Before it, the cell sum could not be evaluated at all.
./mfc.sh test -o IBM), GNU 13.4 + Open MPI09FDDC81) has no torque--gpu acc, H100961cde5(on a branch merging all candidates)Out of scope: the cell sum still covers only the local rank's cells, and periodic markers are still compared undecoded. Both are noted in #1994.
Relation to #1992 (closed, tracked by
pr-to-do#2068). That PR decodes periodic markers and replaces0/0on a rank holding none of the body with the dummy value 1. It does not fix point 1. With #1992 alone, the setup-time call still finds no marked cells, but now every body that needs the cell sum getsmoment = 1instead of NaN. For the airfoil above, that is 1 kg·m² instead of 5.7e-14, and the body effectively cannot rotate. The two changes are complementary. They overlap on one line, the finalmoment = ...assignment. If #1992 is reopened first, the rebase keeps itscount > 0guard and drops*cell_volume.Side effects
moving_ibm = 2):s_ibm_setup, afters_apply_ib_patchesands_compute_centroid_offset. Nothing between the old and new positions readspatch_ib%moment.Contribution Policy
All contributions are expected to demonstrate:
If these expectations are not met, we would prefer to implement the changes ourselves rather than spend time reviewing low-effort submissions.
Acknowledgement
This PR is from Your Team Name participating in the SC26 Student Cluster Competition.
🤖 Generated with Claude Code
https://claude.ai/code/session_01WPhkY8p1EHhGY7jScizJmC