Skip to content

Add hemisphere shell particle cloud packing - #1667

Open
BCKim55 wants to merge 14 commits into
MFlowCode:masterfrom
BCKim55:feature/particle-cloud-hemi-shell
Open

Add hemisphere shell particle cloud packing#1667
BCKim55 wants to merge 14 commits into
MFlowCode:masterfrom
BCKim55:feature/particle-cloud-hemi-shell

Conversation

@BCKim55

@BCKim55 BCKim55 commented Jul 22, 2026

Copy link
Copy Markdown

Description

Adds a hemisphere-shell particle cloud packing option for immersed-boundary particle clouds.

This introduces particle_cloud(i)%packing_method = 3, which randomly places spherical/circular IBM particles inside a hemisphere-shell region while enforcing:

  • inner and outer shell-radius clearance,
  • hemisphere plane clearance,
  • bounding-box clearance,
  • particle-particle non-overlap using the existing spatial hash approach.

This also adds shell_inner_radius and shell_outer_radius particle cloud parameters. The local verification example was removed from this PR to avoid introducing a new golden test in the same change.

Type of change

  • New feature

Testing

  • ./mfc.sh format
  • ./mfc.sh validate examples/*/case.py
  • ./mfc.sh validate examples/3D_mibm_particle_cloud_hemi_shell/case.py
  • ./mfc.sh run examples/3D_mibm_particle_cloud_hemi_shell/case.py --clean --no-debug

Additional local checks:

  • Verified generated ib_state_0.dat particle positions.
  • Confirmed no shell-boundary violations.
  • Confirmed no particle overlap violations.
  • Confirmed VF 0.2 succeeds with min_spacing=0.02.
  • Confirmed VF 0.3 succeeds when min_spacing=0.0.

Checklist

  • I added or updated tests for new behavior
  • I updated documentation if user-facing behavior changed
GPU changes (expand if you modified src/simulation/)
  • GPU results match CPU results
  • Tested on NVIDIA GPU or AMD GPU

@BCKim55
BCKim55 requested a review from sbryngelson as a code owner July 22, 2026 06:52
@sbryngelson
sbryngelson marked this pull request as draft July 22, 2026 13:04
@wilfonba

wilfonba commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

I don't think this is implemented quite right. The example you added highlights this fact. It defines a hemispherical particle cloud using a cubic domain. I think instead you should add a particle_cloud(i)%geometry variable, and then treat the particle cloud more like the fluid patches are treated. Also, a hemispherical shell is not a packing method in the same way that rejection sampling and lattice placement are packing methods, so using the existing acking_method variable for this isn't the right thing to do. You can place particles in a hemispherical shell using either rejection sampling, lattice placement, or some other packing method that's not implemented yet.

Edit: Your s_particle_cloud_random_hemi_shell routine appears to do rejection sampling, which adds to the confusion of what packing_method means.

@BCKim55

BCKim55 commented Jul 23, 2026

Copy link
Copy Markdown
Author

Thanks Ben, that makes sense. I agree that the hemisphere shell should be treated as a particle-cloud geometry rather than a packing method.

I’ll refactor this so that particle_cloud(i)%packing_method remains responsible for the placement algorithm, e.g. rejection sampling or lattice, and add a separate particle_cloud(i)%geometry option for the cloud shape. Then the current hemisphere-shell implementation will become the rejection-sampling path for geometry = hemisphere shell, while unsupported combinations such as hemisphere-shell lattice packing can error out explicitly for now.

I’ll also remove or adjust the example so it does not imply that a cubic domain defines the hemispherical cloud.

@BCKim55
BCKim55 force-pushed the feature/particle-cloud-hemi-shell branch from 81e9038 to 933f66c Compare July 23, 2026 23:21
Comment thread src/simulation/m_particle_cloud.fpp Outdated
Comment thread src/simulation/m_particle_cloud.fpp Outdated
Comment thread src/simulation/m_particle_cloud.fpp Outdated
@BCKim55
BCKim55 force-pushed the feature/particle-cloud-hemi-shell branch from 933f66c to 4aff083 Compare July 25, 2026 15:01

@BCKim55 BCKim55 left a comment

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks for the feedback. I updated the hemisphere-shell path to remove the redundant box-bounds logic and rely on the shell radii for the placement region. I also changed the dimensionality checks to use num_dims < 3 and removed the extra direction variables in the 3D sampling path.

Comment thread src/simulation/m_particle_cloud.fpp Outdated
Comment thread src/simulation/m_particle_cloud.fpp Outdated

@sbryngelson sbryngelson left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Request changes

  1. Missing regression coverage. This PR adds the hemisphere-shell execution path but removes the local example and adds no test fixture. The existing particle-cloud case is box-only, so CI never executes geometry = 2. Please add a small deterministic 2D or 3D case that checks generated particle positions for shell/plane clearance and non-overlap.

  2. Documentation was not updated. docs/documentation/case.md does not document geometry, shell_inner_radius, or shell_outer_radius, and its length_[x,y,z] description is inaccurate for geometry = 2, where those extents are ignored. Please update the Particle Clouds section accordingly.

Comment thread toolchain/mfc/case_validator.py Outdated
Comment thread src/simulation/m_particle_cloud.fpp Outdated
@BCKim55
BCKim55 marked this pull request as ready for review July 28, 2026 05:11
@BCKim55

BCKim55 commented Jul 28, 2026

Copy link
Copy Markdown
Author

Hi Spencer, I addressed the requested validation, documentation, and regression coverage changes. CI is now passing, and the PR is ready for another look when you have time.

@codecov

codecov Bot commented Jul 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 72.11538% with 29 lines in your changes missing coverage. Please review.
✅ Project coverage is 61.63%. Comparing base (55fb1b1) to head (38cfcdc).
⚠️ Report is 7 commits behind head on master.

Files with missing lines Patch % Lines
src/simulation/m_particle_cloud.fpp 70.40% 17 Missing and 12 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1667      +/-   ##
==========================================
+ Coverage   61.59%   61.63%   +0.03%     
==========================================
  Files          84       84              
  Lines       21493    21567      +74     
  Branches     3176     3188      +12     
==========================================
+ Hits        13239    13293      +54     
- Misses       6078     6089      +11     
- Partials     2176     2185       +9     

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

@sbryngelson sbryngelson left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the revisions. Documentation and validation are genuinely addressed:

  • case.md now documents geometry, shell_inner_radius, shell_outer_radius, and qualifies length_x[y,z] as box-only.
  • The Python validator and m_checker.fpp now enforce the same condition, and shell_outer_radius > shell_inner_radius + 2*radius is exactly the sampler's feasibility requirement (r_outer > r_inner after the +/- radius insets), so the s_mpi_abort path is no longer reachable from valid input.
  • geometry and both new reals are broadcast in m_mpi_proxy.fpp.
  • The sampling math is right: the 2D sqrt CDF and the 3D cube-root CDF with uniform cos(polar) both give uniform density in the shell.

The test coverage point is not yet addressed, though, and that is the blocking item. Details inline.

Comment thread toolchain/mfc/test_particle_cloud.py Outdated
Comment thread toolchain/mfc/test_particle_cloud.py Outdated
Comment thread toolchain/mfc/test/cases.py
Comment thread src/simulation/m_particle_cloud.fpp Outdated
Comment thread src/simulation/m_particle_cloud.fpp Outdated
Comment thread src/simulation/m_particle_cloud.fpp Outdated
Comment thread docs/documentation/case.md Outdated
@sbryngelson
sbryngelson marked this pull request as draft July 29, 2026 13:26
@BCKim55
BCKim55 marked this pull request as ready for review August 10, 2026 18:24
@BCKim55

BCKim55 commented Aug 10, 2026

Copy link
Copy Markdown
Author

Hi Spencer,

I’ve pushed the latest fixes and the PR is ready for re-review.

The blocking regression coverage item is now addressed for particle clouds. The new checks validate generated ib_state_0.dat particle count, shell/plane clearance, box bounds, and non-overlap. I also fixed the single-precision test reader issue that caused the Ubuntu GNU no-debug CI failure.

All GitHub checks are now passing: 60 success, 5 skipped, 0 failures.

Thanks again!

@sbryngelson sbryngelson left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the revisions. The design is now right, and everything from my previous two rounds landed:

  • The geometry to cloud_geometry rename resolves the collision with geom = 2 (circle) and geom = 8 (sphere) in the same routine.
  • Integer exponents are back in the innermost loop, and s_get_cloud_bin now runs once per candidate.
  • The Python mirror implementation is gone in favour of parsing real ib_state_0.dat output.
  • 2D, 3D, and box goldens all exist. All six golden dirs are new, so the squared-distance refactor did not perturb the box path.
  • Sampling math verified independently: the 2D sqrt radial CDF and the 3D cube-root CDF with uniform cos(polar) both give uniform density, and the plane-clearance cut preserves uniformity on the remaining region.

./mfc.sh precheck passes all 7 checks, the 4 new pytest cases pass, and ./mfc.sh test -l lists exactly the 6 new cases matching the 6 new golden dirs.

What is left is one test-fixture problem that undermines the 3D coverage I asked for, a validation-surface gap, and two latent bugs. Details inline.

Blocking

  1. The 3D particles are sub-cell (radius = 0.6*dx), so the 3D golden may not be observing the feature it was added to cover. The 2D goldens do carry real signal; only the 3D case needs fixing.
  2. The box branch of the new ib_state assertion is only valid for packing_method = 1. Separately, this exposed what looks like a genuine pre-existing bug in s_particle_cloud_lattice: its outer loops have no ymax/zmax bound, so lattice clouds can place particles outside the declared region and potentially outside the domain. Not yours to fix here, but it should get an issue.
  3. The m_checker shell-thickness guard is vacuous when radius is unset, since dflt_real = -1.e6_wp swamps the right-hand side. More broadly, nothing requires radius, mass, or num_particles to be set for any cloud.
  4. Domain containment is enforced only in case_validator.py. Please mirror it into m_checker, same as you did for the radii checks.
  5. cloud_geometry = 2 is unguarded in 1D.

Design, and the one I would push hardest on

s_particle_cloud_random_hemi_shell is still a near-verbatim copy of s_particle_cloud_random_box. Extracting the overlap check was the right first step, but roughly 60 of its 110 lines are still duplicated. Collapsing both into a single rejection packer with a geometry select case inside the loop removes that and flattens the dispatch in s_generate_particle_clouds. The cloud_geometry enum invites a third geometry, and a third geometry triples the copy.

Housekeeping

The PR description is stale. It still describes particle_cloud(i)%packing_method = 3, which is the design @wilfonba asked you to change, and it lists examples/3D_mibm_particle_cloud_hemi_shell/case.py under Testing though no such example is in the PR. Release notes get assembled from PR bodies, so please fix it before merge.

Comment thread toolchain/mfc/test/cases.py Outdated
Comment thread toolchain/mfc/test/test.py Outdated
Comment thread src/simulation/m_checker.fpp Outdated
Comment thread src/simulation/m_checker.fpp Outdated
Comment thread src/simulation/m_checker.fpp Outdated
Comment thread toolchain/mfc/test/test.py Outdated
Comment thread toolchain/mfc/test/cases.py Outdated
Comment thread toolchain/mfc/test/cases.py
Comment thread toolchain/mfc/case_validator.py Outdated
Comment thread toolchain/mfc/params/definitions.py Outdated
…state precision

Collapse s_particle_cloud_random_box/_hemi_shell into one s_particle_cloud_rejection_pack with a geometry-specific candidate sampler and flat packing-method dispatch (net -254 LOC in simulation/); fix f_xorshift sign-bit fold that could place a NaN centre; drop the dead redundant shell-radii check. Move input-only guards to case_validator.py (radius/mass/num_particles positivity, 1D hemisphere reject, one-radius wall standoff, _is_numeric guards). Make the ib_state test reader key field width and tolerance off the --single build flag only (wp stays double under --mixed), name the record-layout constants, guard file_per_process, and gate the box-bounds assertion on packing_method==1. Give the 3D golden a cell-spanning radius, the 2D case a wall standoff, and the box case ~50 particles. Revert an unrelated lag_params reflow and document the shell orientation/containment rules.
sbryngelson
sbryngelson previously approved these changes Aug 19, 2026
@sbryngelson
sbryngelson removed the request for review from danieljvickers August 19, 2026 03:44
@sbryngelson

Copy link
Copy Markdown
Member

Architectural note for after this lands (tracked in #1737): the particle-cloud packer is really geometry preprocessing — rejection/lattice/hemisphere-shell/periodic sampling, spatial hashing — that currently sits in the solver startup only because IBM marker computation is simulation-side. It'd be cleaner to expand the compact particle_cloud spec in pre_process, write the IB-patch list to a file, and have the solver just read it (net ~-525 lines in simulation/). Not blocking this PR — flagging so the subsystem doesn't keep accreting knobs solver-side. Design sketch in #1737.

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.

4 participants