feat(vof): NeoN building blocks for the incompressibleVoFNeon solver - #562
Open
HenningScheufler wants to merge 8 commits into
Open
feat(vof): NeoN building blocks for the incompressibleVoFNeon solver#562HenningScheufler wants to merge 8 commits into
HenningScheufler wants to merge 8 commits into
Conversation
The div/laplacian operators are declared `extern template`, so including their headers in the _neon binding TU does not instantiate them — their self-registration only fires in libNeoN. Compiled `-fvisibility=hidden`, _neon gets a private, empty copy of the runtime-selection factory table, so scheme resolution at assembly time aborts with "Could not find constructor for Gauss". Force explicit instantiation here so the self-registration runs inside _neon and populates its table. Marked with a TODO to drop once the factory table is shared across shared objects.
Drives Expression.read from Python — the call that performs the runtime-selection
factory lookup (create("Gauss")) — to guard the explicit-instantiation fix. Without
that fix the lookup aborts with "Could not find constructor for Gauss". A scalar
equation covers the <scalar> instantiation; a vector equation additionally covers
<Vec3> and <Vec3, scalar> (vector div/laplacian build both same-type and
scalar-matrix strategies).
Adds the minimal bindings the test needs: Expression.read, and
Dictionary.insert_dict / insert_token_list (so a nested divSchemes/laplacianSchemes
dictionary can be built from Python).
Static nanobind gives each extension module its own private nanobind runtime, so types cannot be exchanged across modules reliably (it happens to work when everything is built against one nanobind, but breaks in isolated CI builds). Build _neon against a shared nanobind runtime so it can exchange types with neofoam_bindings and pybFoam (which also uses NB_SHARED) — e.g. so create_adapter_run_time accepts pybFoam's Foam::Time.
NeoN CPM-pinned nanobind 2.9.2 while pybFoam (and pyOFTools) build against pip's 2.13.0. The _neon binding shares pybFoam's libnanobind.so at runtime, but nanobind's ndarray_create signature changed after 2.9.2 (gained a size_t arg), so _neon built against 2.9.2 failed to resolve the symbol from pybFoam's 2.13.0 lib (undefined symbol in CI). Bump to 2.13.0 so the ABIs match; keep it overridable so a downstream can track its own pybFoam. CPM_USE_LOCAL_PACKAGES still reuses an installed nanobind when present.
Add the NeoN-core discretisation primitives the NeoFOAM incompressibleVoF / neoInterFoam solver needs, on top of develop: - ddtOperator: density-weighted overload (rho on the diagonal, oldTime(rho) on the rhs) for the interFoam ddt(rho, U) momentum term; imp::ddt(rho, phi) dsl. - reconstruct: fvc::reconstruct(surfaceScalar) -> volVector least-squares surface-flux -> cell-vector op (inv(sum Sf(x)Sf/|Sf|) & sum (Sf/|Sf|) ssf), with a trace-regularisation so it is correct on 2D (empty-direction) meshes. - mules: bounded FCT flux limiter (MULES::explicitSolve/limit/limiter, simplified rho=1 / Sp=Su=0 / no-compression path) — conservatively bounds alpha in [0,1] without clamping; matches OpenFOAM's lambdam/lambdap limiter. - surfaceField: value assignment helper used by the VoF flux updates. - bindings: expose nn.reconstruct, nn.mules_explicit_solve, imp.ddt(rho,phi). Verified against OpenFOAM/pybFoam from the NeoFOAM side (reconstruct/MULES/ surface-tension parity to machine precision; MULES matches pybFoam.vof).
Add the FixedFluxPressure<scalar> volume boundary condition and register it in boundary.hpp. correctBoundaryCondition re-derives the boundary value from the existing per-face refGrad (it does NOT overwrite refGrad from a stored uniform); an external caller (constrainPressure) sets refGrad each PISO corrector so the pressure projection cancels the wall face flux. Used by the incompressibleVoFNeon solver's buoyant p_rgh correction.
MULES::explicitSolve is a VoF-specific FCT algorithm, not a NeoN building block; move it to NeoFOAM (src/bindings/vofOperators.cpp) beside MULES::correct so NeoN stays algorithm-free and only provides the generic primitives it composes from (parallelFor / surfaceIntegrate / mesh views / Vector). Removes the mules operator, header, and Python binding + their CMake/registration entries.
|
Thank you for your PR, here are some useful tips:
|
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.
NeoN building blocks for the
incompressibleVoFNeonsolverAdds the generic NeoN primitives the NeoFOAM-side VoF solver composes from, keeping NeoN building-blocks-only (no VoF/MULES algorithm lives here).
What's here
FixedFluxPressure<scalar>volume boundary —correctBoundaryConditionre-derives the boundary value from the existing per-facerefGrad(it does not overwrite it); an external caller (constrainPressure, NeoFOAM side) setsrefGradeach PISO corrector so the pressure projection cancels the wall face flux. Used by the buoyantp_rghcorrection.ddt+reconstructfor the VoF momentum/pressure path._neon(+ regression test), build_neonwith nanobindNB_SHARED, pin nanobind to 2.13.0 to match pybFoam's ABI.Not here (by design)
The MULES FCT limiter was briefly added on this branch and then removed (
refactor(vof): remove MULES from NeoN): MULES is a VoF-specific algorithm, so it now lives in NeoFOAM'svofOperators.cppalongsidemules_correct. The net diff adds no MULES to NeoN.Paired with the NeoFOAM PR (
feat/incompressibleVoF) that consumes these primitives; the NeoFOAM side pins this commit via itssrc/NeoNsubmodule.🤖 Generated with Claude Code
https://claude.ai/code/session_01BdqJykWhD6VvPjWR3tvAez