Skip to content

feat: improved support for compositional simulations - #4158

Open
victorapm wants to merge 13 commits into
developfrom
feature/paludettomag1/ncomp
Open

victorapm wants to merge 13 commits into
developfrom
feature/paludettomag1/ncomp

Conversation

@victorapm

@victorapm victorapm commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

Adds GEOS_MAX_FLUID_COMPONENTS (note this is a cmake build option) to control the maximum number of fluid components instantiated at build time. The default remains 5, with supported values from 2 to 20.

The setting controls kernel generation and dispatch, and expands fluid storage when needed. Simulations exceeding the compiled limit fail during setup with a clear error. The table-based OBL solver remains capped at nine components.

Validated with CPU builds, serial/MPI dispatch tests, well and boundary-condition tests, and numerical comparisons of equivalent 4-, 15- and 20-component fluids.

Add GEOS_MAX_COMPONENTS with a default of five and a supported range of two to nine. Drive component dispatch, generated kernels, explicit instantiations, and fluid-type selection from the configured limit, and reject oversized solver inputs during setup.

Add component and fluid-selector tests, CMake option validation, and nine-component reservoir, well, CFL, and Dirichlet smoke cases. CPU Release builds and all feature tests pass at limits two and nine; configuration checks also pass at five and eight.
Keep the default instantiation limit at five and grow constitutive working arrays for larger configured limits. Cap table-based OBL dispatch at nine components to avoid exponential interpolation workspace growth.

Validate the 2-20 option range, serial and MPI dispatch, nine- and twenty-component well and Dirichlet simulations, and the OBL limit error. A full CPU build and numerical comparisons of equivalent four-, fifteen- and twenty-component fluids passed.
Rename the CMake option and generated macro consistently in dispatch, kernel generation, storage sizing, setup diagnostics, tests and documentation.

Validate the option range, configure fresh builds at the default and limits 2, 15 and 20, and pass twelve C++ syntax checks covering selectors, solver setup and generated hybrid kernels.
Report the requested component count, constitutive storage capacity and GEOS_MAX_FLUID_COMPONENTS setting when an oversized fluid model is rejected before solver setup.

Add a regression test for the diagnostic and pass selector and option tests in builds configured for two and twenty fluid components.
@victorapm victorapm self-assigned this Oct 2, 2026
@victorapm victorapm added the ci: run integrated tests Allows to run the integrated tests in GEOS CI label Oct 2, 2026
@victorapm victorapm added the ci: run code coverage enables running of the code coverage CI jobs label Oct 2, 2026
@victorapm victorapm added the ci: run device builds Allows to run the device (CUDA/HIP) builds label Oct 2, 2026
Comment thread src/docs/sphinx/buildGuide/BuildProcess.rst
OBL table interpolation keeps a per-thread workspace of (2^(NC+1)-1) x numOps doubles. With energy, eight components need about 679 KiB and nine about 1.45 MiB, both above the 512 KiB CUDA local-memory limit. Seven components need about 307 KiB.

Define the cap once as GEOS_OBL_COMPONENT_CAP and use it in the CMake clamp, the generated config, the solver input check and the option test. Let kernelSpecs.json name the variable that bounds a key's NCOMP range instead of matching the OBL key by name. Register the OBL rejection test in every multiphysics build, since the check it covers does not depend on GEOS_MAX_FLUID_COMPONENTS.
The FVM Dirichlet templates crossed every component count up to GEOS_MAX_FLUID_COMPONENTS with every fluid type. Most of those kernels could never run, because component dispatch only covers each fluid's min_n_components to max_n_components range.

Record the restricted ranges of the black-oil, dead-oil and CO2-brine fluids under NCOMP_BOUNDS in kernelSpecs.json, and generate only those combinations. A twenty-component build now generates 280 isothermal Dirichlet translation units instead of 494, and the default build 70 instead of 104.
Each hybrid flux and Dirichlet translation unit instantiated every component count for its face count, so a twenty-component build put 120 kernel launches in each file. Generate one translation unit per (NF, NC) pair, keeping per-file compiler memory independent of GEOS_MAX_FLUID_COMPONENTS.
MultiphasePoromechanics rejects more than three components, but the conforming-fracture flux kernel dispatched through the shared component switch and was instantiated up to GEOS_MAX_FLUID_COMPONENTS. Skip the larger instantiations at compile time and report an error if one is requested.
Add the source decks and generator script to CMAKE_CONFIGURE_DEPENDS so that editing them reconfigures the build and regenerates the twenty-component decks. Run the generator inside a function so its variables stay out of the directory scope.
@victorapm
victorapm requested a review from frankfeifan as a code owner October 2, 2026 18:21
List the steps for raising GEOS_MAX_FLUID_COMPONENTS: set it in the host-config or on the CMake command line, reconfigure, and rebuild. State that kernelSpecs.json needs no edits, and add a commented example to the quick-start host-config template.

Reduce each NCOMP list in kernelSpecs.json to its lowest component count, the only value the configure step reads, so the lists no longer look like hand-maintained ranges. The generated kernels are unchanged.
Factor separators and whitespace in array validation and use unambiguous real-number alternatives. Padded multidimensional arrays no longer stall during XML loading, including the eight-component CoCO2 binary-interaction matrix.

Add valid and malformed 8x8 and 20x20 matrix regression tests. Six focused tests passed in an eight-component CPU build with SuiteSparse. The unchanged CoCO2 deck completed all 7440 days in 419 timesteps with no timestep cuts.
@victorapm
victorapm requested a review from wrtobin as a code owner October 2, 2026 18:58

@dkachuma dkachuma left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good to me.

integer constexpr maxComponents = std::min( FluidType::max_n_components, GEOS_MAX_FLUID_COMPONENTS );
if constexpr (FluidType::min_n_components > maxComponents)
{
GEOS_THROW( GEOS_FMT( "Fluid {} requires at least {} components, but GEOS_MAX_FLUID_COMPONENTS is {}.",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I would use a static assert here. We really shouldn't set GEOS_MAX_FLUID_COMPONENTS < FluidType::min_n_components which is typically 2.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the comment, Dick! Should be addressed in b37e3d6

Replace the selector's configuration error with a static assertion. Require a build limit of at least three to cover black-oil fluids, retain two-component dispatch, and update option validation and documentation. Add coverage for black-oil component counts.
@victorapm

Copy link
Copy Markdown
Contributor Author

Needs code owner review from @MelReyCG , @OmarDuran , @bd713 , @corbett5 , @frankfeifan , @jhuang2601 , @joshua-white and/or @rrsettgast Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci: run code coverage enables running of the code coverage CI jobs ci: run device builds Allows to run the device (CUDA/HIP) builds ci: run integrated tests Allows to run the integrated tests in GEOS CI flag: ready for review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants