diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index d8e9ea002..1c1146e79 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -5,3 +5,5 @@ c726b259409b93e0a6df12d199f87eab8caa10db 88dc8509543b34140a6015e361888644c5f5e0fe # reformat simplified-fields d521b8ce2e0d510d7472d2ac011cfc84b670f918 +# reformat after the 0.4 reorganization +9675a362ba1a39515bda5cee679ad5036de46c18 diff --git a/.github/workflows/clang-tidy.yml b/.github/workflows/clang-tidy.yml index 2329580a5..42d58ea00 100644 --- a/.github/workflows/clang-tidy.yml +++ b/.github/workflows/clang-tidy.yml @@ -191,7 +191,7 @@ jobs: -DCMAKE_CXX_COMPILER=mpicxx \ -DCMAKE_Fortran_COMPILER=mpifort \ -DPCMS_ENABLE_PETSC=ON \ - -DPETSC_LINK_STATIC=ON \ + -DPCMS_PETSC_LINK_STATIC=ON \ -DPETSC_DIR=${{ runner.temp }}/petsc-openmpi \ -DPETSC_ARCH=ubuntu-kokkos \ -DPCMS_TIMEOUT=10 \ diff --git a/.github/workflows/cmake-test.yml b/.github/workflows/cmake-test.yml index 413cd5cff..2ba495320 100644 --- a/.github/workflows/cmake-test.yml +++ b/.github/workflows/cmake-test.yml @@ -242,7 +242,7 @@ jobs: run: | echo "PCMS_ENABLE_PETSC=-DPCMS_ENABLE_PETSC=${{ matrix.petsc }}" >> $GITHUB_ENV if [ "${{ matrix.petsc }}" = "ON" ]; then - echo "PCMS_PETSC_OPTIONS=-DPETSC_LINK_STATIC=ON -DPETSC_DIR=${{ runner.temp }}/petsc -DPETSC_ARCH=ubuntu-kokkos" >> $GITHUB_ENV + echo "PCMS_PETSC_OPTIONS=-DPCMS_PETSC_LINK_STATIC=ON -DPETSC_DIR=${{ runner.temp }}/petsc -DPETSC_ARCH=ubuntu-kokkos" >> $GITHUB_ENV else echo "PCMS_PETSC_OPTIONS=" >> $GITHUB_ENV fi @@ -281,7 +281,7 @@ jobs: ${{ env.PCMS_ENABLE_PETSC }} ${{ env.PCMS_PETSC_OPTIONS }} -DPCMS_TIMEOUT=10 - -DPCMS_ENABLE_Python=${{ matrix.python_api }} + -DPCMS_ENABLE_PYTHON=${{ matrix.python_api }} -DCatch2_DIR=${{ runner.temp }}/build-Catch2/install/lib/cmake/Catch2 -DOmega_h_DIR=${{ runner.temp }}/build-omega_h/install/lib/cmake/Omega_h ${{ env.PCMS_MESHFIELDS_DIR }} @@ -332,8 +332,9 @@ jobs: if: matrix.python_api == 'OFF' shell: bash run: | - # Configure and build the test - # it should only ask for pcms_DIR/ROOT to find all dependencies + # Build examples/external-usage-example against the install tree only + # (installed headers, exported targets). The package config no longer + # bakes in dependency paths, so they come from CMAKE_PREFIX_PATH. ls ${{ runner.temp }}/build-pcms/install/lib/cmake/pcms echo "-------- PCMS CONFIG -------------" cat ${{ runner.temp }}/build-pcms/install/lib/cmake/pcms/pcms-config.cmake @@ -346,9 +347,15 @@ jobs: -B ${{github.workspace}}/examples/external-usage-example/build \ -S ${{github.workspace}}/examples/external-usage-example/ \ -Dpcms_DIR=${{ runner.temp }}/build-pcms/install/lib/cmake/pcms \ - ${{ matrix.petsc == 'ON' && format('-DPETSC_LINK_STATIC=ON -DPETSC_DIR={0}/petsc -DPETSC_ARCH=ubuntu-kokkos', runner.temp) || '' }} \ + -DCMAKE_PREFIX_PATH="${{ runner.temp }}/build-kokkos/install;${{ runner.temp }}/build-kokkos-kernels/install;${{ runner.temp }}/build-omega_h/install;${{ runner.temp }}/build-redev/install;${{ runner.temp }}/build-ADIOS2/install;${{ runner.temp }}/build-perfstubs/install;${{ runner.temp }}/build-meshFields/install" \ + -DCMAKE_CXX_COMPILER=`which mpicxx` \ + ${{ matrix.petsc == 'ON' && format('-DPCMS_PETSC_LINK_STATIC=ON -DPETSC_DIR={0}/petsc -DPETSC_ARCH=ubuntu-kokkos', runner.temp) || '' }} \ --debug-output cmake --build ${{github.workspace}}/examples/external-usage-example/build + mpirun --oversubscribe -np 1 ${{github.workspace}}/examples/external-usage-example/build/pcms_test + + - name: Check public header includes + run: python3 tools/check-public-includes.py deploy-docs: needs: test-build diff --git a/.github/workflows/self-hosted.yml b/.github/workflows/self-hosted.yml index c4f3d61ce..b5f26e183 100644 --- a/.github/workflows/self-hosted.yml +++ b/.github/workflows/self-hosted.yml @@ -117,7 +117,7 @@ jobs: -DKokkos_DIR=$DEPENDENCY_DIR/${DEVICE_ARCH}/kokkos/install/lib64/cmake/Kokkos/ \ -DKokkosKernels_DIR=$DEPENDENCY_DIR/${DEVICE_ARCH}/kokkos-kernels/install/lib64/cmake/KokkosKernels/ \ -DBUILD_TESTING=ON \ - -DPCMS_ENABLE_Python=ON \ + -DPCMS_ENABLE_PYTHON=ON \ -DPCMS_ENABLE_PETSC=ON \ -DPETSC_ARCH="" \ -DPETSC_DIR=$DEPENDENCY_DIR/${DEVICE_ARCH}/petsc/install \ @@ -168,7 +168,7 @@ jobs: -DKokkos_DIR=$DEPENDENCY_DIR/${DEVICE_ARCH}/kokkos/install/lib64/cmake/Kokkos/ \ -DKokkosKernels_DIR=$DEPENDENCY_DIR/${DEVICE_ARCH}/kokkos-kernels/install/lib64/cmake/KokkosKernels/ \ -DBUILD_TESTING=ON \ - -DPCMS_ENABLE_Python=ON \ + -DPCMS_ENABLE_PYTHON=ON \ -DPCMS_ENABLE_PETSC=ON \ -DPETSC_ARCH="" \ -DPETSC_DIR=$DEPENDENCY_DIR/${DEVICE_ARCH}/petsc/install \ diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..98569d08c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,50 @@ +# Changelog + +## 0.4.0 + +A one-time breaking reorganization so that downstream codes migrate once. +Numerical behavior is unchanged. See [MIGRATION.md](MIGRATION.md) and +`tools/migrate-pcms.sh`; the decisions behind the changes are in +`tools/reorg/decisions.md`. + +### Changed (breaking) + +- Public API: only interfaces and factory functions are public + (`CreateLagrangeSpace`, `CreateSplineSpace`, + `CreatePolynomialReconstructionSpace`, `CreateUniformGridDiscretization`, + `CreateEmptyDiscretization`, `CreateEmptyLayout`, + `CreateConservativeProjection`, `CreateControlVariateProjection`, and the + backend entry points in `pcms/backends//.hpp`). The concrete + spaces, layouts, discretizations and projections are internal. +- Headers: all C++ headers are `.hpp`; only public headers are installed, in + `include/pcms//`; `pcms.h` is replaced by the umbrella + `pcms/pcms.hpp`; core public headers no longer include Omega_h, MFEM, + MeshFields, PETSc or ADIOS2. +- Namespaces: backend code is in `pcms::backend::`, internal code in + `pcms::`; the public API stays in `pcms::`. +- Omega_h types left the core public signatures (`MakeConstRank2View`, + `CreateUniformGridFromMesh` and the Omega_h `OverlapMask` constructors moved + to the Omega_h backend; `UniformGrid` point queries take any indexable + point). +- `pcms::Mode` is a PCMS enum instead of an alias of `redev::Mode`. +- Python API mirrors the C++ factories; the class-based constructors are + removed. +- Macros `MAX_DIM` and `ACTIVE_GPU_EXECUTION` are `PCMS_`-prefixed. +- Build: CMake 3.23 required; options renamed to `PCMS_ENABLE_` / + `PCMS_` form (old names still accepted in 0.4, deprecated); `pcms::core` is + a deprecated alias of `pcms::pcms`; `pcms::transfer` no longer depends on + the coupler, redev or ADIOS2; package files installed to + `lib/cmake/pcms`; no baked dependency paths; `SameMinorVersion` + compatibility; libraries have `VERSION`/`SOVERSION`; the SWIG interface + files are no longer installed. + +### Added + +- `PCMS_ENABLE_COUPLER` to build without redev and ADIOS2. +- Factory functions and backend headers listed above; `FunctionSpace` + discretizations in Python (`pcms.backend.omega_h`). +- Tests that every public header compiles on its own and that core public + headers include no backend library; CI builds and runs + `examples/external-usage-example` against the install tree. +- `tools/migrate-pcms.sh` with `tools/reorg/header-map.txt` and + `tools/reorg/symbol-map.txt`. diff --git a/CMakeLists.txt b/CMakeLists.txt index 938fc4d8e..e22cac9f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,16 +1,21 @@ -cmake_minimum_required(VERSION 3.19) +cmake_minimum_required(VERSION 3.23) project( pcms - VERSION 0.3.0 + VERSION 0.4.0 LANGUAGES CXX) include(GNUInstallDirs) +# The package config files go to /lib/cmake/pcms on every platform. +set(PCMS_INSTALL_CMAKEDIR "lib/cmake/pcms" + CACHE STRING "Install directory of the pcms CMake package files") include(CMakePackageConfigHelpers) # use _ROOT variables for configurations cmake_policy(SET CMP0074 NEW) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") +# map options renamed in 0.4 (e.g. PCMS_ENABLE_Python) to their new names +include(PcmsRenamedOptions) option(PCMS_ENABLE_ASAN "enable address sanitizer" OFF) set(PCMS_HAS_ASAN OFF) @@ -41,13 +46,14 @@ endif() option(PCMS_ENABLE_SERVER "enable the coupling server implementation" ON) option(PCMS_ENABLE_CLIENT "enable the coupling client implementation" ON) +option(PCMS_ENABLE_COUPLER "Build the coupler (requires redev and ADIOS2)" ON) option(PCMS_ENABLE_XGC "enable xgc field adapter" ON) option(PCMS_ENABLE_OMEGA_H "enable Omega_h field adapter" OFF) option(PCMS_ENABLE_MFEM "enable MFEM field adapter" OFF) option(PCMS_ENABLE_TRANSIENT "Enable pcms transient module" ON) option(PCMS_ENABLE_C "Enable pcms C api" ON) -option(PCMS_ENABLE_Python "Enable pcms Python api" OFF) +option(PCMS_ENABLE_PYTHON "Enable pcms Python api" OFF) option(PCMS_ENABLE_PRINT "PCMS print statements enabled" ON) option(PCMS_ENABLE_EXAMPLES "Build the in-tree C++ examples" ON) @@ -69,21 +75,25 @@ set(PCMS_PROJECTION_KSP_RTOL 1e-14 CACHE STRING set(PCMS_PROJECTION_KSP_ATOL 1e-50 CACHE STRING "Default absolute tolerance for the projection mass-matrix solve") -option(PETSC_LINK_STATIC "Use pkg-config --static results for PETSc" +option(PCMS_PETSC_LINK_STATIC "Use pkg-config --static results for PETSc" ${_pcms_link_petsc_static_default}) # find package before fortran enabled, so we don't require the adios2 fortran # interfaces this is important because adios2 build with clang/gfortran is # broken -find_package(redev 4.3.0 REQUIRED) +if(PCMS_ENABLE_COUPLER) + find_package(redev 4.3.0 REQUIRED) +elseif(PCMS_ENABLE_PYTHON) + message(FATAL_ERROR "PCMS_ENABLE_PYTHON requires PCMS_ENABLE_COUPLER") +endif() -if (PCMS_ENABLE_Python) +if (PCMS_ENABLE_PYTHON) set(CMAKE_POSITION_INDEPENDENT_CODE TRUE) endif () if(PCMS_ENABLE_C) enable_language(C) - option(PCMS_ENABLE_Fortran "Enable pcms fortran api" ON) - if(PCMS_ENABLE_Fortran) + option(PCMS_ENABLE_FORTRAN "Enable pcms fortran api" ON) + if(PCMS_ENABLE_FORTRAN) enable_language(Fortran) endif() endif() @@ -130,7 +140,9 @@ if(PROJECT_IS_TOP_LEVEL) endif() endif() -message(STATUS "Found redev: ${redev_DIR} (found version ${redev_VERSION})") +if(PCMS_ENABLE_COUPLER) + message(STATUS "Found redev: ${redev_DIR} (found version ${redev_VERSION})") +endif() if(PCMS_ENABLE_OMEGA_H) find_package(Omega_h REQUIRED VERSION 10) message( @@ -148,7 +160,9 @@ if(PCMS_ENABLE_MFEM) endif() endif() # adios2 adds C and Fortran depending on how it was built -find_package(ADIOS2 CONFIG 2.10.2 REQUIRED) +if(PCMS_ENABLE_COUPLER) + find_package(ADIOS2 CONFIG 2.10.2 REQUIRED) +endif() find_package(Kokkos CONFIG 4.5 REQUIRED) option(PCMS_ENABLE_MESHFIELDS "Enable MeshFields support" ON) @@ -179,33 +193,36 @@ if(NOT BUILD_TESTING) COMMENT "Test installed PUMIPic utilities") endif() -add_executable(smoke_test test/test_ohClassPtn.cpp) -target_link_libraries(smoke_test pcms::core test_support) -# Uses a mesh vendored in test/data so the install check works without -# PCMS_TEST_DATA_DIR (e.g. with BUILD_TESTING=OFF). -dual_mpi_test( - TESTNAME - smoke_test - TIMEOUT - 4 - NAME1 - rdv - EXE1 - smoke_test - PROCS1 - 2 - ARGS1 - 1 - ${CMAKE_CURRENT_SOURCE_DIR}/test/data/cyclone23/mesh.osh/ - NAME2 - app - EXE2 - smoke_test - PROCS2 - 1 - ARGS2 - 0 - ${CMAKE_CURRENT_SOURCE_DIR}/test/data/cyclone23/mesh.osh/) +# the smoke test exercises the coupler +if(TARGET pcms::coupler) + add_executable(smoke_test test/test_ohClassPtn.cpp) + target_link_libraries(smoke_test pcms::pcms test_support) + # Uses a mesh vendored in test/data so the install check works without + # PCMS_TEST_DATA_DIR (e.g. with BUILD_TESTING=OFF). + dual_mpi_test( + TESTNAME + smoke_test + TIMEOUT + 4 + NAME1 + rdv + EXE1 + smoke_test + PROCS1 + 2 + ARGS1 + 1 + ${CMAKE_CURRENT_SOURCE_DIR}/test/data/cyclone23/mesh.osh/ + NAME2 + app + EXE2 + smoke_test + PROCS2 + 1 + ARGS2 + 0 + ${CMAKE_CURRENT_SOURCE_DIR}/test/data/cyclone23/mesh.osh/) +endif() if(BUILD_TESTING) add_subdirectory(test) diff --git a/Doxyfile b/Doxyfile index 2d9ad0e90..01aa960f9 100644 --- a/Doxyfile +++ b/Doxyfile @@ -2287,7 +2287,7 @@ PREDEFINED = PCMS_ENABLE_SERVER \ PCMS_ENABLE_MFEM \ PCMS_ENABLE_C \ PCMS_ENABLE_TRANSIENT \ - PCMS_ENABLE_Fortran \ + PCMS_ENABLE_FORTRAN \ PCMS_ENABLE_MESHFIELDS \ PCMS_ENABLE_PETSC \ KOKKOS_INLINE_FUNCTION= \ diff --git a/MIGRATION.md b/MIGRATION.md new file mode 100644 index 000000000..0128f4757 --- /dev/null +++ b/MIGRATION.md @@ -0,0 +1,209 @@ +# Migrating from PCMS 0.3 to 0.4 + +PCMS 0.4 reorganizes the library so that downstream codes migrate once: the +public API is now a small set of interfaces and factory functions, everything +else is internal. Behavior and numerical results do not change. + +Most of the mechanical work is done by `tools/migrate-pcms.sh`: + +```sh +tools/migrate-pcms.sh --dry-run path/to/your/code # show what would change +tools/migrate-pcms.sh path/to/your/code # apply it +``` + +It rewrites includes, renamed names, macros, CMake options and targets, and +Python code, and lists every place that needs a manual change (with the +replacement). The rest of this document explains those changes. + +## Building and linking + +- **Requirements:** CMake 3.23 or newer. +- **Link `pcms::pcms`.** It links every PCMS library that was built and is the + supported way to use PCMS. `pcms::core` still works in 0.4 as a deprecated + alias of `pcms::pcms` (CMake prints a deprecation warning) and will be + removed. The other targets are `pcms::utility`, `pcms::discretization`, + `pcms::localization`, `pcms::field`, `pcms::transfer`, `pcms::coupler`, + `pcms::transient`, `pcms::capi`, `pcms::fortranapi`. +- **Renamed options** (the old names still work in 0.4, with a deprecation + warning): `PCMS_ENABLE_Python` → `PCMS_ENABLE_PYTHON`, + `PCMS_ENABLE_Fortran` → `PCMS_ENABLE_FORTRAN`, + `PETSC_LINK_STATIC` → `PCMS_PETSC_LINK_STATIC`. +- **New option** `PCMS_ENABLE_COUPLER` (default `ON`): with `OFF`, PCMS builds + without redev and ADIOS2 (no coupler, no C/Fortran client API, no Python). +- **Finding PCMS:** the package files are in `/lib/cmake/pcms`. The + package no longer bakes in the paths of its dependencies: make them findable + as usual (`CMAKE_PREFIX_PATH`, `_ROOT` or `_DIR`) for + Kokkos, KokkosKernels, perfstubs, Omega_h, and, if PCMS was built with them, + redev, ADIOS2, MeshFields, MFEM and PETSc. +- **Versions:** `find_package(pcms 0.4)` accepts only 0.4.x + (`SameMinorVersion`); shared libraries have SOVERSION `0.4`. + +## Headers + +- All C++ headers end in `.hpp` (the C API headers in `pcms/capi/` stay `.h`). +- Only the public headers are installed, under `include/pcms//`. + `pcms/pcms.hpp` includes the whole public API; backend headers are included + separately (`pcms/backends/omega_h/omega_h.hpp`, + `pcms/backends/mfem/mfem.hpp`, `pcms/backends/xgc/xgc.hpp`). +- The top-level `pcms.h` is replaced by `pcms/pcms.hpp`. +- `tools/reorg/header-map.txt` lists every old path and its replacement; + headers marked "private" are no longer installed and their classes must be + replaced by the public API below. +- Core public headers no longer include Omega_h, MFEM, MeshFields, PETSc or + ADIOS2. Code that got Omega_h declarations through a PCMS header must + include the Omega_h headers it uses. + +## Creating spaces, fields and transfers + +The concrete classes are internal. Use the factories, which return the +interfaces `Discretization`, `FunctionSpace`, `FieldFactory`, `FieldLayout` +and `TransferOperator`: + +| 0.3 | 0.4 | +|---|---| +| `LagrangeFunctionSpace::FromMesh(mesh, order, n, csys, gid_name, backend, layout_name)` | `CreateLagrangeSpace(backend::omega_h::CreateDiscretization(mesh, gid_name), order, n, csys, {implementation, layout_name})` | +| `... FromMesh(mesh, order, n, csys, owned_mask, ...)` | `CreateLagrangeSpace(backend::omega_h::CreateDiscretization(mesh, owned_mask, gid_name), ...)` | +| `LagrangeFunctionSpace::FromUniformGrid(grid, n, csys, order)` | `CreateLagrangeSpace(CreateUniformGridDiscretization(grid), order, n, csys)` | +| `LagrangeFunctionSpace::Backend::{MeshFields,OmegaH}` | `LagrangeImplementation::{MeshFields,OmegaH}` (in `LagrangeOptions`) | +| `SplineFunctionSpace::FromUniformGrid(grid, csys)` | `CreateSplineSpace(CreateUniformGridDiscretization(grid), csys)` | +| `PolynomialReconstructionFunctionSpace::Create(points, opts)` | `CreatePolynomialReconstructionSpace(points, opts)` | +| `PolynomialReconstructionFunctionSpace::FromMesh(mesh, dim, csys, opts)` | `CreatePolynomialReconstructionSpace(backend::omega_h::CreateDiscretization(mesh), dim, csys, opts)` | +| `EmptyFieldLayout(csys, n)` | `CreateEmptyLayout(csys, n)` | +| `OmegaHConservativeProjection(src, tgt, mass)` | `CreateConservativeProjection(src, tgt, {mass})` | +| `OmegaHControlVariateProjection(src, tgt, samples, sampling, seed, mass)` | `CreateControlVariateProjection(src, tgt, {samples, sampling, seed, mass})` | +| `XGCFieldFactory(rc, n, layout_name)` | `backend::xgc::CreateFieldFactory(rc, n, layout_name)` | +| `factory.CreateField(name, make_unique>(factory.GetXGCLayout(), basis, data, comm))` | `backend::xgc::CreateField(factory, name, data, comm, basis)` | +| `MFEMFieldFactory(pmesh, pfes, gf, csys, layout_name)` | `backend::mfem::CreateFieldFactory(pmesh, pfes, gf, csys, layout_name)` | +| `MFEMLayout::OverlapMaskFromAttribute(pmesh, attr)` | `backend::mfem::OverlapMaskFromAttribute(pmesh, attr)` | +| `OverlapMask(size, omega_h_mask)` | `OverlapMask(size, backend::omega_h::OverlapMaskFromArray(omega_h_mask))` | +| `MakeConstRank2View(omega_h_array, dim)` | `backend::omega_h::MakeConstRank2View(omega_h_array, dim)` | +| `CreateUniformGridFromMesh(mesh, ...)` | `backend::omega_h::CreateUniformGridFromMesh(mesh, ...)` | +| `CreateUniformGridBinaryField<2>(mesh, ...).second` | `backend::omega_h::CreateUniformGridBinaryField(mesh, ...)` | + +(`backend::` is `pcms::backend::`; all other names are in `pcms::`.) Factories +for a combination PCMS does not support (e.g. a Lagrange space on an XGC +discretization) throw `pcms_error`. The projection factories throw in a build +without PETSc and MeshFields. + +`MakeEQDSKField` is unchanged except that `EQDSKField::space` is a +`std::shared_ptr`. + +`UniformGrid::ClosestCellID` and `IsPointInBounds` accept any point type +indexable with `[i]` (`Kokkos::Array`, a subview, `Omega_h::Vector`). + +## Namespaces + +- The public API stays in `pcms::`. +- Backend code is in `pcms::backend::` (`omega_h`, `mfem`, `xgc`, + `point_cloud`, `uniform_grid`, `omega_h_meshfields`). +- Internal code is in `pcms::utility`, `pcms::discretization`, + `pcms::localization`, `pcms::field`, `pcms::transfer` and `pcms::coupler`. + `tools/reorg/symbol-map.txt` lists every name that moved. + +## Coupler + +`pcms::Mode` is now a PCMS enum (`Deferred`, `Synchronous`) instead of an +alias of `redev::Mode`. `SendField`, `ReceiveField`, `SendData`, +`ReceiveData` and the handles' `Send`/`Receive` take `pcms::Mode`: replace +`redev::Mode::X` with `pcms::Mode::X` in those calls. The `OverlapMask` +constructors taking Omega_h arrays are gone (see the table). + +## Macros + +`MAX_DIM` → `PCMS_MAX_DIM`, `ACTIVE_GPU_EXECUTION` → +`PCMS_ACTIVE_GPU_EXECUTION`, and the configuration macro +`PCMS_ENABLE_Fortran` → `PCMS_ENABLE_FORTRAN`. + +## Python + +The Python module mirrors the C++ factories; the class-based constructors are +removed: + +| 0.3 | 0.4 | +|---|---| +| `pcms.LagrangeFunctionSpace.from_mesh(mesh, order, n, csys, backend=...)` | `pcms.create_lagrange_space(pcms.backend.omega_h.create_discretization(mesh), order, n, csys, implementation=pcms.LagrangeImplementation.X)` | +| `pcms.LagrangeFunctionSpace.from_uniform_grid(grid, n, csys, order)` | `pcms.create_lagrange_space(pcms.create_uniform_grid_discretization(grid), order, n, csys)` | +| `pcms.PolynomialReconstructionFunctionSpace.create(coords, opts)` | `pcms.create_polynomial_reconstruction_space(coords, opts)` | +| `pcms.PolynomialReconstructionFunctionSpace.from_mesh(mesh, dim, csys, opts)` | `pcms.create_polynomial_reconstruction_space(pcms.backend.omega_h.create_discretization(mesh), dim, csys, opts)` | +| `pcms.OmegaHConservativeProjection(src, tgt, ...)` | `pcms.create_conservative_projection(src, tgt, ...)` | +| `pcms.OmegaHControlVariateProjection(src, tgt, ...)` | `pcms.create_control_variate_projection(src, tgt, ...)` | +| `space.mesh()` | `pcms.backend.omega_h.get_mesh(space.get_discretization())` | +| `pcms.create_uniform_grid_binary_field(mesh, divs)` | `pcms.backend.omega_h.create_uniform_grid_binary_field(mesh, divs)` | +| `pcms.create_uniform_grid_from_mesh(mesh, divs)` | `pcms.backend.omega_h.create_uniform_grid_from_mesh(mesh, divs)` | +| `pcms.map_entity_field_to_vertices_{average,mls}(mesh, ...)` | `pcms.backend.omega_h.map_entity_field_to_vertices_{average,mls}(mesh, ...)` | +| `pcms.compute_entity_centroids(mesh, dim)`, `pcms.compute_entity_centroids_few(mesh, dim)` | `pcms.backend.omega_h.compute_entity_centroids(mesh, dim)` | + +`tools/reorg/python_api_names.py` (run by `migrate-pcms.sh`) rewrites these +calls. + +## Porting open pull requests + +A pull request written against 0.3 is ported with a merge and the scripts +that made the reorganization (all are idempotent): + +1. Bring the branch up to date with the last `develop` commit before the + reorganization (c33f816c) and resolve those conflicts as usual. +2. Merge the reorganization. In conflicting C++, Python and Markdown files + keep the branch's side of each conflicting hunk (steps 3 and 4 re-apply + the reorganization's changes to them); git applies the branch's edits to + renamed and moved files: + + ```sh + git merge -X find-renames + for f in $(git diff --name-only --diff-filter=U -- '*.cpp' '*.hpp' '*.h' '*.py' '*.md'); do + # only files changed on both sides; a file one side deleted or moved + # (modify/delete) is left for the by-hand step + [ "$(git ls-files -u -- "$f" | wc -l)" -eq 3 ] || continue + git show :2:$f > $f.ours; git show :1:$f > $f.base; git show :3:$f > $f.theirs + git merge-file --ours $f.ours $f.base $f.theirs && mv $f.ours $f && rm $f.base $f.theirs && git add $f + done + ``` + + Resolve the remaining conflicts by hand (CMake lists and modify/delete + conflicts, see below), then + commit the merge. Do not use `git merge -X ours` for the whole merge: in + CMake files it silently drops the reorganization's changes. + +3. After committing the merge, re-apply the namespace changes and keep them + only in the files that carry the branch's changes (those that differ from + the merged `develop`, `HEAD^2`): + + ```sh + for b in xgc mfem omega_h_meshfields point_cloud uniform_grid omega_h; do + tools/reorg/backend_namespace.py $b tools/reorg/namespaces/$b.txt; done + for l in utility discretization localization field transfer coupler; do + tools/reorg/sublib_namespace.py $l tools/reorg/namespaces/sublib-$l.txt \ + tools/reorg/namespaces/sublib-$l-files.txt; done + git diff --name-only | grep -vxF -f <(git diff --name-only HEAD^2 HEAD) | xargs -r git checkout -- + ``` + +4. Migrate includes and names in the branch's files, and format them: + + ```sh + tools/migrate-pcms.sh --in-tree $(git diff --name-only --diff-filter=d HEAD^2) + clang-format -i $(git diff --name-only --diff-filter=d HEAD^2 | grep -E '\.(cpp|hpp|h)$') + ``` + + `--in-tree` rewrites private headers and internal names to their new + locations instead of reporting them. + +What is left by hand: + +- CMake source lists: keep the reorganization's list and add the branch's + new files. +- New headers: name them `.hpp`, decide public (`include/pcms//`) or + private (next to the sources), and list them accordingly. +- Files the reorganization rewrote beyond rename detection (git reports a + modify/delete conflict): re-apply the branch's hunks to the new file, or + delete it if the branch deleted it. +- New or renamed files in a sub-library or backend directory: before step 3, + add them to `tools/reorg/namespaces/sublib--files.txt` (or the + backend's list), remove the names they replace, and add the namespace-scope + names they declare to `sublib-.txt`, so that step 3 moves them into + `pcms::` with the rest of the library. + +## C and Fortran APIs + +Unchanged, except that the C headers are installed in `include/pcms/capi/` +and the installed include directory is `include` (include them as +`pcms/capi/.h`, as the build tree already required). diff --git a/cdash/nightly.cmake b/cdash/nightly.cmake index c53abe9c9..937324c31 100644 --- a/cdash/nightly.cmake +++ b/cdash/nightly.cmake @@ -185,7 +185,7 @@ SET(CONFIGURE_OPTIONS "-DCMAKE_C_COMPILER=mpicc" "-DPCMS_TIMEOUT=100" "-DPCMS_ENABLE_PETSC=ON" - "-DPETSC_LINK_STATIC=ON" + "-DPCMS_PETSC_LINK_STATIC=ON" "-DPETSC_DIR=${CTEST_DASHBOARD_ROOT}/petsc" "-DPETSC_ARCH=cuda-kokkos" "-Dredev_DIR=${CTEST_DASHBOARD_ROOT}/build-redev/install/lib64/cmake/redev" diff --git a/cmake/FindPETSc.cmake b/cmake/FindPETSc.cmake index e54c68c59..96293cb24 100644 --- a/cmake/FindPETSc.cmake +++ b/cmake/FindPETSc.cmake @@ -24,7 +24,7 @@ endif() # note, there are a number of additional properties that # can be extracted / set on a target. We just do the basic # set for now. See: https://cmake.org/cmake/help/latest/module/FindPkgConfig.html -if(PETSC_LINK_STATIC) +if(PCMS_PETSC_LINK_STATIC) set(PETSC_LIBRARIES ${_petsc_STATIC_LIBRARIES}) set(PETSC_INCLUDE_DIRS ${_petsc_STATIC_INCLUDE_DIRS}) set(PETSC_LIBRARY_DIRS ${_petsc_STATIC_LIBRARY_DIRS}) diff --git a/cmake/PcmsRenamedOptions.cmake b/cmake/PcmsRenamedOptions.cmake new file mode 100644 index 000000000..b80220134 --- /dev/null +++ b/cmake/PcmsRenamedOptions.cmake @@ -0,0 +1,26 @@ +# Options renamed in PCMS 0.4. For one release the old names are still +# honored: a value given under the old name is copied to the new name, with a +# deprecation message. Remove this file in the release after 0.4. + +# pcms_renamed_option( ) +# If is set (cache or -D), store its value in the cache under +# and drop from the cache. If both are set to different values, +# wins and a warning is printed. Must be called before option( ...). +function(pcms_renamed_option old new) + if(NOT DEFINED ${old}) + return() + endif() + if(DEFINED ${new} AND NOT "${${new}}" STREQUAL "${${old}}") + message(WARNING "Both ${old} (deprecated) and ${new} are set; " + "using ${new}=${${new}}.") + else() + message(DEPRECATION "${old} is deprecated and will be removed in the next " + "release; use ${new} instead.") + set(${new} "${${old}}" CACHE BOOL "" FORCE) + endif() + unset(${old} CACHE) +endfunction() + +pcms_renamed_option(PCMS_ENABLE_Python PCMS_ENABLE_PYTHON) +pcms_renamed_option(PCMS_ENABLE_Fortran PCMS_ENABLE_FORTRAN) +pcms_renamed_option(PETSC_LINK_STATIC PCMS_PETSC_LINK_STATIC) diff --git a/config.cmake.in b/config.cmake.in index 347c22384..aa28395da 100644 --- a/config.cmake.in +++ b/config.cmake.in @@ -5,14 +5,19 @@ include(CMakeFindDependencyMacro) # this will let us find any installed FindXXX.cmake e.g., petsc / gmsh list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") -find_dependency(redev CONFIG HINTS @redev_DIR@) -find_dependency(Kokkos CONFIG HINTS @Kokkos_DIR@) -find_dependency(KokkosKernels CONFIG HINTS @KokkosKernels_DIR@) -find_dependency(ADIOS2 CONFIG HINTS @ADIOS2_DIR@) +if(@PCMS_ENABLE_COUPLER@) + find_dependency(redev CONFIG) +endif() +find_dependency(Kokkos CONFIG) +find_dependency(KokkosKernels CONFIG) +if(@PCMS_ENABLE_COUPLER@) + find_dependency(ADIOS2 CONFIG) +endif() +find_dependency(perfstubs CONFIG) find_dependency(MPI) if(@PCMS_ENABLE_MESHFIELDS@) - find_dependency(meshfields CONFIG HINTS @meshfields_DIR@) + find_dependency(meshfields CONFIG) endif() if(@PCMS_ENABLE_PETSC@) @@ -26,11 +31,11 @@ if(@PCMS_ENABLE_PETSC@) endif() if(@PCMS_ENABLE_OMEGA_H@) - find_dependency(Omega_h CONFIG HINTS @Omega_h_DIR@) + find_dependency(Omega_h CONFIG) endif() if(@PCMS_ENABLE_MFEM@) - find_dependency(MFEM CONFIG HINTS @MFEM_DIR@) + find_dependency(MFEM CONFIG) endif() include("${CMAKE_CURRENT_LIST_DIR}/pcms_utility-targets.cmake") @@ -40,22 +45,29 @@ endif() include("${CMAKE_CURRENT_LIST_DIR}/pcms_discretization-targets.cmake") include("${CMAKE_CURRENT_LIST_DIR}/pcms_localization-targets.cmake") include("${CMAKE_CURRENT_LIST_DIR}/pcms_field-targets.cmake") -include("${CMAKE_CURRENT_LIST_DIR}/pcms_coupler-targets.cmake") -include("${CMAKE_CURRENT_LIST_DIR}/pcms_core-targets.cmake") +if(@PCMS_ENABLE_COUPLER@) + include("${CMAKE_CURRENT_LIST_DIR}/pcms_coupler-targets.cmake") +endif() include("${CMAKE_CURRENT_LIST_DIR}/pcms_transfer-targets.cmake") if(@PCMS_ENABLE_C@) - include("${CMAKE_CURRENT_LIST_DIR}/pcms_capi_core-targets.cmake") + if(@PCMS_ENABLE_COUPLER@) + include("${CMAKE_CURRENT_LIST_DIR}/pcms_capi_core-targets.cmake") + endif() include("${CMAKE_CURRENT_LIST_DIR}/pcms_capi_transfer-targets.cmake") include("${CMAKE_CURRENT_LIST_DIR}/pcms_capi-targets.cmake") endif() -if(@PCMS_ENABLE_Fortran@) - include("${CMAKE_CURRENT_LIST_DIR}/pcms_fortranapi_core-targets.cmake") +if(@PCMS_ENABLE_FORTRAN@) + if(@PCMS_ENABLE_COUPLER@) + include("${CMAKE_CURRENT_LIST_DIR}/pcms_fortranapi_core-targets.cmake") + endif() include("${CMAKE_CURRENT_LIST_DIR}/pcms_fortranapi_transfer-targets.cmake") include("${CMAKE_CURRENT_LIST_DIR}/pcms_fortranapi-targets.cmake") endif() include("${CMAKE_CURRENT_LIST_DIR}/pcms-targets.cmake") +# deprecated pcms::core links pcms::pcms, so it is loaded after it +include("${CMAKE_CURRENT_LIST_DIR}/pcms_core-targets.cmake") # must be called at the end of the config file check_required_components(pcms) diff --git a/docs/conf.py b/docs/conf.py index 139a20b15..e76b8ab6d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -68,7 +68,7 @@ except ImportError: logger.warning( "the pcms Python module is not importable; the Python API page will " - "be empty. Build PCMS with -DPCMS_ENABLE_Python=ON and add it to " + "be empty. Build PCMS with -DPCMS_ENABLE_PYTHON=ON and add it to " "PYTHONPATH." ) autodoc_mock_imports = ["pcms"] diff --git a/examples/coordinate-transformation-example/coordinate_transformations.cpp b/examples/coordinate-transformation-example/coordinate_transformations.cpp index ea2a923a8..5f46fe01c 100644 --- a/examples/coordinate-transformation-example/coordinate_transformations.cpp +++ b/examples/coordinate-transformation-example/coordinate_transformations.cpp @@ -11,11 +11,11 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include -#include +#include #include #include #include @@ -86,19 +86,19 @@ Real MaxErrorFromXYZ(const Field& b) /// theta in [0, 1.6]. Target: the Cartesian unit cube, which lies inside it. void BuildSpaces(Omega_h::Library& lib, Omega_h::Mesh& src_mesh, Omega_h::Mesh& tgt_mesh, - std::shared_ptr& src, - std::shared_ptr& tgt) + std::shared_ptr& src, + std::shared_ptr& tgt) { src_mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 2.0, 1.6, 1.1, 8, 8, 6, false); - src = LagrangeFunctionSpace::FromMesh( + src = pcms::field::LagrangeFunctionSpace::FromMesh( src_mesh, 1, 3, csys::CylindricalRThetaZ::Create(), "global", - LagrangeFunctionSpace::Backend::OmegaH); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); tgt_mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1.0, 1.0, 1.0, 4, 4, 4, false); - tgt = LagrangeFunctionSpace::FromMesh(tgt_mesh, 1, 3, - csys::Cartesian::Create(3), "global", - LagrangeFunctionSpace::Backend::OmegaH); + tgt = pcms::field::LagrangeFunctionSpace::FromMesh( + tgt_mesh, 1, 3, csys::Cartesian::Create(3), "global", + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); } void CaseA() @@ -130,7 +130,7 @@ void CaseB(Omega_h::Library& lib) { std::puts("(b) cylindrical points, Cartesian components on both sides"); Omega_h::Mesh src_mesh(&lib), tgt_mesh(&lib); - std::shared_ptr src, tgt; + std::shared_ptr src, tgt; BuildSpaces(lib, src_mesh, tgt_mesh, src, tgt); // A borrowed basis: the space's points are (r, theta, z), but the field's @@ -160,7 +160,7 @@ void CaseC(Omega_h::Library& lib) { std::puts("(c) cylindrical points and components -> Cartesian"); Omega_h::Mesh src_mesh(&lib), tgt_mesh(&lib); - std::shared_ptr src, tgt; + std::shared_ptr src, tgt; BuildSpaces(lib, src_mesh, tgt_mesh, src, tgt); // B = r e_r + z e_z in physical cylindrical components, which is (x, y, z) diff --git a/examples/external-usage-example/CMakeLists.txt b/examples/external-usage-example/CMakeLists.txt index 4b96f046d..2122fa0fe 100644 --- a/examples/external-usage-example/CMakeLists.txt +++ b/examples/external-usage-example/CMakeLists.txt @@ -3,7 +3,7 @@ # with an external project. # ############################################################################## -cmake_minimum_required(VERSION 3.19) +cmake_minimum_required(VERSION 3.23) project(pcms_installation_test) list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") @@ -16,5 +16,5 @@ find_package(pcms REQUIRED) add_executable(pcms_test main.cpp) # Link the pcms library to the executable Other target names cound be found in -# your installation's /lib64/cmake/pcms/pcms-targets.cmake +# your installation's /lib/cmake/pcms/pcms-targets.cmake target_link_libraries(pcms_test PUBLIC pcms::pcms) diff --git a/examples/external-usage-example/main.cpp b/examples/external-usage-example/main.cpp index 3af974b30..f2efb7b03 100644 --- a/examples/external-usage-example/main.cpp +++ b/examples/external-usage-example/main.cpp @@ -1,9 +1,61 @@ -#include -#include +// Uses PCMS through its installed public headers only: builds two Lagrange +// spaces on uniform grids, interpolates a constant field from one to the +// other, and checks the result. It also includes a C API header to check that +// the installed C headers are usable. + +#include #include -int main() + +#include +#include + +#include +#include +#include + +int main(int argc, char** argv) { - std::cout << "Testing PCMS dependency export..." << std::endl; - pcms::printInfo("Dependency test successful!\n"); - return 0; + MPI_Init(&argc, &argv); + int mismatches = 0; + { + Kokkos::ScopeGuard kokkos(argc, argv); + + // Two uniform grids over the unit square. + const pcms::UniformGrid<2> coarse{ + .edge_length = {1.0, 1.0}, .bot_left = {0.0, 0.0}, .divisions = {4, 4}}; + const pcms::UniformGrid<2> fine{ + .edge_length = {1.0, 1.0}, .bot_left = {0.0, 0.0}, .divisions = {9, 7}}; + const auto cartesian = pcms::csys::Cartesian::Create(2); + + auto source_space = pcms::CreateLagrangeSpace( + pcms::CreateUniformGridDiscretization(coarse), 1, 1, cartesian); + auto target_space = pcms::CreateLagrangeSpace( + pcms::CreateUniformGridDiscretization(fine), 1, 1, cartesian); + + auto source = source_space->CreateFunction("source"); + auto target = target_space->CreateFunction("target"); + + // A constant field is reproduced exactly by linear interpolation. + const pcms::Real value = 2.5; + const auto num_source = + source.GetLayout().GetDOFHolderCoordinates().GetValues().extent(0); + std::vector values(num_source, value); + source.SetDOFHolderDataUncheckedHost( + pcms::Rank2View(values.data(), + num_source, 1)); + + pcms::Interpolator interpolate(*source_space, *target_space); + interpolate.Apply(source, target); + + const auto result = target.GetDOFHolderDataHost().GetValues(); + for (std::size_t i = 0; i < result.extent(0); ++i) { + if (std::abs(result.data_handle()[i] - value) > 1e-12) { + ++mismatches; + } + } + pcms::printInfo("interpolated %d values, %d mismatches\n", + static_cast(result.extent(0)), mismatches); + } + MPI_Finalize(); + return mismatches == 0 ? 0 : 1; } diff --git a/examples/python-api-example/coordinate_transformations.py b/examples/python-api-example/coordinate_transformations.py index 4f19ee920..d82aebaaa 100644 --- a/examples/python-api-example/coordinate_transformations.py +++ b/examples/python-api-example/coordinate_transformations.py @@ -42,14 +42,20 @@ def build_spaces(world): it.""" src_mesh = omega_h.build_box(world, omega_h.Family.SIMPLEX, 2.0, 1.6, 1.1, 8, 8, 6, False) - src = pcms.LagrangeFunctionSpace.from_mesh( - src_mesh, 1, 3, pcms.csys.CylindricalRThetaZ.create(), - backend=pcms.LagrangeFunctionSpace.Backend.OmegaH) + src = pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(src_mesh), + 1, + 3, + pcms.csys.CylindricalRThetaZ.create(), + implementation=pcms.LagrangeImplementation.OmegaH) tgt_mesh = omega_h.build_box(world, omega_h.Family.SIMPLEX, 1.0, 1.0, 1.0, 4, 4, 4, False) - tgt = pcms.LagrangeFunctionSpace.from_mesh( - tgt_mesh, 1, 3, pcms.csys.Cartesian.create(3), - backend=pcms.LagrangeFunctionSpace.Backend.OmegaH) + tgt = pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(tgt_mesh), + 1, + 3, + pcms.csys.Cartesian.create(3), + implementation=pcms.LagrangeImplementation.OmegaH) return src, tgt diff --git a/examples/python-api-example/example_conservative_transfer.py b/examples/python-api-example/example_conservative_transfer.py index 4b8ed9d2b..644a9a2d3 100644 --- a/examples/python-api-example/example_conservative_transfer.py +++ b/examples/python-api-example/example_conservative_transfer.py @@ -188,10 +188,11 @@ def main(plot_path=None): # The conservative-projection operators require the native Omega_h # Lagrange backend (not the default MeshFields layout). - source_space = pcms.LagrangeFunctionSpace.from_mesh( - source_mesh, 1, 1, - backend=pcms.LagrangeFunctionSpace.Backend.OmegaH, - ) + source_space = pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(source_mesh), + 1, + 1, + implementation=pcms.LagrangeImplementation.OmegaH) source_field = evaluate_function_onto_field(source_space, source_function) source_integral = integral_of_field(source_mesh, source_field) @@ -204,10 +205,11 @@ def main(plot_path=None): print(f"\nTarget mesh : {target_mesh.nverts()} verts, " f"{target_mesh.nelems()} elems (read from {target_path})") - target_space = pcms.LagrangeFunctionSpace.from_mesh( - target_mesh, 1, 1, - backend=pcms.LagrangeFunctionSpace.Backend.OmegaH, - ) + target_space = pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(target_mesh), + 1, + 1, + implementation=pcms.LagrangeImplementation.OmegaH) # Analytic reference values at the target DOF holders. target_template = target_space.create_function() @@ -220,9 +222,9 @@ def main(plot_path=None): # 3a. Mesh-intersection conservative projection. mi_target = target_space.create_function() - mesh_intersection = pcms.OmegaHConservativeProjection( - source_space, target_space - ) + mesh_intersection = pcms.create_conservative_projection( + source_space, + target_space) mesh_intersection.apply(source_field, mi_target) report("mesh intersection (exact quadrature)", mi_target, target_mesh, target_coords, reference_values, source_integral) @@ -232,23 +234,22 @@ def main(plot_path=None): # integral is still conserved exactly, but the max nodal error # grows relative to the consistent mass matrix. lumped_target = target_space.create_function() - lumped_projection = pcms.OmegaHConservativeProjection( - source_space, target_space, - mass_matrix_type=pcms.MassMatrixType.Lumped, - ) + lumped_projection = pcms.create_conservative_projection( + source_space, + target_space, + mass_matrix_type=pcms.MassMatrixType.Lumped) lumped_projection.apply(source_field, lumped_target) report("mesh intersection (lumped mass)", lumped_target, target_mesh, target_coords, reference_values, source_integral) # 3c. Monte Carlo (control-variate) conservative projection. mc_target = target_space.create_function() - monte_carlo = pcms.OmegaHControlVariateProjection( + monte_carlo = pcms.create_control_variate_projection( source_space, target_space, samples_per_element=64, sampling=pcms.MonteCarloSampling.UniformRandom, - seed=8675309, - ) + seed=8675309) monte_carlo.apply(source_field, mc_target) report("Monte Carlo (control variate, UniformRandom)", mc_target, target_mesh, target_coords, reference_values, source_integral) @@ -260,18 +261,19 @@ def main(plot_path=None): print("\nMixed-order mesh-intersection projections:") # 4a. P1 source -> P0 target (project the linear field to cell averages). - target_p0_space = pcms.LagrangeFunctionSpace.from_mesh( - target_mesh, 0, 1, - backend=pcms.LagrangeFunctionSpace.Backend.OmegaH, - ) + target_p0_space = pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(target_mesh), + 0, + 1, + implementation=pcms.LagrangeImplementation.OmegaH) p1_to_p0 = target_p0_space.create_function() # Analytic reference at the P0 DOF holders (element centroids). p0_coords = (p1_to_p0.get_layout() .get_dof_holder_coordinates().get_values()) p0_reference = source_function(p0_coords[:, 0], p0_coords[:, 1]) - proj_p1_p0 = pcms.OmegaHConservativeProjection( - source_space, target_p0_space - ) + proj_p1_p0 = pcms.create_conservative_projection( + source_space, + target_p0_space) proj_p1_p0.apply(source_field, p1_to_p0) report("P1 -> P0 (cell averages)", p1_to_p0, target_mesh, p0_coords, p0_reference, source_integral, @@ -279,17 +281,18 @@ def main(plot_path=None): # 4b. P0 source -> P1 target. Build a P0 source field by sampling the # analytic function at the source element centroids. - source_p0_space = pcms.LagrangeFunctionSpace.from_mesh( - source_mesh, 0, 1, - backend=pcms.LagrangeFunctionSpace.Backend.OmegaH, - ) + source_p0_space = pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(source_mesh), + 0, + 1, + implementation=pcms.LagrangeImplementation.OmegaH) source_p0_field = evaluate_function_onto_field(source_p0_space, source_function) source_p0_integral = integral_of_p0_field(source_mesh, source_p0_field) p0_to_p1 = target_space.create_function() - proj_p0_p1 = pcms.OmegaHConservativeProjection( - source_p0_space, target_space - ) + proj_p0_p1 = pcms.create_conservative_projection( + source_p0_space, + target_space) proj_p0_p1.apply(source_p0_field, p0_to_p1) report("P0 -> P1", p0_to_p1, target_mesh, target_coords, reference_values, source_p0_integral) diff --git a/examples/python-api-example/flow_example.py b/examples/python-api-example/flow_example.py index 8af16de2d..830d1fb87 100644 --- a/examples/python-api-example/flow_example.py +++ b/examples/python-api-example/flow_example.py @@ -34,14 +34,14 @@ def demonstrate_face_field_transfer(mesh): print(f"Face field: min={face_field_values.min():.6f}, max={face_field_values.max():.6f}, mean={face_field_values.mean():.6f}") # Use the C++ implementation from pcms Python API - # vertex_field_values = pcms.map_entity_field_to_vertices_mls( + # vertex_field_values = pcms.backend.omega_h.map_entity_field_to_vertices_mls( # mesh, # face_field_values, # face_dim, # interp_degree=2, # ) # Alternative method (simple averaging): - vertex_field_values = pcms.map_entity_field_to_vertices_average( + vertex_field_values = pcms.backend.omega_h.map_entity_field_to_vertices_average( mesh, face_field_values, face_dim ) print( @@ -50,17 +50,19 @@ def demonstrate_face_field_transfer(mesh): f"mean={vertex_field_values.mean():.6f}" ) - omega_h_factory = pcms.LagrangeFunctionSpace.from_mesh( - mesh, 1, 1 - ) + omega_h_factory = pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(mesh), + 1, + 1) omega_h_field = omega_h_factory.create_function() omega_h_field.set_dof_holder_data(vertex_field_values) divisions = [1000, 500] - grid = pcms.create_uniform_grid_from_mesh(mesh, divisions) - ug_factory = pcms.LagrangeFunctionSpace.from_uniform_grid( - grid, 1 - ) + grid = pcms.backend.omega_h.create_uniform_grid_from_mesh(mesh, divisions) + ug_factory = pcms.create_lagrange_space( + pcms.create_uniform_grid_discretization(grid), + 1, + 1) ug_field = ug_factory.create_function() print(f"Interpolating field from OmegaH mesh to uniform grid...") diff --git a/include/pcms/backends/mfem/mfem.hpp b/include/pcms/backends/mfem/mfem.hpp new file mode 100644 index 000000000..61c7aeedf --- /dev/null +++ b/include/pcms/backends/mfem/mfem.hpp @@ -0,0 +1,36 @@ +#ifndef PCMS_BACKENDS_MFEM_MFEM_HPP +#define PCMS_BACKENDS_MFEM_MFEM_HPP + +// Public entry points of the MFEM backend: wrap MFEM grid functions in place. + +#include "pcms/field/field_factory.hpp" +#include "pcms/utility/coordinate_system.hpp" +#include "pcms/utility/memory_spaces.hpp" + +#include +#include + +#include +#include + +namespace pcms::backend::mfem +{ + +/// Field factory for order-1 H1 (vertex) fields of pfes on pmesh whose values +/// live in gf (not copied). The MFEM objects are borrowed and must outlive +/// the factory and its fields. layout_name identifies the layout in the +/// coupler. +std::shared_ptr CreateFieldFactory( + ::mfem::ParMesh& pmesh, ::mfem::ParFiniteElementSpace& pfes, + ::mfem::ParGridFunction& gf, + std::shared_ptr coordinate_system, + std::string layout_name = ""); + +/// Per-vertex overlap mask (true where a vertex belongs to an element with +/// the given attribute), for ApplicationComm::SetLayoutOverlapMask. +Kokkos::View OverlapMaskFromAttribute( + ::mfem::ParMesh& pmesh, int attribute); + +} // namespace pcms::backend::mfem + +#endif // PCMS_BACKENDS_MFEM_MFEM_HPP diff --git a/include/pcms/backends/omega_h/omega_h.hpp b/include/pcms/backends/omega_h/omega_h.hpp new file mode 100644 index 000000000..1c3b2a452 --- /dev/null +++ b/include/pcms/backends/omega_h/omega_h.hpp @@ -0,0 +1,110 @@ +#ifndef PCMS_BACKENDS_OMEGA_H_OMEGA_H_HPP +#define PCMS_BACKENDS_OMEGA_H_OMEGA_H_HPP + +// Public entry points of the Omega_h backend: build PCMS objects from an +// Omega_h mesh. This header (and only backend headers) may use Omega_h types. + +#include "pcms/discretization/discretization.hpp" +#include "pcms/field/field.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/memory_spaces.hpp" +#include "pcms/utility/types.hpp" +#include "pcms/utility/uniform_grid.hpp" + +#include +#include +#include +#include + +#include +#include +#include + +namespace pcms::backend::omega_h +{ + +/// Discretization on an Omega_h mesh. The mesh is borrowed and must outlive +/// the discretization and everything created from it. global_id_name names +/// the tag holding global entity ids. +std::shared_ptr CreateDiscretization( + Omega_h::Mesh& mesh, std::string global_id_name = "global"); + +/// As above, with per-vertex ownership given by owned_mask (1 = owned) +/// instead of the mesh's partition. +std::shared_ptr CreateDiscretization( + Omega_h::Mesh& mesh, Omega_h::Read owned_mask, + std::string global_id_name = "global"); + +/// The Omega_h mesh of a discretization created by CreateDiscretization. +/// Throws pcms_error if the discretization is not Omega_h-based. +Omega_h::Mesh& GetMesh(const Discretization& discretization); + +/// 0/1 field on the vertices of a 2D uniform grid marking the vertices that +/// lie inside mesh. The grid is given, or covers the mesh's bounding box with +/// the given number of cells per axis. +Field CreateUniformGridBinaryField(Omega_h::Mesh& mesh, + const UniformGrid<2>& grid); +Field CreateUniformGridBinaryField(Omega_h::Mesh& mesh, + std::array divisions); + +/// Rank-2 view of an Omega_h array that holds dim values per entity (e.g. +/// mesh.coords()), without copying. +template +auto MakeConstRank2View(Omega_h::Read array, int dim) +{ + // Omega_h arrays are layout_right 1D arrays + return Rank2View( + array.data(), array.size() / dim, dim); +} + +/// Uniform grid covering the bounding box of mesh with divisions[i] cells +/// along axis i. +template +UniformGrid CreateUniformGridFromMesh(Omega_h::Mesh& mesh, + const std::array& divisions) +{ + auto bbox = Omega_h::get_bounding_box(&mesh); + Kokkos::Array edge_length; + Kokkos::Array bot_left; + Kokkos::Array divs; + for (unsigned i = 0; i < dim; ++i) { + bot_left[i] = bbox.min[i]; + edge_length[i] = bbox.max[i] - bbox.min[i]; + divs[i] = divisions[i]; + } + return UniformGrid{ + .edge_length = edge_length, .bot_left = bot_left, .divisions = divs}; +} + +/// Uniform grid covering the bounding box of mesh with cells_per_dim cells +/// along every axis. +template +UniformGrid CreateUniformGridFromMesh(Omega_h::Mesh& mesh, + LO cells_per_dim) +{ + std::array divisions; + for (unsigned i = 0; i < dim; ++i) + divisions[i] = cells_per_dim; + return CreateUniformGridFromMesh(mesh, divisions); +} + +/// Host mask (true where mask[i] != 0) for OverlapMask(size, mask). +inline Kokkos::View OverlapMaskFromArray( + Omega_h::HostRead mask) +{ + Kokkos::View out("overlap_info", mask.size()); + for (Omega_h::LO i = 0; i < mask.size(); ++i) { + out(i) = static_cast(mask[i]); + } + return out; +} + +inline Kokkos::View OverlapMaskFromArray( + Omega_h::Read mask) +{ + return OverlapMaskFromArray(Omega_h::HostRead(mask)); +} + +} // namespace pcms::backend::omega_h + +#endif // PCMS_BACKENDS_OMEGA_H_OMEGA_H_HPP diff --git a/src/pcms/discretization/discretization/xgc_reverse_classification.h b/include/pcms/backends/xgc/reverse_classification.hpp similarity index 85% rename from src/pcms/discretization/discretization/xgc_reverse_classification.h rename to include/pcms/backends/xgc/reverse_classification.hpp index b451782ac..9b9a9ace6 100644 --- a/src/pcms/discretization/discretization/xgc_reverse_classification.h +++ b/include/pcms/backends/xgc/reverse_classification.hpp @@ -1,10 +1,10 @@ -#ifndef PCMS_DISCRETIZATION_XGC_REVERSE_CLASSIFICATION_H -#define PCMS_DISCRETIZATION_XGC_REVERSE_CLASSIFICATION_H +#ifndef PCMS_BACKENDS_XGC_REVERSE_CLASSIFICATION_HPP +#define PCMS_BACKENDS_XGC_REVERSE_CLASSIFICATION_HPP -#include "pcms/configuration.h" -#include "pcms/utility/arrays.h" -#include "pcms/utility/memory_spaces.h" -#include "pcms/utility/types.h" +#include "pcms/configuration.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/memory_spaces.hpp" +#include "pcms/utility/types.hpp" #include #include @@ -13,10 +13,10 @@ #ifdef PCMS_ENABLE_OMEGA_H #include -#include "pcms/utility/assert.h" +#include "pcms/utility/assert.hpp" #endif -namespace pcms +namespace pcms::backend::xgc { struct DimID @@ -29,15 +29,15 @@ struct DimID } }; -} // namespace pcms +} // namespace pcms::backend::xgc namespace std { template <> -struct hash +struct hash { - std::size_t operator()(const pcms::DimID& key) const noexcept + std::size_t operator()(const pcms::backend::xgc::DimID& key) const noexcept { auto h1 = hash{}(key.dim); auto h2 = hash{}(key.id); @@ -48,7 +48,7 @@ struct hash } // namespace std -namespace pcms +namespace pcms::backend::xgc { /// /// This datastructure represents the reverse classification @@ -134,6 +134,6 @@ template #endif -} // namespace pcms +} // namespace pcms::backend::xgc -#endif // PCMS_DISCRETIZATION_XGC_REVERSE_CLASSIFICATION_H +#endif // PCMS_BACKENDS_XGC_REVERSE_CLASSIFICATION_HPP diff --git a/include/pcms/backends/xgc/xgc.hpp b/include/pcms/backends/xgc/xgc.hpp new file mode 100644 index 000000000..090d2e955 --- /dev/null +++ b/include/pcms/backends/xgc/xgc.hpp @@ -0,0 +1,41 @@ +#ifndef PCMS_BACKENDS_XGC_XGC_HPP +#define PCMS_BACKENDS_XGC_XGC_HPP + +// Public entry points of the XGC backend: wrap XGC's own field arrays. + +#include "pcms/backends/xgc/reverse_classification.hpp" +#include "pcms/field/field.hpp" +#include "pcms/field/field_factory.hpp" +#include "pcms/field/value_view.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/memory_spaces.hpp" +#include "pcms/utility/types.hpp" + +#include + +#include +#include + +namespace pcms::backend::xgc +{ + +/// Field factory for XGC fields on the plane described by +/// reverse_classification with num_plane_nodes nodes. layout_name identifies +/// the layout in the coupler. +std::shared_ptr CreateFieldFactory( + const ReverseClassificationVertex& reverse_classification, LO num_plane_nodes, + std::string layout_name = ""); + +/// Field named name whose values live in XGC's array data (not copied). +/// factory must come from CreateFieldFactory. plane_comm, if given, is the +/// communicator of the ranks sharing the plane. T is one of int8_t, int32_t, +/// int64_t, float, double. +template +Field CreateField(const FieldFactory& factory, std::string name, + Rank1View data, + MPI_Comm plane_comm = MPI_COMM_NULL, + ValueBasis basis = {}); + +} // namespace pcms::backend::xgc + +#endif // PCMS_BACKENDS_XGC_XGC_HPP diff --git a/src/pcms/capi/client.h b/include/pcms/capi/client.h similarity index 96% rename from src/pcms/capi/client.h rename to include/pcms/capi/client.h index b17a664f1..fb18b67e7 100644 --- a/src/pcms/capi/client.h +++ b/include/pcms/capi/client.h @@ -1,5 +1,5 @@ -#ifndef PCMS_COUPLING_CAPI_CLIENT_H -#define PCMS_COUPLING_CAPI_CLIENT_H +#ifndef PCMS_CAPI_CLIENT_H +#define PCMS_CAPI_CLIENT_H #include #include @@ -99,4 +99,4 @@ void pcms_end_receive_phase(PcmsClientHandle); } #endif -#endif // PCMS_COUPLING_CLIENT_H +#endif // PCMS_CAPI_CLIENT_H diff --git a/src/pcms/capi/interpolator.h b/include/pcms/capi/interpolator.h similarity index 98% rename from src/pcms/capi/interpolator.h rename to include/pcms/capi/interpolator.h index c557e1a29..96f862859 100644 --- a/src/pcms/capi/interpolator.h +++ b/include/pcms/capi/interpolator.h @@ -8,11 +8,11 @@ * hard-coded for RBF, Gaussian weight function. */ -#ifndef PCMS_INTERPOLATOR_CAPI_H -#define PCMS_INTERPOLATOR_CAPI_H +#ifndef PCMS_CAPI_INTERPOLATOR_H +#define PCMS_CAPI_INTERPOLATOR_H #include -#include "mesh.h" +#include "pcms/capi/mesh.h" #ifdef __cplusplus extern "C" { @@ -179,4 +179,4 @@ void pcms_interpolate(PcmsInterpolatorHandle interpolator, void* input, } #endif -#endif // PCMS_INTERPOLATOR_CAPI_H +#endif // PCMS_CAPI_INTERPOLATOR_H diff --git a/src/pcms/capi/kokkos.h b/include/pcms/capi/kokkos.h similarity index 56% rename from src/pcms/capi/kokkos.h rename to include/pcms/capi/kokkos.h index 3c0a4fad6..dadf30273 100644 --- a/src/pcms/capi/kokkos.h +++ b/include/pcms/capi/kokkos.h @@ -1,5 +1,5 @@ -#ifndef PCMS_SRC_PCMS_CAPI_KOKKOS_H -#define PCMS_SRC_PCMS_CAPI_KOKKOS_H +#ifndef PCMS_CAPI_KOKKOS_H +#define PCMS_CAPI_KOKKOS_H #ifdef __cplusplus extern "C" { @@ -12,4 +12,4 @@ void pcms_kokkos_finalize(); } #endif -#endif // PCMS_SRC_PCMS_CAPI_KOKKOS_H +#endif // PCMS_CAPI_KOKKOS_H diff --git a/src/pcms/capi/mesh.h b/include/pcms/capi/mesh.h similarity index 95% rename from src/pcms/capi/mesh.h rename to include/pcms/capi/mesh.h index cb138ed65..160d94b59 100644 --- a/src/pcms/capi/mesh.h +++ b/include/pcms/capi/mesh.h @@ -1,5 +1,5 @@ -#ifndef PCMS_OMEGA_H_MESH_CAPI_H -#define PCMS_OMEGA_H_MESH_CAPI_H +#ifndef PCMS_CAPI_MESH_H +#define PCMS_CAPI_MESH_H #ifdef __cplusplus extern "C" { @@ -75,4 +75,4 @@ void pcms_destroy_omega_h_library(PcmsOmegaHLibraryHandle oh_lib_handle); } #endif -#endif // PCMS_OMEGA_H_MESH_CAPI_H +#endif // PCMS_CAPI_MESH_H diff --git a/src/pcms/coupler/coupler.hpp b/include/pcms/coupler/coupler.hpp similarity index 86% rename from src/pcms/coupler/coupler.hpp rename to include/pcms/coupler/coupler.hpp index 7bdf23118..05e921160 100644 --- a/src/pcms/coupler/coupler.hpp +++ b/include/pcms/coupler/coupler.hpp @@ -1,17 +1,17 @@ -#ifndef COUPLER2_H_ -#define COUPLER2_H_ - -#include "pcms/coupler/coupler_types.h" -#include "pcms/field/field.h" -#include "pcms/field/field_layout.h" -#include "pcms/coupler/field_layout_communicator.h" -#include "pcms/coupler/field_communicator.hpp" -#include "pcms/coupler/field_exchange_planner.h" -#include "pcms/coupler/overlap_mask.h" -#include "pcms/utility/assert.h" -#include "pcms/utility/common.h" -#include "pcms/utility/profile.h" -#include "pcms/coupler/global_communicator.h" +#ifndef PCMS_COUPLER_COUPLER_HPP +#define PCMS_COUPLER_COUPLER_HPP + +#include "pcms/coupler/coupler_types.hpp" +#include "pcms/field/field.hpp" +#include "pcms/field/field_layout.hpp" +#include "pcms/coupler/detail/field_layout_communicator.hpp" +#include "pcms/coupler/detail/field_communicator.hpp" +#include "pcms/coupler/detail/field_exchange_planner.hpp" +#include "pcms/coupler/overlap_mask.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/detail/common.hpp" +#include "pcms/utility/detail/profile.hpp" +#include "pcms/coupler/detail/global_communicator.hpp" #include namespace pcms @@ -31,13 +31,13 @@ class GlobalDataInterface PCMS_FUNCTION_TIMER; } - void Send(redev::Mode mode = redev::Mode::Synchronous) + void Send(Mode mode = Mode::Synchronous) { PCMS_FUNCTION_TIMER; comm_.Send(data_, variable_name_, mode); } - void Receive(redev::Mode mode = redev::Mode::Synchronous) + void Receive(Mode mode = Mode::Synchronous) { PCMS_FUNCTION_TIMER; comm_.Receive(data_, variable_name_, mode); @@ -47,7 +47,7 @@ class GlobalDataInterface Rank1View data_; std::string variable_name_; MPI_Comm mpi_comm_; - GlobalCommunicator comm_; + pcms::coupler::GlobalCommunicator comm_; }; using GlobalDataVariant = std::variant, GlobalDataInterface, @@ -65,8 +65,8 @@ class FieldHandle { } - void Send(redev::Mode mode = redev::Mode::Synchronous) const; - void Receive(redev::Mode mode = redev::Mode::Synchronous) const; + void Send(Mode mode = Mode::Synchronous) const; + void Receive(Mode mode = Mode::Synchronous) const; [[nodiscard]] Field& GetField() const; private: @@ -81,8 +81,8 @@ class DataHandle : app_(app), name_(std::move(name)) { } - void Send(redev::Mode mode = redev::Mode::Synchronous) const; - void Receive(redev::Mode mode = redev::Mode::Synchronous) const; + void Send(Mode mode = Mode::Synchronous) const; + void Receive(Mode mode = Mode::Synchronous) const; [[nodiscard]] const std::string& GetName() const noexcept { return name_; } @@ -158,19 +158,17 @@ class ApplicationComm FunctionHandle AddFunction(Function&& function, bool participates = true); - void SendField(const std::string& name, - redev::Mode mode = redev::Mode::Synchronous) + void SendField(const std::string& name, Mode mode = Mode::Synchronous) { PCMS_FUNCTION_TIMER; PCMS_ALWAYS_ASSERT(InSendPhase()); - FieldCommunicator2Ptr& communicator = + pcms::coupler::FieldCommunicator2Ptr& communicator = detail::find_or_error(name, field_communicators_); std::visit( [mode](auto& field_communicator) { field_communicator->Send(mode); }, communicator); }; - void ReceiveField(const std::string& name, - redev::Mode mode = redev::Mode::Synchronous) + void ReceiveField(const std::string& name, Mode mode = Mode::Synchronous) { PCMS_FUNCTION_TIMER; PCMS_ALWAYS_ASSERT(InReceivePhase()); @@ -178,8 +176,7 @@ class ApplicationComm [mode](auto& field_communicator) { field_communicator->Receive(); }, detail::find_or_error(name, field_communicators_)); }; - void SendData(const std::string& name, - redev::Mode mode = redev::Mode::Synchronous) + void SendData(const std::string& name, Mode mode = Mode::Synchronous) { PCMS_FUNCTION_TIMER; PCMS_ALWAYS_ASSERT(InSendPhase()); @@ -188,8 +185,7 @@ class ApplicationComm detail::find_or_error(name, global_data_interfaces_)); } - void ReceiveData(const std::string& name, - redev::Mode mode = redev::Mode::Synchronous) + void ReceiveData(const std::string& name, Mode mode = Mode::Synchronous) { PCMS_FUNCTION_TIMER; PCMS_ALWAYS_ASSERT(InReceivePhase()); @@ -253,7 +249,7 @@ class ApplicationComm // Returns the communicator for `layout`, creating it (MPI split + overlap // mask lookup + planner) on first use and reusing it for any later // field/function whose layout has the same name. - FieldLayoutCommunicator& GetOrCreateLayoutCommunicator( + pcms::coupler::FieldLayoutCommunicator& GetOrCreateLayoutCommunicator( const FieldLayout& layout, bool participates); template @@ -264,13 +260,14 @@ class ApplicationComm redev::Channel channel_; std::map fields_; std::map functions_; - std::vector> + std::vector> owned_field_layout_communicators_; // map is used rather than unordered_map because we give pointers to the // internal data and rehash of unordered_map can cause pointer invalidation. // map is less cache friendly, but pointers are not invalidated. - std::map field_communicators_; - std::map> + std::map + field_communicators_; + std::map> field_layout_communicators_; std::map> layout_overlap_masks_; std::map global_data_interfaces_; @@ -292,14 +289,14 @@ DataHandle ApplicationComm::AddData(std::string name, } template -void DataHandle::Send(redev::Mode mode) const +void DataHandle::Send(Mode mode) const { PCMS_ALWAYS_ASSERT(app_ != nullptr); app_->SendData(name_, mode); } template -void DataHandle::Receive(redev::Mode mode) const +void DataHandle::Receive(Mode mode) const { PCMS_ALWAYS_ASSERT(app_ != nullptr); @@ -359,14 +356,14 @@ class CouplerComm } // namespace pcms template -void pcms::FieldHandle::Send(redev::Mode mode) const +void pcms::FieldHandle::Send(pcms::Mode mode) const { PCMS_ALWAYS_ASSERT(app_ != nullptr); app_->SendField(name_, mode); } template -void pcms::FieldHandle::Receive(redev::Mode mode) const +void pcms::FieldHandle::Receive(pcms::Mode mode) const { PCMS_ALWAYS_ASSERT(app_ != nullptr); app_->ReceiveField(name_, mode); @@ -411,11 +408,11 @@ void pcms::ApplicationComm::RegisterFieldCommunicator(Field& field_obj, "' cannot be exchanged: its values are not accessible " "through PCMS (the field data provides no DOFAccess)"); } - FieldLayoutCommunicator& layout_communicator = + pcms::coupler::FieldLayoutCommunicator& layout_communicator = GetOrCreateLayoutCommunicator(field_obj.GetLayout(), participates); - FieldCommunicator2Ptr field_communicator = - std::make_unique>(name, layout_communicator, - field_obj); + pcms::coupler::FieldCommunicator2Ptr field_communicator = + std::make_unique>( + name, layout_communicator, field_obj); auto [it, inserted] = field_communicators_.emplace(name, std::move(field_communicator)); if (!inserted) { @@ -470,4 +467,4 @@ pcms::FunctionHandle pcms::ApplicationComm::AddFunction( return FunctionHandle{this, std::move(name), std::move(space)}; } -#endif // COUPLER2_H_ +#endif // PCMS_COUPLER_COUPLER_HPP diff --git a/include/pcms/coupler/coupler_types.hpp b/include/pcms/coupler/coupler_types.hpp new file mode 100644 index 000000000..e100f61d7 --- /dev/null +++ b/include/pcms/coupler/coupler_types.hpp @@ -0,0 +1,29 @@ +#ifndef PCMS_COUPLER_COUPLER_TYPES_HPP +#define PCMS_COUPLER_COUPLER_TYPES_HPP + +#include + +namespace pcms +{ + +using ProcessType = redev::ProcessType; +/// Whether a send or receive completes before returning (Synchronous) or +/// is completed by the communication phase (Deferred). +enum class Mode +{ + Deferred, + Synchronous +}; + +namespace detail +{ +inline redev::Mode ToRedev(Mode mode) noexcept +{ + return mode == Mode::Deferred ? redev::Mode::Deferred + : redev::Mode::Synchronous; +} +} // namespace detail + +} // namespace pcms + +#endif // PCMS_COUPLER_COUPLER_TYPES_HPP diff --git a/src/pcms/coupler/field_communicator.hpp b/include/pcms/coupler/detail/field_communicator.hpp similarity index 74% rename from src/pcms/coupler/field_communicator.hpp rename to include/pcms/coupler/detail/field_communicator.hpp index 8dc8de534..b220d3b22 100644 --- a/src/pcms/coupler/field_communicator.hpp +++ b/include/pcms/coupler/detail/field_communicator.hpp @@ -1,18 +1,19 @@ -#ifndef FIELD_COMMUNICATOR2_H_ -#define FIELD_COMMUNICATOR2_H_ +#ifndef PCMS_COUPLER_DETAIL_FIELD_COMMUNICATOR_HPP +#define PCMS_COUPLER_DETAIL_FIELD_COMMUNICATOR_HPP -#include "pcms/coupler/field_layout_communicator.h" -#include "pcms/field/field.h" -#include "pcms/field/field_layout.h" -#include "pcms/coupler/field_serializer.h" -#include "pcms/utility/profile.h" -#include "pcms/utility/assert.h" -#include "pcms/utility/inclusive_scan.h" -#include "pcms/utility/arrays.h" +#include "pcms/coupler/coupler_types.hpp" +#include "pcms/coupler/detail/field_layout_communicator.hpp" +#include "pcms/field/field.hpp" +#include "pcms/field/field_layout.hpp" +#include "pcms/coupler/detail/field_serializer.hpp" +#include "pcms/utility/detail/profile.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/detail/inclusive_scan.hpp" +#include "pcms/utility/arrays.hpp" #include #include -namespace pcms +namespace pcms::coupler { template @@ -35,13 +36,13 @@ class FieldCommunicator layout_comm_.SetOutMessageLayout(comm_); } - void Send(redev::Mode mode = redev::Mode::Synchronous) + void Send(Mode mode = Mode::Synchronous) { PCMS_FUNCTION_TIMER; PCMS_ALWAYS_ASSERT(layout_comm_.GetChannel().InSendCommunicationPhase()); auto buffer = make_array_view(comm_buffer_); serializer_.Serialize(field_, buffer, layout_comm_.GetPermutationArray()); - comm_.Send(buffer.data_handle(), mode); + comm_.Send(buffer.data_handle(), detail::ToRedev(mode)); } void Receive() @@ -71,6 +72,6 @@ using FieldCommunicator2Ptr = std::variant, FieldCommunicator2PtrT, FieldCommunicator2PtrT, FieldCommunicator2PtrT, FieldCommunicator2PtrT>; -} // namespace pcms +} // namespace pcms::coupler -#endif // FIELD_COMMUNICATOR2_H_ +#endif // PCMS_COUPLER_DETAIL_FIELD_COMMUNICATOR_HPP diff --git a/src/pcms/coupler/field_exchange_planner.h b/include/pcms/coupler/detail/field_exchange_planner.hpp similarity index 82% rename from src/pcms/coupler/field_exchange_planner.h rename to include/pcms/coupler/detail/field_exchange_planner.hpp index 5e5ae29fe..38f35bdf0 100644 --- a/src/pcms/coupler/field_exchange_planner.h +++ b/include/pcms/coupler/detail/field_exchange_planner.hpp @@ -1,13 +1,13 @@ -#ifndef PCMS_FIELD_EXCHANGE_PLANNER_H -#define PCMS_FIELD_EXCHANGE_PLANNER_H +#ifndef PCMS_COUPLER_DETAIL_FIELD_EXCHANGE_PLANNER_HPP +#define PCMS_COUPLER_DETAIL_FIELD_EXCHANGE_PLANNER_HPP -#include "pcms/field/field_layout.h" -#include "pcms/utility/arrays.h" -#include "overlap_mask.h" +#include "pcms/field/field_layout.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/coupler/overlap_mask.hpp" #include #include -namespace pcms +namespace pcms::coupler { struct ExchangePlan @@ -56,5 +56,5 @@ class GenericFieldExchangePlanner : public FieldExchangePlanner Rank1View gid_message) const override; }; -} // namespace pcms -#endif // PCMS_FIELD_EXCHANGE_PLANNER_H +} // namespace pcms::coupler +#endif // PCMS_COUPLER_DETAIL_FIELD_EXCHANGE_PLANNER_HPP diff --git a/src/pcms/coupler/field_layout_communicator.h b/include/pcms/coupler/detail/field_layout_communicator.hpp similarity index 82% rename from src/pcms/coupler/field_layout_communicator.h rename to include/pcms/coupler/detail/field_layout_communicator.hpp index 68d3572ba..8827e5bbe 100644 --- a/src/pcms/coupler/field_layout_communicator.h +++ b/include/pcms/coupler/detail/field_layout_communicator.hpp @@ -1,15 +1,15 @@ -#ifndef FIELD_LAYOUT_COMMUNICATOR_H_ -#define FIELD_LAYOUT_COMMUNICATOR_H_ - -#include "pcms/field/field_layout.h" -#include "field_exchange_planner.h" -#include "overlap_mask.h" -#include "pcms/utility/profile.h" -#include "pcms/utility/arrays.h" +#ifndef PCMS_COUPLER_DETAIL_FIELD_LAYOUT_COMMUNICATOR_HPP +#define PCMS_COUPLER_DETAIL_FIELD_LAYOUT_COMMUNICATOR_HPP + +#include "pcms/field/field_layout.hpp" +#include "pcms/coupler/detail/field_exchange_planner.hpp" +#include "pcms/coupler/overlap_mask.hpp" +#include "pcms/utility/detail/profile.hpp" +#include "pcms/utility/arrays.hpp" #include #include -namespace pcms +namespace pcms::coupler { class FieldLayoutCommunicator @@ -76,6 +76,6 @@ class FieldLayoutCommunicator std::unique_ptr overlap_mask_; bool own_mpi_comm_ = false; }; -} // namespace pcms +} // namespace pcms::coupler -#endif // FIELD_LAYOUT_COMMUNICATOR_H_ +#endif // PCMS_COUPLER_DETAIL_FIELD_LAYOUT_COMMUNICATOR_HPP diff --git a/src/pcms/coupler/field_serializer.h b/include/pcms/coupler/detail/field_serializer.hpp similarity index 86% rename from src/pcms/coupler/field_serializer.h rename to include/pcms/coupler/detail/field_serializer.hpp index 883b61418..28c0b881b 100644 --- a/src/pcms/coupler/field_serializer.h +++ b/include/pcms/coupler/detail/field_serializer.hpp @@ -1,13 +1,13 @@ -#ifndef PCMS_FIELD_SERIALIZER_H -#define PCMS_FIELD_SERIALIZER_H +#ifndef PCMS_COUPLER_DETAIL_FIELD_SERIALIZER_HPP +#define PCMS_COUPLER_DETAIL_FIELD_SERIALIZER_HPP -#include "pcms/field/field.h" -#include "pcms/utility/arrays.h" -#include "pcms/utility/memory_spaces.h" -#include "pcms/utility/types.h" +#include "pcms/field/field.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/memory_spaces.hpp" +#include "pcms/utility/types.hpp" #include -namespace pcms +namespace pcms::coupler { // Packs a field's owned values into, and unpacks them from, an exchange @@ -66,6 +66,6 @@ class FieldSerializer } }; -} // namespace pcms +} // namespace pcms::coupler -#endif // PCMS_FIELD_SERIALIZER_H +#endif // PCMS_COUPLER_DETAIL_FIELD_SERIALIZER_HPP diff --git a/src/pcms/coupler/global_communicator.h b/include/pcms/coupler/detail/global_communicator.hpp similarity index 72% rename from src/pcms/coupler/global_communicator.h rename to include/pcms/coupler/detail/global_communicator.hpp index fc3bf3479..c3999f5fe 100644 --- a/src/pcms/coupler/global_communicator.h +++ b/include/pcms/coupler/detail/global_communicator.hpp @@ -1,11 +1,13 @@ -#ifndef PCMS_GLOBAL_COMMUNICATOR_H -#define PCMS_GLOBAL_COMMUNICATOR_H +#ifndef PCMS_COUPLER_DETAIL_GLOBAL_COMMUNICATOR_HPP +#define PCMS_COUPLER_DETAIL_GLOBAL_COMMUNICATOR_HPP #include -#include -#include -namespace pcms +#include +#include +#include +#include +#include +namespace pcms::coupler { -using redev::Mode; template struct GlobalCommunicator { @@ -31,7 +33,7 @@ struct GlobalCommunicator PCMS_ALWAYS_ASSERT(channel_.InSendCommunicationPhase()); auto msg_size = static_cast(msg.extent(0)); comm_.SetCommParams(VarName, msg_size); - comm_.Send(msg.data_handle(), mode); + comm_.Send(msg.data_handle(), detail::ToRedev(mode)); } void Receive(Rank1View destination, std::string VarName, Mode mode = Mode::Synchronous) @@ -40,7 +42,7 @@ struct GlobalCommunicator PCMS_ALWAYS_ASSERT(channel_.InReceiveCommunicationPhase()); auto msg_size = static_cast(destination.extent(0)); comm_.SetCommParams(VarName, msg_size); - comm_.Recv(destination.data_handle(), msg_size, mode); + comm_.Recv(destination.data_handle(), msg_size, detail::ToRedev(mode)); } private: @@ -49,5 +51,5 @@ struct GlobalCommunicator std::string name_; redev::BidirectionalComm comm_; }; -} // namespace pcms -#endif // PCMS_GLOBAL_COMMUNICATOR_H \ No newline at end of file +} // namespace pcms::coupler +#endif // PCMS_COUPLER_DETAIL_GLOBAL_COMMUNICATOR_HPP \ No newline at end of file diff --git a/src/pcms/coupler/overlap_mask.h b/include/pcms/coupler/overlap_mask.hpp similarity index 67% rename from src/pcms/coupler/overlap_mask.h rename to include/pcms/coupler/overlap_mask.hpp index 1a917abb4..825285258 100644 --- a/src/pcms/coupler/overlap_mask.h +++ b/include/pcms/coupler/overlap_mask.hpp @@ -1,10 +1,9 @@ -#ifndef PCMS_OVERLAP_MASK_H -#define PCMS_OVERLAP_MASK_H +#ifndef PCMS_COUPLER_OVERLAP_MASK_HPP +#define PCMS_COUPLER_OVERLAP_MASK_HPP -#include "pcms/field/field_layout.h" -#include "pcms/utility/arrays.h" -#include "pcms/utility/assert.h" -#include +#include "pcms/field/field_layout.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/assert.hpp" #include namespace pcms @@ -38,25 +37,6 @@ struct OverlapMask Kokkos::deep_copy(is_overlap_, is_overlap_host); } - // Construct from Omega_h host array - OverlapMask(size_t size, Omega_h::HostRead is_overlap_host) - : is_overlap_("overlap_info", size) - { - for (size_t i = 0; i < size; ++i) { - is_overlap_[i] = static_cast(is_overlap_host[i]); - } - } - - // Construct from Omega_h device array - OverlapMask(size_t size, Omega_h::Read is_overlap_device) - : is_overlap_("overlap_info", size) - { - auto is_overlap_host = Omega_h::HostRead(is_overlap_device); - for (size_t i = 0; i < size; ++i) { - is_overlap_[i] = static_cast(is_overlap_host[i]); - } - } - // Get the mask, evaluating the function against the layout if one was given Kokkos::View GetMask( const FieldLayout& layout) const @@ -78,4 +58,4 @@ struct OverlapMask } // namespace pcms -#endif // PCMS_OVERLAP_MASK_H +#endif // PCMS_COUPLER_OVERLAP_MASK_HPP diff --git a/include/pcms/discretization/discretization.hpp b/include/pcms/discretization/discretization.hpp new file mode 100644 index 000000000..00a595433 --- /dev/null +++ b/include/pcms/discretization/discretization.hpp @@ -0,0 +1,46 @@ +#ifndef PCMS_DISCRETIZATION_DISCRETIZATION_HPP +#define PCMS_DISCRETIZATION_DISCRETIZATION_HPP + +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/entity_types.hpp" +#include "pcms/utility/uniform_grid.hpp" + +#include + +namespace pcms +{ + +using ClassificationDimension = int8_t; +using ClassificationId = LO; + +class Discretization +{ +public: + virtual bool SameEntities(const Discretization& other) const noexcept = 0; + + virtual int GetDimension() const = 0; + + virtual LO GetNumEntities(int entity_dim) const = 0; + + virtual Rank1View + GetEntityClassificationDimensions(int entity_dim) const = 0; + + virtual Rank1View + GetEntityClassificationIds(int entity_dim) const = 0; + + virtual ~Discretization() noexcept = default; +}; + +/// Discretization of a uniform (structured) grid: its vertices and cells. +std::shared_ptr CreateUniformGridDiscretization( + const UniformGrid<2>& grid); +std::shared_ptr CreateUniformGridDiscretization( + const UniformGrid<3>& grid); + +/// Discretization with no entities, for spaces that only evaluate (e.g. +/// fields provided by an external code). +std::shared_ptr CreateEmptyDiscretization(); + +} // namespace pcms + +#endif // PCMS_DISCRETIZATION_DISCRETIZATION_HPP diff --git a/src/pcms/field/coordinate_map.hpp b/include/pcms/field/coordinate_map.hpp similarity index 96% rename from src/pcms/field/coordinate_map.hpp rename to include/pcms/field/coordinate_map.hpp index 529460bed..df0ddb880 100644 --- a/src/pcms/field/coordinate_map.hpp +++ b/include/pcms/field/coordinate_map.hpp @@ -1,11 +1,11 @@ #ifndef PCMS_FIELD_COORDINATE_MAP_HPP #define PCMS_FIELD_COORDINATE_MAP_HPP -#include "pcms/field/coordinate_system.hpp" -#include "pcms/field/coordinate_view.hpp" +#include "pcms/utility/coordinate_system.hpp" +#include "pcms/utility/coordinate_view.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/utility/arrays.h" -#include "pcms/utility/memory_spaces.h" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/memory_spaces.hpp" #include #include diff --git a/src/pcms/field/eqdsk_field.h b/include/pcms/field/eqdsk_field.hpp similarity index 79% rename from src/pcms/field/eqdsk_field.h rename to include/pcms/field/eqdsk_field.hpp index 5dbbe5284..129acc03c 100644 --- a/src/pcms/field/eqdsk_field.h +++ b/include/pcms/field/eqdsk_field.hpp @@ -1,19 +1,20 @@ -#ifndef PCMS_EQDSK_FIELD_H -#define PCMS_EQDSK_FIELD_H +#ifndef PCMS_FIELD_EQDSK_FIELD_HPP +#define PCMS_FIELD_EQDSK_FIELD_HPP -#include "pcms/utility/eqdsk.h" -#include "pcms/field/layout/uniform_grid.h" -#include "pcms/field/function_space/spline.h" +#include "pcms/utility/eqdsk.hpp" +#include "pcms/discretization/discretization.hpp" +#include "pcms/field/field.hpp" +#include "pcms/field/function_spaces.hpp" #include -#include "pcms/field/coordinate_systems/cylindrical.hpp" +#include "pcms/utility/coordinate_systems/cylindrical.hpp" namespace pcms { struct EQDSKField { - std::shared_ptr space; + std::shared_ptr space; Field field; }; @@ -21,7 +22,7 @@ struct EQDSKField struct EQDSKFieldWithData { EQDSKData data; - std::shared_ptr space; + std::shared_ptr space; Field field; }; @@ -43,8 +44,9 @@ struct EQDSKFieldWithData inline EQDSKField MakeEQDSKField(const EQDSKData& eqdsk_data) { // EQDSK is a poloidal plane in cylindrical RZ coordinates - auto space = SplineFunctionSpace::FromUniformGrid( - eqdsk_data.grid, csys::CylindricalRZ::Create()); + auto space = + CreateSplineSpace(CreateUniformGridDiscretization(eqdsk_data.grid), + csys::CylindricalRZ::Create()); Field field = space->CreateFunction(); field.SetDOFHolderDataUnchecked(Rank2View( eqdsk_data.PSIZR.data(), eqdsk_data.PSIZR.extent(0), 1)); @@ -75,4 +77,4 @@ inline EQDSKFieldWithData MakeEQDSKField(const std::string& filename) } // namespace pcms -#endif // PCMS_EQDSK_FIELD_H +#endif // PCMS_FIELD_EQDSK_FIELD_HPP diff --git a/src/pcms/field/evaluation_request.h b/include/pcms/field/evaluation_request.hpp similarity index 84% rename from src/pcms/field/evaluation_request.h rename to include/pcms/field/evaluation_request.hpp index e26b6cdaf..6bf1c38e5 100644 --- a/src/pcms/field/evaluation_request.h +++ b/include/pcms/field/evaluation_request.hpp @@ -1,11 +1,11 @@ -#ifndef PCMS_EVALUATION_REQUEST_H -#define PCMS_EVALUATION_REQUEST_H +#ifndef PCMS_FIELD_EVALUATION_REQUEST_HPP +#define PCMS_FIELD_EVALUATION_REQUEST_HPP -#include "pcms/field/coordinate_view.hpp" -#include "field_layout.h" -#include "out_of_bounds_policy.h" -#include "pcms/utility/arrays.h" -#include "pcms/utility/memory_spaces.h" +#include "pcms/utility/coordinate_view.hpp" +#include "pcms/field/field_layout.hpp" +#include "pcms/field/out_of_bounds_policy.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/memory_spaces.hpp" #include @@ -64,4 +64,4 @@ struct EvaluationRequest } // namespace pcms -#endif // PCMS_EVALUATION_REQUEST_H +#endif // PCMS_FIELD_EVALUATION_REQUEST_HPP diff --git a/src/pcms/field/field.h b/include/pcms/field/field.hpp similarity index 96% rename from src/pcms/field/field.h rename to include/pcms/field/field.hpp index ab70297bd..76c584d30 100644 --- a/src/pcms/field/field.h +++ b/include/pcms/field/field.hpp @@ -1,11 +1,11 @@ -#ifndef PCMS_COUPLING_FIELD_H -#define PCMS_COUPLING_FIELD_H - -#include "field_data.h" -#include "field_layout.h" -#include "pcms/utility/arrays.h" -#include "pcms/utility/memory_spaces.h" -#include "pcms/utility/types.h" +#ifndef PCMS_FIELD_FIELD_HPP +#define PCMS_FIELD_FIELD_HPP + +#include "pcms/field/field_data.hpp" +#include "pcms/field/field_layout.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/memory_spaces.hpp" +#include "pcms/utility/types.hpp" #include #include #include @@ -229,4 +229,4 @@ using FunctionVariant = } // namespace pcms -#endif // PCMS_COUPLING_FIELD_H +#endif // PCMS_FIELD_FIELD_HPP diff --git a/src/pcms/field/field_data.h b/include/pcms/field/field_data.hpp similarity index 90% rename from src/pcms/field/field_data.h rename to include/pcms/field/field_data.hpp index bed91f930..d4fd898f1 100644 --- a/src/pcms/field/field_data.h +++ b/include/pcms/field/field_data.hpp @@ -1,9 +1,9 @@ -#ifndef PCMS_FIELD_DATA_H -#define PCMS_FIELD_DATA_H +#ifndef PCMS_FIELD_FIELD_DATA_HPP +#define PCMS_FIELD_FIELD_DATA_HPP #include "pcms/field/value_view.hpp" -#include "pcms/utility/arrays.h" -#include "pcms/utility/memory_spaces.h" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/memory_spaces.hpp" #include #include @@ -53,4 +53,4 @@ using FieldDataVariant = std::variant< } // namespace pcms -#endif // PCMS_FIELD_DATA_H +#endif // PCMS_FIELD_FIELD_DATA_HPP diff --git a/src/pcms/field/field_factory.h b/include/pcms/field/field_factory.hpp similarity index 94% rename from src/pcms/field/field_factory.h rename to include/pcms/field/field_factory.hpp index 936672632..f1624c8f7 100644 --- a/src/pcms/field/field_factory.h +++ b/include/pcms/field/field_factory.hpp @@ -1,11 +1,11 @@ -#ifndef PCMS_FIELD_FACTORY_H -#define PCMS_FIELD_FACTORY_H +#ifndef PCMS_FIELD_FIELD_FACTORY_HPP +#define PCMS_FIELD_FIELD_FACTORY_HPP -#include "field.h" -#include "field_data.h" -#include "field_layout.h" +#include "pcms/field/field.hpp" +#include "pcms/field/field_data.hpp" +#include "pcms/field/field_layout.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/utility/types.h" +#include "pcms/utility/types.hpp" #include #include #include @@ -120,4 +120,4 @@ Field FieldFactory::CreateField(std::string name, } // namespace pcms -#endif // PCMS_FIELD_FACTORY_H +#endif // PCMS_FIELD_FIELD_FACTORY_HPP diff --git a/src/pcms/field/field_layout.h b/include/pcms/field/field_layout.hpp similarity index 92% rename from src/pcms/field/field_layout.h rename to include/pcms/field/field_layout.hpp index 1c8477347..ac2e3d784 100644 --- a/src/pcms/field/field_layout.h +++ b/include/pcms/field/field_layout.hpp @@ -1,14 +1,14 @@ -#ifndef PCMS_FIELD_LAYOUT_H -#define PCMS_FIELD_LAYOUT_H +#ifndef PCMS_FIELD_FIELD_LAYOUT_HPP +#define PCMS_FIELD_FIELD_LAYOUT_HPP #include #include #include #include -#include "pcms/discretization/discretization.h" -#include "pcms/utility/types.h" -#include "pcms/utility/arrays.h" -#include "pcms/field/coordinate_system.hpp" -#include "pcms/field/coordinate_view.hpp" +#include "pcms/discretization/discretization.hpp" +#include "pcms/utility/types.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/coordinate_system.hpp" +#include "pcms/utility/coordinate_view.hpp" namespace pcms { @@ -112,4 +112,4 @@ class FieldLayout }; } // namespace pcms -#endif // PCMS_FIELD_LAYOUT_H +#endif // PCMS_FIELD_FIELD_LAYOUT_HPP diff --git a/src/pcms/field/function_space.h b/include/pcms/field/function_space.hpp similarity index 89% rename from src/pcms/field/function_space.h rename to include/pcms/field/function_space.hpp index 78aeb8a58..eaa96e855 100644 --- a/src/pcms/field/function_space.h +++ b/include/pcms/field/function_space.hpp @@ -1,21 +1,21 @@ -#ifndef PCMS_FUNCTION_SPACE_H -#define PCMS_FUNCTION_SPACE_H - -#include "pcms/field/coordinate_system.hpp" -#include "pcms/field/coordinate_view.hpp" -#include "evaluation_request.h" -#include "field.h" -#include "field_data.h" -#include "field_factory.h" -#include "field_layout.h" +#ifndef PCMS_FIELD_FUNCTION_SPACE_HPP +#define PCMS_FIELD_FUNCTION_SPACE_HPP + +#include "pcms/utility/coordinate_system.hpp" +#include "pcms/utility/coordinate_view.hpp" +#include "pcms/field/evaluation_request.hpp" +#include "pcms/field/field.hpp" +#include "pcms/field/field_data.hpp" +#include "pcms/field/field_factory.hpp" +#include "pcms/field/field_layout.hpp" #include "pcms/field/value_view.hpp" -#include "out_of_bounds_policy.h" -#include "point_evaluator.h" +#include "pcms/field/out_of_bounds_policy.hpp" +#include "pcms/field/point_evaluator.hpp" #include "pcms/field/point_evaluator_factory.hpp" -#include "pcms/discretization/discretization.h" -#include "pcms/utility/arrays.h" -#include "pcms/utility/memory_spaces.h" -#include "pcms/utility/types.h" +#include "pcms/discretization/discretization.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/memory_spaces.hpp" +#include "pcms/utility/types.hpp" #include #include #include @@ -164,4 +164,4 @@ inline EvaluationRequest EvaluationRequest::FromFunctionSpace( } // namespace pcms -#endif // PCMS_FUNCTION_SPACE_H +#endif // PCMS_FIELD_FUNCTION_SPACE_HPP diff --git a/include/pcms/field/function_spaces.hpp b/include/pcms/field/function_spaces.hpp new file mode 100644 index 000000000..40d49d2e2 --- /dev/null +++ b/include/pcms/field/function_spaces.hpp @@ -0,0 +1,72 @@ +#ifndef PCMS_FIELD_FUNCTION_SPACES_HPP +#define PCMS_FIELD_FUNCTION_SPACES_HPP + +// Factories for the function spaces PCMS provides. Each takes a +// Discretization (see pcms/discretization/discretization.hpp and the backend +// headers) and returns the FunctionSpace interface. + +#include "pcms/discretization/discretization.hpp" +#include "pcms/field/field_layout.hpp" +#include "pcms/field/function_space.hpp" +#include "pcms/localization/mls_options.hpp" +#include "pcms/utility/coordinate_system.hpp" +#include "pcms/utility/coordinate_view.hpp" +#include "pcms/utility/memory_spaces.hpp" + +#include +#include + +namespace pcms +{ + +/// Which implementation evaluates Lagrange fields on an Omega_h +/// discretization. Default is MeshFields when PCMS is built with MeshFields, +/// Omega_h otherwise. +enum class LagrangeImplementation +{ + Default, + MeshFields, + OmegaH +}; + +struct LagrangeOptions +{ + LagrangeImplementation implementation = LagrangeImplementation::Default; + /// Name of the layout; it identifies the layout in the coupler. + std::string layout_name; +}; + +/// Nodal Lagrange space of the given order with num_components components on +/// an Omega_h discretization (orders 0-2, depending on the implementation) +/// or a 2D/3D uniform-grid discretization (order 1). Throws pcms_error for +/// other discretizations. +std::shared_ptr CreateLagrangeSpace( + std::shared_ptr discretization, int order, + int num_components, std::shared_ptr coordinate_system, + LagrangeOptions options = {}); + +/// Bicubic spline space on a 2D uniform-grid discretization. +std::shared_ptr CreateSplineSpace( + std::shared_ptr discretization, + std::shared_ptr coordinate_system); + +/// Moving-least-squares polynomial reconstruction from values at points. +std::shared_ptr CreatePolynomialReconstructionSpace( + CoordinateView points, MLSOptions options = {}); + +/// As above, with the points being the entities of dimension +/// source_entity_dim of an Omega_h discretization. +std::shared_ptr CreatePolynomialReconstructionSpace( + std::shared_ptr discretization, int source_entity_dim, + std::shared_ptr coordinate_system, + MLSOptions options = {}); + +/// Layout without degrees of freedom, for evaluation-only spaces that +/// implement FunctionSpace outside PCMS (e.g. fields of an external code). +std::shared_ptr CreateEmptyLayout( + std::shared_ptr coordinate_system, + int num_components = 1); + +} // namespace pcms + +#endif // PCMS_FIELD_FUNCTION_SPACES_HPP diff --git a/src/pcms/field/out_of_bounds_policy.h b/include/pcms/field/out_of_bounds_policy.hpp similarity index 85% rename from src/pcms/field/out_of_bounds_policy.h rename to include/pcms/field/out_of_bounds_policy.hpp index 7e3cdc1f6..4ec9a0d4b 100644 --- a/src/pcms/field/out_of_bounds_policy.h +++ b/include/pcms/field/out_of_bounds_policy.hpp @@ -1,7 +1,7 @@ -#ifndef PCMS_OUT_OF_BOUNDS_POLICY_H -#define PCMS_OUT_OF_BOUNDS_POLICY_H +#ifndef PCMS_FIELD_OUT_OF_BOUNDS_POLICY_HPP +#define PCMS_FIELD_OUT_OF_BOUNDS_POLICY_HPP -#include "pcms/utility/types.h" +#include "pcms/utility/types.hpp" namespace pcms { @@ -31,4 +31,4 @@ struct OutOfBoundsPolicy } // namespace pcms -#endif // PCMS_OUT_OF_BOUNDS_POLICY_H +#endif // PCMS_FIELD_OUT_OF_BOUNDS_POLICY_HPP diff --git a/src/pcms/field/point_evaluator.h b/include/pcms/field/point_evaluator.hpp similarity index 94% rename from src/pcms/field/point_evaluator.h rename to include/pcms/field/point_evaluator.hpp index 9ccd66fe9..ce099ff3d 100644 --- a/src/pcms/field/point_evaluator.h +++ b/include/pcms/field/point_evaluator.hpp @@ -1,10 +1,10 @@ -#ifndef PCMS_POINT_EVALUATOR_H -#define PCMS_POINT_EVALUATOR_H +#ifndef PCMS_FIELD_POINT_EVALUATOR_HPP +#define PCMS_FIELD_POINT_EVALUATOR_HPP #include "pcms/field/value_view.hpp" -#include "pcms/utility/arrays.h" -#include "pcms/utility/memory_spaces.h" -#include "pcms/utility/types.h" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/memory_spaces.hpp" +#include "pcms/utility/types.hpp" #include #include #include @@ -115,4 +115,4 @@ using PointEvaluatorVariant = } // namespace pcms -#endif // PCMS_POINT_EVALUATOR_H +#endif // PCMS_FIELD_POINT_EVALUATOR_HPP diff --git a/src/pcms/field/point_evaluator_factory.hpp b/include/pcms/field/point_evaluator_factory.hpp similarity index 88% rename from src/pcms/field/point_evaluator_factory.hpp rename to include/pcms/field/point_evaluator_factory.hpp index 5622a9fcb..03f3290c9 100644 --- a/src/pcms/field/point_evaluator_factory.hpp +++ b/include/pcms/field/point_evaluator_factory.hpp @@ -1,12 +1,12 @@ #ifndef PCMS_FIELD_POINT_EVALUATOR_FACTORY_HPP #define PCMS_FIELD_POINT_EVALUATOR_FACTORY_HPP -#include "pcms/field/coordinate_system.hpp" -#include "pcms/field/evaluation_request.h" -#include "pcms/field/field_factory.h" -#include "pcms/field/point_evaluator.h" -#include "pcms/utility/assert.h" -#include "pcms/utility/types.h" +#include "pcms/utility/coordinate_system.hpp" +#include "pcms/field/evaluation_request.hpp" +#include "pcms/field/field_factory.hpp" +#include "pcms/field/point_evaluator.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/types.hpp" #include #include #include diff --git a/src/pcms/field/data/simple.h b/include/pcms/field/simple_field_data.hpp similarity index 82% rename from src/pcms/field/data/simple.h rename to include/pcms/field/simple_field_data.hpp index facfd032e..0070bc726 100644 --- a/src/pcms/field/data/simple.h +++ b/include/pcms/field/simple_field_data.hpp @@ -1,11 +1,11 @@ -#ifndef PCMS_SIMPLE_FIELD_DATA_H -#define PCMS_SIMPLE_FIELD_DATA_H - -#include "../field_data.h" -#include "../field_layout.h" -#include "pcms/utility/arrays.h" -#include "pcms/utility/assert.h" -#include "pcms/utility/memory_spaces.h" +#ifndef PCMS_FIELD_SIMPLE_FIELD_DATA_HPP +#define PCMS_FIELD_SIMPLE_FIELD_DATA_HPP + +#include "pcms/field/field_data.hpp" +#include "pcms/field/field_layout.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/memory_spaces.hpp" #include #include #include @@ -60,4 +60,4 @@ class SimpleFieldData } // namespace pcms -#endif // PCMS_SIMPLE_FIELD_DATA_H +#endif // PCMS_FIELD_SIMPLE_FIELD_DATA_HPP diff --git a/src/pcms/field/transformed_source.hpp b/include/pcms/field/transformed_source.hpp similarity index 90% rename from src/pcms/field/transformed_source.hpp rename to include/pcms/field/transformed_source.hpp index e27f033f6..1491f2777 100644 --- a/src/pcms/field/transformed_source.hpp +++ b/include/pcms/field/transformed_source.hpp @@ -2,19 +2,19 @@ #define PCMS_FIELD_TRANSFORMED_SOURCE_HPP #include "pcms/field/coordinate_map.hpp" -#include "pcms/field/coordinate_system.hpp" -#include "pcms/field/evaluation_request.h" -#include "pcms/field/field.h" -#include "pcms/field/field_data.h" -#include "pcms/field/out_of_bounds_policy.h" -#include "pcms/field/point_evaluator.h" +#include "pcms/utility/coordinate_system.hpp" +#include "pcms/field/evaluation_request.hpp" +#include "pcms/field/field.hpp" +#include "pcms/field/field_data.hpp" +#include "pcms/field/out_of_bounds_policy.hpp" +#include "pcms/field/point_evaluator.hpp" #include "pcms/field/point_evaluator_factory.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/utility/arrays.h" -#include "pcms/utility/assert.h" -#include "pcms/utility/memory_spaces.h" -#include "pcms/utility/profile.h" -#include "pcms/utility/types.h" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/memory_spaces.hpp" +#include "pcms/utility/detail/profile.hpp" +#include "pcms/utility/types.hpp" #include #include #include diff --git a/src/pcms/field/value_view.hpp b/include/pcms/field/value_view.hpp similarity index 98% rename from src/pcms/field/value_view.hpp rename to include/pcms/field/value_view.hpp index bed7eddc8..f67dddb4d 100644 --- a/src/pcms/field/value_view.hpp +++ b/include/pcms/field/value_view.hpp @@ -1,9 +1,9 @@ #ifndef PCMS_FIELD_VALUE_VIEW_HPP #define PCMS_FIELD_VALUE_VIEW_HPP -#include "pcms/field/coordinate_system.hpp" -#include "pcms/utility/arrays.h" -#include "pcms/utility/assert.h" +#include "pcms/utility/coordinate_system.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/assert.hpp" #include #include #include diff --git a/include/pcms/localization/mls_options.hpp b/include/pcms/localization/mls_options.hpp new file mode 100644 index 000000000..5ec51196a --- /dev/null +++ b/include/pcms/localization/mls_options.hpp @@ -0,0 +1,99 @@ +#ifndef PCMS_LOCALIZATION_MLS_OPTIONS_HPP +#define PCMS_LOCALIZATION_MLS_OPTIONS_HPP + +namespace pcms +{ + +/** + * @brief Enumeration of supported radial basis functions (RBFs) for MLS + * interpolation. + * + * Specifies the kernel type used for computing weights in Moving Least Squares + * (MLS) interpolation. Each RBF defines a different spatial weighting behavior, + * influencing locality, smoothness, and conditioning of the interpolant. + * + * ### Values: + * + * - **RBF_GAUSSIAN (0)** + * \f$ \phi(r) = \exp\left(-\left(\frac{a r}{r_c}\right)^2\right) \f$ + * Infinitely smooth and compactly supported. + * `a` is the shape (decay) parameter — smaller values give wider influence. + * Good for smooth interpolants; may cause ill-conditioning for large `a`. + * + * - **RBF_C4 (1)** + * Compactly supported, \f$ C^4\f$-continuous polynomial kernel. + * Does not require a shape parameter. + * Efficient, stable, and good for local approximations. + * + * - **RBF_CONST (2)** + * Uniform weights within support: + * \f$ \phi(r) = 1 \text{ for } r < r_c \f$, otherwise 0. + * Equivalent to averaging. + * + * - **NO_OP (3)** + * Disables internal RBF weighting logic. + * Always returns \f$ \phi = 1 \f$ regardless of distance. + * Useful for methods like SPR patching + * + * - **RBF_MULTIQUADRIC (4)** + * \f$ \phi(r) = \sqrt{1 + \left(\frac{a r}{r_c}\right)^2} \f$ + * Smooth and locally supported. + * `a` controls the width; higher values increase conditioning issues. + * + * - **RBF_INVMULTIQUADRIC (5)** + * \f$ \phi(r) = \frac{1}{\sqrt{1 + \left(\frac{a r}{r_c}\right)^2}} \f$ + * Compactly supported and generally more stable than MQ. + * `a` adjusts the decay; larger `a` leads to faster fall-off. + * + * - **RBF_THINPLATESPLINE (6)** + * \f$ \phi(r) = \left(\frac{a r}{r_c}\right)^2 \log\left(\frac{a + * r}{r_c}\right) \f$ Classic 2D surface fitting kernel. No explicit shape + * parameter is required, but `a` can scale smoothness. + * + * - **RBF_CUBIC (7)** + * \f$ \phi(r) = \left(\frac{a r}{r_c}\right)^3 \f$ + * Smooth with compact support. + * Simple and effective for local interpolation. + * + * --- + * + * @note + * - The shape parameter `a` (also called decay or spread factor) is required + * for Gaussian, MQ, IMQ, ThinPlateSpline, and Cubic kernels. + * - All kernels are compactly supported within the cutoff radius \f$ r_c \f$. + * - A good starting value for `a` is 3–5. Avoid `a = 0` (leads to constant + * behavior). + * - In cases of ill-conditioning, use regularization (`lambda > 0`). + * + * @see mls_interpolation() + */ +enum class RadialBasisFunction +{ + RBF_GAUSSIAN = 0, + RBF_C4, + RBF_CONST, + NO_OP, + RBF_MULTIQUADRIC, + RBF_INVMULTIQUADRIC, + RBF_THINPLATESPLINE, + RBF_CUBIC +}; + +/// Configuration for Moving Least Squares evaluation. +/// Passed to PolynomialReconstructionFunctionSpace::Create and +/// PointCloudEvaluatorFactory. +struct MLSOptions +{ + double radius = 0.5; + unsigned min_req_supports = 10; + unsigned degree = 3; + bool adapt_radius = true; + double lambda = 0.0; + double tol = 1e-6; + double decay_factor = 5.0; + RadialBasisFunction basis = RadialBasisFunction::RBF_GAUSSIAN; +}; + +} // namespace pcms + +#endif // PCMS_LOCALIZATION_MLS_OPTIONS_HPP diff --git a/include/pcms/pcms.hpp b/include/pcms/pcms.hpp new file mode 100644 index 000000000..99e302faf --- /dev/null +++ b/include/pcms/pcms.hpp @@ -0,0 +1,66 @@ +#ifndef PCMS_PCMS_HPP +#define PCMS_PCMS_HPP + +// Umbrella header: includes the public PCMS API that is enabled in this +// build. Backend adapters (pcms/backends/...) are not included; include the +// backend header you use explicitly. pcms/version.hpp is not included (it +// defines a non-inline function). + +#include "pcms/configuration.hpp" + +// utility +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/detail/common.hpp" +#include "pcms/utility/coordinate_system.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_systems/cylindrical.hpp" +#include "pcms/utility/coordinate_view.hpp" +#include "pcms/utility/entity_types.hpp" +#include "pcms/utility/eqdsk.hpp" +#include "pcms/utility/memory_spaces.hpp" +#include "pcms/utility/print.hpp" +#include "pcms/utility/detail/profile.hpp" +#include "pcms/utility/types.hpp" +#include "pcms/utility/uniform_grid.hpp" + +// discretization and localization +#include "pcms/discretization/discretization.hpp" +#include "pcms/localization/mls_options.hpp" + +// field +#include "pcms/field/coordinate_map.hpp" +#include "pcms/field/evaluation_request.hpp" +#include "pcms/field/field.hpp" +#include "pcms/field/field_data.hpp" +#include "pcms/field/field_factory.hpp" +#include "pcms/field/field_layout.hpp" +#include "pcms/field/function_space.hpp" +#include "pcms/field/out_of_bounds_policy.hpp" +#include "pcms/field/point_evaluator.hpp" +#include "pcms/field/point_evaluator_factory.hpp" +#include "pcms/field/transformed_source.hpp" +#include "pcms/field/value_view.hpp" +#ifdef PCMS_ENABLE_OMEGA_H +#include "pcms/field/eqdsk_field.hpp" +#endif + +// transfer +#include "pcms/transfer/copy.hpp" +#include "pcms/transfer/interpolator.hpp" +#include "pcms/transfer/mass_matrix_type.hpp" +#include "pcms/transfer/transfer_operator.hpp" + +// coupler +#ifdef PCMS_ENABLE_COUPLER +#include "pcms/coupler/coupler.hpp" +#include "pcms/coupler/coupler_types.hpp" +#include "pcms/coupler/overlap_mask.hpp" +#endif + +// transient +#ifdef PCMS_ENABLE_TRANSIENT +#include "pcms/transient/timestepper.hpp" +#endif + +#endif // PCMS_PCMS_HPP diff --git a/src/pcms/transfer/copy.h b/include/pcms/transfer/copy.hpp similarity index 80% rename from src/pcms/transfer/copy.h rename to include/pcms/transfer/copy.hpp index 73d63f32f..dc3df2775 100644 --- a/src/pcms/transfer/copy.h +++ b/include/pcms/transfer/copy.hpp @@ -1,11 +1,11 @@ -#ifndef PCMS_TRANSFER_FIELD2_H_ -#define PCMS_TRANSFER_FIELD2_H_ -#include "pcms/field/field.h" -#include "pcms/field/field_data.h" -#include "pcms/field/function_space.h" -#include "pcms/utility/assert.h" -#include "pcms/utility/profile.h" -#include "pcms/utility/types.h" +#ifndef PCMS_TRANSFER_COPY_HPP +#define PCMS_TRANSFER_COPY_HPP +#include "pcms/field/field.hpp" +#include "pcms/field/field_data.hpp" +#include "pcms/field/function_space.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/detail/profile.hpp" +#include "pcms/utility/types.hpp" #include "pcms/transfer/transfer_operator.hpp" #include #include @@ -56,4 +56,4 @@ class Copy : public TransferOperator } // namespace pcms -#endif // PCMS_TRANSFER_FIELD2_H_ +#endif // PCMS_TRANSFER_COPY_HPP diff --git a/src/pcms/transfer/interpolator.h b/include/pcms/transfer/interpolator.hpp similarity index 85% rename from src/pcms/transfer/interpolator.h rename to include/pcms/transfer/interpolator.hpp index 959f5be39..11f829d8c 100644 --- a/src/pcms/transfer/interpolator.h +++ b/include/pcms/transfer/interpolator.hpp @@ -1,16 +1,16 @@ -#ifndef PCMS_FIELD_INTERPOLATOR_H -#define PCMS_FIELD_INTERPOLATOR_H +#ifndef PCMS_TRANSFER_INTERPOLATOR_HPP +#define PCMS_TRANSFER_INTERPOLATOR_HPP -#include "pcms/field/field.h" -#include "pcms/field/field_data.h" -#include "pcms/field/function_space.h" +#include "pcms/field/field.hpp" +#include "pcms/field/field_data.hpp" +#include "pcms/field/function_space.hpp" #include "pcms/field/point_evaluator_factory.hpp" -#include "pcms/field/out_of_bounds_policy.h" -#include "pcms/field/point_evaluator.h" -#include "pcms/utility/arrays.h" -#include "pcms/utility/memory_spaces.h" -#include "pcms/utility/profile.h" -#include "pcms/utility/types.h" +#include "pcms/field/out_of_bounds_policy.hpp" +#include "pcms/field/point_evaluator.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/memory_spaces.hpp" +#include "pcms/utility/detail/profile.hpp" +#include "pcms/utility/types.hpp" #include #include #include "pcms/transfer/transfer_operator.hpp" @@ -78,4 +78,4 @@ class Interpolator : public TransferOperator } // namespace pcms -#endif // PCMS_FIELD_INTERPOLATOR_H +#endif // PCMS_TRANSFER_INTERPOLATOR_HPP diff --git a/src/pcms/transfer/mass_matrix_type.hpp b/include/pcms/transfer/mass_matrix_type.hpp similarity index 100% rename from src/pcms/transfer/mass_matrix_type.hpp rename to include/pcms/transfer/mass_matrix_type.hpp diff --git a/src/pcms/transfer/monte_carlo_sampling.hpp b/include/pcms/transfer/monte_carlo_sampling.hpp similarity index 100% rename from src/pcms/transfer/monte_carlo_sampling.hpp rename to include/pcms/transfer/monte_carlo_sampling.hpp diff --git a/include/pcms/transfer/projection.hpp b/include/pcms/transfer/projection.hpp new file mode 100644 index 000000000..471585be0 --- /dev/null +++ b/include/pcms/transfer/projection.hpp @@ -0,0 +1,51 @@ +#ifndef PCMS_TRANSFER_PROJECTION_HPP +#define PCMS_TRANSFER_PROJECTION_HPP + +// Factories for the Galerkin projections. They are always declared; in a +// build without the implementing backends (PETSc and MeshFields) they throw +// pcms_error. + +#include "pcms/field/function_space.hpp" +#include "pcms/field/point_evaluator_factory.hpp" +#include "pcms/transfer/mass_matrix_type.hpp" +#include "pcms/transfer/monte_carlo_sampling.hpp" +#include "pcms/transfer/transfer_operator.hpp" +#include "pcms/utility/types.hpp" + +#include +#include + +namespace pcms +{ + +struct ConservativeProjectionOptions +{ + MassMatrixType mass_matrix_type = MassMatrixType::Consistent; +}; + +/// Conservative (Galerkin L2) projection from source_space to target_space +/// using exact mesh intersection. Both spaces must be scalar Lagrange spaces +/// on Omega_h discretizations. +std::unique_ptr> CreateConservativeProjection( + const FunctionSpace& source_space, const FunctionSpace& target_space, + ConservativeProjectionOptions options = {}); + +struct ControlVariateProjectionOptions +{ + int samples_per_element = 1; + MonteCarloSampling sampling = MonteCarloSampling::UniformRandom; + std::uint64_t seed = 8675309; + MassMatrixType mass_matrix_type = MassMatrixType::Consistent; +}; + +/// Galerkin projection of any evaluable source onto target_space, with the +/// right-hand side estimated by Monte Carlo sampling with a control variate. +/// target_space must be a scalar Lagrange space on an Omega_h +/// discretization. +std::unique_ptr> CreateControlVariateProjection( + const PointEvaluatorFactory& source, const FunctionSpace& target_space, + ControlVariateProjectionOptions options = {}); + +} // namespace pcms + +#endif // PCMS_TRANSFER_PROJECTION_HPP diff --git a/src/pcms/transfer/transfer_operator.hpp b/include/pcms/transfer/transfer_operator.hpp similarity index 67% rename from src/pcms/transfer/transfer_operator.hpp rename to include/pcms/transfer/transfer_operator.hpp index be78a9cb1..7e475ebc0 100644 --- a/src/pcms/transfer/transfer_operator.hpp +++ b/include/pcms/transfer/transfer_operator.hpp @@ -1,5 +1,5 @@ -#ifndef PCMS_TRANSFER_TRANSFER_H -#define PCMS_TRANSFER_TRANSFER_H +#ifndef PCMS_TRANSFER_TRANSFER_OPERATOR_HPP +#define PCMS_TRANSFER_TRANSFER_OPERATOR_HPP namespace pcms { @@ -20,4 +20,4 @@ class TransferOperator } // namespace pcms -#endif +#endif // PCMS_TRANSFER_TRANSFER_OPERATOR_HPP diff --git a/src/pcms/transient/timestepper.hpp b/include/pcms/transient/timestepper.hpp similarity index 97% rename from src/pcms/transient/timestepper.hpp rename to include/pcms/transient/timestepper.hpp index 00337c36b..1b626b074 100644 --- a/src/pcms/transient/timestepper.hpp +++ b/include/pcms/transient/timestepper.hpp @@ -1,7 +1,7 @@ #ifndef PCMS_TRANSIENT_TIMESTEPPER_HPP #define PCMS_TRANSIENT_TIMESTEPPER_HPP -#include "pcms/utility/types.h" +#include "pcms/utility/types.hpp" namespace pcms { diff --git a/src/pcms/utility/arrays.h b/include/pcms/utility/arrays.hpp similarity index 97% rename from src/pcms/utility/arrays.h rename to include/pcms/utility/arrays.hpp index ca7f64904..c7ba9658d 100644 --- a/src/pcms/utility/arrays.h +++ b/include/pcms/utility/arrays.hpp @@ -1,10 +1,8 @@ -#ifndef PCMS_COUPLING_ARRAYS_H -#define PCMS_COUPLING_ARRAYS_H +#ifndef PCMS_UTILITY_ARRAYS_HPP +#define PCMS_UTILITY_ARRAYS_HPP #include "mdspan/mdspan.hpp" -#include "pcms/utility/types.h" -#include "pcms/utility/memory_spaces.h" - -#include +#include "pcms/utility/types.hpp" +#include "pcms/utility/memory_spaces.hpp" namespace pcms { @@ -244,14 +242,6 @@ auto MakeConstRank2View(const Kokkos::View& view) view.data(), view.extent(0), view.extent(1)); } -template -auto MakeConstRank2View(Omega_h::Read array, int dim) -{ - // Cannonical usage of Omega_h arrays is a layout_right 1D array - return Rank2View( - array.data(), array.size() / dim, dim); -} - // Flatten a contiguous (exhaustive) 2D [dof][comp] view into a 1D view over the // same storage. Intended for boundary code (serialization, element-wise // comparison) that wants a flat [num_dof_holder * num_components] view rather @@ -503,4 +493,4 @@ void CopyRank1ViewToDevice(Rank1View dest, } } // namespace pcms -#endif // PCMS_COUPLING_ARRAYS_H +#endif // PCMS_UTILITY_ARRAYS_HPP diff --git a/src/pcms/utility/assert.h b/include/pcms/utility/assert.hpp similarity index 97% rename from src/pcms/utility/assert.h rename to include/pcms/utility/assert.hpp index b5be9419f..162bb3f09 100644 --- a/src/pcms/utility/assert.h +++ b/include/pcms/utility/assert.hpp @@ -1,5 +1,5 @@ -#ifndef PCMS_COUPLING_ASSERT_H -#define PCMS_COUPLING_ASSERT_H +#ifndef PCMS_UTILITY_ASSERT_HPP +#define PCMS_UTILITY_ASSERT_HPP #include #include @@ -56,4 +56,4 @@ struct pcms_error : std::runtime_error void Pcms_Assert_Fail(const char* msg) __attribute__((noreturn)); } // namespace pcms -#endif // PCMS_COUPLING_ASSERT_H +#endif // PCMS_UTILITY_ASSERT_HPP diff --git a/src/pcms/utility/bounding_box.h b/include/pcms/utility/bounding_box.hpp similarity index 79% rename from src/pcms/utility/bounding_box.h rename to include/pcms/utility/bounding_box.hpp index 32a0c21b4..0751c679a 100644 --- a/src/pcms/utility/bounding_box.h +++ b/include/pcms/utility/bounding_box.hpp @@ -1,6 +1,6 @@ -#ifndef PCMS_COUPLING_BOUNDING_BOX_H -#define PCMS_COUPLING_BOUNDING_BOX_H -#include "pcms/utility/types.h" +#ifndef PCMS_UTILITY_BOUNDING_BOX_HPP +#define PCMS_UTILITY_BOUNDING_BOX_HPP +#include "pcms/utility/types.hpp" #include #include namespace pcms @@ -28,4 +28,4 @@ KOKKOS_INLINE_FUNCTION bool intersects(const AABBox& a, } } // namespace pcms -#endif // PCMS_COUPLING_BOUNDING_BOX_H +#endif // PCMS_UTILITY_BOUNDING_BOX_HPP diff --git a/src/pcms/field/coordinate_system.hpp b/include/pcms/utility/coordinate_system.hpp similarity index 89% rename from src/pcms/field/coordinate_system.hpp rename to include/pcms/utility/coordinate_system.hpp index 2fd41c132..d0907086a 100644 --- a/src/pcms/field/coordinate_system.hpp +++ b/include/pcms/utility/coordinate_system.hpp @@ -1,5 +1,5 @@ -#ifndef PCMS_FIELD_COORDINATE_SYSTEM_HPP -#define PCMS_FIELD_COORDINATE_SYSTEM_HPP +#ifndef PCMS_UTILITY_COORDINATE_SYSTEM_HPP +#define PCMS_UTILITY_COORDINATE_SYSTEM_HPP #include #include @@ -45,4 +45,4 @@ class CoordinateSystem } // namespace pcms -#endif // PCMS_FIELD_COORDINATE_SYSTEM_HPP +#endif // PCMS_UTILITY_COORDINATE_SYSTEM_HPP diff --git a/src/pcms/field/coordinate_systems/cartesian.hpp b/include/pcms/utility/coordinate_systems/cartesian.hpp similarity index 84% rename from src/pcms/field/coordinate_systems/cartesian.hpp rename to include/pcms/utility/coordinate_systems/cartesian.hpp index 02b64199e..a03517fae 100644 --- a/src/pcms/field/coordinate_systems/cartesian.hpp +++ b/include/pcms/utility/coordinate_systems/cartesian.hpp @@ -1,8 +1,8 @@ -#ifndef PCMS_FIELD_COORDINATE_SYSTEMS_CARTESIAN_HPP -#define PCMS_FIELD_COORDINATE_SYSTEMS_CARTESIAN_HPP +#ifndef PCMS_UTILITY_COORDINATE_SYSTEMS_CARTESIAN_HPP +#define PCMS_UTILITY_COORDINATE_SYSTEMS_CARTESIAN_HPP -#include "pcms/field/coordinate_system.hpp" -#include "pcms/utility/assert.h" +#include "pcms/utility/coordinate_system.hpp" +#include "pcms/utility/assert.hpp" #include namespace pcms @@ -56,4 +56,4 @@ class Cartesian final : public CoordinateSystem } // namespace csys } // namespace pcms -#endif // PCMS_FIELD_COORDINATE_SYSTEMS_CARTESIAN_HPP +#endif // PCMS_UTILITY_COORDINATE_SYSTEMS_CARTESIAN_HPP diff --git a/src/pcms/field/coordinate_systems/cylindrical.hpp b/include/pcms/utility/coordinate_systems/cylindrical.hpp similarity index 88% rename from src/pcms/field/coordinate_systems/cylindrical.hpp rename to include/pcms/utility/coordinate_systems/cylindrical.hpp index ecbbb41dd..8f03fcc06 100644 --- a/src/pcms/field/coordinate_systems/cylindrical.hpp +++ b/include/pcms/utility/coordinate_systems/cylindrical.hpp @@ -1,7 +1,7 @@ -#ifndef PCMS_FIELD_COORDINATE_SYSTEMS_CYLINDRICAL_HPP -#define PCMS_FIELD_COORDINATE_SYSTEMS_CYLINDRICAL_HPP +#ifndef PCMS_UTILITY_COORDINATE_SYSTEMS_CYLINDRICAL_HPP +#define PCMS_UTILITY_COORDINATE_SYSTEMS_CYLINDRICAL_HPP -#include "pcms/field/coordinate_system.hpp" +#include "pcms/utility/coordinate_system.hpp" namespace pcms { @@ -73,4 +73,4 @@ class CylindricalRZ final : public CoordinateSystem } // namespace csys } // namespace pcms -#endif // PCMS_FIELD_COORDINATE_SYSTEMS_CYLINDRICAL_HPP +#endif // PCMS_UTILITY_COORDINATE_SYSTEMS_CYLINDRICAL_HPP diff --git a/src/pcms/field/coordinate_view.hpp b/include/pcms/utility/coordinate_view.hpp similarity index 79% rename from src/pcms/field/coordinate_view.hpp rename to include/pcms/utility/coordinate_view.hpp index 075ec727b..1cd15f2f5 100644 --- a/src/pcms/field/coordinate_view.hpp +++ b/include/pcms/utility/coordinate_view.hpp @@ -1,9 +1,9 @@ -#ifndef PCMS_FIELD_COORDINATE_VIEW_HPP -#define PCMS_FIELD_COORDINATE_VIEW_HPP +#ifndef PCMS_UTILITY_COORDINATE_VIEW_HPP +#define PCMS_UTILITY_COORDINATE_VIEW_HPP -#include "pcms/field/coordinate_system.hpp" -#include "pcms/utility/arrays.h" -#include "pcms/utility/assert.h" +#include "pcms/utility/coordinate_system.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/assert.hpp" #include #include @@ -43,4 +43,4 @@ class CoordinateView } // namespace pcms -#endif // PCMS_FIELD_COORDINATE_VIEW_HPP +#endif // PCMS_UTILITY_COORDINATE_VIEW_HPP diff --git a/src/pcms/utility/common.h b/include/pcms/utility/detail/common.hpp similarity index 90% rename from src/pcms/utility/common.h rename to include/pcms/utility/detail/common.hpp index e23a16e74..0bec4dc93 100644 --- a/src/pcms/utility/common.h +++ b/include/pcms/utility/detail/common.hpp @@ -1,6 +1,6 @@ -#ifndef PCMS_COUPLING_COMMON_H -#define PCMS_COUPLING_COMMON_H -#include "pcms/utility/assert.h" +#ifndef PCMS_UTILITY_DETAIL_COMMON_HPP +#define PCMS_UTILITY_DETAIL_COMMON_HPP +#include "pcms/utility/assert.hpp" #include #include #include @@ -54,4 +54,4 @@ auto find_many_or_error(const std::vector& keys, std::map& map) } // namespace detail } // namespace pcms -#endif // PCMS_COUPLING_COMMON_H +#endif // PCMS_UTILITY_DETAIL_COMMON_HPP diff --git a/src/pcms/utility/inclusive_scan.h b/include/pcms/utility/detail/inclusive_scan.hpp similarity index 70% rename from src/pcms/utility/inclusive_scan.h rename to include/pcms/utility/detail/inclusive_scan.hpp index d69b5156a..646ee2d9b 100644 --- a/src/pcms/utility/inclusive_scan.h +++ b/include/pcms/utility/detail/inclusive_scan.hpp @@ -1,5 +1,5 @@ -#ifndef PCMS_INCLUSIVE_SCAN_H -#define PCMS_INCLUSIVE_SCAN_H +#ifndef PCMS_UTILITY_DETAIL_INCLUSIVE_SCAN_HPP +#define PCMS_UTILITY_DETAIL_INCLUSIVE_SCAN_HPP namespace pcms { template @@ -14,4 +14,4 @@ OutputIt inclusive_scan(InputIt first, InputIt last, OutputIt d_first) return d_first; } } // namespace pcms -#endif +#endif // PCMS_UTILITY_DETAIL_INCLUSIVE_SCAN_HPP diff --git a/src/pcms/utility/profile.h b/include/pcms/utility/detail/profile.hpp similarity index 73% rename from src/pcms/utility/profile.h rename to include/pcms/utility/detail/profile.hpp index 6f20352af..ad1ca50fc 100644 --- a/src/pcms/utility/profile.h +++ b/include/pcms/utility/detail/profile.hpp @@ -1,5 +1,5 @@ -#ifndef PCMS_SRC_PCMS_PROFILE_H -#define PCMS_SRC_PCMS_PROFILE_H +#ifndef PCMS_UTILITY_DETAIL_PROFILE_HPP +#define PCMS_UTILITY_DETAIL_PROFILE_HPP #include // perfstubs currently has a buffer overflow @@ -9,4 +9,4 @@ // #define PCMS_FUNCTION_TIMER PERFSTUBS_SCOPED_TIMER_FUNC() #define PCMS_FUNCTION_TIMER -#endif // PCMS_SRC_PCMS_PROFILE_H +#endif // PCMS_UTILITY_DETAIL_PROFILE_HPP diff --git a/src/pcms/utility/entity_types.h b/include/pcms/utility/entity_types.hpp similarity index 59% rename from src/pcms/utility/entity_types.h rename to include/pcms/utility/entity_types.hpp index 90e36bb47..d60c8d90d 100644 --- a/src/pcms/utility/entity_types.h +++ b/include/pcms/utility/entity_types.hpp @@ -1,5 +1,5 @@ -#ifndef PCMS_UTILITY_ENTITY_TYPES_H -#define PCMS_UTILITY_ENTITY_TYPES_H +#ifndef PCMS_UTILITY_ENTITY_TYPES_HPP +#define PCMS_UTILITY_ENTITY_TYPES_HPP namespace pcms { @@ -11,4 +11,4 @@ inline constexpr int Region = 3; } // namespace pcms -#endif // PCMS_UTILITY_ENTITY_TYPES_H +#endif // PCMS_UTILITY_ENTITY_TYPES_HPP diff --git a/src/pcms/utility/eqdsk.h b/include/pcms/utility/eqdsk.hpp similarity index 95% rename from src/pcms/utility/eqdsk.h rename to include/pcms/utility/eqdsk.hpp index 57474171b..7999f02c2 100644 --- a/src/pcms/utility/eqdsk.h +++ b/include/pcms/utility/eqdsk.hpp @@ -1,9 +1,9 @@ -#ifndef PCMS_UTILITY_EQDSK_H -#define PCMS_UTILITY_EQDSK_H +#ifndef PCMS_UTILITY_EQDSK_HPP +#define PCMS_UTILITY_EQDSK_HPP -#include "pcms/utility/types.h" -#include "pcms/utility/uniform_grid.h" -#include "pcms/utility/memory_spaces.h" +#include "pcms/utility/types.hpp" +#include "pcms/utility/uniform_grid.hpp" +#include "pcms/utility/memory_spaces.hpp" #include #include #include @@ -136,4 +136,4 @@ struct EQDSKData } // namespace pcms -#endif // PCMS_UTILITY_EQDSK_H +#endif // PCMS_UTILITY_EQDSK_HPP diff --git a/src/pcms/utility/memory_spaces.h b/include/pcms/utility/memory_spaces.hpp similarity index 89% rename from src/pcms/utility/memory_spaces.h rename to include/pcms/utility/memory_spaces.hpp index b927d6342..901b8f34f 100644 --- a/src/pcms/utility/memory_spaces.h +++ b/include/pcms/utility/memory_spaces.hpp @@ -1,5 +1,5 @@ -#ifndef PCMS_COUPLING_MEMORY_SPACES_H -#define PCMS_COUPLING_MEMORY_SPACES_H +#ifndef PCMS_UTILITY_MEMORY_SPACES_HPP +#define PCMS_UTILITY_MEMORY_SPACES_HPP #include namespace pcms @@ -26,4 +26,4 @@ using DeviceMemorySpace = HostMemorySpace; } // namespace pcms -#endif // PCMS_COUPLING_MEMORY_SPACES_H +#endif // PCMS_UTILITY_MEMORY_SPACES_HPP diff --git a/src/pcms/utility/print.h b/include/pcms/utility/print.hpp similarity index 77% rename from src/pcms/utility/print.h rename to include/pcms/utility/print.hpp index 5ac8fd3b1..1cacb45d8 100644 --- a/src/pcms/utility/print.h +++ b/include/pcms/utility/print.hpp @@ -1,6 +1,6 @@ -#ifndef PCMS_PRINT_H -#define PCMS_PRINT_H -#include "pcms/configuration.h" +#ifndef PCMS_UTILITY_PRINT_HPP +#define PCMS_UTILITY_PRINT_HPP +#include "pcms/configuration.hpp" #include #include @@ -10,7 +10,7 @@ namespace pcms #if defined(__CUDA_ARCH__) || defined(__HIP_DEVICE_COMPILE__) || \ defined(__SYCL_DEVICE_ONLY__) -#define ACTIVE_GPU_EXECUTION +#define PCMS_ACTIVE_GPU_EXECUTION #endif FILE* getStdout(); @@ -30,7 +30,7 @@ void printError(const char* fmt, const Args&... args) template KOKKOS_INLINE_FUNCTION void printInfo(const char* fmt, const Args&... args) { -#if defined(PCMS_ENABLE_PRINT) && !defined(ACTIVE_GPU_EXECUTION) +#if defined(PCMS_ENABLE_PRINT) && !defined(PCMS_ACTIVE_GPU_EXECUTION) fprintf(getStdout(), fmt, args...); #endif } @@ -39,7 +39,7 @@ template KOKKOS_INLINE_FUNCTION void printDebugInfo(const char* fmt, const Args&... args) { #if !defined(NDEBUG) && defined(PCMS_ENABLE_PRINT) -#if !defined(ACTIVE_GPU_EXECUTION) +#if !defined(PCMS_ACTIVE_GPU_EXECUTION) fprintf(getStdout(), fmt, args...); #else // For GPU execution printf(fmt, args...); @@ -52,4 +52,4 @@ KOKKOS_INLINE_FUNCTION void printDebugInfo(const char* fmt, const Args&... args) } // namespace pcms -#endif // PCMS_PRINT_H +#endif // PCMS_UTILITY_PRINT_HPP diff --git a/src/pcms/utility/types.h b/include/pcms/utility/types.hpp similarity index 92% rename from src/pcms/utility/types.h rename to include/pcms/utility/types.hpp index b36c72c8d..90c990439 100644 --- a/src/pcms/utility/types.h +++ b/include/pcms/utility/types.hpp @@ -1,6 +1,6 @@ -#ifndef PCMS_COUPLING_TYPES_H -#define PCMS_COUPLING_TYPES_H -#include "assert.h" +#ifndef PCMS_UTILITY_TYPES_HPP +#define PCMS_UTILITY_TYPES_HPP +#include "pcms/utility/assert.hpp" #include #include @@ -70,4 +70,4 @@ auto apply_to_type(Type t, F&& f) } // namespace pcms -#endif // PCMS_COUPLING_TYPES_H +#endif // PCMS_UTILITY_TYPES_HPP diff --git a/src/pcms/utility/uniform_grid.h b/include/pcms/utility/uniform_grid.hpp similarity index 60% rename from src/pcms/utility/uniform_grid.h rename to include/pcms/utility/uniform_grid.hpp index e6730fcec..c4a211ce2 100644 --- a/src/pcms/utility/uniform_grid.h +++ b/include/pcms/utility/uniform_grid.hpp @@ -1,10 +1,7 @@ -#ifndef PCMS_COUPLING_UNIFORM_GRID_H -#define PCMS_COUPLING_UNIFORM_GRID_H -#include "pcms/utility/bounding_box.h" -#include "Omega_h_vector.hpp" -#include "Omega_h_bbox.hpp" -#include "Omega_h_mesh.hpp" -#include +#ifndef PCMS_UTILITY_UNIFORM_GRID_HPP +#define PCMS_UTILITY_UNIFORM_GRID_HPP +#include "pcms/utility/bounding_box.hpp" +#include #include #include #include @@ -29,11 +26,11 @@ struct UniformGrid } /// return the grid cell ID that the input point is inside or closest to if /// the point lies outside - // take the view as a template because it might be a subview type - // template - //[[nodiscard]] KOKKOS_INLINE_FUNCTION LO ClosestCellID(const T& point) const + /// `point` is any type indexable with point[i] for i < dim (e.g. + /// Kokkos::Array, a subview, Omega_h::Vector). + template [[nodiscard]] KOKKOS_INLINE_FUNCTION LO - ClosestCellID(const Omega_h::Vector& point) const + ClosestCellID(const Point& point) const { Kokkos::Array indexes; @@ -83,9 +80,11 @@ struct UniformGrid return {.center = center, .half_width = half_width}; } - /// Check if a point is within the grid bounds + /// Check if a point is within the grid bounds. `point` is any type + /// indexable with point[i] for i < dim. + template [[nodiscard]] KOKKOS_INLINE_FUNCTION bool IsPointInBounds( - const Omega_h::Vector& point) const + const Point& point) const { for (size_t i = 0; i < dim; ++i) { Real coord = point[i]; @@ -161,63 +160,6 @@ LO DivisionsPerAxisForMesh(LO nelems, LO min_divisions = 10) return std::max(per_axis, min_divisions); } -/** - * \brief Create a uniform grid layout from an Omega_h mesh as a bounding box - * - * This function computes the bounding box of the given mesh and creates a - * uniform Cartesian grid that covers the entire mesh domain. The grid cells - * are uniformly distributed across each dimension. - * - * \tparam dim Spatial dimension of the mesh (2 or 3) - * \param mesh The Omega_h mesh to create the grid from - * \param divisions Array specifying the number of cells in each dimension - * \return UniformGrid A uniform grid covering the mesh bounding box - * - */ -template -UniformGrid CreateUniformGridFromMesh(Omega_h::Mesh& mesh, - const std::array& divisions) -{ - // Get the bounding box of the mesh - auto bbox = Omega_h::get_bounding_box(&mesh); - - // Calculate edge lengths and bottom-left corner - Kokkos::Array edge_length; - Kokkos::Array bot_left; - Kokkos::Array divs; - - for (unsigned i = 0; i < dim; ++i) { - bot_left[i] = bbox.min[i]; - edge_length[i] = bbox.max[i] - bbox.min[i]; - divs[i] = divisions[i]; - } - - return UniformGrid{ - .edge_length = edge_length, .bot_left = bot_left, .divisions = divs}; -} - -/** - * \brief Create a uniform grid with equal divisions in all dimensions - * - * This is a convenience function that creates a uniform grid with the same - * number of cells in each dimension. - * - * \tparam dim Spatial dimension of the mesh (2 or 3) - * \param mesh The Omega_h mesh to create the grid from - * \param cells_per_dim Number of cells per dimension (same for all dimensions) - * \return UniformGrid A uniform grid covering the mesh bounding box - * - */ -template -UniformGrid CreateUniformGridFromMesh(Omega_h::Mesh& mesh, - LO cells_per_dim) -{ - std::array divisions; - for (unsigned i = 0; i < dim; ++i) - divisions[i] = cells_per_dim; - return CreateUniformGridFromMesh(mesh, divisions); -} - } // namespace pcms -#endif // PCMS_COUPLING_UNIFORM_GRID_H +#endif // PCMS_UTILITY_UNIFORM_GRID_HPP diff --git a/pyproject.toml b/pyproject.toml index 25dc90ec0..58184df3a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ name = "pcms" version = "0.4.0" [tool.scikit-build.cmake.define] -PCMS_ENABLE_Python = true +PCMS_ENABLE_PYTHON = true [tool.pytest.ini_options] testpaths = ["test/python"] diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e9d9313c6..2adb0686d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,17 +1,7 @@ -# TODO split out the field transfer library -set( - PCMS_HEADERS - pcms.h -) - -set( - PCMS_SOURCES - pcms.cpp -) +find_package(perfstubs REQUIRED) -configure_file(pcms/version.h.in pcms/version.h) -configure_file(pcms/configuration.h.in pcms/configuration.h) -list(APPEND PCMS_HEADERS ${CMAKE_CURRENT_BINARY_DIR}/pcms/version.h ${CMAKE_CURRENT_BINARY_DIR}/pcms/configuration.h) +configure_file(pcms/version.hpp.in pcms/version.hpp) +configure_file(pcms/configuration.hpp.in pcms/configuration.hpp) add_subdirectory(pcms/utility) if(PCMS_ENABLE_TRANSIENT) @@ -20,82 +10,55 @@ endif() add_subdirectory(pcms/discretization) add_subdirectory(pcms/localization) add_subdirectory(pcms/field) -add_subdirectory(pcms/coupler) - - - -find_package(Kokkos REQUIRED) -find_package(perfstubs REQUIRED) - -add_library(pcms_core ${PCMS_SOURCES}) -set_target_properties( - pcms_core PROPERTIES OUTPUT_NAME pcmscore EXPORT_NAME - core -) -add_library(pcms::core ALIAS pcms_core) -target_compile_features(pcms_core PUBLIC cxx_std_20) -target_link_libraries( - pcms_core PUBLIC redev::redev - MPI::MPI_CXX Kokkos::kokkos perfstubs pcms::utility pcms::localization pcms::field pcms::coupler -) - -if(PCMS_HAS_ASAN) - target_compile_options( - pcms_core PRIVATE -fsanitize=address - -fno-omit-frame-pointer - ) +if(PCMS_ENABLE_COUPLER) + add_subdirectory(pcms/coupler) endif() +# backend adapters; each adds its files to the core targets above +add_subdirectory(pcms/backends) -# export the library -set_target_properties(pcms_core PROPERTIES PUBLIC_HEADER "${PCMS_HEADERS}") -target_include_directories( - pcms_core - PUBLIC "$" - "$" - "$" -) +# Top-level and generated headers. They are found through pcms::utility's +# include directories (source and binary src/ directories). install( - TARGETS pcms_core - EXPORT pcms_core-targets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - INCLUDES - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/pcms -) + FILES ../include/pcms/pcms.hpp ${CMAKE_CURRENT_BINARY_DIR}/pcms/version.hpp + ${CMAKE_CURRENT_BINARY_DIR}/pcms/configuration.hpp + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/pcms) configure_package_config_file( "${CMAKE_SOURCE_DIR}/config.cmake.in" "${CMAKE_BINARY_DIR}/pcms-config.cmake" - INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pcms + INSTALL_DESTINATION ${PCMS_INSTALL_CMAKEDIR} ) write_basic_package_version_file( "${PROJECT_BINARY_DIR}/pcms-config-version.cmake" - COMPATIBILITY AnyNewerVersion + COMPATIBILITY SameMinorVersion ) install( FILES "${PROJECT_BINARY_DIR}/pcms-config.cmake" "${PROJECT_BINARY_DIR}/pcms-config-version.cmake" - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pcms + DESTINATION ${PCMS_INSTALL_CMAKEDIR} ) +# FindPETSc.cmake stays installed: the package config calls +# find_dependency(PETSc) when PETSc is enabled, which needs it. install(FILES "${CMAKE_SOURCE_DIR}/cmake/FindPETSc.cmake" - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pcms) + DESTINATION ${PCMS_INSTALL_CMAKEDIR}) -install( - EXPORT pcms_core-targets - NAMESPACE pcms:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pcms -) +# pcms::pcms links every PCMS library that was built; downstream codes +# should link it. add_library(pcms_pcms INTERFACE) -target_link_libraries(pcms_pcms INTERFACE pcms::core) +add_library(pcms::pcms ALIAS pcms_pcms) +target_link_libraries( + pcms_pcms INTERFACE pcms::utility pcms::discretization pcms::localization + pcms::field) +if(TARGET pcms::coupler) + target_link_libraries(pcms_pcms INTERFACE pcms::coupler) +endif() if(PCMS_ENABLE_TRANSIENT) target_link_libraries(pcms_pcms INTERFACE pcms::transient) endif() set_target_properties(pcms_pcms PROPERTIES EXPORT_NAME pcms) -if (PCMS_ENABLE_Python) +if (PCMS_ENABLE_PYTHON) # Disable LTO/IPO before adding Python subdirectory to avoid fatbinData conflicts set(CMAKE_INTERPROCEDURAL_OPTIMIZATION OFF) add_subdirectory(pcms/pythonapi) @@ -104,7 +67,7 @@ if(PCMS_ENABLE_C) add_subdirectory(pcms/capi) target_link_libraries(pcms_pcms INTERFACE pcms::capi) endif() -if(PCMS_ENABLE_Fortran) +if(PCMS_ENABLE_FORTRAN) add_subdirectory(pcms/fortranapi) target_link_libraries(pcms_pcms INTERFACE pcms::fortranapi) endif() @@ -112,6 +75,34 @@ endif() add_subdirectory(pcms/transfer) target_link_libraries(pcms_pcms INTERFACE pcms::transfer) +# Library versions: the SOVERSION is major.minor, since 0.x releases may +# break the ABI in every minor release (find_package uses SameMinorVersion). +foreach( + lib IN + ITEMS pcms_utility pcms_discretization pcms_localization pcms_field + pcms_transfer pcms_coupler pcms_transient pcms_capi_core + pcms_capi_transfer pcms_fortranapi_core pcms_fortranapi_transfer) + if(TARGET ${lib}) + set_target_properties( + ${lib} PROPERTIES VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}) + endif() +endforeach() + +# Deprecated: pcms::core used to be the coupler plus everything else. Kept +# for one release as an alias of pcms::pcms. +add_library(pcms_core INTERFACE) +add_library(pcms::core ALIAS pcms_core) +target_link_libraries(pcms_core INTERFACE pcms_pcms) +set_target_properties( + pcms_core PROPERTIES EXPORT_NAME core DEPRECATION + "pcms::core is deprecated; link pcms::pcms instead.") +install(TARGETS pcms_core EXPORT pcms_core-targets) +install( + EXPORT pcms_core-targets + NAMESPACE pcms:: + DESTINATION ${PCMS_INSTALL_CMAKEDIR}) + install( TARGETS pcms_pcms EXPORT pcms-targets @@ -123,13 +114,8 @@ install( ) -# install external headers -install( - DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/pcms/external/ - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/pcms/external -) install( EXPORT pcms-targets NAMESPACE pcms:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pcms + DESTINATION ${PCMS_INSTALL_CMAKEDIR} ) diff --git a/src/pcms.cpp b/src/pcms.cpp deleted file mode 100644 index 2d357381c..000000000 --- a/src/pcms.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include "pcms.h" -#include "pcms/utility/types.h" -#include "redev.h" -#include "Omega_h_mesh.hpp" - -namespace pcms -{ -static_assert(std::is_same_v, - "pcms and redev real types must match"); -static_assert(std::is_same_v, - "pcms and redev LO types must match"); -static_assert(std::is_same_v, - "pcms and redev GO types must match"); -#ifdef PCMS_ENABLE_OMEGA_H -static_assert(std::is_same_v, - "pcms and Omega_h real types must match"); -static_assert(std::is_same_v, - "pcms and Omega_h LO types must match"); -static_assert(std::is_same_v, - "pcms and Omega_h GO types must match"); -#endif -} // namespace pcms diff --git a/src/pcms.h b/src/pcms.h deleted file mode 100644 index a98dc025d..000000000 --- a/src/pcms.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef PCMS_H_ -#define PCMS_H_ - -#include "pcms/configuration.h" -#include "pcms/utility/common.h" -#include "pcms/utility/profile.h" - -#endif diff --git a/src/pcms/backends/CMakeLists.txt b/src/pcms/backends/CMakeLists.txt new file mode 100644 index 000000000..4736dc82b --- /dev/null +++ b/src/pcms/backends/CMakeLists.txt @@ -0,0 +1,14 @@ +# Backend adapters. A backend is a directory and a namespace +# (pcms::backend::), not a separate library: each backend adds its +# sources and headers to the core target that uses it. +add_subdirectory(omega_h) +add_subdirectory(xgc) +add_subdirectory(point_cloud) +add_subdirectory(uniform_grid) +if(PCMS_ENABLE_MFEM) + add_subdirectory(mfem) +endif() +# bridges: built only when both backends are enabled +if(PCMS_ENABLE_OMEGA_H AND PCMS_ENABLE_MESHFIELDS) + add_subdirectory(omega_h_meshfields) +endif() diff --git a/src/pcms/backends/mfem/CMakeLists.txt b/src/pcms/backends/mfem/CMakeLists.txt new file mode 100644 index 000000000..5ca0d06d6 --- /dev/null +++ b/src/pcms/backends/mfem/CMakeLists.txt @@ -0,0 +1,9 @@ +# MFEM backend: layout, field data and field factory, part of pcms::field. +# Public header: include/pcms/backends/mfem/. +target_sources( + pcms_field + PRIVATE layout.cpp field_data.cpp mfem.cpp layout.hpp field_data.hpp + field_factory.hpp + PUBLIC FILE_SET field TYPE HEADERS BASE_DIRS ${PROJECT_SOURCE_DIR}/include/pcms + FILES ${PROJECT_SOURCE_DIR}/include/pcms/backends/mfem/mfem.hpp) +target_link_libraries(pcms_field PUBLIC mfem) diff --git a/src/pcms/field/data/mfem.cpp b/src/pcms/backends/mfem/field_data.cpp similarity index 81% rename from src/pcms/field/data/mfem.cpp rename to src/pcms/backends/mfem/field_data.cpp index 00405bad9..3bdd545ad 100644 --- a/src/pcms/field/data/mfem.cpp +++ b/src/pcms/backends/mfem/field_data.cpp @@ -1,14 +1,14 @@ -#include "pcms/field/data/mfem.hpp" +#include "pcms/backends/mfem/field_data.hpp" -#include "pcms/utility/arrays.h" -#include "pcms/utility/assert.h" -#include "pcms/utility/profile.h" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/detail/profile.hpp" -namespace pcms +namespace pcms::backend::mfem { -MFEMVertexFieldData::MFEMVertexFieldData(mfem::ParFiniteElementSpace& pfes, - mfem::ParGridFunction& gf, +MFEMVertexFieldData::MFEMVertexFieldData(::mfem::ParFiniteElementSpace& pfes, + ::mfem::ParGridFunction& gf, ValueBasis basis) : pfes_(pfes), gf_(gf), @@ -38,10 +38,10 @@ Rank2View MFEMVertexFieldData::GatherHost() const // Pull owner values into a true-DOF vector via the parallel restriction so // every shared vertex reports its owner's value. - mfem::Vector true_values(pfes_.GetTrueVSize()); + ::mfem::Vector true_values(pfes_.GetTrueVSize()); gf_.GetTrueDofs(true_values); - mfem::Array vdofs; + ::mfem::Array vdofs; const int nv = pfes_.GetNDofs(); for (int v = 0; v < nv; ++v) { pfes_.GetVertexDofs(v, vdofs); @@ -64,8 +64,8 @@ void MFEMVertexFieldData::ScatterHost( // Scatter received owner values into a true-DOF vector, then distribute to // all local DOFs (including shared, non-owned vertices) via the parallel // prolongation. - mfem::Vector true_values(pfes_.GetTrueVSize()); - mfem::Array vdofs; + ::mfem::Vector true_values(pfes_.GetTrueVSize()); + ::mfem::Array vdofs; for (int v = 0; v < nv; ++v) { pfes_.GetVertexDofs(v, vdofs); PCMS_ALWAYS_ASSERT(vdofs.Size() == 1); @@ -94,4 +94,4 @@ void MFEMVertexFieldData::SetOwnedValues( ScatterHost(MakeConstRank2View(host_data_)); } -} // namespace pcms +} // namespace pcms::backend::mfem diff --git a/src/pcms/field/data/mfem.hpp b/src/pcms/backends/mfem/field_data.hpp similarity index 66% rename from src/pcms/field/data/mfem.hpp rename to src/pcms/backends/mfem/field_data.hpp index be7837a13..6b1c71c4c 100644 --- a/src/pcms/field/data/mfem.hpp +++ b/src/pcms/backends/mfem/field_data.hpp @@ -1,13 +1,13 @@ -#ifndef PCMS_FIELD_DATA_MFEM_HPP -#define PCMS_FIELD_DATA_MFEM_HPP +#ifndef PCMS_BACKENDS_MFEM_FIELD_DATA_HPP +#define PCMS_BACKENDS_MFEM_FIELD_DATA_HPP -#include "pcms/field/field_data.h" +#include "pcms/field/field_data.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/utility/arrays.h" +#include "pcms/utility/arrays.hpp" #include -namespace pcms +namespace pcms::backend::mfem { // FieldData backend for an MFEM order-1 H1 (vertex) scalar field. @@ -16,8 +16,8 @@ class MFEMVertexFieldData , public DOFAccess { public: - MFEMVertexFieldData(mfem::ParFiniteElementSpace& pfes, - mfem::ParGridFunction& gf, ValueBasis basis = {}); + MFEMVertexFieldData(::mfem::ParFiniteElementSpace& pfes, + ::mfem::ParGridFunction& gf, ValueBasis basis = {}); FieldValueType GetValueType() const override; const ValueBasis& GetValueBasis() const override; @@ -32,13 +32,13 @@ class MFEMVertexFieldData Rank2View GatherHost() const; void ScatterHost(Rank2View data); - mfem::ParFiniteElementSpace& pfes_; - mfem::ParGridFunction& gf_; + ::mfem::ParFiniteElementSpace& pfes_; + ::mfem::ParGridFunction& gf_; ValueBasis basis_; mutable Kokkos::View host_data_; mutable Kokkos::View device_data_; }; -} // namespace pcms +} // namespace pcms::backend::mfem -#endif // PCMS_FIELD_DATA_MFEM_HPP +#endif // PCMS_BACKENDS_MFEM_FIELD_DATA_HPP diff --git a/src/pcms/field/function_space/mfem.hpp b/src/pcms/backends/mfem/field_factory.hpp similarity index 78% rename from src/pcms/field/function_space/mfem.hpp rename to src/pcms/backends/mfem/field_factory.hpp index a3b8820d9..493531587 100644 --- a/src/pcms/field/function_space/mfem.hpp +++ b/src/pcms/backends/mfem/field_factory.hpp @@ -1,12 +1,12 @@ -#ifndef PCMS_MFEM_FIELD_FACTORY_HPP -#define PCMS_MFEM_FIELD_FACTORY_HPP +#ifndef PCMS_BACKENDS_MFEM_FIELD_FACTORY_HPP +#define PCMS_BACKENDS_MFEM_FIELD_FACTORY_HPP -#include "pcms/field/coordinate_system.hpp" -#include "pcms/field/data/mfem.hpp" -#include "pcms/field/field_factory.h" -#include "pcms/field/layout/mfem.hpp" -#include "pcms/utility/assert.h" -#include "pcms/utility/common.h" +#include "pcms/utility/coordinate_system.hpp" +#include "pcms/backends/mfem/field_data.hpp" +#include "pcms/field/field_factory.hpp" +#include "pcms/backends/mfem/layout.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/detail/common.hpp" #include @@ -14,7 +14,7 @@ #include #include -namespace pcms +namespace pcms::backend::mfem { // Communication-only field factory for an MFEM order-1 H1 (vertex) scalar @@ -26,8 +26,8 @@ namespace pcms class MFEMFieldFactory : public FieldFactory { public: - MFEMFieldFactory(mfem::ParMesh& pmesh, mfem::ParFiniteElementSpace& pfes, - mfem::ParGridFunction& gf, + MFEMFieldFactory(::mfem::ParMesh& pmesh, ::mfem::ParFiniteElementSpace& pfes, + ::mfem::ParGridFunction& gf, std::shared_ptr coordinate_system, std::string layout_name = "") : layout_(std::make_shared(pmesh, pfes, @@ -84,10 +84,10 @@ class MFEMFieldFactory : public FieldFactory private: std::shared_ptr layout_; - mfem::ParFiniteElementSpace& pfes_; - mfem::ParGridFunction& gf_; + ::mfem::ParFiniteElementSpace& pfes_; + ::mfem::ParGridFunction& gf_; }; -} // namespace pcms +} // namespace pcms::backend::mfem -#endif // PCMS_MFEM_FIELD_FACTORY_HPP +#endif // PCMS_BACKENDS_MFEM_FIELD_FACTORY_HPP diff --git a/src/pcms/field/layout/mfem.cpp b/src/pcms/backends/mfem/layout.cpp similarity index 87% rename from src/pcms/field/layout/mfem.cpp rename to src/pcms/backends/mfem/layout.cpp index 3e70e584c..d00ddd1ff 100644 --- a/src/pcms/field/layout/mfem.cpp +++ b/src/pcms/backends/mfem/layout.cpp @@ -1,13 +1,13 @@ -#include "pcms/field/layout/mfem.hpp" +#include "pcms/backends/mfem/layout.hpp" -#include "pcms/discretization/discretization/point_cloud.hpp" -#include "pcms/utility/arrays.h" -#include "pcms/utility/assert.h" -#include "pcms/utility/profile.h" +#include "pcms/backends/point_cloud/discretization.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/detail/profile.hpp" #include -namespace pcms +namespace pcms::backend::mfem { namespace @@ -16,13 +16,14 @@ namespace std::shared_ptr MakeVertexDiscretization( int dim, Kokkos::View coords_host) { - return std::make_shared(dim, coords_host); + return std::make_shared( + dim, coords_host); } } // namespace MFEMLayout::MFEMLayout( - mfem::ParMesh& pmesh, mfem::ParFiniteElementSpace& pfes, + ::mfem::ParMesh& pmesh, ::mfem::ParFiniteElementSpace& pfes, std::shared_ptr coordinate_system) : pmesh_(pmesh), pfes_(pfes), dim_(pmesh.SpaceDimension()) { @@ -45,7 +46,7 @@ MFEMLayout::MFEMLayout( coords_ = Kokkos::View("mfem_coords", nv, dim_); Kokkos::deep_copy(coords_, coords_host); - mfem::Array vertex_gids; + ::mfem::Array vertex_gids; pmesh_.GetGlobalVertexIndices(vertex_gids); gids_host_ = Kokkos::View("mfem_gids", nv); owned_host_ = Kokkos::View("mfem_owned", nv); @@ -54,7 +55,7 @@ MFEMLayout::MFEMLayout( classification_ids_host_ = Kokkos::View("mfem_class_ids", nv); - mfem::Array vdofs; + ::mfem::Array vdofs; for (int v = 0; v < nv; ++v) { pfes_.GetVertexDofs(v, vdofs); PCMS_ALWAYS_ASSERT(vdofs.Size() == 1); @@ -146,7 +147,7 @@ MFEMLayout::GetDOFHolderClassificationIdsHost() const } Kokkos::View MFEMLayout::OverlapMaskFromAttribute( - mfem::ParMesh& pmesh, int attribute) + ::mfem::ParMesh& pmesh, int attribute) { PCMS_FUNCTION_TIMER; @@ -154,7 +155,7 @@ Kokkos::View MFEMLayout::OverlapMaskFromAttribute( Kokkos::View overlap("mfem_overlap_mask", nv); Kokkos::deep_copy(overlap, false); - mfem::Array verts; + ::mfem::Array verts; for (int e = 0; e < pmesh.GetNE(); ++e) { if (pmesh.GetAttribute(e) != attribute) { continue; @@ -168,4 +169,4 @@ Kokkos::View MFEMLayout::OverlapMaskFromAttribute( return overlap; } -} // namespace pcms +} // namespace pcms::backend::mfem diff --git a/src/pcms/field/layout/mfem.hpp b/src/pcms/backends/mfem/layout.hpp similarity index 72% rename from src/pcms/field/layout/mfem.hpp rename to src/pcms/backends/mfem/layout.hpp index edad78ead..d0c66b799 100644 --- a/src/pcms/field/layout/mfem.hpp +++ b/src/pcms/backends/mfem/layout.hpp @@ -1,21 +1,21 @@ -#ifndef PCMS_FIELD_LAYOUT_MFEM_HPP -#define PCMS_FIELD_LAYOUT_MFEM_HPP +#ifndef PCMS_BACKENDS_MFEM_LAYOUT_HPP +#define PCMS_BACKENDS_MFEM_LAYOUT_HPP -#include "pcms/field/coordinate_system.hpp" -#include "pcms/field/field_layout.h" +#include "pcms/utility/coordinate_system.hpp" +#include "pcms/field/field_layout.hpp" #include #include -namespace pcms +namespace pcms::backend::mfem { // Field layout for an MFEM order-1 H1 (vertex) scalar field. class MFEMLayout : public FieldLayout { public: - MFEMLayout(mfem::ParMesh& pmesh, mfem::ParFiniteElementSpace& pfes, + MFEMLayout(::mfem::ParMesh& pmesh, ::mfem::ParFiniteElementSpace& pfes, std::shared_ptr coordinate_system); std::shared_ptr GetDiscretization() @@ -39,18 +39,18 @@ class MFEMLayout : public FieldLayout Rank1View GetDOFHolderClassificationIdsHost() const override; - mfem::ParMesh& GetMesh() const noexcept { return pmesh_; } - mfem::ParFiniteElementSpace& GetFESpace() const noexcept { return pfes_; } + ::mfem::ParMesh& GetMesh() const noexcept { return pmesh_; } + ::mfem::ParFiniteElementSpace& GetFESpace() const noexcept { return pfes_; } // Build a per-vertex overlap mask from MFEM element attributes static Kokkos::View OverlapMaskFromAttribute( - mfem::ParMesh& pmesh, int attribute); + ::mfem::ParMesh& pmesh, int attribute); private: void AssertVertexScalarSpace() const; - mfem::ParMesh& pmesh_; - mfem::ParFiniteElementSpace& pfes_; + ::mfem::ParMesh& pmesh_; + ::mfem::ParFiniteElementSpace& pfes_; int dim_; Kokkos::View coords_; @@ -61,6 +61,6 @@ class MFEMLayout : public FieldLayout std::shared_ptr discretization_; }; -} // namespace pcms +} // namespace pcms::backend::mfem -#endif // PCMS_FIELD_LAYOUT_MFEM_HPP +#endif // PCMS_BACKENDS_MFEM_LAYOUT_HPP diff --git a/src/pcms/backends/mfem/mfem.cpp b/src/pcms/backends/mfem/mfem.cpp new file mode 100644 index 000000000..1ee46dda6 --- /dev/null +++ b/src/pcms/backends/mfem/mfem.cpp @@ -0,0 +1,24 @@ +#include "pcms/backends/mfem/mfem.hpp" +#include "pcms/backends/mfem/field_factory.hpp" +#include "pcms/backends/mfem/layout.hpp" + +namespace pcms::backend::mfem +{ + +std::shared_ptr CreateFieldFactory( + ::mfem::ParMesh& pmesh, ::mfem::ParFiniteElementSpace& pfes, + ::mfem::ParGridFunction& gf, + std::shared_ptr coordinate_system, + std::string layout_name) +{ + return std::make_shared( + pmesh, pfes, gf, std::move(coordinate_system), std::move(layout_name)); +} + +Kokkos::View OverlapMaskFromAttribute( + ::mfem::ParMesh& pmesh, int attribute) +{ + return MFEMLayout::OverlapMaskFromAttribute(pmesh, attribute); +} + +} // namespace pcms::backend::mfem diff --git a/src/pcms/backends/omega_h/CMakeLists.txt b/src/pcms/backends/omega_h/CMakeLists.txt new file mode 100644 index 000000000..2e0893551 --- /dev/null +++ b/src/pcms/backends/omega_h/CMakeLists.txt @@ -0,0 +1,23 @@ +# Omega_h adapter. Public header: include/pcms/backends/omega_h/. + +# Adjacency search: part of pcms::localization, which always uses Omega_h. +target_sources(pcms_localization PRIVATE adj_search.cpp adj_search.hpp + queue_visited.hpp) + +if(PCMS_ENABLE_OMEGA_H) + # discretization and the public entry points: part of pcms::discretization + target_sources( + pcms_discretization + PRIVATE discretization.cpp omega_h.cpp discretization.hpp + PUBLIC FILE_SET field_discretization TYPE HEADERS BASE_DIRS + ${PROJECT_SOURCE_DIR}/include/pcms FILES + ${PROJECT_SOURCE_DIR}/include/pcms/backends/omega_h/omega_h.hpp) + + # layouts, Lagrange evaluator and the uniform-grid binary field: part of + # pcms::field + target_sources( + pcms_field + PRIVATE entity_layout.cpp lagrange_layout.cpp uniform_grid_binary_field.cpp + entity_layout.hpp lagrange_layout.hpp lagrange_evaluator.hpp + uniform_grid_binary_field.hpp) +endif() diff --git a/src/pcms/localization/adj_search.cpp b/src/pcms/backends/omega_h/adj_search.cpp similarity index 89% rename from src/pcms/localization/adj_search.cpp rename to src/pcms/backends/omega_h/adj_search.cpp index b15925d71..7e1a6b655 100644 --- a/src/pcms/localization/adj_search.cpp +++ b/src/pcms/backends/omega_h/adj_search.cpp @@ -1,13 +1,13 @@ -#include "pcms/localization/adj_search.hpp" +#include "pcms/backends/omega_h/adj_search.hpp" #include -namespace pcms +namespace pcms::backend::omega_h { // Debug helper retained intentionally: useful for diagnosing point-localization // failures while developing support-search logic. [[maybe_unused]] static void checkTargetPoints( - const Kokkos::View& results, + const Kokkos::View& results, const Kokkos::View& owning_cell_ids) { Kokkos::fence(); @@ -90,7 +90,7 @@ static Omega_h::Write locate_target_cells( }); Kokkos::fence(); - pcms::GridPointSearch2D search_cell(source_mesh, 10, 10); + pcms::localization::GridPointSearch2D search_cell(source_mesh, 10, 10); auto results = search_cell(target_points); auto owning_cell_ids = search_cell.GetOwningElementIds(results); Omega_h::parallel_for( @@ -113,7 +113,7 @@ static Omega_h::Write locate_target_cells( }); Kokkos::fence(); - pcms::GridPointSearch3D search_cell(source_mesh, 10, 10, 10); + pcms::localization::GridPointSearch3D search_cell(source_mesh, 10, 10, 10); auto results = search_cell(target_points); auto owning_cell_ids = search_cell.GetOwningElementIds(results); Omega_h::parallel_for( @@ -171,7 +171,7 @@ OMEGA_H_INLINE void add_support_if_unvisited_and_within_cutoff( } const Omega_h::Real dist = - pcms::distance_squared(target_coords, candidate_coords, dim); + pcms::utility::distance_squared(target_coords, candidate_coords, dim); if (dist <= cutoff_distance) { count++; queue.push_back(candidate_id); @@ -300,7 +300,8 @@ void FindSupports::adjBasedSearchCentroidNodes( OMEGA_H_CHECK_PRINTF(source_mesh.dim() == 2, "Only 2D meshes are supported but found %d\n", source_mesh.dim()); - auto cell_centroids = pcms::get_entity_centroids(source_mesh, Omega_h::FACE); + auto cell_centroids = + pcms::utility::get_entity_centroids(source_mesh, Omega_h::FACE); Omega_h::parallel_for( nvertices, @@ -358,13 +359,11 @@ void FindSupports::adjBasedSearchCentroidNodes( "count the number of supports in each target point"); } -SupportResults searchNeighbors(Omega_h::Mesh& source_mesh, - const Omega_h::Reals& target_coords, - Omega_h::LO nvertices_target, - Omega_h::Real& cutoffDistance, - Omega_h::LO min_req_support, - Omega_h::LO max_allowed_support, - bool adapt_radius) +pcms::localization::SupportResults searchNeighbors( + Omega_h::Mesh& source_mesh, const Omega_h::Reals& target_coords, + Omega_h::LO nvertices_target, Omega_h::Real& cutoffDistance, + Omega_h::LO min_req_support, Omega_h::LO max_allowed_support, + bool adapt_radius) { Omega_h::Write nSupports( nvertices_target, 0, "number of supports in each target vertex"); @@ -405,15 +404,16 @@ SupportResults searchNeighbors(Omega_h::Mesh& source_mesh, unsigned min_supports_found = 0; unsigned max_supports_found = 0; - minmax(nSupports, min_supports_found, max_supports_found); + pcms::localization::minmax(nSupports, min_supports_found, + max_supports_found); r_adjust_loop++; pcms::printInfo( "Iter: %d min_nSupports: %d max_nSupports: %d, max_radius %f\n", r_adjust_loop, min_supports_found, max_supports_found, max_radius); - if (within_number_of_support_range(min_supports_found, max_supports_found, - min_req_support, - 3 * min_req_support)) { + if (pcms::localization::within_number_of_support_range( + min_supports_found, max_supports_found, min_req_support, + 3 * min_req_support)) { break; } @@ -425,8 +425,8 @@ SupportResults searchNeighbors(Omega_h::Mesh& source_mesh, break; } - adapt_radii(min_req_support, max_allowed_support, nvertices_target, - radii2, nSupports); + pcms::localization::adapt_radii(min_req_support, max_allowed_support, + nvertices_target, radii2, nSupports); } pcms::printInfo("INFO: Took %d loops to adjust the radius\n", @@ -446,15 +446,14 @@ SupportResults searchNeighbors(Omega_h::Mesh& source_mesh, supports_ptr, nSupports, supports_idx, radii2, false); - return SupportResults{read(supports_ptr), read(supports_idx), radii2}; + return pcms::localization::SupportResults{read(supports_ptr), + read(supports_idx), radii2}; } -SupportResults searchNeighbors(Omega_h::Mesh& source_mesh, - Omega_h::Mesh& target_mesh, - Omega_h::Real& cutoffDistance, - Omega_h::LO min_req_support, - Omega_h::LO max_allowed_support, - bool adapt_radius) +pcms::localization::SupportResults searchNeighbors( + Omega_h::Mesh& source_mesh, Omega_h::Mesh& target_mesh, + Omega_h::Real& cutoffDistance, Omega_h::LO min_req_support, + Omega_h::LO max_allowed_support, bool adapt_radius) { auto target_coords = target_mesh.coords(); auto result = searchNeighbors( @@ -464,9 +463,10 @@ SupportResults searchNeighbors(Omega_h::Mesh& source_mesh, return result; } -SupportResults searchNeighbors(Omega_h::Mesh& mesh, - Omega_h::Real cutoffDistance, - Omega_h::LO min_support, bool adapt_radius) +pcms::localization::SupportResults searchNeighbors(Omega_h::Mesh& mesh, + Omega_h::Real cutoffDistance, + Omega_h::LO min_support, + bool adapt_radius) { Omega_h::Write supports_ptr; Omega_h::Write supports_idx; @@ -503,7 +503,7 @@ SupportResults searchNeighbors(Omega_h::Mesh& mesh, Kokkos::fence(); unsigned min_nSupports = 0; unsigned max_nSupports = 0; - minmax(nSupports, min_nSupports, max_nSupports); + pcms::localization::minmax(nSupports, min_nSupports, max_nSupports); r_adjust_loop++; pcms::printInfo( @@ -511,8 +511,8 @@ SupportResults searchNeighbors(Omega_h::Mesh& mesh, "max_radius %f\n", r_adjust_loop, min_nSupports, max_nSupports, r_adjust_loop, max_radius); - if (within_number_of_support_range(min_nSupports, max_nSupports, - min_support, 3 * min_support)) { + if (pcms::localization::within_number_of_support_range( + min_nSupports, max_nSupports, min_support, 3 * min_support)) { break; } @@ -524,8 +524,8 @@ SupportResults searchNeighbors(Omega_h::Mesh& mesh, break; } - adapt_radii(min_support, 3 * min_support, radii2.size(), radii2, - nSupports); + pcms::localization::adapt_radii(min_support, 3 * min_support, + radii2.size(), radii2, nSupports); } pcms::printInfo("INFO: Took %d loops to adjust the radius\n", r_adjust_loop); @@ -547,7 +547,8 @@ SupportResults searchNeighbors(Omega_h::Mesh& mesh, radii2, false); mesh.add_tag(Omega_h::VERT, "support_radius", 1, radii2); - return SupportResults{read(supports_ptr), read(supports_idx), radii2}; + return pcms::localization::SupportResults{read(supports_ptr), + read(supports_idx), radii2}; } -} // namespace pcms +} // namespace pcms::backend::omega_h diff --git a/src/pcms/backends/omega_h/adj_search.hpp b/src/pcms/backends/omega_h/adj_search.hpp new file mode 100644 index 000000000..c857d3370 --- /dev/null +++ b/src/pcms/backends/omega_h/adj_search.hpp @@ -0,0 +1,61 @@ +#ifndef PCMS_BACKENDS_OMEGA_H_ADJ_SEARCH_HPP +#define PCMS_BACKENDS_OMEGA_H_ADJ_SEARCH_HPP + +#include +#include +#include +#include +#include +#include + +#include + +namespace pcms::backend::omega_h +{ + +static constexpr int max_dim = 3; + +class FindSupports +{ +private: + Omega_h::Mesh& source_mesh; + Omega_h::Mesh& target_mesh; + +public: + FindSupports(Omega_h::Mesh& source_mesh_, Omega_h::Mesh& target_mesh_) + : source_mesh(source_mesh_), target_mesh(target_mesh_) {}; + + FindSupports(Omega_h::Mesh& mesh_) + : source_mesh(mesh_), target_mesh(mesh_) {}; + + void adjBasedSearch(Omega_h::Write& supports_ptr, + Omega_h::Write& nSupports, + Omega_h::Write& support_idx, + Omega_h::Write& radii2, + bool is_build_csr_call); + + void adjBasedSearchCentroidNodes(Omega_h::Write& supports_ptr, + Omega_h::Write& nSupports, + Omega_h::Write& support_idx, + Omega_h::Write& radii2, + bool is_build_csr_call); +}; + +pcms::localization::SupportResults searchNeighbors( + Omega_h::Mesh& source_mesh, const Omega_h::Reals& target_coords, + Omega_h::LO n_targets, Omega_h::Real& cutoffDistance, + Omega_h::LO min_req_support = 12, Omega_h::LO max_allowed_support = 36, + bool adapt_radius = true); + +pcms::localization::SupportResults searchNeighbors( + Omega_h::Mesh& source_mesh, Omega_h::Mesh& target_mesh, + Omega_h::Real& cutoffDistance, Omega_h::LO min_req_support = 12, + Omega_h::LO max_allowed_support = 36, bool adapt_radius = true); + +pcms::localization::SupportResults searchNeighbors(Omega_h::Mesh& mesh, + Omega_h::Real cutoffDistance, + Omega_h::LO min_support = 12, + bool adapt_radius = true); +} // namespace pcms::backend::omega_h + +#endif // PCMS_BACKENDS_OMEGA_H_ADJ_SEARCH_HPP diff --git a/src/pcms/discretization/discretization/omega_h.cpp b/src/pcms/backends/omega_h/discretization.cpp similarity index 72% rename from src/pcms/discretization/discretization/omega_h.cpp rename to src/pcms/backends/omega_h/discretization.cpp index fcc6f5caa..7b9322d2d 100644 --- a/src/pcms/discretization/discretization/omega_h.cpp +++ b/src/pcms/backends/omega_h/discretization.cpp @@ -1,9 +1,18 @@ -#include "pcms/discretization/discretization/omega_h.hpp" -#include "pcms/utility/assert.h" -#include "pcms/utility/mesh_geometry.h" +#include "pcms/backends/omega_h/discretization.hpp" +#include "pcms/utility/types.hpp" +#include +#include "pcms/utility/assert.hpp" +#include "pcms/utility/mesh_geometry.hpp" -namespace pcms +namespace pcms::backend::omega_h { +// pcms and Omega_h exchange data without conversion +static_assert(std::is_same_v, + "pcms and Omega_h real types must match"); +static_assert(std::is_same_v, + "pcms and Omega_h LO types must match"); +static_assert(std::is_same_v, + "pcms and Omega_h GO types must match"); static_assert(std::is_same_v, "ClassificationId must match Omega_h::ClassId for direct views"); @@ -11,6 +20,15 @@ static_assert( std::is_same_v, "ClassificationDimension must match Omega_h::I8 for direct views"); +OmegaHDiscretization::OmegaHDiscretization( + Omega_h::Mesh& mesh, std::string global_id_name, + std::optional> owned_mask) + : OmegaHDiscretization(mesh) +{ + global_id_name_ = std::move(global_id_name); + owned_mask_ = std::move(owned_mask); +} + OmegaHDiscretization::OmegaHDiscretization(Omega_h::Mesh& mesh) : mesh_(mesh) { for (int entity_dim = 0; entity_dim <= max_entity_dim_; ++entity_dim) { @@ -66,4 +84,4 @@ OmegaHDiscretization::GetEntityClassificationIds(int entity_dim) const ids.size()); } -} // namespace pcms +} // namespace pcms::backend::omega_h diff --git a/src/pcms/discretization/discretization/omega_h.hpp b/src/pcms/backends/omega_h/discretization.hpp similarity index 52% rename from src/pcms/discretization/discretization/omega_h.hpp rename to src/pcms/backends/omega_h/discretization.hpp index 3fcb7eabc..3d380b096 100644 --- a/src/pcms/discretization/discretization/omega_h.hpp +++ b/src/pcms/backends/omega_h/discretization.hpp @@ -1,14 +1,16 @@ -#ifndef PCMS_DISCRETIZATION_DISCRETIZATION_OMEGA_H_H -#define PCMS_DISCRETIZATION_DISCRETIZATION_OMEGA_H_H +#ifndef PCMS_BACKENDS_OMEGA_H_DISCRETIZATION_HPP +#define PCMS_BACKENDS_OMEGA_H_DISCRETIZATION_HPP -#include "pcms/discretization/discretization.h" +#include "pcms/discretization/discretization.hpp" #include #include #include +#include +#include -namespace pcms +namespace pcms::backend::omega_h { class OmegaHDiscretization : public Discretization @@ -16,6 +18,12 @@ class OmegaHDiscretization : public Discretization public: explicit OmegaHDiscretization(Omega_h::Mesh& mesh); + // global_id_name: tag holding global vertex/element ids; owned_mask: + // optional per-vertex ownership used instead of the mesh's partition. + OmegaHDiscretization( + Omega_h::Mesh& mesh, std::string global_id_name, + std::optional> owned_mask = std::nullopt); + bool SameEntities(const Discretization& other) const noexcept override; int GetDimension() const override; @@ -31,16 +39,28 @@ class OmegaHDiscretization : public Discretization // The Omega_h mesh this discretization is defined on. Omega_h::Mesh& GetMesh() const noexcept { return mesh_; } + const std::string& GetGlobalIdName() const noexcept + { + return global_id_name_; + } + + const std::optional>& GetOwnedMask() const noexcept + { + return owned_mask_; + } + private: static constexpr int max_entity_dim_ = Region; Omega_h::Mesh& mesh_; + std::string global_id_name_ = "global"; + std::optional> owned_mask_; std::array, max_entity_dim_ + 1> class_dims_by_dim_; std::array, max_entity_dim_ + 1> class_ids_by_dim_; }; -} // namespace pcms +} // namespace pcms::backend::omega_h -#endif // PCMS_DISCRETIZATION_DISCRETIZATION_OMEGA_H_H +#endif // PCMS_BACKENDS_OMEGA_H_DISCRETIZATION_HPP diff --git a/src/pcms/field/layout/omega_h_entity.cpp b/src/pcms/backends/omega_h/entity_layout.cpp similarity index 90% rename from src/pcms/field/layout/omega_h_entity.cpp rename to src/pcms/backends/omega_h/entity_layout.cpp index bbf5e4ae1..5f6901726 100644 --- a/src/pcms/field/layout/omega_h_entity.cpp +++ b/src/pcms/backends/omega_h/entity_layout.cpp @@ -1,10 +1,10 @@ -#include "pcms/field/layout/omega_h_entity.h" +#include "pcms/backends/omega_h/entity_layout.hpp" -#include "pcms/utility/assert.h" -#include "pcms/utility/mesh_geometry.h" -#include "pcms/utility/omega_h_array_utils.h" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/mesh_geometry.hpp" +#include "pcms/utility/omega_h_array_utils.hpp" -namespace pcms +namespace pcms::backend::omega_h { namespace @@ -56,13 +56,14 @@ OmegaHEntityLayout::OmegaHEntityLayout( std::string global_id_name) // dimension_ is the first member, so this runs before the class_ids_/ // class_dims_ initializers below read the mesh's classification tags. - : dimension_((EnsureClassification(mesh), mesh.dim())), + : dimension_((pcms::utility::EnsureClassification(mesh), mesh.dim())), entity_dim_(entity_dim), num_components_(num_components), num_global_dof_holder_(mesh.nglobal_ents(entity_dim)), gids_(BuildGids(mesh, entity_dim, global_id_name)), - coords_(get_entity_centroids(mesh, entity_dim)), - coords_2d_(ConvertCoordsTo2D(coords_, mesh.nents(entity_dim), mesh.dim())), + coords_(pcms::utility::get_entity_centroids(mesh, entity_dim)), + coords_2d_(pcms::utility::ConvertCoordsTo2D(coords_, mesh.nents(entity_dim), + mesh.dim())), class_ids_(mesh.get_array(entity_dim, "class_id")), class_dims_(mesh.get_array(entity_dim, "class_dim")), owned_(BuildOwned(mesh, entity_dim)), @@ -159,4 +160,4 @@ OmegaHEntityLayout::GetDOFHolderClassificationIdsHost() const return make_const_array_view(classification_ids_host_); } -} // namespace pcms +} // namespace pcms::backend::omega_h diff --git a/src/pcms/field/layout/omega_h_entity.h b/src/pcms/backends/omega_h/entity_layout.hpp similarity index 85% rename from src/pcms/field/layout/omega_h_entity.h rename to src/pcms/backends/omega_h/entity_layout.hpp index 65f651478..a1ae99e05 100644 --- a/src/pcms/field/layout/omega_h_entity.h +++ b/src/pcms/backends/omega_h/entity_layout.hpp @@ -1,12 +1,12 @@ -#ifndef PCMS_FIELD_LAYOUT_OMEGA_H_ENTITY_H -#define PCMS_FIELD_LAYOUT_OMEGA_H_ENTITY_H +#ifndef PCMS_BACKENDS_OMEGA_H_ENTITY_LAYOUT_HPP +#define PCMS_BACKENDS_OMEGA_H_ENTITY_LAYOUT_HPP #include -#include "pcms/discretization/discretization/omega_h.hpp" -#include "pcms/field/field_layout.h" +#include "pcms/backends/omega_h/discretization.hpp" +#include "pcms/field/field_layout.hpp" -namespace pcms +namespace pcms::backend::omega_h { class OmegaHEntityLayout : public FieldLayout @@ -56,6 +56,6 @@ class OmegaHEntityLayout : public FieldLayout std::shared_ptr discretization_; }; -} // namespace pcms +} // namespace pcms::backend::omega_h -#endif // PCMS_FIELD_LAYOUT_OMEGA_H_ENTITY_H +#endif // PCMS_BACKENDS_OMEGA_H_ENTITY_LAYOUT_HPP diff --git a/src/pcms/field/evaluator/omega_h_lagrange.h b/src/pcms/backends/omega_h/lagrange_evaluator.hpp similarity index 89% rename from src/pcms/field/evaluator/omega_h_lagrange.h rename to src/pcms/backends/omega_h/lagrange_evaluator.hpp index 72bc95db1..82e8354cd 100644 --- a/src/pcms/field/evaluator/omega_h_lagrange.h +++ b/src/pcms/backends/omega_h/lagrange_evaluator.hpp @@ -1,16 +1,16 @@ -#ifndef PCMS_OMEGA_H_LAGRANGE_EVALUATOR_FACTORY_H -#define PCMS_OMEGA_H_LAGRANGE_EVALUATOR_FACTORY_H - -#include "pcms/field/layout/omega_h_lagrange.h" -#include "pcms/field/field_evaluator_factory.h" -#include "pcms/field/out_of_bounds_policy.h" -#include "pcms/field/point_evaluator.h" -#include "pcms/field/field_data.h" -#include "pcms/localization/point_search.h" -#include "pcms/utility/assert.h" -#include "pcms/utility/arrays.h" -#include "pcms/utility/profile.h" -#include "pcms/utility/types.h" +#ifndef PCMS_BACKENDS_OMEGA_H_LAGRANGE_EVALUATOR_HPP +#define PCMS_BACKENDS_OMEGA_H_LAGRANGE_EVALUATOR_HPP + +#include "pcms/backends/omega_h/lagrange_layout.hpp" +#include "pcms/field/field_evaluator_factory.hpp" +#include "pcms/field/out_of_bounds_policy.hpp" +#include "pcms/field/point_evaluator.hpp" +#include "pcms/field/field_data.hpp" +#include "pcms/localization/point_search.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/detail/profile.hpp" +#include "pcms/utility/types.hpp" #include #include @@ -18,7 +18,7 @@ #include #include -namespace pcms +namespace pcms::backend::omega_h { // --------------------------------------------------------------------------- @@ -41,7 +41,7 @@ template struct CopyCoordsFunctor { using DefaultLayout = - detail::default_layout_for_memory_space_t; + pcms::detail::default_layout_for_memory_space_t; Kokkos::View coords_d; Rank2View raw_coords; @@ -65,8 +65,9 @@ struct CopyCoordsFunctor template OmegaHLagrangeLocHint BuildLagrangeLocHint( Omega_h::Mesh& mesh, int mesh_dim, - Kokkos::View::Result*, - DeviceMemorySpace> + Kokkos::View< + typename pcms::localization::PointLocalizationSearch::Result*, + DeviceMemorySpace> results, Kokkos::View coords_d, Kokkos::View owning_ids, OutOfBoundsMode mode) @@ -179,15 +180,16 @@ OmegaHLagrangeLocHint BuildLagrangeLocHint( mode}; } -inline std::variant MakeSearch( - Omega_h::Mesh& mesh) +inline std::variant +MakeSearch(Omega_h::Mesh& mesh) { if (mesh.dim() == 2) { const auto n = DivisionsPerAxisForMesh<2>(mesh.nelems()); - return GridPointSearch2D(mesh, n, n); + return pcms::localization::GridPointSearch2D(mesh, n, n); } else if (mesh.dim() == 3) { const auto n = DivisionsPerAxisForMesh<3>(mesh.nelems()); - return GridPointSearch3D(mesh, n, n, n); + return pcms::localization::GridPointSearch3D(mesh, n, n, n); } throw std::invalid_argument( "OmegaHLagrangeEvaluatorFactory: only 2D and 3D meshes are supported"); @@ -207,7 +209,7 @@ inline std::variant MakeSearch( // Output shape: [num_query_points][num_components]. template > + pcms::detail::default_layout_for_memory_space_t> class OmegaHLagrangePointEvaluator : public PointEvaluator { public: @@ -313,7 +315,8 @@ class OmegaHLagrangePointEvaluator : public PointEvaluator // simplex meshes backed by Omega_h. It owns the spatial search structure and // creates OmegaHLagrangePointEvaluator instances on demand. template -class OmegaHLagrangeEvaluatorFactory : public FieldEvaluatorFactory +class OmegaHLagrangeEvaluatorFactory + : public pcms::field::FieldEvaluatorFactory { public: explicit OmegaHLagrangeEvaluatorFactory( @@ -333,7 +336,8 @@ class OmegaHLagrangeEvaluatorFactory : public FieldEvaluatorFactory /// operators which must locate points on the same mesh, such as the /// conservative transfer's intersection search, reuse it rather than build /// and hold a second copy of the candidate map. - [[nodiscard]] const GridPointSearchVariant& GetSearch() const noexcept + [[nodiscard]] const pcms::localization::GridPointSearchVariant& GetSearch() + const noexcept { return search_; } @@ -383,9 +387,9 @@ class OmegaHLagrangeEvaluatorFactory : public FieldEvaluatorFactory private: std::shared_ptr layout_; - GridPointSearchVariant search_; + pcms::localization::GridPointSearchVariant search_; }; -} // namespace pcms +} // namespace pcms::backend::omega_h -#endif // PCMS_OMEGA_H_LAGRANGE_EVALUATOR_FACTORY_H +#endif // PCMS_BACKENDS_OMEGA_H_LAGRANGE_EVALUATOR_HPP diff --git a/src/pcms/field/layout/omega_h_lagrange.cpp b/src/pcms/backends/omega_h/lagrange_layout.cpp similarity index 91% rename from src/pcms/field/layout/omega_h_lagrange.cpp rename to src/pcms/backends/omega_h/lagrange_layout.cpp index df1b6f25c..866fa56ed 100644 --- a/src/pcms/field/layout/omega_h_lagrange.cpp +++ b/src/pcms/backends/omega_h/lagrange_layout.cpp @@ -1,11 +1,11 @@ -#include "pcms/field/layout/omega_h_lagrange.h" -#include "pcms/utility/assert.h" -#include "pcms/utility/mesh_geometry.h" -#include "pcms/utility/omega_h_array_utils.h" -#include "pcms/utility/profile.h" +#include "pcms/backends/omega_h/lagrange_layout.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/mesh_geometry.hpp" +#include "pcms/utility/omega_h_array_utils.hpp" +#include "pcms/utility/detail/profile.hpp" #include -namespace pcms +namespace pcms::backend::omega_h { namespace @@ -88,11 +88,12 @@ OmegaHLagrangeLayout::OmegaHLagrangeLayout( ResolveCoordinateSystem(std::move(coordinate_system), mesh_.dim())); int entity_dim = EntityDimForOrder(order_, mesh_.dim()); - EnsureClassification(mesh_); + pcms::utility::EnsureClassification(mesh_); gids_ = BuildGids(mesh_, entity_dim, global_id_name_); gids_host_ = Omega_h::HostWrite(gids_); - coords_ = get_entity_centroids(mesh_, entity_dim); - coords_2d_ = ConvertCoordsTo2D(coords_, mesh_.nents(entity_dim), mesh_.dim()); + coords_ = pcms::utility::get_entity_centroids(mesh_, entity_dim); + coords_2d_ = pcms::utility::ConvertCoordsTo2D( + coords_, mesh_.nents(entity_dim), mesh_.dim()); owned_ = BuildOwned(mesh_, entity_dim); owned_host_ = Kokkos::View("owned_host", owned_.size()); @@ -135,11 +136,12 @@ OmegaHLagrangeLayout::OmegaHLagrangeLayout( ResolveCoordinateSystem(std::move(coordinate_system), mesh_.dim())); int entity_dim = EntityDimForOrder(order_, mesh_.dim()); - EnsureClassification(mesh_); + pcms::utility::EnsureClassification(mesh_); gids_ = BuildGids(mesh_, entity_dim, global_id_name_); gids_host_ = Omega_h::HostWrite(gids_); - coords_ = get_entity_centroids(mesh_, entity_dim); - coords_2d_ = ConvertCoordsTo2D(coords_, mesh_.nents(entity_dim), mesh_.dim()); + coords_ = pcms::utility::get_entity_centroids(mesh_, entity_dim); + coords_2d_ = pcms::utility::ConvertCoordsTo2D( + coords_, mesh_.nents(entity_dim), mesh_.dim()); owned_ = BuildOwned(mesh_, entity_dim, owned_mask); owned_host_ = Kokkos::View("owned_host", owned_.size()); @@ -259,4 +261,4 @@ Omega_h::Mesh& OmegaHLagrangeLayout::GetMesh() const return mesh_; } -} // namespace pcms +} // namespace pcms::backend::omega_h diff --git a/src/pcms/field/layout/omega_h_lagrange.h b/src/pcms/backends/omega_h/lagrange_layout.hpp similarity index 85% rename from src/pcms/field/layout/omega_h_lagrange.h rename to src/pcms/backends/omega_h/lagrange_layout.hpp index 7951bb0e6..2582e8c7b 100644 --- a/src/pcms/field/layout/omega_h_lagrange.h +++ b/src/pcms/backends/omega_h/lagrange_layout.hpp @@ -1,13 +1,13 @@ -#ifndef PCMS_ADAPTER_OMEGA_H_LAGRANGE_LAYOUT_H -#define PCMS_ADAPTER_OMEGA_H_LAGRANGE_LAYOUT_H +#ifndef PCMS_BACKENDS_OMEGA_H_LAGRANGE_LAYOUT_HPP +#define PCMS_BACKENDS_OMEGA_H_LAGRANGE_LAYOUT_HPP #include -#include "pcms/utility/arrays.h" -#include "pcms/discretization/discretization/omega_h.hpp" -#include "pcms/field/field_layout.h" -#include "pcms/field/field.h" +#include "pcms/utility/arrays.hpp" +#include "pcms/backends/omega_h/discretization.hpp" +#include "pcms/field/field_layout.hpp" +#include "pcms/field/field.hpp" -namespace pcms +namespace pcms::backend::omega_h { // Layout for native Omega_h Lagrange fields. @@ -73,5 +73,5 @@ class OmegaHLagrangeLayout : public FieldLayout std::shared_ptr discretization_; }; -} // namespace pcms -#endif // PCMS_ADAPTER_OMEGA_H_LAGRANGE_LAYOUT_H +} // namespace pcms::backend::omega_h +#endif // PCMS_BACKENDS_OMEGA_H_LAGRANGE_LAYOUT_HPP diff --git a/src/pcms/backends/omega_h/omega_h.cpp b/src/pcms/backends/omega_h/omega_h.cpp new file mode 100644 index 000000000..3375eedf5 --- /dev/null +++ b/src/pcms/backends/omega_h/omega_h.cpp @@ -0,0 +1,33 @@ +#include "pcms/backends/omega_h/omega_h.hpp" +#include "pcms/backends/omega_h/discretization.hpp" +#include "pcms/utility/assert.hpp" + +namespace pcms::backend::omega_h +{ + +std::shared_ptr CreateDiscretization( + Omega_h::Mesh& mesh, std::string global_id_name) +{ + return std::make_shared(mesh, + std::move(global_id_name)); +} + +std::shared_ptr CreateDiscretization( + Omega_h::Mesh& mesh, Omega_h::Read owned_mask, + std::string global_id_name) +{ + return std::make_shared(mesh, std::move(global_id_name), + std::move(owned_mask)); +} + +Omega_h::Mesh& GetMesh(const Discretization& discretization) +{ + const auto* oh = dynamic_cast(&discretization); + if (oh == nullptr) { + throw pcms_error("pcms::backend::omega_h::GetMesh: the discretization is " + "not based on an Omega_h mesh"); + } + return oh->GetMesh(); +} + +} // namespace pcms::backend::omega_h diff --git a/src/pcms/localization/queue_visited.hpp b/src/pcms/backends/omega_h/queue_visited.hpp similarity index 90% rename from src/pcms/localization/queue_visited.hpp rename to src/pcms/backends/omega_h/queue_visited.hpp index bab16e69c..e5d57360e 100644 --- a/src/pcms/localization/queue_visited.hpp +++ b/src/pcms/backends/omega_h/queue_visited.hpp @@ -1,5 +1,5 @@ -#ifndef PCMS_LOCALIZATION_QUEUE_VISITED_HPP -#define PCMS_LOCALIZATION_QUEUE_VISITED_HPP +#ifndef PCMS_BACKENDS_OMEGA_H_QUEUE_VISITED_HPP +#define PCMS_BACKENDS_OMEGA_H_QUEUE_VISITED_HPP #include #include @@ -7,9 +7,9 @@ #include #include #include -#include "pcms/configuration.h" +#include "pcms/configuration.hpp" -namespace pcms +namespace pcms::backend::omega_h { class Queue @@ -139,5 +139,5 @@ int Track::size() return count; } -} // namespace pcms -#endif // PCMS_LOCALIZATION_QUEUE_VISITED_HPP +} // namespace pcms::backend::omega_h +#endif // PCMS_BACKENDS_OMEGA_H_QUEUE_VISITED_HPP diff --git a/src/pcms/backends/omega_h/uniform_grid_binary_field.cpp b/src/pcms/backends/omega_h/uniform_grid_binary_field.cpp new file mode 100644 index 000000000..c0afb38d1 --- /dev/null +++ b/src/pcms/backends/omega_h/uniform_grid_binary_field.cpp @@ -0,0 +1,19 @@ +#include "pcms/backends/omega_h/omega_h.hpp" +#include "pcms/backends/omega_h/uniform_grid_binary_field.hpp" + +namespace pcms::backend::omega_h +{ + +Field CreateUniformGridBinaryField(Omega_h::Mesh& mesh, + const UniformGrid<2>& grid) +{ + return CreateUniformGridBinaryField<2>(mesh, grid).second; +} + +Field CreateUniformGridBinaryField(Omega_h::Mesh& mesh, + std::array divisions) +{ + return CreateUniformGridBinaryField<2>(mesh, divisions).second; +} + +} // namespace pcms::backend::omega_h diff --git a/src/pcms/field/uniform_grid_binary_field.h b/src/pcms/backends/omega_h/uniform_grid_binary_field.hpp similarity index 60% rename from src/pcms/field/uniform_grid_binary_field.h rename to src/pcms/backends/omega_h/uniform_grid_binary_field.hpp index 1643815e2..0b8e170fd 100644 --- a/src/pcms/field/uniform_grid_binary_field.h +++ b/src/pcms/backends/omega_h/uniform_grid_binary_field.hpp @@ -1,23 +1,24 @@ -#ifndef PCMS_UNIFORM_GRID_BINARY_FIELD_H -#define PCMS_UNIFORM_GRID_BINARY_FIELD_H +#ifndef PCMS_BACKENDS_OMEGA_H_UNIFORM_GRID_BINARY_FIELD_HPP +#define PCMS_BACKENDS_OMEGA_H_UNIFORM_GRID_BINARY_FIELD_HPP -#include "pcms/field/layout/uniform_grid.h" -#include "pcms/field/data/simple.h" -#include "pcms/field/function_space/lagrange.h" +#include "pcms/backends/uniform_grid/layout.hpp" +#include "pcms/field/simple_field_data.hpp" +#include "pcms/field/function_space/lagrange.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/localization/point_search.h" -#include "pcms/utility/arrays.h" -#include "pcms/utility/types.h" -#include "pcms/utility/uniform_grid.h" +#include "pcms/localization/point_search.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/types.hpp" +#include "pcms/utility/uniform_grid.hpp" #include #include #include #include #include -#include "pcms/field/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" +#include "pcms/backends/omega_h/omega_h.hpp" -namespace pcms +namespace pcms::backend::omega_h { /** @@ -34,12 +35,15 @@ namespace pcms * \return Pair of (layout, field) with binary mask values. */ template -std::pair>, Field> +std::pair>, + Field> CreateUniformGridBinaryField(Omega_h::Mesh& mesh, const UniformGrid& grid) { - auto function_space = LagrangeFunctionSpace::FromUniformGrid( + auto function_space = pcms::field::LagrangeFunctionSpace::FromUniformGrid( grid, 1, csys::Cartesian::Deferred()); - auto layout = std::dynamic_pointer_cast>( + auto layout = std::dynamic_pointer_cast< + const pcms::backend::uniform_grid::UniformGridFieldLayout>( function_space->GetLayout()); PCMS_ALWAYS_ASSERT(layout != nullptr); Field field = function_space->template CreateFunction(""); @@ -57,13 +61,16 @@ CreateUniformGridBinaryField(Omega_h::Mesh& mesh, const UniformGrid& grid) }); // Run point-in-mesh search - Kokkos::View::Result*> results_d; + Kokkos::View< + typename pcms::localization::PointLocalizationSearch::Result*> + results_d; if constexpr (Dim == 2) { - GridPointSearch2D search(mesh, grid.divisions[0], grid.divisions[1]); + pcms::localization::GridPointSearch2D search(mesh, grid.divisions[0], + grid.divisions[1]); results_d = search(coords_d); } else { - GridPointSearch3D search(mesh, grid.divisions[0], grid.divisions[1], - grid.divisions[2]); + pcms::localization::GridPointSearch3D search( + mesh, grid.divisions[0], grid.divisions[1], grid.divisions[2]); results_d = search(coords_d); } auto results_h = @@ -83,7 +90,9 @@ CreateUniformGridBinaryField(Omega_h::Mesh& mesh, const UniformGrid& grid) * \brief Convenience overload: derives the grid from the mesh bounding box. */ template -std::pair>, Field> +std::pair>, + Field> CreateUniformGridBinaryField(Omega_h::Mesh& mesh, const std::array& divisions) { @@ -91,6 +100,6 @@ CreateUniformGridBinaryField(Omega_h::Mesh& mesh, mesh, CreateUniformGridFromMesh(mesh, divisions)); } -} // namespace pcms +} // namespace pcms::backend::omega_h -#endif // PCMS_UNIFORM_GRID_BINARY_FIELD_H +#endif // PCMS_BACKENDS_OMEGA_H_UNIFORM_GRID_BINARY_FIELD_HPP diff --git a/src/pcms/backends/omega_h_meshfields/CMakeLists.txt b/src/pcms/backends/omega_h_meshfields/CMakeLists.txt new file mode 100644 index 000000000..dd865b12d --- /dev/null +++ b/src/pcms/backends/omega_h_meshfields/CMakeLists.txt @@ -0,0 +1,5 @@ +# Omega_h + MeshFields bridge: the MeshFields field adapter, part of +# pcms::field. Built only when both backends are enabled. No public headers. +target_sources(pcms_field PRIVATE layout.cpp layout.hpp evaluator_backend.hpp + evaluator.hpp field_data.hpp) +target_link_libraries(pcms_field PRIVATE meshfields::meshfields) diff --git a/src/pcms/field/evaluator/mesh_fields.h b/src/pcms/backends/omega_h_meshfields/evaluator.hpp similarity index 86% rename from src/pcms/field/evaluator/mesh_fields.h rename to src/pcms/backends/omega_h_meshfields/evaluator.hpp index 6f9a8c78c..8f970abf8 100644 --- a/src/pcms/field/evaluator/mesh_fields.h +++ b/src/pcms/backends/omega_h_meshfields/evaluator.hpp @@ -1,17 +1,17 @@ -#ifndef PCMS_ADAPTER_MESHFIELDS_MESH_FIELDS_EVALUATOR_FACTORY_H -#define PCMS_ADAPTER_MESHFIELDS_MESH_FIELDS_EVALUATOR_FACTORY_H - -#include "pcms/field/evaluator/mesh_fields_backend.h" -#include "pcms/field/data/mesh_fields.h" -#include "pcms/field/field_evaluator_factory.h" -#include "pcms/field/out_of_bounds_policy.h" -#include "pcms/field/point_evaluator.h" -#include "pcms/field/field_data.h" -#include "pcms/utility/profile.h" -#include "pcms/utility/arrays.h" +#ifndef PCMS_BACKENDS_OMEGA_H_MESHFIELDS_EVALUATOR_HPP +#define PCMS_BACKENDS_OMEGA_H_MESHFIELDS_EVALUATOR_HPP + +#include "pcms/backends/omega_h_meshfields/evaluator_backend.hpp" +#include "pcms/backends/omega_h_meshfields/field_data.hpp" +#include "pcms/field/field_evaluator_factory.hpp" +#include "pcms/field/out_of_bounds_policy.hpp" +#include "pcms/field/point_evaluator.hpp" +#include "pcms/field/field_data.hpp" +#include "pcms/utility/detail/profile.hpp" +#include "pcms/utility/arrays.hpp" #include -namespace pcms +namespace pcms::backend::omega_h_meshfields { // MeshFieldsPointEvaluator implements PointEvaluator for @@ -97,7 +97,7 @@ class MeshFieldsPointEvaluator : public PointEvaluator // MeshFields-backed simplex meshes. It owns the spatial search structure and // the MeshFieldBackend (which holds the internal shape field). template -class MeshFieldsEvaluatorFactory : public FieldEvaluatorFactory +class MeshFieldsEvaluatorFactory : public pcms::field::FieldEvaluatorFactory { public: explicit MeshFieldsEvaluatorFactory( @@ -157,9 +157,9 @@ class MeshFieldsEvaluatorFactory : public FieldEvaluatorFactory private: std::shared_ptr layout_; Omega_h::Mesh& mesh_; - mutable GridPointSearch2D search_; + mutable pcms::localization::GridPointSearch2D search_; }; -} // namespace pcms +} // namespace pcms::backend::omega_h_meshfields -#endif // PCMS_ADAPTER_MESHFIELDS_MESH_FIELDS_EVALUATOR_FACTORY_H +#endif // PCMS_BACKENDS_OMEGA_H_MESHFIELDS_EVALUATOR_HPP diff --git a/src/pcms/field/evaluator/mesh_fields_backend.h b/src/pcms/backends/omega_h_meshfields/evaluator_backend.hpp similarity index 92% rename from src/pcms/field/evaluator/mesh_fields_backend.h rename to src/pcms/backends/omega_h_meshfields/evaluator_backend.hpp index e59025e80..88a232f14 100644 --- a/src/pcms/field/evaluator/mesh_fields_backend.h +++ b/src/pcms/backends/omega_h_meshfields/evaluator_backend.hpp @@ -1,5 +1,5 @@ -#ifndef PCMS_ADAPTER_MESHFIELDS_MESH_FIELDS_BACKEND_H -#define PCMS_ADAPTER_MESHFIELDS_MESH_FIELDS_BACKEND_H +#ifndef PCMS_BACKENDS_OMEGA_H_MESHFIELDS_EVALUATOR_BACKEND_HPP +#define PCMS_BACKENDS_OMEGA_H_MESHFIELDS_EVALUATOR_BACKEND_HPP // Backend types shared between MeshFieldsAdapter2 and // MeshFieldsEvaluatorFactory. Extracted here to avoid a circular include. @@ -9,14 +9,14 @@ #include #include -#include "pcms/field/layout/mesh_fields.h" -#include "pcms/utility/types.h" -#include "pcms/utility/assert.h" -#include "pcms/utility/arrays.h" -#include "pcms/localization/point_search.h" -#include "pcms/field/field.h" // OutOfBoundsMode +#include "pcms/backends/omega_h_meshfields/layout.hpp" +#include "pcms/utility/types.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/localization/point_search.hpp" +#include "pcms/field/field.hpp" // OutOfBoundsMode -namespace pcms +namespace pcms::backend::omega_h_meshfields { // --------------------------------------------------------------------------- @@ -219,12 +219,12 @@ struct ComputeOffsetsDeviceFunctor struct CountPointsPerElementFunctor { Kokkos::View elem_counts_; - Kokkos::View search_results_; + Kokkos::View search_results_; Kokkos::View owning_elem_ids_; CountPointsPerElementFunctor( Kokkos::View elem_counts, - Kokkos::View search_results, + Kokkos::View search_results, Kokkos::View owning_elem_ids) : elem_counts_(elem_counts), search_results_(search_results), @@ -247,7 +247,7 @@ struct FillCoordinatesAndIndicesFunctor Kokkos::View offsets_; Kokkos::View coordinates_; Kokkos::View indices_; - Kokkos::View search_results_; + Kokkos::View search_results_; Kokkos::View owning_elem_ids_; Omega_h::Int dim_; @@ -255,7 +255,7 @@ struct FillCoordinatesAndIndicesFunctor Omega_h::Mesh& mesh, Kokkos::View elem_counts, Kokkos::View offsets, Kokkos::View coordinates, Kokkos::View indices, - Kokkos::View search_results, + Kokkos::View search_results, Kokkos::View owning_elem_ids) : mesh_(mesh), elem_counts_(elem_counts), @@ -287,16 +287,16 @@ struct FillCoordinatesAndIndicesFunctor // Device-side functors for processing search results struct FilterValidPointsFunctor { - Kokkos::View search_results_; + Kokkos::View search_results_; Kokkos::View valid_flags_; Kokkos::View owning_elem_ids_; Omega_h::Int mesh_dim_; OutOfBoundsMode mode_; - FilterValidPointsFunctor(Kokkos::View results, - Kokkos::View flags, - Kokkos::View owning_elem_ids, - Omega_h::Int mesh_dim, OutOfBoundsMode mode) + FilterValidPointsFunctor( + Kokkos::View results, + Kokkos::View flags, Kokkos::View owning_elem_ids, + Omega_h::Int mesh_dim, OutOfBoundsMode mode) : search_results_(results), valid_flags_(flags), owning_elem_ids_(owning_elem_ids), @@ -362,15 +362,15 @@ struct CompactIndicesFunctor struct CountPerElementFunctor { - Kokkos::View search_results_; + Kokkos::View search_results_; Kokkos::View valid_indices_; Kokkos::View owning_elem_ids_; Kokkos::View elem_counts_; - CountPerElementFunctor(Kokkos::View results, - Kokkos::View valid_indices, - Kokkos::View owning_elem_ids, - Kokkos::View elem_counts) + CountPerElementFunctor( + Kokkos::View results, + Kokkos::View valid_indices, Kokkos::View owning_elem_ids, + Kokkos::View elem_counts) : search_results_(results), valid_indices_(valid_indices), owning_elem_ids_(owning_elem_ids), @@ -389,7 +389,7 @@ struct CountPerElementFunctor struct FillCoordinatesDeviceFunctor { - Kokkos::View search_results_; + Kokkos::View search_results_; Kokkos::View valid_indices_; Kokkos::View owning_elem_ids_; Kokkos::View elem_counts_; @@ -403,7 +403,7 @@ struct FillCoordinatesDeviceFunctor Omega_h::Int dim_; FillCoordinatesDeviceFunctor( - Kokkos::View results, + Kokkos::View results, Kokkos::View valid_indices, Kokkos::View owning_elem_ids, Kokkos::View elem_counts, Kokkos::View offsets, Kokkos::View coordinates, Kokkos::View indices, @@ -491,7 +491,9 @@ struct MeshFieldsAdapter2LocalizationHint // Host-side constructor (legacy, for compatibility) MeshFieldsAdapter2LocalizationHint( Omega_h::Mesh& mesh, - Kokkos::View search_results, + Kokkos::View + search_results, Kokkos::View global_coords, Kokkos::View owning_elem_ids, OutOfBoundsMode mode) : mode_(mode), num_valid_(0), num_missing_(0) @@ -602,7 +604,8 @@ struct MeshFieldsAdapter2LocalizationHint // Device-side constructor MeshFieldsAdapter2LocalizationHint( Omega_h::Mesh& mesh, - Kokkos::View search_results_d, + Kokkos::View + search_results_d, Kokkos::View global_coords, Kokkos::View owning_elem_ids, OutOfBoundsMode mode) : mode_(mode), num_valid_(0), num_missing_(0) @@ -718,6 +721,6 @@ struct MeshFieldsAdapter2LocalizationHint Kokkos::View missing_indices_d_; }; -} // namespace pcms +} // namespace pcms::backend::omega_h_meshfields -#endif // PCMS_ADAPTER_MESHFIELDS_MESH_FIELDS_BACKEND_H \ No newline at end of file +#endif // PCMS_BACKENDS_OMEGA_H_MESHFIELDS_EVALUATOR_BACKEND_HPP \ No newline at end of file diff --git a/src/pcms/field/data/mesh_fields.h b/src/pcms/backends/omega_h_meshfields/field_data.hpp similarity index 88% rename from src/pcms/field/data/mesh_fields.h rename to src/pcms/backends/omega_h_meshfields/field_data.hpp index 0a60b59af..37203e001 100644 --- a/src/pcms/field/data/mesh_fields.h +++ b/src/pcms/backends/omega_h_meshfields/field_data.hpp @@ -1,17 +1,17 @@ -#ifndef PCMS_ADAPTER_MESHFIELDS_MESH_FIELDS_FIELD_DATA_H -#define PCMS_ADAPTER_MESHFIELDS_MESH_FIELDS_FIELD_DATA_H +#ifndef PCMS_BACKENDS_OMEGA_H_MESHFIELDS_FIELD_DATA_HPP +#define PCMS_BACKENDS_OMEGA_H_MESHFIELDS_FIELD_DATA_HPP -#include "pcms/field/layout/mesh_fields.h" -#include "pcms/field/evaluator/mesh_fields_backend.h" -#include "pcms/field/field_data.h" +#include "pcms/backends/omega_h_meshfields/layout.hpp" +#include "pcms/backends/omega_h_meshfields/evaluator_backend.hpp" +#include "pcms/field/field_data.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/utility/assert.h" -#include "pcms/utility/arrays.h" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/arrays.hpp" #include #include -namespace pcms +namespace pcms::backend::omega_h_meshfields { namespace @@ -123,6 +123,6 @@ class MeshFieldsFieldData Kokkos::View device_data_; }; -} // namespace pcms +} // namespace pcms::backend::omega_h_meshfields -#endif // PCMS_ADAPTER_MESHFIELDS_MESH_FIELDS_FIELD_DATA_H +#endif // PCMS_BACKENDS_OMEGA_H_MESHFIELDS_FIELD_DATA_HPP diff --git a/src/pcms/field/layout/mesh_fields.cpp b/src/pcms/backends/omega_h_meshfields/layout.cpp similarity index 96% rename from src/pcms/field/layout/mesh_fields.cpp rename to src/pcms/backends/omega_h_meshfields/layout.cpp index e93e02bc4..d5ad96a3c 100644 --- a/src/pcms/field/layout/mesh_fields.cpp +++ b/src/pcms/backends/omega_h_meshfields/layout.cpp @@ -1,12 +1,12 @@ -#include "pcms/field/layout/mesh_fields.h" -#include "pcms/utility/assert.h" -#include "pcms/utility/inclusive_scan.h" -#include "pcms/utility/profile.h" +#include "pcms/backends/omega_h_meshfields/layout.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/detail/inclusive_scan.hpp" +#include "pcms/utility/detail/profile.hpp" #include #include #include -namespace pcms +namespace pcms::backend::omega_h_meshfields { /* * Field Layout @@ -260,7 +260,8 @@ MeshFieldsAdapterLayout::MeshFieldsAdapterLayout( static_cast(static_cast(class_dims_h[i])); classification_ids_host_(i) = static_cast(class_ids_h[i]); } - discretization_ = std::make_shared(mesh_); + discretization_ = + std::make_shared(mesh_); } std::shared_ptr @@ -378,4 +379,4 @@ MeshFieldsAdapterLayout::GetDOFHolderClassificationIdsHost() const return make_const_array_view(classification_ids_host_); } -} // namespace pcms +} // namespace pcms::backend::omega_h_meshfields diff --git a/src/pcms/field/layout/mesh_fields.h b/src/pcms/backends/omega_h_meshfields/layout.hpp similarity index 84% rename from src/pcms/field/layout/mesh_fields.h rename to src/pcms/backends/omega_h_meshfields/layout.hpp index 004fd2028..8e57d7102 100644 --- a/src/pcms/field/layout/mesh_fields.h +++ b/src/pcms/backends/omega_h_meshfields/layout.hpp @@ -1,16 +1,16 @@ -#ifndef PCMS_ADAPTER_MESHFIELDS_MESH_FIELDS_ADAPTER_LAYOUT_H -#define PCMS_ADAPTER_MESHFIELDS_MESH_FIELDS_ADAPTER_LAYOUT_H +#ifndef PCMS_BACKENDS_OMEGA_H_MESHFIELDS_LAYOUT_HPP +#define PCMS_BACKENDS_OMEGA_H_MESHFIELDS_LAYOUT_HPP #include -#include "pcms/utility/arrays.h" -#include "pcms/discretization/discretization/omega_h.hpp" -#include "pcms/field/field_layout.h" -#include "pcms/field/field.h" +#include "pcms/utility/arrays.hpp" +#include "pcms/backends/omega_h/discretization.hpp" +#include "pcms/field/field_layout.hpp" +#include "pcms/field/field.hpp" #include -namespace pcms +namespace pcms::backend::omega_h_meshfields { class MeshFieldsAdapterLayout : public FieldLayout { @@ -72,5 +72,5 @@ class MeshFieldsAdapterLayout : public FieldLayout std::shared_ptr discretization_; }; -} // namespace pcms -#endif // PCMS_ADAPTER_MESHFIELDS_MESH_FIELDS_ADAPTER_LAYOUT_H +} // namespace pcms::backend::omega_h_meshfields +#endif // PCMS_BACKENDS_OMEGA_H_MESHFIELDS_LAYOUT_HPP diff --git a/src/pcms/backends/point_cloud/CMakeLists.txt b/src/pcms/backends/point_cloud/CMakeLists.txt new file mode 100644 index 000000000..9fb185e5a --- /dev/null +++ b/src/pcms/backends/point_cloud/CMakeLists.txt @@ -0,0 +1,15 @@ +# Point-cloud backend (no external dependency). No public headers. + +# discretization: part of pcms::discretization +target_sources(pcms_discretization PRIVATE discretization.cpp + discretization.hpp) + +# layout and field data: part of pcms::field +target_sources(pcms_field PRIVATE layout.cpp field_data.cpp layout.hpp + field_data.hpp) + +# MLS evaluation and localization use Omega_h arrays (as before) +if(PCMS_ENABLE_OMEGA_H) + target_sources(pcms_field PRIVATE localization.hpp mls_evaluator.hpp + evaluator.hpp) +endif() diff --git a/src/pcms/discretization/discretization/point_cloud.cpp b/src/pcms/backends/point_cloud/discretization.cpp similarity index 92% rename from src/pcms/discretization/discretization/point_cloud.cpp rename to src/pcms/backends/point_cloud/discretization.cpp index 94e851cc1..cb1ce5f7d 100644 --- a/src/pcms/discretization/discretization/point_cloud.cpp +++ b/src/pcms/backends/point_cloud/discretization.cpp @@ -1,6 +1,6 @@ -#include "pcms/discretization/discretization/point_cloud.hpp" +#include "pcms/backends/point_cloud/discretization.hpp" -namespace pcms +namespace pcms::backend::point_cloud { PointCloudDiscretization::PointCloudDiscretization( @@ -52,4 +52,4 @@ PointCloudDiscretization::GetEntityClassificationIds(int entity_dim) const : Rank1View(nullptr, 0); } -} // namespace pcms +} // namespace pcms::backend::point_cloud diff --git a/src/pcms/discretization/discretization/point_cloud.hpp b/src/pcms/backends/point_cloud/discretization.hpp similarity index 75% rename from src/pcms/discretization/discretization/point_cloud.hpp rename to src/pcms/backends/point_cloud/discretization.hpp index 271e378c2..a2a669dfa 100644 --- a/src/pcms/discretization/discretization/point_cloud.hpp +++ b/src/pcms/backends/point_cloud/discretization.hpp @@ -1,11 +1,11 @@ -#ifndef PCMS_DISCRETIZATION_DISCRETIZATION_POINT_CLOUD_H -#define PCMS_DISCRETIZATION_DISCRETIZATION_POINT_CLOUD_H +#ifndef PCMS_BACKENDS_POINT_CLOUD_DISCRETIZATION_HPP +#define PCMS_BACKENDS_POINT_CLOUD_DISCRETIZATION_HPP -#include "pcms/discretization/discretization.h" +#include "pcms/discretization/discretization.hpp" #include -namespace pcms +namespace pcms::backend::point_cloud { class PointCloudDiscretization : public Discretization @@ -34,6 +34,6 @@ class PointCloudDiscretization : public Discretization Kokkos::View class_ids_; }; -} // namespace pcms +} // namespace pcms::backend::point_cloud -#endif // PCMS_DISCRETIZATION_DISCRETIZATION_POINT_CLOUD_H +#endif // PCMS_BACKENDS_POINT_CLOUD_DISCRETIZATION_HPP diff --git a/src/pcms/field/evaluator/point_cloud.h b/src/pcms/backends/point_cloud/evaluator.hpp similarity index 56% rename from src/pcms/field/evaluator/point_cloud.h rename to src/pcms/backends/point_cloud/evaluator.hpp index 9d62ef1ac..ce29d8a5f 100644 --- a/src/pcms/field/evaluator/point_cloud.h +++ b/src/pcms/backends/point_cloud/evaluator.hpp @@ -1,32 +1,34 @@ -#ifndef PCMS_POINT_CLOUD_EVALUATOR_FACTORY_H -#define PCMS_POINT_CLOUD_EVALUATOR_FACTORY_H - -#include "pcms/field/field_evaluator_factory.h" -#include "pcms/field/out_of_bounds_policy.h" -#include "pcms/field/point_evaluator.h" -#include "pcms/field/field_data.h" -#include "pcms/field/evaluation_request.h" -#include "pcms/field/evaluator/mls_options.h" -#include "pcms/field/evaluator/mls_point_cloud.h" -#include "pcms/localization/localization_path_selection.h" -#include "pcms/localization/mesh_localization.h" -#include "pcms/localization/localization_factory.h" -#include "pcms/utility/assert.h" -#include "pcms/utility/omega_h_array_utils.h" +#ifndef PCMS_BACKENDS_POINT_CLOUD_EVALUATOR_HPP +#define PCMS_BACKENDS_POINT_CLOUD_EVALUATOR_HPP + +#include "pcms/field/field_evaluator_factory.hpp" +#include "pcms/field/out_of_bounds_policy.hpp" +#include "pcms/field/point_evaluator.hpp" +#include "pcms/field/field_data.hpp" +#include "pcms/field/evaluation_request.hpp" +#include "pcms/localization/mls_options.hpp" +#include "pcms/backends/point_cloud/mls_evaluator.hpp" +#include "pcms/field/localization_path_selection.hpp" +#include "pcms/localization/mesh_localization.hpp" +#include "pcms/localization/localization_factory.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/omega_h_array_utils.hpp" #include #include #include -namespace pcms +namespace pcms::backend::point_cloud { -class PointCloudEvaluatorFactory : public FieldEvaluatorFactory +class PointCloudEvaluatorFactory + : public pcms::field::FieldEvaluatorFactory { public: - PointCloudEvaluatorFactory(std::shared_ptr layout, - std::shared_ptr localization, - MLSOptions options = {}) + PointCloudEvaluatorFactory( + std::shared_ptr layout, + std::shared_ptr localization, + MLSOptions options = {}) : layout_(std::move(layout)), localization_(std::move(localization)), options_(options) @@ -63,20 +65,22 @@ class PointCloudEvaluatorFactory : public FieldEvaluatorFactory const auto src_view = layout_->GetDOFHolderCoordinates().GetValues(); const int dim = layout_->GetDimension(); Omega_h::Reals source_coords = - flatten_to_omega_h_reals(src_view, "src_coords"); + pcms::utility::flatten_to_omega_h_reals(src_view, "src_coords"); // Extract target coordinates for the MLS solve. const auto tgt_view = coords.GetValues(); PCMS_ALWAYS_ASSERT(static_cast(tgt_view.extent(1)) == dim); Omega_h::Reals target_coords_oh = - flatten_to_omega_h_reals(tgt_view, "tgt_coords"); + pcms::utility::flatten_to_omega_h_reals(tgt_view, "tgt_coords"); - SupportResults supports; - auto path = - detail::SelectLocalizationPath(*layout_, request.GetQueryLayout()); - if (path == detail::LocalizationPath::CentroidToVertexAdjacencySearch) { + pcms::localization::SupportResults supports; + auto path = pcms::field::detail::SelectLocalizationPath( + *layout_, request.GetQueryLayout()); + if (path == pcms::field::detail::LocalizationPath:: + CentroidToVertexAdjacencySearch) { auto* adjacency = - dynamic_cast(localization_.get()); + dynamic_cast( + localization_.get()); PCMS_ALWAYS_ASSERT(adjacency != nullptr); supports = adjacency->BuildSameMeshCentroidToVertex(); } else { @@ -90,10 +94,10 @@ class PointCloudEvaluatorFactory : public FieldEvaluatorFactory private: std::shared_ptr layout_; - std::shared_ptr localization_; + std::shared_ptr localization_; MLSOptions options_; }; -} // namespace pcms +} // namespace pcms::backend::point_cloud -#endif // PCMS_POINT_CLOUD_EVALUATOR_FACTORY_H +#endif // PCMS_BACKENDS_POINT_CLOUD_EVALUATOR_HPP diff --git a/src/pcms/field/data/point_cloud.cpp b/src/pcms/backends/point_cloud/field_data.cpp similarity index 71% rename from src/pcms/field/data/point_cloud.cpp rename to src/pcms/backends/point_cloud/field_data.cpp index d50e512d3..a90e305b1 100644 --- a/src/pcms/field/data/point_cloud.cpp +++ b/src/pcms/backends/point_cloud/field_data.cpp @@ -1,10 +1,10 @@ -#include "pcms/field/data/point_cloud.h" -#include "pcms/field/layout/point_cloud.h" -#include "pcms/utility/profile.h" -#include "pcms/utility/assert.h" -#include "pcms/utility/arrays.h" +#include "pcms/backends/point_cloud/field_data.hpp" +#include "pcms/backends/point_cloud/layout.hpp" +#include "pcms/utility/detail/profile.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/arrays.hpp" -namespace pcms +namespace pcms::backend::point_cloud { PointCloud::PointCloud(std::shared_ptr layout) @@ -36,4 +36,4 @@ void PointCloud::SetOwnedValues(Rank2View data) CopyDeviceRank2ViewToDeviceView(device_data_, data); } -} // namespace pcms +} // namespace pcms::backend::point_cloud diff --git a/src/pcms/field/data/point_cloud.h b/src/pcms/backends/point_cloud/field_data.hpp similarity index 68% rename from src/pcms/field/data/point_cloud.h rename to src/pcms/backends/point_cloud/field_data.hpp index a7006b9e0..0e9c49890 100644 --- a/src/pcms/field/data/point_cloud.h +++ b/src/pcms/backends/point_cloud/field_data.hpp @@ -1,13 +1,13 @@ -#ifndef POINT_CLOUD_H_ -#define POINT_CLOUD_H_ +#ifndef PCMS_BACKENDS_POINT_CLOUD_FIELD_DATA_HPP +#define PCMS_BACKENDS_POINT_CLOUD_FIELD_DATA_HPP -#include "pcms/field/field_data.h" +#include "pcms/field/field_data.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/utility/arrays.h" -#include "pcms/field/layout/point_cloud.h" +#include "pcms/utility/arrays.hpp" +#include "pcms/backends/point_cloud/layout.hpp" #include -namespace pcms +namespace pcms::backend::point_cloud { class PointCloud : public FieldData @@ -30,6 +30,6 @@ class PointCloud ValueBasis basis_; Kokkos::View device_data_; }; -} // namespace pcms +} // namespace pcms::backend::point_cloud -#endif // POINT_CLOUD_H_ +#endif // PCMS_BACKENDS_POINT_CLOUD_FIELD_DATA_HPP diff --git a/src/pcms/field/layout/point_cloud.cpp b/src/pcms/backends/point_cloud/layout.cpp similarity index 96% rename from src/pcms/field/layout/point_cloud.cpp rename to src/pcms/backends/point_cloud/layout.cpp index 1c020e279..b1bfb658d 100644 --- a/src/pcms/field/layout/point_cloud.cpp +++ b/src/pcms/backends/point_cloud/layout.cpp @@ -1,9 +1,10 @@ -#include "pcms/field/layout/point_cloud.h" -#include "pcms/utility/arrays.h" +#include "pcms/backends/point_cloud/layout.hpp" +#include "pcms/utility/arrays.hpp" #include +#include #include -namespace pcms +namespace pcms::backend::point_cloud { namespace @@ -173,4 +174,4 @@ PointCloudLayout::GetDOFHolderClassificationIdsHost() const return make_const_array_view(classification_ids_host_); } -} // namespace pcms +} // namespace pcms::backend::point_cloud diff --git a/src/pcms/field/layout/point_cloud.h b/src/pcms/backends/point_cloud/layout.hpp similarity index 86% rename from src/pcms/field/layout/point_cloud.h rename to src/pcms/backends/point_cloud/layout.hpp index 1754c0add..537c6f7a3 100644 --- a/src/pcms/field/layout/point_cloud.h +++ b/src/pcms/backends/point_cloud/layout.hpp @@ -1,10 +1,10 @@ -#ifndef POINT_CLOUD_LAYOUT_H_ -#define POINT_CLOUD_LAYOUT_H_ +#ifndef PCMS_BACKENDS_POINT_CLOUD_LAYOUT_HPP +#define PCMS_BACKENDS_POINT_CLOUD_LAYOUT_HPP -#include "pcms/field/field.h" -#include "pcms/discretization/discretization/point_cloud.hpp" +#include "pcms/field/field.hpp" +#include "pcms/backends/point_cloud/discretization.hpp" -namespace pcms +namespace pcms::backend::point_cloud { class PointCloudLayout : public FieldLayout @@ -59,6 +59,6 @@ class PointCloudLayout : public FieldLayout Kokkos::View classification_ids_host_; std::shared_ptr discretization_; }; -} // namespace pcms +} // namespace pcms::backend::point_cloud -#endif // POINT_CLOUD_LAYOUT_H_ +#endif // PCMS_BACKENDS_POINT_CLOUD_LAYOUT_HPP diff --git a/src/pcms/localization/point_cloud_localization.h b/src/pcms/backends/point_cloud/localization.hpp similarity index 58% rename from src/pcms/localization/point_cloud_localization.h rename to src/pcms/backends/point_cloud/localization.hpp index 6605380bd..a8ad09dae 100644 --- a/src/pcms/localization/point_cloud_localization.h +++ b/src/pcms/backends/point_cloud/localization.hpp @@ -1,25 +1,26 @@ -#ifndef PCMS_LOCALIZATION_POINT_CLOUD_LOCALIZATION_H -#define PCMS_LOCALIZATION_POINT_CLOUD_LOCALIZATION_H +#ifndef PCMS_BACKENDS_POINT_CLOUD_LOCALIZATION_HPP +#define PCMS_BACKENDS_POINT_CLOUD_LOCALIZATION_HPP -#include "pcms/localization/localization_factory.h" -#include "pcms/localization/mls_support_helpers.h" -#include "pcms/field/layout/point_cloud.h" -#include "pcms/field/evaluator/mls_options.h" -#include "pcms/utility/assert.h" -#include "pcms/utility/omega_h_array_utils.h" +#include "pcms/localization/localization_factory.hpp" +#include "pcms/localization/mls_support_helpers.hpp" +#include "pcms/backends/point_cloud/layout.hpp" +#include "pcms/localization/mls_options.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/omega_h_array_utils.hpp" #include #include #include -namespace pcms +namespace pcms::backend::point_cloud { // LocalizationFactory implementation using N^2 point-cloud search. // // Holds a reference to the PointCloudLayout so source coordinates are not // copied at construction time; they are extracted from the layout in Build(). -class PointCloudLocalizationFactory : public LocalizationFactory +class PointCloudLocalizationFactory + : public pcms::localization::LocalizationFactory { public: PointCloudLocalizationFactory(std::shared_ptr layout, @@ -28,7 +29,7 @@ class PointCloudLocalizationFactory : public LocalizationFactory { } - SupportResults Build( + pcms::localization::SupportResults Build( CoordinateView target_coords) const override { // Euclidean search structures are valid wherever @@ -44,16 +45,16 @@ class PointCloudLocalizationFactory : public LocalizationFactory const auto src_view = layout_->GetCoordinates(); const int dim = layout_->GetDimension(); Omega_h::Reals source_coords = - flatten_to_omega_h_reals(src_view, "src_coords"); + pcms::utility::flatten_to_omega_h_reals(src_view, "src_coords"); const auto tgt_view = target_coords.GetValues(); PCMS_ALWAYS_ASSERT(static_cast(tgt_view.extent(1)) == dim); Omega_h::Reals target_coords_oh = - flatten_to_omega_h_reals(tgt_view, "tgt_coords"); + pcms::utility::flatten_to_omega_h_reals(tgt_view, "tgt_coords"); - return BuildPointCloudSupports(source_coords, target_coords_oh, dim, - options_.radius, options_.min_req_supports, - options_.adapt_radius); + return pcms::localization::BuildPointCloudSupports( + source_coords, target_coords_oh, dim, options_.radius, + options_.min_req_supports, options_.adapt_radius); } private: @@ -61,6 +62,6 @@ class PointCloudLocalizationFactory : public LocalizationFactory MLSOptions options_; }; -} // namespace pcms +} // namespace pcms::backend::point_cloud -#endif // PCMS_LOCALIZATION_POINT_CLOUD_LOCALIZATION_H +#endif // PCMS_BACKENDS_POINT_CLOUD_LOCALIZATION_HPP diff --git a/src/pcms/field/evaluator/mls_point_cloud.h b/src/pcms/backends/point_cloud/mls_evaluator.hpp similarity index 80% rename from src/pcms/field/evaluator/mls_point_cloud.h rename to src/pcms/backends/point_cloud/mls_evaluator.hpp index 1a66ee2d1..6601837d1 100644 --- a/src/pcms/field/evaluator/mls_point_cloud.h +++ b/src/pcms/backends/point_cloud/mls_evaluator.hpp @@ -1,17 +1,17 @@ -#ifndef PCMS_FIELD_EVALUATOR_MLS_POINT_CLOUD_H -#define PCMS_FIELD_EVALUATOR_MLS_POINT_CLOUD_H +#ifndef PCMS_BACKENDS_POINT_CLOUD_MLS_EVALUATOR_HPP +#define PCMS_BACKENDS_POINT_CLOUD_MLS_EVALUATOR_HPP -#include "pcms/field/point_evaluator.h" -#include "pcms/field/field_data.h" -#include "pcms/field/evaluator/mls_options.h" +#include "pcms/field/point_evaluator.hpp" +#include "pcms/field/field_data.hpp" +#include "pcms/localization/mls_options.hpp" #include "pcms/field/evaluator/mls_interpolation.hpp" -#include "pcms/localization/adj_search.hpp" -#include "pcms/utility/assert.h" +#include "pcms/backends/omega_h/adj_search.hpp" +#include "pcms/utility/assert.hpp" #include #include -namespace pcms +namespace pcms::backend::point_cloud { // MLSPointEvaluator is a concrete PointEvaluator that evaluates a @@ -28,7 +28,8 @@ class MLSPointEvaluator : public PointEvaluator { public: MLSPointEvaluator(Omega_h::Reals source_coords, Omega_h::Reals target_coords, - SupportResults supports, int dim, MLSOptions options) + pcms::localization::SupportResults supports, int dim, + MLSOptions options) : source_coords_(std::move(source_coords)), target_coords_(std::move(target_coords)), supports_(std::move(supports)), @@ -73,7 +74,7 @@ class MLSPointEvaluator : public PointEvaluator KOKKOS_LAMBDA(int i) { src_w[i] = device_data(i, 0); }); Omega_h::Reals source_values(src_w); - auto result = mls_interpolation( + auto result = pcms::field::mls_interpolation( source_values, source_coords_, target_coords_, supports_, dim_, static_cast(options_.degree), options_.basis, options_.lambda, options_.tol, options_.decay_factor); @@ -88,11 +89,11 @@ class MLSPointEvaluator : public PointEvaluator private: Omega_h::Reals source_coords_; Omega_h::Reals target_coords_; - SupportResults supports_; + pcms::localization::SupportResults supports_; int dim_; MLSOptions options_; }; -} // namespace pcms +} // namespace pcms::backend::point_cloud -#endif // PCMS_FIELD_EVALUATOR_MLS_POINT_CLOUD_H +#endif // PCMS_BACKENDS_POINT_CLOUD_MLS_EVALUATOR_HPP diff --git a/src/pcms/backends/uniform_grid/CMakeLists.txt b/src/pcms/backends/uniform_grid/CMakeLists.txt new file mode 100644 index 000000000..4bc4cd35e --- /dev/null +++ b/src/pcms/backends/uniform_grid/CMakeLists.txt @@ -0,0 +1,13 @@ +# Uniform-grid backend (no external dependency). No public headers. + +# discretization: part of pcms::discretization (header only) +target_sources(pcms_discretization PRIVATE discretization.hpp) + +# layout, evaluators and spline interpolators: part of pcms::field, built +# with PCMS_ENABLE_OMEGA_H as before +if(PCMS_ENABLE_OMEGA_H) + target_sources( + pcms_field + PRIVATE layout.cpp layout.hpp evaluator.hpp spline_interpolator.hpp + spline_evaluator.hpp linear_interpolant.hpp multidimarray.hpp) +endif() diff --git a/src/pcms/discretization/discretization/uniform_grid.hpp b/src/pcms/backends/uniform_grid/discretization.hpp similarity index 90% rename from src/pcms/discretization/discretization/uniform_grid.hpp rename to src/pcms/backends/uniform_grid/discretization.hpp index ee34763c5..db8b26080 100644 --- a/src/pcms/discretization/discretization/uniform_grid.hpp +++ b/src/pcms/backends/uniform_grid/discretization.hpp @@ -1,12 +1,12 @@ -#ifndef PCMS_DISCRETIZATION_DISCRETIZATION_UNIFORM_GRID_H -#define PCMS_DISCRETIZATION_DISCRETIZATION_UNIFORM_GRID_H +#ifndef PCMS_BACKENDS_UNIFORM_GRID_DISCRETIZATION_HPP +#define PCMS_BACKENDS_UNIFORM_GRID_DISCRETIZATION_HPP -#include "pcms/discretization/discretization.h" -#include "pcms/utility/uniform_grid.h" +#include "pcms/discretization/discretization.hpp" +#include "pcms/utility/uniform_grid.hpp" #include -namespace pcms +namespace pcms::backend::uniform_grid { template @@ -15,6 +15,8 @@ class UniformGridDiscretization : public Discretization public: explicit UniformGridDiscretization(UniformGrid grid); + const UniformGrid& GetGrid() const noexcept { return grid_; } + bool SameEntities(const Discretization& other) const noexcept override; int GetDimension() const override; @@ -117,6 +119,6 @@ UniformGridDiscretization::GetEntityClassificationIds(int entity_dim) const return Rank1View(nullptr, 0); } -} // namespace pcms +} // namespace pcms::backend::uniform_grid -#endif // PCMS_DISCRETIZATION_DISCRETIZATION_UNIFORM_GRID_H +#endif // PCMS_BACKENDS_UNIFORM_GRID_DISCRETIZATION_HPP diff --git a/src/pcms/field/evaluator/uniform_grid.h b/src/pcms/backends/uniform_grid/evaluator.hpp similarity index 93% rename from src/pcms/field/evaluator/uniform_grid.h rename to src/pcms/backends/uniform_grid/evaluator.hpp index 35fdd293b..18d9f9ffe 100644 --- a/src/pcms/field/evaluator/uniform_grid.h +++ b/src/pcms/backends/uniform_grid/evaluator.hpp @@ -1,21 +1,22 @@ -#ifndef PCMS_UNIFORM_GRID_EVALUATOR_FACTORY_H -#define PCMS_UNIFORM_GRID_EVALUATOR_FACTORY_H +#ifndef PCMS_BACKENDS_UNIFORM_GRID_EVALUATOR_HPP +#define PCMS_BACKENDS_UNIFORM_GRID_EVALUATOR_HPP -#include "pcms/field/layout/uniform_grid.h" -#include "pcms/utility/types.h" +#include "pcms/backends/uniform_grid/layout.hpp" +#include "pcms/utility/types.hpp" #include -#include "pcms/field/field_evaluator_factory.h" -#include "pcms/field/out_of_bounds_policy.h" -#include "pcms/field/point_evaluator.h" -#include "pcms/field/field_data.h" -#include "pcms/utility/assert.h" -#include "pcms/utility/profile.h" -#include "pcms/transfer/linear_interpolant.hpp" -#include "pcms/transfer/multidimarray.hpp" +#include "pcms/field/field_evaluator_factory.hpp" +#include "pcms/field/out_of_bounds_policy.hpp" +#include "pcms/field/point_evaluator.hpp" +#include "pcms/field/field_data.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/detail/profile.hpp" +#include "pcms/backends/uniform_grid/linear_interpolant.hpp" +#include "pcms/backends/uniform_grid/multidimarray.hpp" #include +#include -namespace pcms +namespace pcms::backend::uniform_grid { // --------------------------------------------------------------------------- @@ -91,7 +92,7 @@ Kokkos::View FilledPointIndices( // - values has extents [num_query_points][num_components]. template > + pcms::detail::default_layout_for_memory_space_t> class UniformGridPointEvaluator : public PointEvaluator { public: @@ -252,7 +253,8 @@ class UniformGridPointEvaluator : public PointEvaluator // Localization logic is taken directly from // UniformGridField::GetLocalizationHint. template -class UniformGridEvaluatorFactory : public FieldEvaluatorFactory +class UniformGridEvaluatorFactory + : public pcms::field::FieldEvaluatorFactory { public: explicit UniformGridEvaluatorFactory( @@ -349,6 +351,6 @@ class UniformGridEvaluatorFactory : public FieldEvaluatorFactory using UniformGridEvaluatorFactory2D = UniformGridEvaluatorFactory<2>; -} // namespace pcms +} // namespace pcms::backend::uniform_grid -#endif // PCMS_UNIFORM_GRID_EVALUATOR_FACTORY_H +#endif // PCMS_BACKENDS_UNIFORM_GRID_EVALUATOR_HPP diff --git a/src/pcms/field/layout/uniform_grid.cpp b/src/pcms/backends/uniform_grid/layout.cpp similarity index 97% rename from src/pcms/field/layout/uniform_grid.cpp rename to src/pcms/backends/uniform_grid/layout.cpp index 5887d0966..f51bbf42e 100644 --- a/src/pcms/field/layout/uniform_grid.cpp +++ b/src/pcms/backends/uniform_grid/layout.cpp @@ -1,9 +1,9 @@ -#include "pcms/field/layout/uniform_grid.h" -#include "pcms/utility/profile.h" -#include "pcms/utility/assert.h" +#include "pcms/backends/uniform_grid/layout.hpp" +#include "pcms/utility/detail/profile.hpp" +#include "pcms/utility/assert.hpp" #include -namespace pcms +namespace pcms::backend::uniform_grid { namespace @@ -315,4 +315,4 @@ int UniformGridFieldLayout::GetOrder() const template class UniformGridFieldLayout<2>; template class UniformGridFieldLayout<3>; -} // namespace pcms +} // namespace pcms::backend::uniform_grid diff --git a/src/pcms/field/layout/uniform_grid.h b/src/pcms/backends/uniform_grid/layout.hpp similarity index 81% rename from src/pcms/field/layout/uniform_grid.h rename to src/pcms/backends/uniform_grid/layout.hpp index 21828edd8..9c8c908d6 100644 --- a/src/pcms/field/layout/uniform_grid.h +++ b/src/pcms/backends/uniform_grid/layout.hpp @@ -1,15 +1,15 @@ -#ifndef PCMS_UNIFORM_GRID_FIELD_LAYOUT_H -#define PCMS_UNIFORM_GRID_FIELD_LAYOUT_H +#ifndef PCMS_BACKENDS_UNIFORM_GRID_LAYOUT_HPP +#define PCMS_BACKENDS_UNIFORM_GRID_LAYOUT_HPP -#include "pcms/utility/arrays.h" -#include "pcms/discretization/discretization/uniform_grid.hpp" -#include "pcms/field/field_layout.h" -#include "pcms/field/field.h" -#include "pcms/utility/uniform_grid.h" +#include "pcms/utility/arrays.hpp" +#include "pcms/backends/uniform_grid/discretization.hpp" +#include "pcms/field/field_layout.hpp" +#include "pcms/field/field.hpp" +#include "pcms/utility/uniform_grid.hpp" #include -namespace pcms +namespace pcms::backend::uniform_grid { template class UniformGridFieldLayout : public FieldLayout @@ -67,5 +67,5 @@ class UniformGridFieldLayout : public FieldLayout using UniformGridFieldLayout2D = UniformGridFieldLayout<2>; -} // namespace pcms -#endif // PCMS_UNIFORM_GRID_FIELD_LAYOUT_H +} // namespace pcms::backend::uniform_grid +#endif // PCMS_BACKENDS_UNIFORM_GRID_LAYOUT_HPP diff --git a/src/pcms/transfer/linear_interpolant.hpp b/src/pcms/backends/uniform_grid/linear_interpolant.hpp similarity index 90% rename from src/pcms/transfer/linear_interpolant.hpp rename to src/pcms/backends/uniform_grid/linear_interpolant.hpp index bf0afe355..845280adb 100644 --- a/src/pcms/transfer/linear_interpolant.hpp +++ b/src/pcms/backends/uniform_grid/linear_interpolant.hpp @@ -1,12 +1,12 @@ -#ifndef PCMS_TRANSFER_LINEAR_INTERPOLANT_HPP -#define PCMS_TRANSFER_LINEAR_INTERPOLANT_HPP +#ifndef PCMS_BACKENDS_UNIFORM_GRID_LINEAR_INTERPOLANT_HPP +#define PCMS_BACKENDS_UNIFORM_GRID_LINEAR_INTERPOLANT_HPP #include -#include "multidimarray.hpp" -#define MAX_DIM 10 +#include "pcms/backends/uniform_grid/multidimarray.hpp" +#define PCMS_MAX_DIM 10 -namespace pcms +namespace pcms::backend::uniform_grid { KOKKOS_INLINE_FUNCTION @@ -73,7 +73,7 @@ double linear_interpolant(const IntVecView& dimensions, { int dim = dimensions.extent(0); double sum = 0; - int ids[MAX_DIM]; + int ids[PCMS_MAX_DIM]; int array_size = 1 << dim; for (int i = 0; i < array_size; ++i) { @@ -137,7 +137,7 @@ class RegularGridInterpolator Kokkos::parallel_for( "linear interpolation", N, KOKKOS_LAMBDA(int j) { - double linear_basis_each_dir[MAX_DIM] = {0.0}; + double linear_basis_each_dir[PCMS_MAX_DIM] = {0.0}; auto parametric_coord_each_point = Kokkos::subview(parametric_coords_, j, Kokkos::ALL()); auto index_each_point = Kokkos::subview(indices_, j, Kokkos::ALL()); @@ -171,9 +171,9 @@ inline Result parametric_indices(const RealMatView& points, Kokkos::parallel_for( N, KOKKOS_LAMBDA(int j) { - int indcs[MAX_DIM] = {0}; - double limits[MAX_DIM] = {0.0}; - double parametric_coord_each[MAX_DIM] = {0.0}; + int indcs[PCMS_MAX_DIM] = {0}; + double limits[PCMS_MAX_DIM] = {0.0}; + double parametric_coord_each[PCMS_MAX_DIM] = {0.0}; auto point_coord = Kokkos::subview(points, j, Kokkos::ALL()); find_indices(num_bins, range, point_coord, indcs); find_limits(num_bins, range, indcs, limits); @@ -197,6 +197,6 @@ double test_function(double* coord) } return fun_value; } -} // namespace pcms +} // namespace pcms::backend::uniform_grid -#endif // PCMS_TRANSFER_LINEAR_INTERPOLANT_HPP +#endif // PCMS_BACKENDS_UNIFORM_GRID_LINEAR_INTERPOLANT_HPP diff --git a/src/pcms/transfer/multidimarray.hpp b/src/pcms/backends/uniform_grid/multidimarray.hpp similarity index 77% rename from src/pcms/transfer/multidimarray.hpp rename to src/pcms/backends/uniform_grid/multidimarray.hpp index 8e08948f3..c626ff5d9 100644 --- a/src/pcms/transfer/multidimarray.hpp +++ b/src/pcms/backends/uniform_grid/multidimarray.hpp @@ -1,9 +1,9 @@ -#ifndef PCMS_TRANSFER_MULTIDIMARRAY_HPP -#define PCMS_TRANSFER_MULTIDIMARRAY_HPP +#ifndef PCMS_BACKENDS_UNIFORM_GRID_MULTIDIMARRAY_HPP +#define PCMS_BACKENDS_UNIFORM_GRID_MULTIDIMARRAY_HPP #include -namespace pcms +namespace pcms::backend::uniform_grid { using RealMatView = Kokkos::View; @@ -36,5 +36,5 @@ inline int calculateTotalSize(const HostIntVecView& dimensions) } return size; } -} // namespace pcms -#endif // PCMS_TRANSFER_MULTIDIMARRAY_HPP +} // namespace pcms::backend::uniform_grid +#endif // PCMS_BACKENDS_UNIFORM_GRID_MULTIDIMARRAY_HPP diff --git a/src/pcms/field/evaluator/uniform_grid_spline.h b/src/pcms/backends/uniform_grid/spline_evaluator.hpp similarity index 92% rename from src/pcms/field/evaluator/uniform_grid_spline.h rename to src/pcms/backends/uniform_grid/spline_evaluator.hpp index bd60147fc..34c28cce8 100644 --- a/src/pcms/field/evaluator/uniform_grid_spline.h +++ b/src/pcms/backends/uniform_grid/spline_evaluator.hpp @@ -1,19 +1,20 @@ -#ifndef PCMS_UNIFORM_GRID_SPLINE_EVALUATOR_FACTORY_H -#define PCMS_UNIFORM_GRID_SPLINE_EVALUATOR_FACTORY_H - -#include "pcms/field/evaluator/spline_interpolator.hpp" -#include "pcms/field/evaluator/uniform_grid.h" -#include "pcms/field/field_data.h" -#include "pcms/field/field_evaluator_factory.h" -#include "pcms/field/layout/uniform_grid.h" -#include "pcms/field/out_of_bounds_policy.h" -#include "pcms/field/point_evaluator.h" -#include "pcms/utility/assert.h" -#include "pcms/utility/types.h" +#ifndef PCMS_BACKENDS_UNIFORM_GRID_SPLINE_EVALUATOR_HPP +#define PCMS_BACKENDS_UNIFORM_GRID_SPLINE_EVALUATOR_HPP + +#include "pcms/backends/uniform_grid/spline_interpolator.hpp" +#include "pcms/backends/uniform_grid/evaluator.hpp" +#include "pcms/field/field_data.hpp" +#include "pcms/field/field_evaluator_factory.hpp" +#include "pcms/backends/uniform_grid/layout.hpp" +#include "pcms/field/out_of_bounds_policy.hpp" +#include "pcms/field/point_evaluator.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/types.hpp" #include +#include -namespace pcms +namespace pcms::backend::uniform_grid { namespace detail @@ -34,7 +35,7 @@ struct InitCoordsFunctor } // namespace detail template > + pcms::detail::default_layout_for_memory_space_t> class UniformGridSplinePointEvaluator2D : public PointEvaluator { @@ -197,7 +198,8 @@ class UniformGridSplinePointEvaluator2D Kokkos::View y_coords_; }; -class UniformGridSplineEvaluatorFactory2D : public FieldEvaluatorFactory +class UniformGridSplineEvaluatorFactory2D + : public pcms::field::FieldEvaluatorFactory { public: explicit UniformGridSplineEvaluatorFactory2D( @@ -300,6 +302,6 @@ class UniformGridSplineEvaluatorFactory2D : public FieldEvaluatorFactory UniformGrid<2> grid_; }; -} // namespace pcms +} // namespace pcms::backend::uniform_grid -#endif // PCMS_UNIFORM_GRID_SPLINE_EVALUATOR_FACTORY_H +#endif // PCMS_BACKENDS_UNIFORM_GRID_SPLINE_EVALUATOR_HPP diff --git a/src/pcms/field/evaluator/spline_interpolator.hpp b/src/pcms/backends/uniform_grid/spline_interpolator.hpp similarity index 99% rename from src/pcms/field/evaluator/spline_interpolator.hpp rename to src/pcms/backends/uniform_grid/spline_interpolator.hpp index fcae0c77f..189d913b7 100644 --- a/src/pcms/field/evaluator/spline_interpolator.hpp +++ b/src/pcms/backends/uniform_grid/spline_interpolator.hpp @@ -1,17 +1,17 @@ -#ifndef PCMS_TRANSFER_SPLINE_INTERPOLATOR_HPP -#define PCMS_TRANSFER_SPLINE_INTERPOLATOR_HPP +#ifndef PCMS_BACKENDS_UNIFORM_GRID_SPLINE_INTERPOLATOR_HPP +#define PCMS_BACKENDS_UNIFORM_GRID_SPLINE_INTERPOLATOR_HPP #include "mdspan/mdspan.hpp" -#include "pcms/utility/arrays.h" -#include "pcms/utility/assert.h" -#include "pcms/utility/memory_spaces.h" -#include "pcms/utility/types.h" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/memory_spaces.hpp" +#include "pcms/utility/types.hpp" #include #include #include #include -namespace pcms +namespace pcms::backend::uniform_grid { namespace detail @@ -3023,5 +3023,5 @@ CompactBiCubicSplineInterpolator:: << std::endl; } -} // namespace pcms -#endif // PCMS_TRANSFER_SPLINE_INTERPOLATOR_HPP +} // namespace pcms::backend::uniform_grid +#endif // PCMS_BACKENDS_UNIFORM_GRID_SPLINE_INTERPOLATOR_HPP diff --git a/src/pcms/backends/xgc/CMakeLists.txt b/src/pcms/backends/xgc/CMakeLists.txt new file mode 100644 index 000000000..1c68cd412 --- /dev/null +++ b/src/pcms/backends/xgc/CMakeLists.txt @@ -0,0 +1,20 @@ +# XGC backend. Public header: include/pcms/backends/xgc/. + +# Discretization and reverse classification: part of pcms::discretization +# (built regardless of PCMS_ENABLE_XGC, as before). +target_sources( + pcms_discretization + PRIVATE discretization.cpp reverse_classification.cpp discretization.hpp + PUBLIC FILE_SET field_discretization TYPE HEADERS BASE_DIRS + ${PROJECT_SOURCE_DIR}/include/pcms FILES + ${PROJECT_SOURCE_DIR}/include/pcms/backends/xgc/reverse_classification.hpp) + +# Layout, field data and field factory: part of pcms::field. +if(PCMS_ENABLE_XGC) + target_sources( + pcms_field + PRIVATE layout.cpp xgc.cpp field_data.hpp field_factory.hpp layout.hpp + PUBLIC FILE_SET field TYPE HEADERS BASE_DIRS + ${PROJECT_SOURCE_DIR}/include/pcms FILES + ${PROJECT_SOURCE_DIR}/include/pcms/backends/xgc/xgc.hpp) +endif() diff --git a/src/pcms/discretization/discretization/xgc.cpp b/src/pcms/backends/xgc/discretization.cpp similarity index 95% rename from src/pcms/discretization/discretization/xgc.cpp rename to src/pcms/backends/xgc/discretization.cpp index cacf41c54..26b14f51a 100644 --- a/src/pcms/discretization/discretization/xgc.cpp +++ b/src/pcms/backends/xgc/discretization.cpp @@ -1,11 +1,11 @@ -#include "pcms/discretization/discretization/xgc.hpp" +#include "pcms/backends/xgc/discretization.hpp" -namespace pcms +namespace pcms::backend::xgc { struct ClassifyVertsFunctor { - pcms::DimID geom; + pcms::backend::xgc::DimID geom; Kokkos::View verts; Kokkos::View class_dims_; Kokkos::View class_ids_; @@ -92,4 +92,4 @@ XGCDiscretization::GetEntityClassificationIds(int entity_dim) const : Rank1View(nullptr, 0); } -} // namespace pcms +} // namespace pcms::backend::xgc diff --git a/src/pcms/discretization/discretization/xgc.hpp b/src/pcms/backends/xgc/discretization.hpp similarity index 73% rename from src/pcms/discretization/discretization/xgc.hpp rename to src/pcms/backends/xgc/discretization.hpp index fb1d06d31..eb4f8a73d 100644 --- a/src/pcms/discretization/discretization/xgc.hpp +++ b/src/pcms/backends/xgc/discretization.hpp @@ -1,12 +1,12 @@ -#ifndef PCMS_DISCRETIZATION_DISCRETIZATION_XGC_H -#define PCMS_DISCRETIZATION_DISCRETIZATION_XGC_H +#ifndef PCMS_BACKENDS_XGC_DISCRETIZATION_HPP +#define PCMS_BACKENDS_XGC_DISCRETIZATION_HPP -#include "pcms/discretization/discretization.h" -#include "pcms/discretization/discretization/xgc_reverse_classification.h" +#include "pcms/discretization/discretization.hpp" +#include "pcms/backends/xgc/reverse_classification.hpp" #include -namespace pcms +namespace pcms::backend::xgc { class XGCDiscretization : public Discretization @@ -34,6 +34,6 @@ class XGCDiscretization : public Discretization Kokkos::View class_ids_; }; -} // namespace pcms +} // namespace pcms::backend::xgc -#endif // PCMS_DISCRETIZATION_DISCRETIZATION_XGC_H +#endif // PCMS_BACKENDS_XGC_DISCRETIZATION_HPP diff --git a/src/pcms/field/data/xgc.h b/src/pcms/backends/xgc/field_data.hpp similarity index 90% rename from src/pcms/field/data/xgc.h rename to src/pcms/backends/xgc/field_data.hpp index 9caf89d74..0d52e4404 100644 --- a/src/pcms/field/data/xgc.h +++ b/src/pcms/backends/xgc/field_data.hpp @@ -1,15 +1,15 @@ -#ifndef PCMS_XGC_FIELD_DATA_H -#define PCMS_XGC_FIELD_DATA_H +#ifndef PCMS_BACKENDS_XGC_FIELD_DATA_HPP +#define PCMS_BACKENDS_XGC_FIELD_DATA_HPP -#include "pcms/field/layout/xgc.h" -#include "pcms/field/field_data.h" -#include "pcms/utility/assert.h" -#include "pcms/utility/mpi_type.h" +#include "pcms/backends/xgc/layout.hpp" +#include "pcms/field/field_data.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/mpi_type.hpp" #include #include #include -namespace pcms +namespace pcms::backend::xgc { template @@ -86,7 +86,7 @@ class XGCFieldData } if (plane_comm_ != MPI_COMM_NULL) { MPI_Bcast(data_.data_handle(), static_cast(data_.size()), - GetMPIType(T{}), 0, plane_comm_); + pcms::utility::GetMPIType(T{}), 0, plane_comm_); } } @@ -113,6 +113,6 @@ class XGCFieldData MPI_Comm plane_comm_ = MPI_COMM_NULL; }; -} // namespace pcms +} // namespace pcms::backend::xgc -#endif // PCMS_XGC_FIELD_DATA_H +#endif // PCMS_BACKENDS_XGC_FIELD_DATA_HPP diff --git a/src/pcms/field/function_space/xgc.h b/src/pcms/backends/xgc/field_factory.hpp similarity index 85% rename from src/pcms/field/function_space/xgc.h rename to src/pcms/backends/xgc/field_factory.hpp index ee0b63b2a..a4edf5c8e 100644 --- a/src/pcms/field/function_space/xgc.h +++ b/src/pcms/backends/xgc/field_factory.hpp @@ -1,14 +1,14 @@ -#ifndef PCMS_XGC_FIELD_FACTORY_H -#define PCMS_XGC_FIELD_FACTORY_H +#ifndef PCMS_BACKENDS_XGC_FIELD_FACTORY_HPP +#define PCMS_BACKENDS_XGC_FIELD_FACTORY_HPP -#include "pcms/field/data/xgc.h" -#include "pcms/field/field.h" -#include "pcms/field/field_factory.h" +#include "pcms/backends/xgc/field_data.hpp" +#include "pcms/field/field.hpp" +#include "pcms/field/field_factory.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/utility/common.h" +#include "pcms/utility/detail/common.hpp" #include -namespace pcms +namespace pcms::backend::xgc { // XGC is a comm-only backend @@ -78,6 +78,6 @@ class XGCFieldFactory : public FieldFactory std::shared_ptr layout_; }; -} // namespace pcms +} // namespace pcms::backend::xgc -#endif // PCMS_XGC_FIELD_FACTORY_H +#endif // PCMS_BACKENDS_XGC_FIELD_FACTORY_HPP diff --git a/src/pcms/field/layout/xgc.cpp b/src/pcms/backends/xgc/layout.cpp similarity index 94% rename from src/pcms/field/layout/xgc.cpp rename to src/pcms/backends/xgc/layout.cpp index 54d9eecfd..306638806 100644 --- a/src/pcms/field/layout/xgc.cpp +++ b/src/pcms/backends/xgc/layout.cpp @@ -1,9 +1,9 @@ -#include "pcms/field/layout/xgc.h" -#include "pcms/utility/assert.h" -#include "pcms/utility/entity_types.h" -#include "pcms/field/coordinate_systems/cylindrical.hpp" +#include "pcms/backends/xgc/layout.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/entity_types.hpp" +#include "pcms/utility/coordinate_systems/cylindrical.hpp" -namespace pcms +namespace pcms::backend::xgc { struct InitilizeXGCMembersFunctor @@ -151,4 +151,4 @@ LO XGCFieldLayout::GetFullDataSize() const noexcept return num_plane_nodes_; } -} // namespace pcms +} // namespace pcms::backend::xgc diff --git a/src/pcms/field/layout/xgc.h b/src/pcms/backends/xgc/layout.hpp similarity index 82% rename from src/pcms/field/layout/xgc.h rename to src/pcms/backends/xgc/layout.hpp index 8d3e3ff43..c481c66ab 100644 --- a/src/pcms/field/layout/xgc.h +++ b/src/pcms/backends/xgc/layout.hpp @@ -1,11 +1,11 @@ -#ifndef PCMS_XGC_FIELD_LAYOUT_H -#define PCMS_XGC_FIELD_LAYOUT_H +#ifndef PCMS_BACKENDS_XGC_LAYOUT_HPP +#define PCMS_BACKENDS_XGC_LAYOUT_HPP -#include "pcms/discretization/discretization/xgc.hpp" -#include "pcms/discretization/discretization/xgc_reverse_classification.h" -#include "pcms/field/field_layout.h" +#include "pcms/backends/xgc/discretization.hpp" +#include "pcms/backends/xgc/reverse_classification.hpp" +#include "pcms/field/field_layout.hpp" -namespace pcms +namespace pcms::backend::xgc { class XGCFieldLayout : public FieldLayout @@ -47,6 +47,6 @@ class XGCFieldLayout : public FieldLayout std::shared_ptr discretization_; }; -} // namespace pcms +} // namespace pcms::backend::xgc -#endif // PCMS_XGC_FIELD_LAYOUT_H +#endif // PCMS_BACKENDS_XGC_LAYOUT_HPP diff --git a/src/pcms/discretization/discretization/xgc_reverse_classification.cpp b/src/pcms/backends/xgc/reverse_classification.cpp similarity index 96% rename from src/pcms/discretization/discretization/xgc_reverse_classification.cpp rename to src/pcms/backends/xgc/reverse_classification.cpp index 8c1f9e73d..76a7f3621 100644 --- a/src/pcms/discretization/discretization/xgc_reverse_classification.cpp +++ b/src/pcms/backends/xgc/reverse_classification.cpp @@ -1,13 +1,13 @@ -#include "pcms/discretization/discretization/xgc_reverse_classification.h" +#include "pcms/backends/xgc/reverse_classification.hpp" #include "mpi.h" -#include "pcms/utility/assert.h" +#include "pcms/utility/assert.hpp" #include #include #include -namespace pcms +namespace pcms::backend::xgc { std::vector ReverseClassificationVertex::Serialize() const @@ -165,4 +165,4 @@ std::ostream& operator<<(std::ostream& os, const ReverseClassificationVertex& v) return os; } -} // namespace pcms +} // namespace pcms::backend::xgc diff --git a/src/pcms/backends/xgc/xgc.cpp b/src/pcms/backends/xgc/xgc.cpp new file mode 100644 index 000000000..a0e1265dc --- /dev/null +++ b/src/pcms/backends/xgc/xgc.cpp @@ -0,0 +1,46 @@ +#include "pcms/backends/xgc/xgc.hpp" +#include "pcms/backends/xgc/field_data.hpp" +#include "pcms/backends/xgc/field_factory.hpp" +#include "pcms/utility/assert.hpp" + +#include + +namespace pcms::backend::xgc +{ + +std::shared_ptr CreateFieldFactory( + const ReverseClassificationVertex& reverse_classification, LO num_plane_nodes, + std::string layout_name) +{ + return std::make_shared( + reverse_classification, num_plane_nodes, std::move(layout_name)); +} + +template +Field CreateField(const FieldFactory& factory, std::string name, + Rank1View data, MPI_Comm plane_comm, + ValueBasis basis) +{ + const auto* xgc_factory = dynamic_cast(&factory); + if (xgc_factory == nullptr) { + throw pcms_error("pcms::backend::xgc::CreateField: the factory was not " + "created by pcms::backend::xgc::CreateFieldFactory"); + } + return xgc_factory->CreateField( + std::move(name), + std::make_unique>(xgc_factory->GetXGCLayout(), + std::move(basis), data, plane_comm)); +} + +#define PCMS_XGC_INSTANTIATE_CREATE_FIELD(T) \ + template Field CreateField(const FieldFactory&, std::string, \ + Rank1View, MPI_Comm, \ + ValueBasis); +PCMS_XGC_INSTANTIATE_CREATE_FIELD(int8_t) +PCMS_XGC_INSTANTIATE_CREATE_FIELD(int32_t) +PCMS_XGC_INSTANTIATE_CREATE_FIELD(int64_t) +PCMS_XGC_INSTANTIATE_CREATE_FIELD(float) +PCMS_XGC_INSTANTIATE_CREATE_FIELD(double) +#undef PCMS_XGC_INSTANTIATE_CREATE_FIELD + +} // namespace pcms::backend::xgc diff --git a/src/pcms/capi/CMakeLists.txt b/src/pcms/capi/CMakeLists.txt index 81819d7a5..775eb9e0f 100644 --- a/src/pcms/capi/CMakeLists.txt +++ b/src/pcms/capi/CMakeLists.txt @@ -1,53 +1,71 @@ -add_library(pcms_capi_core client.cpp kokkos.cpp) -add_library(pcms::capi::core ALIAS pcms_capi_core) +# the C API client wraps the coupler +if(TARGET pcms::coupler) + add_library(pcms_capi_core client.cpp kokkos.cpp) + add_library(pcms::capi::core ALIAS pcms_capi_core) -target_link_libraries( - pcms_capi_core - PUBLIC MPI::MPI_C - PRIVATE pcms::core) + target_link_libraries( + pcms_capi_core + PUBLIC MPI::MPI_C + PRIVATE pcms::coupler) -target_include_directories( - pcms_capi_core - PUBLIC "$" # this makes our - # include path - # pcms/capi - "$") + target_include_directories( + pcms_capi_core + PUBLIC "$" + "$" # this makes our + # include path + # pcms/capi + "$") + + set(CAPI_CORE_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../../../include/pcms/capi/client.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../../include/pcms/capi/kokkos.h) + set_target_properties( + pcms_capi_core PROPERTIES OUTPUT_NAME pcmscapicore + EXPORT_NAME capi::core) + # Only the public headers (include/pcms/...) are installed; the private +# headers next to the sources are private sources of the target. +set(CAPI_CORE_HEADERS_PUBLIC ${CAPI_CORE_HEADERS}) +list(FILTER CAPI_CORE_HEADERS_PUBLIC INCLUDE REGEX "/include/pcms/") +set(CAPI_CORE_HEADERS_PRIVATE ${CAPI_CORE_HEADERS}) +list(FILTER CAPI_CORE_HEADERS_PRIVATE EXCLUDE REGEX "/include/pcms/") +target_sources(pcms_capi_core + PUBLIC FILE_SET core TYPE HEADERS BASE_DIRS ${PROJECT_SOURCE_DIR}/include/pcms + FILES ${CAPI_CORE_HEADERS_PUBLIC} + PRIVATE ${CAPI_CORE_HEADERS_PRIVATE}) +endif() -set(CAPI_CORE_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/client.h - ${CMAKE_CURRENT_SOURCE_DIR}/kokkos.h) -set_target_properties( - pcms_capi_core PROPERTIES OUTPUT_NAME pcmscapicore - EXPORT_NAME capi::core) -target_sources(pcms_capi_core PUBLIC - FILE_SET core - TYPE HEADERS - BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/.. - FILES ${CAPI_CORE_HEADERS}) add_library(pcms_capi_transfer mesh.cpp interpolator.cpp kokkos.cpp) add_library(pcms::capi::transfer ALIAS pcms_capi_transfer) target_link_libraries(pcms_capi_transfer PUBLIC MPI::MPI_C PRIVATE pcms::transfer) target_include_directories(pcms_capi_transfer PUBLIC + "$" "$" # this makes the module path pcms/capi - "$") + "$") -set(CAPI_TRANSFER_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/interpolator.h - ${CMAKE_CURRENT_SOURCE_DIR}/mesh.h) +set(CAPI_TRANSFER_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/../../../include/pcms/capi/interpolator.h + ${CMAKE_CURRENT_SOURCE_DIR}/../../../include/pcms/capi/mesh.h) set_target_properties(pcms_capi_transfer PROPERTIES OUTPUT_NAME pcmscapitransfer EXPORT_NAME capi::transfer) -target_sources(pcms_capi_transfer PUBLIC - FILE_SET transfer - TYPE HEADERS - BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/.. - FILES ${CAPI_TRANSFER_HEADERS}) +# Only the public headers (include/pcms/...) are installed; the private +# headers next to the sources are private sources of the target. +set(CAPI_TRANSFER_HEADERS_PUBLIC ${CAPI_TRANSFER_HEADERS}) +list(FILTER CAPI_TRANSFER_HEADERS_PUBLIC INCLUDE REGEX "/include/pcms/") +set(CAPI_TRANSFER_HEADERS_PRIVATE ${CAPI_TRANSFER_HEADERS}) +list(FILTER CAPI_TRANSFER_HEADERS_PRIVATE EXCLUDE REGEX "/include/pcms/") +target_sources(pcms_capi_transfer + PUBLIC FILE_SET transfer TYPE HEADERS BASE_DIRS ${PROJECT_SOURCE_DIR}/include/pcms + FILES ${CAPI_TRANSFER_HEADERS_PUBLIC} + PRIVATE ${CAPI_TRANSFER_HEADERS_PRIVATE}) # high level interface target add_library(pcms_capi INTERFACE) add_library(pcms::capi ALIAS pcms_capi) set_target_properties(pcms_capi PROPERTIES EXPORT_NAME capi) # link capi libraries to a high level interface library -target_link_libraries(pcms_capi INTERFACE pcms::capi::core) +if(TARGET pcms_capi_core) + target_link_libraries(pcms_capi INTERFACE pcms::capi::core) +endif() target_link_libraries(pcms_capi INTERFACE pcms::capi::transfer) install( TARGETS pcms_capi @@ -61,22 +79,24 @@ install( install( EXPORT pcms_capi-targets NAMESPACE pcms:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pcms) + DESTINATION ${PCMS_INSTALL_CMAKEDIR}) # library targets -install( - TARGETS pcms_capi_core - EXPORT pcms_capi_core-targets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - INCLUDES - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - FILE_SET core DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/pcms) -install( - EXPORT pcms_capi_core-targets - NAMESPACE pcms:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pcms) +if(TARGET pcms_capi_core) + install( + TARGETS pcms_capi_core + EXPORT pcms_capi_core-targets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + FILE_SET core DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/pcms) + install( + EXPORT pcms_capi_core-targets + NAMESPACE pcms:: + DESTINATION ${PCMS_INSTALL_CMAKEDIR}) +endif() install( TARGETS pcms_capi_transfer @@ -90,4 +110,4 @@ install( install( EXPORT pcms_capi_transfer-targets NAMESPACE pcms:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pcms) + DESTINATION ${PCMS_INSTALL_CMAKEDIR}) diff --git a/src/pcms/capi/client.cpp b/src/pcms/capi/client.cpp index 414579bf3..2170a1f8e 100644 --- a/src/pcms/capi/client.cpp +++ b/src/pcms/capi/client.cpp @@ -1,19 +1,19 @@ -#include "client.h" -#include "pcms.h" -#include "pcms/field/field_factory.h" -#include "pcms/field/function_space/xgc.h" -#include "pcms/field/data/xgc.h" -#include "pcms/field/layout/xgc.h" -#include "pcms/discretization/discretization/xgc_reverse_classification.h" +#include "pcms/capi/client.h" +#include "pcms/pcms.hpp" +#include "pcms/field/field_factory.hpp" +#include "pcms/backends/xgc/field_factory.hpp" +#include "pcms/backends/xgc/field_data.hpp" +#include "pcms/backends/xgc/layout.hpp" +#include "pcms/backends/xgc/reverse_classification.hpp" #include "pcms/coupler/coupler.hpp" -#include "pcms/field/layout/empty.h" -#include "pcms/field/data/simple.h" -#include "pcms/utility/assert.h" +#include "pcms/field/layout/empty.hpp" +#include "pcms/field/simple_field_data.hpp" +#include "pcms/utility/assert.hpp" #include #include #include #include -#include "pcms/field/coordinate_systems/cylindrical.hpp" +#include "pcms/utility/coordinate_systems/cylindrical.hpp" namespace pcms { @@ -24,11 +24,11 @@ namespace detail template struct XGCFieldRegistration { - XGCFieldFactory function_space; + pcms::backend::xgc::XGCFieldFactory function_space; MPI_Comm plane_comm; Rank1View data; - XGCFieldRegistration(XGCFieldFactory fs, MPI_Comm comm, + XGCFieldRegistration(pcms::backend::xgc::XGCFieldFactory fs, MPI_Comm comm, Rank1View d) : function_space(std::move(fs)), plane_comm(comm), data(d) { @@ -44,7 +44,8 @@ class EmptyFieldFactory : public FieldFactory EmptyFieldFactory(std::string layout_name, std::shared_ptr system) { - auto layout = std::make_shared(std::move(system)); + auto layout = + std::make_shared(std::move(system)); layout->SetName(std::move(layout_name)); layout_ = layout; } @@ -90,7 +91,7 @@ class EmptyFieldFactory : public FieldFactory } private: - std::shared_ptr layout_; + std::shared_ptr layout_; }; } // namespace detail @@ -129,7 +130,7 @@ ClientState::HandleVariant RegisterField( // not the arbitrary adapter name given at creation. registration.function_space.SetLayoutName(name); auto field = registration.function_space.template CreateField( - std::move(name), std::make_unique>( + std::move(name), std::make_unique>( registration.function_space.GetXGCLayout(), ValueBasis{}, registration.data, registration.plane_comm)); return ClientState::HandleVariant{ @@ -173,14 +174,15 @@ void pcms_destroy_client(PcmsClientHandle client) PcmsReverseClassificationHandle pcms_load_reverse_classification( const char* file, MPI_Comm comm) { - auto* rc = new pcms::ReverseClassificationVertex{ - pcms::ReadReverseClassificationVertex(file, comm)}; + auto* rc = new pcms::backend::xgc::ReverseClassificationVertex{ + pcms::backend::xgc::ReadReverseClassificationVertex(file, comm)}; return {reinterpret_cast(rc)}; } void pcms_destroy_reverse_classification(PcmsReverseClassificationHandle rc) { - delete reinterpret_cast(rc.pointer); + delete reinterpret_cast( + rc.pointer); } void pcms_set_overlap_mask(PcmsClientHandle client_handle, const char* name, @@ -258,11 +260,12 @@ void pcms_receive_field(PcmsFieldHandle field_handle) template void pcms_create_xgc_field_adapter_t( const char* /* name */, MPI_Comm comm, void* data, int size, - const pcms::ReverseClassificationVertex& reverse_classification, + const pcms::backend::xgc::ReverseClassificationVertex& reverse_classification, pcms::FieldAdapterVariant& field_adapter) { PCMS_ALWAYS_ASSERT((size > 0) ? (data != nullptr) : true); - auto function_space = pcms::XGCFieldFactory(reverse_classification, size); + auto function_space = + pcms::backend::xgc::XGCFieldFactory(reverse_classification, size); pcms::Rank1View data_view( reinterpret_cast(data), size); field_adapter.emplace>( @@ -276,7 +279,8 @@ PcmsFieldAdapterHandle pcms_create_xgc_field_adapter( auto* field_adapter = new pcms::FieldAdapterVariant{}; PCMS_ALWAYS_ASSERT(rc.pointer != nullptr); auto* reverse_classification = - reinterpret_cast(rc.pointer); + reinterpret_cast( + rc.pointer); PCMS_ALWAYS_ASSERT(reverse_classification != nullptr); switch (data_type) { case PCMS_DOUBLE: @@ -317,7 +321,8 @@ void pcms_destroy_field_adapter(PcmsFieldAdapterHandle adapter_handle) int pcms_reverse_classification_count_verts(PcmsReverseClassificationHandle rc) { auto* reverse_classification = - reinterpret_cast(rc.pointer); + reinterpret_cast( + rc.pointer); PCMS_ALWAYS_ASSERT(reverse_classification != nullptr); return std::accumulate(reverse_classification->begin(), reverse_classification->end(), 0, diff --git a/src/pcms/capi/interpolator.cpp b/src/pcms/capi/interpolator.cpp index 9b5703d17..3d8a0a965 100644 --- a/src/pcms/capi/interpolator.cpp +++ b/src/pcms/capi/interpolator.cpp @@ -3,19 +3,20 @@ // #include #include -#include +#include #include #include #include -#include -#include +#include +#include //[[nodiscard]] PcmsInterpolatorHandle pcms_create_interpolator(PcmsOmegaHMeshHandle oh_mesh, double radius) { auto* source_mesh = reinterpret_cast(oh_mesh.mesh_handle); - auto* interpolator = new pcms::MLSMeshInterpolation(*source_mesh, radius); + auto* interpolator = + new pcms::transfer::MLSMeshInterpolation(*source_mesh, radius); return {reinterpret_cast(interpolator)}; } @@ -29,7 +30,7 @@ PcmsInterpolatorHandle pcms_create_point_based_interpolator( reinterpret_cast(source_points), source_points_size); auto target_points_view = pcms::Rank1View( reinterpret_cast(target_points), target_points_size); - auto* interpolator = new pcms::MLSPointCloudInterpolation( + auto* interpolator = new pcms::transfer::MLSPointCloudInterpolation( source_points_view, target_points_view, 2, radius, min_req_supports, degree, true, lambda, decay_factor); return {reinterpret_cast(interpolator)}; @@ -45,7 +46,8 @@ Omega_h::HostRead read_mesh_centroids(const char* mesh_filename, auto mesh = Omega_h::binary::read(fname, mesh_lib.world()); OMEGA_H_CHECK_PRINTF(mesh.dim() == 2, "Mesh dimension is not 2D %d\n", mesh.dim()); - auto elem_centroids = pcms::get_entity_centroids(mesh, Omega_h::FACE); + auto elem_centroids = + pcms::utility::get_entity_centroids(mesh, Omega_h::FACE); num_elements = mesh.nelems(); OMEGA_H_CHECK_PRINTF(num_elements * 2 == elem_centroids.size(), "Mesh element centroids size does not match the number " @@ -107,7 +109,8 @@ PcmsInterpolatorHandle pcms_create_xgcnodedegas2_interpolator( void pcms_destroy_interpolator(PcmsInterpolatorHandle interpolator) { if (interpolator.pointer != nullptr) { - delete reinterpret_cast(interpolator.pointer); + delete reinterpret_cast( + interpolator.pointer); } } @@ -115,7 +118,7 @@ void pcms_interpolate(PcmsInterpolatorHandle interpolator, void* input, int input_size, void* output, int output_size) { auto* mls_interpolator = - reinterpret_cast(interpolator.pointer); + reinterpret_cast(interpolator.pointer); OMEGA_H_CHECK_PRINTF( input_size == mls_interpolator->getSourceSize(), diff --git a/src/pcms/capi/mesh.cpp b/src/pcms/capi/mesh.cpp index 561efa454..c3e55c54b 100644 --- a/src/pcms/capi/mesh.cpp +++ b/src/pcms/capi/mesh.cpp @@ -1,4 +1,4 @@ -#include "mesh.h" +#include "pcms/capi/mesh.h" #include #include diff --git a/src/pcms/configuration.h.in b/src/pcms/configuration.hpp.in similarity index 81% rename from src/pcms/configuration.h.in rename to src/pcms/configuration.hpp.in index ee0dbaf94..8176d1f76 100644 --- a/src/pcms/configuration.h.in +++ b/src/pcms/configuration.hpp.in @@ -1,12 +1,16 @@ +#ifndef PCMS_CONFIGURATION_HPP +#define PCMS_CONFIGURATION_HPP + #cmakedefine PCMS_ENABLE_SERVER #cmakedefine PCMS_ENABLE_CLIENT +#cmakedefine PCMS_ENABLE_COUPLER #cmakedefine PCMS_ENABLE_XGC #cmakedefine PCMS_ENABLE_OMEGA_H #cmakedefine PCMS_ENABLE_MFEM #cmakedefine PCMS_ENABLE_C #cmakedefine PCMS_ENABLE_TRANSIENT #cmakedefine PCMS_ENABLE_PRINT -#cmakedefine PCMS_ENABLE_Fortran +#cmakedefine PCMS_ENABLE_FORTRAN #cmakedefine PCMS_ENABLE_MESHFIELDS #cmakedefine PCMS_ENABLE_PETSC @@ -17,3 +21,5 @@ #cmakedefine PCMS_INTERSECTION_REL_TOL @PCMS_INTERSECTION_REL_TOL@ #cmakedefine PCMS_PROJECTION_KSP_RTOL @PCMS_PROJECTION_KSP_RTOL@ #cmakedefine PCMS_PROJECTION_KSP_ATOL @PCMS_PROJECTION_KSP_ATOL@ + +#endif // PCMS_CONFIGURATION_HPP diff --git a/src/pcms/coupler/CMakeLists.txt b/src/pcms/coupler/CMakeLists.txt index 397694120..951992719 100644 --- a/src/pcms/coupler/CMakeLists.txt +++ b/src/pcms/coupler/CMakeLists.txt @@ -1,13 +1,13 @@ set(PCMS_COUPLER_HEADERS - coupler_types.h - field_communicator.hpp - coupler.hpp - field_serializer.h - field_layout_communicator.h - field_exchange_planner.h - partition.h - overlap_mask.h - global_communicator.h + ../../../include/pcms/coupler/coupler_types.hpp + ../../../include/pcms/coupler/detail/field_communicator.hpp + ../../../include/pcms/coupler/coupler.hpp + ../../../include/pcms/coupler/detail/field_serializer.hpp + ../../../include/pcms/coupler/detail/field_layout_communicator.hpp + ../../../include/pcms/coupler/detail/field_exchange_planner.hpp + partition.hpp + ../../../include/pcms/coupler/overlap_mask.hpp + ../../../include/pcms/coupler/detail/global_communicator.hpp ) @@ -21,11 +21,16 @@ add_library(pcms_coupler ${PCMS_COUPLER_SOURCES}) set_target_properties(pcms_coupler PROPERTIES OUTPUT_NAME pcmscoupler EXPORT_NAME coupler) -target_sources(pcms_coupler PUBLIC - FILE_SET coupler - TYPE HEADERS - BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/.. - FILES ${PCMS_COUPLER_HEADERS}) +# Only the public headers (include/pcms/...) are installed; the private +# headers next to the sources are private sources of the target. +set(PCMS_COUPLER_HEADERS_PUBLIC ${PCMS_COUPLER_HEADERS}) +list(FILTER PCMS_COUPLER_HEADERS_PUBLIC INCLUDE REGEX "/include/pcms/") +set(PCMS_COUPLER_HEADERS_PRIVATE ${PCMS_COUPLER_HEADERS}) +list(FILTER PCMS_COUPLER_HEADERS_PRIVATE EXCLUDE REGEX "/include/pcms/") +target_sources(pcms_coupler + PUBLIC FILE_SET coupler TYPE HEADERS BASE_DIRS ${PROJECT_SOURCE_DIR}/include/pcms + FILES ${PCMS_COUPLER_HEADERS_PUBLIC} + PRIVATE ${PCMS_COUPLER_HEADERS_PRIVATE}) add_library(pcms::coupler ALIAS pcms_coupler) target_compile_features(pcms_coupler PUBLIC cxx_std_20) @@ -42,7 +47,7 @@ if(PCMS_ENABLE_OMEGA_H) endif() if (PCMS_ENABLE_MESHFIELDS) - target_link_libraries(pcms_coupler PUBLIC meshfields::meshfields) + target_link_libraries(pcms_coupler PRIVATE meshfields::meshfields) endif () target_include_directories(pcms_coupler INTERFACE @@ -62,4 +67,4 @@ install( install( EXPORT pcms_coupler-targets NAMESPACE pcms:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pcms) + DESTINATION ${PCMS_INSTALL_CMAKEDIR}) diff --git a/src/pcms/coupler/coupler.cpp b/src/pcms/coupler/coupler.cpp index f3ffe3efb..e654c47d3 100644 --- a/src/pcms/coupler/coupler.cpp +++ b/src/pcms/coupler/coupler.cpp @@ -1,10 +1,21 @@ #include "pcms/coupler/coupler.hpp" +#include "pcms/utility/types.hpp" +#include "redev.h" +#include namespace pcms { +// pcms and redev exchange data without conversion +static_assert(std::is_same_v, + "pcms and redev real types must match"); +static_assert(std::is_same_v, + "pcms and redev LO types must match"); +static_assert(std::is_same_v, + "pcms and redev GO types must match"); -FieldLayoutCommunicator& ApplicationComm::GetOrCreateLayoutCommunicator( - const FieldLayout& layout, bool participates) +pcms::coupler::FieldLayoutCommunicator& +ApplicationComm::GetOrCreateLayoutCommunicator(const FieldLayout& layout, + bool participates) { PCMS_FUNCTION_TIMER; const std::string& name = layout.GetName(); @@ -38,10 +49,10 @@ FieldLayoutCommunicator& ApplicationComm::GetOrCreateLayoutCommunicator( } auto [it2, inserted] = field_layout_communicators_.emplace( - name, std::make_unique( + name, std::make_unique( name, mpi_comm_subset, redev_, channel_, layout, - std::make_unique(), own_mpi_comm, - overlap_mask)); + std::make_unique(), + own_mpi_comm, overlap_mask)); return *it2->second; } diff --git a/src/pcms/coupler/coupler_types.h b/src/pcms/coupler/coupler_types.h deleted file mode 100644 index 46deb86b1..000000000 --- a/src/pcms/coupler/coupler_types.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef PCMS_COUPLER_TYPES_H_ -#define PCMS_COUPLER_TYPES_H_ - -#include - -namespace pcms -{ - -using ProcessType = redev::ProcessType; -using Mode = redev::Mode; - -} // namespace pcms - -#endif // PCMS_COUPLER_TYPES_H_ diff --git a/src/pcms/coupler/field_exchange_planner.cpp b/src/pcms/coupler/field_exchange_planner.cpp index 88f60d2db..c96ebd90c 100644 --- a/src/pcms/coupler/field_exchange_planner.cpp +++ b/src/pcms/coupler/field_exchange_planner.cpp @@ -1,13 +1,13 @@ -#include "pcms/coupler/field_exchange_planner.h" -#include "partition.h" +#include "pcms/coupler/detail/field_exchange_planner.hpp" +#include "pcms/coupler/partition.hpp" #include "pcms/field/gid_permutation.hpp" -#include "pcms/utility/assert.h" -#include "pcms/utility/inclusive_scan.h" -#include "pcms/utility/profile.h" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/detail/inclusive_scan.hpp" +#include "pcms/utility/detail/profile.hpp" #include #include -namespace pcms +namespace pcms::coupler { namespace @@ -80,7 +80,7 @@ static redev::LOs ConstructPermutation( PCMS_FUNCTION_TIMER; // Holders that do not participate in this exchange (non-owned, or owned but // outside the overlap region) stay unmapped; serialization skips them. - redev::LOs permutation = MakeUnmappedPermutation(num_entries); + redev::LOs permutation = pcms::field::MakeUnmappedPermutation(num_entries); LO entry = 0; for (const auto& rank : reverse_partition) { for (unsigned e = 0; e < rank.second.ent_offsets.size() - 1; ++e) { @@ -111,7 +111,7 @@ static redev::LOs ConstructPermutation( const EntOffsetsArray& ent_offsets, int& payload_length) { PCMS_FUNCTION_TIMER; - GidToIndexMaps gid_to_buffer_index; + pcms::field::GidToIndexMaps gid_to_buffer_index; size_t offset = 0; LO payload_offset = 0; while (true) { @@ -141,9 +141,9 @@ static redev::LOs ConstructPermutation( redev::LOs permutation; permutation.reserve(local_gids.size()); - AppendGidPermutation(local_gids, ent_offsets, gid_to_buffer_index, - permutation, - /*allow_missing=*/true); + pcms::field::AppendGidPermutation(local_gids, ent_offsets, + gid_to_buffer_index, permutation, + /*allow_missing=*/true); REDEV_ALWAYS_ASSERT(permutation.size() == local_gids.size()); payload_length = payload_offset; @@ -335,4 +335,4 @@ void GenericFieldExchangePlanner::FillGidMessage( } } -} // namespace pcms +} // namespace pcms::coupler diff --git a/src/pcms/coupler/field_layout_communicator.cpp b/src/pcms/coupler/field_layout_communicator.cpp index f20b53945..3ba1e7ffb 100644 --- a/src/pcms/coupler/field_layout_communicator.cpp +++ b/src/pcms/coupler/field_layout_communicator.cpp @@ -1,7 +1,7 @@ -#include "pcms/coupler/field_layout_communicator.h" +#include "pcms/coupler/detail/field_layout_communicator.hpp" #include "pcms/field/gid_permutation.hpp" -namespace pcms +namespace pcms::coupler { FieldLayoutCommunicator::FieldLayoutCommunicator( @@ -111,7 +111,7 @@ void FieldLayoutCommunicator::UpdateLayoutNull() PCMS_FUNCTION_TIMER; // This rank exchanges nothing, but it still unpacks on receive (backends // that keep replicas synchronize them there), so every holder is unmapped. - plan_.permutation = MakeUnmappedPermutation( + plan_.permutation = pcms::field::MakeUnmappedPermutation( static_cast(layout_.GetNumOwnedDofHolder())); if (redev_.GetProcessType() == redev::ProcessType::Client) { channel_.BeginSendCommunicationPhase(); @@ -134,4 +134,4 @@ FieldLayoutCommunicator::~FieldLayoutCommunicator() } } -} // namespace pcms +} // namespace pcms::coupler diff --git a/src/pcms/coupler/partition.h b/src/pcms/coupler/partition.hpp similarity index 75% rename from src/pcms/coupler/partition.h rename to src/pcms/coupler/partition.hpp index baba1751b..dc86985f1 100644 --- a/src/pcms/coupler/partition.h +++ b/src/pcms/coupler/partition.hpp @@ -1,12 +1,12 @@ -#ifndef PCMS_PARTITION_H -#define PCMS_PARTITION_H -#include "pcms/utility/common.h" -#include "pcms/utility/profile.h" -#include "pcms/utility/types.h" +#ifndef PCMS_COUPLER_PARTITION_HPP +#define PCMS_COUPLER_PARTITION_HPP +#include "pcms/utility/detail/common.hpp" +#include "pcms/utility/detail/profile.hpp" +#include "pcms/utility/types.hpp" #include #include -namespace pcms +namespace pcms::coupler { struct GetRank { @@ -46,6 +46,6 @@ struct Partition redev::Partition partition_; }; -} // namespace pcms +} // namespace pcms::coupler -#endif // PCMS_PARTITION_H +#endif // PCMS_COUPLER_PARTITION_HPP diff --git a/src/pcms/discretization/CMakeLists.txt b/src/pcms/discretization/CMakeLists.txt index 1afa1f201..0098f1f84 100644 --- a/src/pcms/discretization/CMakeLists.txt +++ b/src/pcms/discretization/CMakeLists.txt @@ -1,34 +1,27 @@ set( PCMS_DISCRETIZATION_HEADERS - discretization.h - discretization/xgc_reverse_classification.h - discretization/empty.hpp - discretization/point_cloud.hpp - discretization/uniform_grid.hpp - discretization/xgc.hpp + ../../../include/pcms/discretization/discretization.hpp + empty.hpp ) -if (PCMS_ENABLE_OMEGA_H) - list(APPEND PCMS_DISCRETIZATION_HEADERS discretization/omega_h.hpp) -endif() set( PCMS_DISCRETIZATION_SOURCES - discretization/empty.cpp - discretization/point_cloud.cpp - discretization/xgc_reverse_classification.cpp - discretization/xgc.cpp + empty.cpp + factories.cpp ) -if (PCMS_ENABLE_OMEGA_H) - list(APPEND PCMS_DISCRETIZATION_SOURCES discretization/omega_h.cpp) -endif() add_library(pcms_discretization ${PCMS_DISCRETIZATION_SOURCES}) add_library(pcms::discretization ALIAS pcms_discretization) -target_sources(pcms_discretization PUBLIC - FILE_SET field_discretization - TYPE HEADERS - BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/.. - FILES ${PCMS_DISCRETIZATION_HEADERS}) +# Only the public headers (include/pcms/...) are installed; the private +# headers next to the sources are private sources of the target. +set(PCMS_DISCRETIZATION_HEADERS_PUBLIC ${PCMS_DISCRETIZATION_HEADERS}) +list(FILTER PCMS_DISCRETIZATION_HEADERS_PUBLIC INCLUDE REGEX "/include/pcms/") +set(PCMS_DISCRETIZATION_HEADERS_PRIVATE ${PCMS_DISCRETIZATION_HEADERS}) +list(FILTER PCMS_DISCRETIZATION_HEADERS_PRIVATE EXCLUDE REGEX "/include/pcms/") +target_sources(pcms_discretization + PUBLIC FILE_SET field_discretization TYPE HEADERS BASE_DIRS ${PROJECT_SOURCE_DIR}/include/pcms + FILES ${PCMS_DISCRETIZATION_HEADERS_PUBLIC} + PRIVATE ${PCMS_DISCRETIZATION_HEADERS_PRIVATE}) target_include_directories( pcms_discretization PUBLIC @@ -65,5 +58,5 @@ install( install( EXPORT pcms_discretization-targets NAMESPACE pcms:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pcms + DESTINATION ${PCMS_INSTALL_CMAKEDIR} ) diff --git a/src/pcms/discretization/discretization.h b/src/pcms/discretization/discretization.h deleted file mode 100644 index 2383ff5b2..000000000 --- a/src/pcms/discretization/discretization.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef PCMS_DISCRETIZATION_DISCRETIZATION_H -#define PCMS_DISCRETIZATION_DISCRETIZATION_H - -#include "pcms/utility/arrays.h" -#include "pcms/utility/entity_types.h" - -namespace pcms -{ - -using ClassificationDimension = int8_t; -using ClassificationId = LO; - -class Discretization -{ -public: - virtual bool SameEntities(const Discretization& other) const noexcept = 0; - - virtual int GetDimension() const = 0; - - virtual LO GetNumEntities(int entity_dim) const = 0; - - virtual Rank1View - GetEntityClassificationDimensions(int entity_dim) const = 0; - - virtual Rank1View - GetEntityClassificationIds(int entity_dim) const = 0; - - virtual ~Discretization() noexcept = default; -}; - -} // namespace pcms - -#endif // PCMS_DISCRETIZATION_DISCRETIZATION_H diff --git a/src/pcms/discretization/discretization/empty.cpp b/src/pcms/discretization/empty.cpp similarity index 85% rename from src/pcms/discretization/discretization/empty.cpp rename to src/pcms/discretization/empty.cpp index 6f082141f..f09ecd7f4 100644 --- a/src/pcms/discretization/discretization/empty.cpp +++ b/src/pcms/discretization/empty.cpp @@ -1,6 +1,6 @@ -#include "pcms/discretization/discretization/empty.hpp" +#include "pcms/discretization/empty.hpp" -namespace pcms +namespace pcms::discretization { EmptyDiscretization::EmptyDiscretization() {} @@ -33,4 +33,4 @@ EmptyDiscretization::GetEntityClassificationIds(int) const return {}; } -} // namespace pcms +} // namespace pcms::discretization diff --git a/src/pcms/discretization/discretization/empty.hpp b/src/pcms/discretization/empty.hpp similarity index 69% rename from src/pcms/discretization/discretization/empty.hpp rename to src/pcms/discretization/empty.hpp index 9cfb18991..d7757da2c 100644 --- a/src/pcms/discretization/discretization/empty.hpp +++ b/src/pcms/discretization/empty.hpp @@ -1,11 +1,11 @@ -#ifndef PCMS_DISCRETIZATION_DISCRETIZATION_EMPTY_H -#define PCMS_DISCRETIZATION_DISCRETIZATION_EMPTY_H +#ifndef PCMS_DISCRETIZATION_EMPTY_HPP +#define PCMS_DISCRETIZATION_EMPTY_HPP -#include "pcms/discretization/discretization.h" +#include "pcms/discretization/discretization.hpp" #include -namespace pcms +namespace pcms::discretization { class EmptyDiscretization : public Discretization @@ -26,6 +26,6 @@ class EmptyDiscretization : public Discretization GetEntityClassificationIds(int entity_dim) const override; }; -} // namespace pcms +} // namespace pcms::discretization -#endif // PCMS_DISCRETIZATION_DISCRETIZATION_EMPTY_H +#endif // PCMS_DISCRETIZATION_EMPTY_HPP diff --git a/src/pcms/discretization/factories.cpp b/src/pcms/discretization/factories.cpp new file mode 100644 index 000000000..aabaea72c --- /dev/null +++ b/src/pcms/discretization/factories.cpp @@ -0,0 +1,27 @@ +#include "pcms/discretization/discretization.hpp" +#include "pcms/discretization/empty.hpp" +#include "pcms/backends/uniform_grid/discretization.hpp" + +namespace pcms +{ + +std::shared_ptr CreateUniformGridDiscretization( + const UniformGrid<2>& grid) +{ + return std::make_shared>( + grid); +} + +std::shared_ptr CreateUniformGridDiscretization( + const UniformGrid<3>& grid) +{ + return std::make_shared>( + grid); +} + +std::shared_ptr CreateEmptyDiscretization() +{ + return std::make_shared(); +} + +} // namespace pcms diff --git a/src/pcms/field/CMakeLists.txt b/src/pcms/field/CMakeLists.txt index 496f60e86..0b1c9215c 100644 --- a/src/pcms/field/CMakeLists.txt +++ b/src/pcms/field/CMakeLists.txt @@ -1,117 +1,68 @@ find_package(KokkosKernels REQUIRED) set(PCMS_FIELD_HEADERS - field.h - coordinate_system.hpp - coordinate_view.hpp - coordinate_systems/cartesian.hpp - coordinate_systems/cylindrical.hpp - coordinate_map.hpp - value_view.hpp - element_dispatch.h - evaluation_request.h + ../../../include/pcms/field/field.hpp + ../../../include/pcms/field/coordinate_map.hpp + ../../../include/pcms/field/value_view.hpp + element_dispatch.hpp + ../../../include/pcms/field/evaluation_request.hpp gid_permutation.hpp - field_layout.h - layout/empty.h - out_of_bounds_policy.h - field_data.h - field_factory.h - function_space.h - point_evaluator.h - point_evaluator_factory.hpp - transformed_source.hpp - data/simple.h + ../../../include/pcms/field/field_layout.hpp + layout/empty.hpp + ../../../include/pcms/field/out_of_bounds_policy.hpp + ../../../include/pcms/field/field_data.hpp + ../../../include/pcms/field/field_factory.hpp + ../../../include/pcms/field/function_space.hpp + ../../../include/pcms/field/point_evaluator.hpp + ../../../include/pcms/field/point_evaluator_factory.hpp + ../../../include/pcms/field/transformed_source.hpp + ../../../include/pcms/field/simple_field_data.hpp function_space/polynomial_reconstruction.hpp - layout/point_cloud.h - data/point_cloud.h + ../../../include/pcms/field/function_spaces.hpp ) set(PCMS_FIELD_SOURCES field_layout.cpp - coordinate_system.cpp coordinate_map.cpp transformed_source.cpp gid_permutation.cpp function_space/polynomial_reconstruction.cpp + function_spaces.cpp layout/empty.cpp - layout/point_cloud.cpp - data/point_cloud.cpp ) if (PCMS_ENABLE_OMEGA_H) list(APPEND PCMS_FIELD_SOURCES function_space/lagrange.cpp function_space/spline.cpp - layout/omega_h_entity.cpp - layout/omega_h_lagrange.cpp - layout/uniform_grid.cpp evaluator/mls_interpolation.cpp ) list(APPEND PCMS_FIELD_HEADERS - function_space/lagrange.h - function_space/spline.h - field_evaluator_factory.h - layout/omega_h_entity.h - layout/omega_h_lagrange.h - evaluator/omega_h_lagrange.h - layout/uniform_grid.h - uniform_grid_binary_field.h - evaluator/uniform_grid.h - evaluator/spline_interpolator.hpp - evaluator/uniform_grid_spline.h - eqdsk_field.h - evaluator/mls_options.h + function_space/lagrange.hpp + function_space/spline.hpp + field_evaluator_factory.hpp + ../../../include/pcms/field/eqdsk_field.hpp evaluator/mls_interpolation.hpp evaluator/mls_interpolation_impl.hpp - evaluator/pcms_interpolator_aliases.hpp - evaluator/pcms_interpolator_view_utils.hpp - evaluator/pcms_interpolator_logger.hpp - evaluator/mls_point_cloud.h - evaluator/point_cloud.h + evaluator/interpolator_aliases.hpp + evaluator/interpolator_view_utils.hpp + evaluator/interpolator_logger.hpp ) endif () -if (PCMS_ENABLE_MFEM) - list(APPEND PCMS_FIELD_SOURCES - layout/mfem.cpp - data/mfem.cpp - ) - list(APPEND PCMS_FIELD_HEADERS - layout/mfem.hpp - data/mfem.hpp - function_space/mfem.hpp - ) -endif () - -if (PCMS_ENABLE_MESHFIELDS) - list(APPEND PCMS_FIELD_SOURCES - layout/mesh_fields.cpp - ) - list(APPEND PCMS_FIELD_HEADERS - layout/mesh_fields.h - evaluator/mesh_fields_backend.h - evaluator/mesh_fields.h - data/mesh_fields.h - ) -endif () - -if(PCMS_ENABLE_XGC) - list(APPEND PCMS_FIELD_HEADERS - data/xgc.h - function_space/xgc.h - layout/xgc.h) - list(APPEND PCMS_FIELD_SOURCES - layout/xgc.cpp) -endif() - add_library(pcms_field ${PCMS_FIELD_SOURCES}) set_target_properties(pcms_field PROPERTIES OUTPUT_NAME pcmsfield EXPORT_NAME field) -target_sources(pcms_field PUBLIC - FILE_SET field - TYPE HEADERS - BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/.. - FILES ${PCMS_FIELD_HEADERS}) +# Only the public headers (include/pcms/...) are installed; the private +# headers next to the sources are private sources of the target. +set(PCMS_FIELD_HEADERS_PUBLIC ${PCMS_FIELD_HEADERS}) +list(FILTER PCMS_FIELD_HEADERS_PUBLIC INCLUDE REGEX "/include/pcms/") +set(PCMS_FIELD_HEADERS_PRIVATE ${PCMS_FIELD_HEADERS}) +list(FILTER PCMS_FIELD_HEADERS_PRIVATE EXCLUDE REGEX "/include/pcms/") +target_sources(pcms_field + PUBLIC FILE_SET field TYPE HEADERS BASE_DIRS ${PROJECT_SOURCE_DIR}/include/pcms + FILES ${PCMS_FIELD_HEADERS_PUBLIC} + PRIVATE ${PCMS_FIELD_HEADERS_PRIVATE}) add_library(pcms::field ALIAS pcms_field) target_compile_features(pcms_field PUBLIC cxx_std_20) @@ -125,13 +76,6 @@ if(PCMS_ENABLE_OMEGA_H) target_link_libraries(pcms_field PRIVATE Kokkos::kokkoskernels) endif() -if(PCMS_ENABLE_MFEM) - target_link_libraries(pcms_field PUBLIC mfem) -endif() - -if (PCMS_ENABLE_MESHFIELDS) - target_link_libraries(pcms_field PUBLIC meshfields::meshfields) -endif () target_include_directories(pcms_field INTERFACE $ @@ -150,4 +94,4 @@ install( install( EXPORT pcms_field-targets NAMESPACE pcms:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pcms) + DESTINATION ${PCMS_INSTALL_CMAKEDIR}) diff --git a/src/pcms/field/coordinate_map.cpp b/src/pcms/field/coordinate_map.cpp index 512b91ceb..977259ff4 100644 --- a/src/pcms/field/coordinate_map.cpp +++ b/src/pcms/field/coordinate_map.cpp @@ -1,8 +1,8 @@ #include "pcms/field/coordinate_map.hpp" -#include "pcms/field/coordinate_systems/cartesian.hpp" -#include "pcms/field/coordinate_systems/cylindrical.hpp" -#include "pcms/utility/assert.h" -#include "pcms/utility/profile.h" +#include "pcms/utility/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_systems/cylindrical.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/detail/profile.hpp" #include #include diff --git a/src/pcms/field/element_dispatch.h b/src/pcms/field/element_dispatch.hpp similarity index 83% rename from src/pcms/field/element_dispatch.h rename to src/pcms/field/element_dispatch.hpp index 67ac1fad7..0622c0a10 100644 --- a/src/pcms/field/element_dispatch.h +++ b/src/pcms/field/element_dispatch.hpp @@ -1,11 +1,11 @@ -#ifndef PCMS_FIELD_ELEMENT_DISPATCH_H -#define PCMS_FIELD_ELEMENT_DISPATCH_H +#ifndef PCMS_FIELD_ELEMENT_DISPATCH_HPP +#define PCMS_FIELD_ELEMENT_DISPATCH_HPP -#include "pcms/utility/assert.h" +#include "pcms/utility/assert.hpp" #include #include -namespace pcms::detail +namespace pcms::field::detail { // Runtime -> compile-time bridge for finite-element order. @@ -32,6 +32,6 @@ auto DispatchByOrder(int order, F&& f) } } -} // namespace pcms::detail +} // namespace pcms::field::detail -#endif // PCMS_FIELD_ELEMENT_DISPATCH_H +#endif // PCMS_FIELD_ELEMENT_DISPATCH_HPP diff --git a/src/pcms/field/evaluator/pcms_interpolator_aliases.hpp b/src/pcms/field/evaluator/interpolator_aliases.hpp similarity index 83% rename from src/pcms/field/evaluator/pcms_interpolator_aliases.hpp rename to src/pcms/field/evaluator/interpolator_aliases.hpp index 6450f44a5..c00ef3cb0 100644 --- a/src/pcms/field/evaluator/pcms_interpolator_aliases.hpp +++ b/src/pcms/field/evaluator/interpolator_aliases.hpp @@ -1,8 +1,8 @@ -#ifndef PCMS_FIELD_EVALUATOR_PCMS_INTERPOLATOR_ALIASES_HPP -#define PCMS_FIELD_EVALUATOR_PCMS_INTERPOLATOR_ALIASES_HPP +#ifndef PCMS_FIELD_EVALUATOR_INTERPOLATOR_ALIASES_HPP +#define PCMS_FIELD_EVALUATOR_INTERPOLATOR_ALIASES_HPP #include -#include "pcms/utility/arrays.h" +#include "pcms/utility/arrays.hpp" namespace pcms { @@ -42,4 +42,4 @@ using RealConstDefaultRank1View = Rank1View; } // namespace pcms -#endif // PCMS_FIELD_EVALUATOR_PCMS_INTERPOLATOR_ALIASES_HPP +#endif // PCMS_FIELD_EVALUATOR_INTERPOLATOR_ALIASES_HPP diff --git a/src/pcms/field/evaluator/pcms_interpolator_logger.hpp b/src/pcms/field/evaluator/interpolator_logger.hpp similarity index 93% rename from src/pcms/field/evaluator/pcms_interpolator_logger.hpp rename to src/pcms/field/evaluator/interpolator_logger.hpp index 9e12439c4..c8a96553e 100644 --- a/src/pcms/field/evaluator/pcms_interpolator_logger.hpp +++ b/src/pcms/field/evaluator/interpolator_logger.hpp @@ -1,10 +1,10 @@ -#ifndef PCMS_FIELD_EVALUATOR_PCMS_INTERPOLATOR_LOGGER_HPP -#define PCMS_FIELD_EVALUATOR_PCMS_INTERPOLATOR_LOGGER_HPP +#ifndef PCMS_FIELD_EVALUATOR_INTERPOLATOR_LOGGER_HPP +#define PCMS_FIELD_EVALUATOR_INTERPOLATOR_LOGGER_HPP -#include +#include #include -namespace pcms +namespace pcms::field { enum class LogLevel { @@ -132,5 +132,5 @@ class Logger } } }; -} // namespace pcms -#endif // PCMS_FIELD_EVALUATOR_PCMS_INTERPOLATOR_LOGGER_HPP +} // namespace pcms::field +#endif // PCMS_FIELD_EVALUATOR_INTERPOLATOR_LOGGER_HPP diff --git a/src/pcms/field/evaluator/pcms_interpolator_view_utils.hpp b/src/pcms/field/evaluator/interpolator_view_utils.hpp similarity index 96% rename from src/pcms/field/evaluator/pcms_interpolator_view_utils.hpp rename to src/pcms/field/evaluator/interpolator_view_utils.hpp index 8762e334a..15c597cde 100644 --- a/src/pcms/field/evaluator/pcms_interpolator_view_utils.hpp +++ b/src/pcms/field/evaluator/interpolator_view_utils.hpp @@ -1,13 +1,13 @@ -#ifndef PCMS_FIELD_EVALUATOR_PCMS_INTERPOLATOR_VIEW_UTILS_HPP -#define PCMS_FIELD_EVALUATOR_PCMS_INTERPOLATOR_VIEW_UTILS_HPP +#ifndef PCMS_FIELD_EVALUATOR_INTERPOLATOR_VIEW_UTILS_HPP +#define PCMS_FIELD_EVALUATOR_INTERPOLATOR_VIEW_UTILS_HPP -#include +#include #include #include #include #include -namespace pcms +namespace pcms::field { namespace detail { @@ -263,6 +263,6 @@ void scale_and_adjust(member_type team, ScratchVecView& diagonal_entries, } } // namespace detail -} // namespace pcms +} // namespace pcms::field -#endif // PCMS_FIELD_EVALUATOR_PCMS_INTERPOLATOR_VIEW_UTILS_HPP +#endif // PCMS_FIELD_EVALUATOR_INTERPOLATOR_VIEW_UTILS_HPP diff --git a/src/pcms/field/evaluator/mls_interpolation.cpp b/src/pcms/field/evaluator/mls_interpolation.cpp index 47fbd97ac..0badfbd01 100644 --- a/src/pcms/field/evaluator/mls_interpolation.cpp +++ b/src/pcms/field/evaluator/mls_interpolation.cpp @@ -3,7 +3,7 @@ #include #include -namespace pcms +namespace pcms::field { // 'a' is a shape parameter @@ -167,9 +167,10 @@ struct RBF_CUBIC Omega_h::Write mls_interpolation( const Omega_h::Reals source_values, const Omega_h::Reals source_coordinates, - const Omega_h::Reals target_coordinates, const SupportResults& support, - const Omega_h::LO& dim, const Omega_h::LO& degree, RadialBasisFunction bf, - double lambda, double tol, double decay_factor) + const Omega_h::Reals target_coordinates, + const pcms::localization::SupportResults& support, const Omega_h::LO& dim, + const Omega_h::LO& degree, RadialBasisFunction bf, double lambda, double tol, + double decay_factor) { const auto nvertices_target = target_coordinates.size() / dim; Omega_h::Write interpolated_values( @@ -259,9 +260,9 @@ int calculate_basis_vector_size(const IntHostMatView& array) return sum; } -int calculate_scratch_shared_size(const SupportResults& support, - const int nvertices_target, int basis_size, - int dim) +int calculate_scratch_shared_size( + const pcms::localization::SupportResults& support, const int nvertices_target, + int basis_size, int dim) { IntDeviceVecView shmem_each_team("stores the size required for each team", nvertices_target); @@ -305,4 +306,4 @@ int calculate_scratch_shared_size(const SupportResults& support, } } // namespace detail -} // namespace pcms +} // namespace pcms::field diff --git a/src/pcms/field/evaluator/mls_interpolation.hpp b/src/pcms/field/evaluator/mls_interpolation.hpp index fe32eae0a..b28d32317 100644 --- a/src/pcms/field/evaluator/mls_interpolation.hpp +++ b/src/pcms/field/evaluator/mls_interpolation.hpp @@ -2,86 +2,11 @@ #define PCMS_FIELD_EVALUATOR_MLS_INTERPOLATION_HPP #include +#include "pcms/localization/mls_options.hpp" +#include "pcms/localization/support_results.hpp" -namespace pcms +namespace pcms::field { -// Forward declaration — full definition is in pcms/localization/adj_search.hpp -struct SupportResults; - -/** - * @brief Enumeration of supported radial basis functions (RBFs) for MLS - * interpolation. - * - * Specifies the kernel type used for computing weights in Moving Least Squares - * (MLS) interpolation. Each RBF defines a different spatial weighting behavior, - * influencing locality, smoothness, and conditioning of the interpolant. - * - * ### Values: - * - * - **RBF_GAUSSIAN (0)** - * \f$ \phi(r) = \exp\left(-\left(\frac{a r}{r_c}\right)^2\right) \f$ - * Infinitely smooth and compactly supported. - * `a` is the shape (decay) parameter — smaller values give wider influence. - * Good for smooth interpolants; may cause ill-conditioning for large `a`. - * - * - **RBF_C4 (1)** - * Compactly supported, \f$ C^4\f$-continuous polynomial kernel. - * Does not require a shape parameter. - * Efficient, stable, and good for local approximations. - * - * - **RBF_CONST (2)** - * Uniform weights within support: - * \f$ \phi(r) = 1 \text{ for } r < r_c \f$, otherwise 0. - * Equivalent to averaging. - * - * - **NO_OP (3)** - * Disables internal RBF weighting logic. - * Always returns \f$ \phi = 1 \f$ regardless of distance. - * Useful for methods like SPR patching - * - * - **RBF_MULTIQUADRIC (4)** - * \f$ \phi(r) = \sqrt{1 + \left(\frac{a r}{r_c}\right)^2} \f$ - * Smooth and locally supported. - * `a` controls the width; higher values increase conditioning issues. - * - * - **RBF_INVMULTIQUADRIC (5)** - * \f$ \phi(r) = \frac{1}{\sqrt{1 + \left(\frac{a r}{r_c}\right)^2}} \f$ - * Compactly supported and generally more stable than MQ. - * `a` adjusts the decay; larger `a` leads to faster fall-off. - * - * - **RBF_THINPLATESPLINE (6)** - * \f$ \phi(r) = \left(\frac{a r}{r_c}\right)^2 \log\left(\frac{a - * r}{r_c}\right) \f$ Classic 2D surface fitting kernel. No explicit shape - * parameter is required, but `a` can scale smoothness. - * - * - **RBF_CUBIC (7)** - * \f$ \phi(r) = \left(\frac{a r}{r_c}\right)^3 \f$ - * Smooth with compact support. - * Simple and effective for local interpolation. - * - * --- - * - * @note - * - The shape parameter `a` (also called decay or spread factor) is required - * for Gaussian, MQ, IMQ, ThinPlateSpline, and Cubic kernels. - * - All kernels are compactly supported within the cutoff radius \f$ r_c \f$. - * - A good starting value for `a` is 3–5. Avoid `a = 0` (leads to constant - * behavior). - * - In cases of ill-conditioning, use regularization (`lambda > 0`). - * - * @see mls_interpolation() - */ -enum class RadialBasisFunction -{ - RBF_GAUSSIAN = 0, - RBF_C4, - RBF_CONST, - NO_OP, - RBF_MULTIQUADRIC, - RBF_INVMULTIQUADRIC, - RBF_THINPLATESPLINE, - RBF_CUBIC -}; /** * @brief Performs Moving Least Squares (MLS) interpolation at target points. @@ -133,9 +58,10 @@ enum class RadialBasisFunction */ Omega_h::Write mls_interpolation( const Omega_h::Reals source_values, const Omega_h::Reals source_coordinates, - const Omega_h::Reals target_coordinates, const SupportResults& support, - const Omega_h::LO& dim, const Omega_h::LO& degree, RadialBasisFunction bf, - double lambda = 0, double tol = 1e-6, double decay_factor = 5.0); + const Omega_h::Reals target_coordinates, + const pcms::localization::SupportResults& support, const Omega_h::LO& dim, + const Omega_h::LO& degree, RadialBasisFunction bf, double lambda = 0, + double tol = 1e-6, double decay_factor = 5.0); -} // namespace pcms +} // namespace pcms::field #endif // PCMS_FIELD_EVALUATOR_MLS_INTERPOLATION_HPP diff --git a/src/pcms/field/evaluator/mls_interpolation_impl.hpp b/src/pcms/field/evaluator/mls_interpolation_impl.hpp index edc8f3bee..e3a3a9e23 100644 --- a/src/pcms/field/evaluator/mls_interpolation_impl.hpp +++ b/src/pcms/field/evaluator/mls_interpolation_impl.hpp @@ -13,12 +13,12 @@ #include #include #include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include @@ -53,7 +53,7 @@ static constexpr int MAX_DIM = 6; * 3 | 1 | 3 | */ -namespace pcms +namespace pcms::field { namespace detail @@ -93,8 +93,9 @@ int calculate_basis_vector_size(const IntHostMatView& array); * * @return The scratch size */ -int calculate_scratch_shared_size(const SupportResults& support, - const int ntargets, int basis_size, int dim); +int calculate_scratch_shared_size( + const pcms::localization::SupportResults& support, const int ntargets, + int basis_size, int dim); /** * * @brief Performs minmax normalization @@ -399,10 +400,10 @@ template void mls_interpolation(RealConstDefaultRank1View source_values, RealConstDefaultRank1View source_coordinates, RealConstDefaultRank1View target_coordinates, - const SupportResults& support, const Omega_h::LO& dim, - const Omega_h::LO& degree, Func rbf_func, - RealDefaultRank1View approx_target_values, double lambda, - double tol) + const pcms::localization::SupportResults& support, + const Omega_h::LO& dim, const Omega_h::LO& degree, + Func rbf_func, RealDefaultRank1View approx_target_values, + double lambda, double tol) { PCMS_FUNCTION_TIMER; static_assert(std::is_invocable_r_v, @@ -609,9 +610,9 @@ void mls_interpolation(RealConstDefaultRank1View source_values, template Omega_h::Write mls_interpolation( const Omega_h::Reals source_values, const Omega_h::Reals source_coordinates, - const Omega_h::Reals target_coordinates, const SupportResults& support, - const Omega_h::LO& dim, const Omega_h::LO& degree, Func rbf_func, - double lambda, double tol) + const Omega_h::Reals target_coordinates, + const pcms::localization::SupportResults& support, const Omega_h::LO& dim, + const Omega_h::LO& degree, Func rbf_func, double lambda, double tol) { const auto ntargets = target_coordinates.size() / dim; @@ -637,6 +638,6 @@ Omega_h::Write mls_interpolation( } } // namespace detail -} // namespace pcms +} // namespace pcms::field #endif // PCMS_FIELD_EVALUATOR_MLS_INTERPOLATION_IMPL_HPP diff --git a/src/pcms/field/evaluator/mls_options.h b/src/pcms/field/evaluator/mls_options.h deleted file mode 100644 index b0db52f0a..000000000 --- a/src/pcms/field/evaluator/mls_options.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef PCMS_FIELD_EVALUATOR_MLS_OPTIONS_H -#define PCMS_FIELD_EVALUATOR_MLS_OPTIONS_H - -#include "pcms/field/evaluator/mls_interpolation.hpp" - -namespace pcms -{ - -/// Configuration for Moving Least Squares evaluation. -/// Passed to PolynomialReconstructionFunctionSpace::Create and -/// PointCloudEvaluatorFactory. -struct MLSOptions -{ - double radius = 0.5; - unsigned min_req_supports = 10; - unsigned degree = 3; - bool adapt_radius = true; - double lambda = 0.0; - double tol = 1e-6; - double decay_factor = 5.0; - RadialBasisFunction basis = RadialBasisFunction::RBF_GAUSSIAN; -}; - -} // namespace pcms - -#endif // PCMS_FIELD_EVALUATOR_MLS_OPTIONS_H diff --git a/src/pcms/field/field_evaluator_factory.h b/src/pcms/field/field_evaluator_factory.hpp similarity index 85% rename from src/pcms/field/field_evaluator_factory.h rename to src/pcms/field/field_evaluator_factory.hpp index e1c066c08..614580bd0 100644 --- a/src/pcms/field/field_evaluator_factory.h +++ b/src/pcms/field/field_evaluator_factory.hpp @@ -1,17 +1,17 @@ -#ifndef PCMS_FIELD_EVALUATOR_FACTORY_H -#define PCMS_FIELD_EVALUATOR_FACTORY_H +#ifndef PCMS_FIELD_FIELD_EVALUATOR_FACTORY_HPP +#define PCMS_FIELD_FIELD_EVALUATOR_FACTORY_HPP -#include "field_layout.h" -#include "pcms/field/coordinate_view.hpp" -#include "evaluation_request.h" -#include "out_of_bounds_policy.h" -#include "point_evaluator.h" -#include "pcms/utility/arrays.h" -#include "pcms/utility/memory_spaces.h" -#include "pcms/discretization/discretization.h" +#include "pcms/field/field_layout.hpp" +#include "pcms/utility/coordinate_view.hpp" +#include "pcms/field/evaluation_request.hpp" +#include "pcms/field/out_of_bounds_policy.hpp" +#include "pcms/field/point_evaluator.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/memory_spaces.hpp" +#include "pcms/discretization/discretization.hpp" #include -namespace pcms +namespace pcms::field { // FieldEvaluatorFactory owns backend-specific knowledge needed to evaluate a @@ -84,6 +84,6 @@ class FieldEvaluatorFactory virtual ~FieldEvaluatorFactory() noexcept = default; }; -} // namespace pcms +} // namespace pcms::field -#endif // PCMS_FIELD_EVALUATOR_FACTORY_H +#endif // PCMS_FIELD_FIELD_EVALUATOR_FACTORY_HPP diff --git a/src/pcms/field/field_layout.cpp b/src/pcms/field/field_layout.cpp index 6e785f9ec..fe6de88d9 100644 --- a/src/pcms/field/field_layout.cpp +++ b/src/pcms/field/field_layout.cpp @@ -1,6 +1,6 @@ -#include "pcms/field/field_layout.h" +#include "pcms/field/field_layout.hpp" #include "pcms/field/gid_permutation.hpp" -#include "pcms/utility/assert.h" +#include "pcms/utility/assert.hpp" namespace pcms { @@ -8,7 +8,7 @@ namespace pcms void FieldLayout::BuildGlobalToLocalPermutation() { const auto permutation = - BuildSortedGidPermutation(GetGidsHost(), GetEntOffsets()); + pcms::field::BuildSortedGidPermutation(GetGidsHost(), GetEntOffsets()); global_to_local_host_ = Kokkos::View( "global_to_local_host", permutation.size()); for (size_t i = 0; i < permutation.size(); ++i) diff --git a/src/pcms/field/function_space/lagrange.cpp b/src/pcms/field/function_space/lagrange.cpp index faeba79ef..52ebfb72f 100644 --- a/src/pcms/field/function_space/lagrange.cpp +++ b/src/pcms/field/function_space/lagrange.cpp @@ -1,22 +1,22 @@ -#include "pcms/field/function_space/lagrange.h" -#include "pcms/configuration.h" -#include "pcms/utility/assert.h" -#include "pcms/utility/common.h" +#include "pcms/field/function_space/lagrange.hpp" +#include "pcms/configuration.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/detail/common.hpp" #ifdef PCMS_ENABLE_MESHFIELDS -#include "pcms/field/layout/mesh_fields.h" -#include "pcms/field/evaluator/mesh_fields.h" -#include "pcms/field/data/mesh_fields.h" +#include "pcms/backends/omega_h_meshfields/layout.hpp" +#include "pcms/backends/omega_h_meshfields/evaluator.hpp" +#include "pcms/backends/omega_h_meshfields/field_data.hpp" #endif -#include "pcms/field/layout/omega_h_lagrange.h" -#include "pcms/field/evaluator/omega_h_lagrange.h" -#include "pcms/field/layout/uniform_grid.h" -#include "pcms/field/evaluator/uniform_grid.h" -#include "pcms/field/data/simple.h" -#include "pcms/utility/uniform_grid.h" +#include "pcms/backends/omega_h/lagrange_layout.hpp" +#include "pcms/backends/omega_h/lagrange_evaluator.hpp" +#include "pcms/backends/uniform_grid/layout.hpp" +#include "pcms/backends/uniform_grid/evaluator.hpp" +#include "pcms/field/simple_field_data.hpp" +#include "pcms/utility/uniform_grid.hpp" #include -namespace pcms +namespace pcms::field { namespace @@ -27,8 +27,12 @@ void ValidateLagrangeWrappedFieldData(const FieldLayout& layout, const FieldData& data) { #ifdef PCMS_ENABLE_MESHFIELDS - if (dynamic_cast(&layout) != nullptr) { - if (dynamic_cast*>(&data) == nullptr) { + if (dynamic_cast< + const pcms::backend::omega_h_meshfields::MeshFieldsAdapterLayout*>( + &layout) != nullptr) { + if (dynamic_cast< + const pcms::backend::omega_h_meshfields::MeshFieldsFieldData*>( + &data) == nullptr) { throw pcms_error( "LagrangeFunctionSpace::CreateField: MeshFields layout requires " "MeshFieldsFieldData"); @@ -44,7 +48,7 @@ void ValidateLagrangeWrappedFieldData(const FieldLayout& layout, } if (data.GetDOFAccess()->GetOwnedValues().size() != - detail::ExpectedFlatFieldDataSize(layout)) { + pcms::detail::ExpectedFlatFieldDataSize(layout)) { throw pcms_error( "LagrangeFunctionSpace::CreateField: field data size does not match " "layout"); @@ -81,19 +85,22 @@ std::shared_ptr LagrangeFunctionSpace::FromMesh( case 2: nodes_per_dim = {1, 1, 0, 0}; break; default: throw pcms_error("Unimplemented Lagrange order"); } - auto mesh_layout = std::make_shared( + auto mesh_layout = std::make_shared< + pcms::backend::omega_h_meshfields::MeshFieldsAdapterLayout>( mesh, nodes_per_dim, num_components, coordinate_system, std::move(global_id_name)); mesh_layout->SetName(layout_name); - auto eval_factory = - std::make_shared>(mesh_layout); + auto eval_factory = std::make_shared< + pcms::backend::omega_h_meshfields::MeshFieldsEvaluatorFactory>( + mesh_layout); return std::make_shared( Key{}, mesh_layout, [mesh_layout](Type t, ValueBasis basis) -> FieldDataVariant { if (t == Type::Float) { if constexpr (std::is_same_v || std::is_same_v) { - return std::make_unique>( + return std::make_unique< + pcms::backend::omega_h_meshfields::MeshFieldsFieldData>( mesh_layout, std::move(basis)); } throw pcms_error( @@ -101,7 +108,8 @@ std::shared_ptr LagrangeFunctionSpace::FromMesh( "float in this build"); } if (t == Type::Real) { - return std::make_unique>( + return std::make_unique< + pcms::backend::omega_h_meshfields::MeshFieldsFieldData>( mesh_layout, std::move(basis)); } throw pcms_error( @@ -120,11 +128,11 @@ std::shared_ptr LagrangeFunctionSpace::FromMesh( "LagrangeFunctionSpace::FromMesh: OmegaH backend only supports " "Lagrange orders 0 and 1"); } - auto layout = std::make_shared( + auto layout = std::make_shared( mesh, order, num_components, coordinate_system, std::move(global_id_name)); layout->SetName(std::move(layout_name)); - auto eval_factory = - std::make_shared>(layout); + auto eval_factory = std::make_shared< + pcms::backend::omega_h::OmegaHLagrangeEvaluatorFactory>(layout); return std::make_shared( Key{}, layout, [layout](Type t, ValueBasis basis) -> FieldDataVariant { @@ -156,12 +164,12 @@ std::shared_ptr LagrangeFunctionSpace::FromMesh( "LagrangeFunctionSpace::FromMesh: OmegaH backend only supports " "Lagrange orders 0 and 1"); } - auto layout = std::make_shared( + auto layout = std::make_shared( mesh, order, num_components, coordinate_system, std::move(owned_mask), std::move(global_id_name)); layout->SetName(std::move(layout_name)); - auto eval_factory = - std::make_shared>(layout); + auto eval_factory = std::make_shared< + pcms::backend::omega_h::OmegaHLagrangeEvaluatorFactory>(layout); return std::make_shared( Key{}, layout, [layout](Type t, ValueBasis basis) -> FieldDataVariant { @@ -186,11 +194,12 @@ std::shared_ptr LagrangeFunctionSpace::FromUniformGrid( throw std::invalid_argument("LagrangeFunctionSpace::FromUniformGrid: only " "orders 0 and 1 are supported"); } - auto ug_layout = std::make_shared>( - grid, num_components, coordinate_system, order); + auto ug_layout = + std::make_shared>( + grid, num_components, coordinate_system, order); ug_layout->SetName(std::move(layout_name)); - auto eval_factory = - std::make_shared>(ug_layout); + auto eval_factory = std::make_shared< + pcms::backend::uniform_grid::UniformGridEvaluatorFactory<2>>(ug_layout); return std::make_shared( Key{}, ug_layout, [ug_layout](Type t, ValueBasis basis) -> FieldDataVariant { @@ -215,11 +224,12 @@ std::shared_ptr LagrangeFunctionSpace::FromUniformGrid( throw std::invalid_argument("LagrangeFunctionSpace::FromUniformGrid: only " "orders 0 and 1 are supported"); } - auto ug_layout = std::make_shared>( - grid, num_components, coordinate_system, order); + auto ug_layout = + std::make_shared>( + grid, num_components, coordinate_system, order); ug_layout->SetName(std::move(layout_name)); - auto eval_factory = - std::make_shared>(ug_layout); + auto eval_factory = std::make_shared< + pcms::backend::uniform_grid::UniformGridEvaluatorFactory<3>>(ug_layout); return std::make_shared( Key{}, ug_layout, [ug_layout](Type t, ValueBasis basis) -> FieldDataVariant { @@ -293,4 +303,4 @@ PointEvaluatorVariant LagrangeFunctionSpace::CreatePointEvaluatorImpl( return evaluator_factory_->CreatePointEvaluator(request); } -} // namespace pcms +} // namespace pcms::field diff --git a/src/pcms/field/function_space/lagrange.h b/src/pcms/field/function_space/lagrange.hpp similarity index 81% rename from src/pcms/field/function_space/lagrange.h rename to src/pcms/field/function_space/lagrange.hpp index ff2078917..41d8ccedd 100644 --- a/src/pcms/field/function_space/lagrange.h +++ b/src/pcms/field/function_space/lagrange.hpp @@ -1,28 +1,28 @@ -#ifndef PCMS_LAGRANGE_FIELD_FACTORY_H -#define PCMS_LAGRANGE_FIELD_FACTORY_H +#ifndef PCMS_FIELD_FUNCTION_SPACE_LAGRANGE_HPP +#define PCMS_FIELD_FUNCTION_SPACE_LAGRANGE_HPP #include -#include "pcms/configuration.h" -#include "pcms/field/field.h" -#include "pcms/field/field_layout.h" -#include "pcms/field/function_space.h" -#include "pcms/field/field_data.h" +#include "pcms/configuration.hpp" +#include "pcms/field/field.hpp" +#include "pcms/field/field_layout.hpp" +#include "pcms/field/function_space.hpp" +#include "pcms/field/field_data.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/field/point_evaluator.h" -#include "pcms/field/out_of_bounds_policy.h" -#include "pcms/field/field_evaluator_factory.h" -#include "pcms/field/coordinate_system.hpp" -#include "pcms/utility/arrays.h" -#include "pcms/utility/types.h" -#include "pcms/utility/memory_spaces.h" -#include "pcms/utility/uniform_grid.h" +#include "pcms/field/point_evaluator.hpp" +#include "pcms/field/out_of_bounds_policy.hpp" +#include "pcms/field/field_evaluator_factory.hpp" +#include "pcms/utility/coordinate_system.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/types.hpp" +#include "pcms/utility/memory_spaces.hpp" +#include "pcms/utility/uniform_grid.hpp" #include #include #include #include -namespace pcms +namespace pcms::field { class LagrangeFunctionSpace : public FunctionSpace @@ -103,6 +103,6 @@ class LagrangeFunctionSpace : public FunctionSpace std::shared_ptr> evaluator_factory_; }; -} // namespace pcms +} // namespace pcms::field -#endif // PCMS_LAGRANGE_FIELD_FACTORY_H +#endif // PCMS_FIELD_FUNCTION_SPACE_LAGRANGE_HPP diff --git a/src/pcms/field/function_space/polynomial_reconstruction.cpp b/src/pcms/field/function_space/polynomial_reconstruction.cpp index 2097ead77..8eb729b30 100644 --- a/src/pcms/field/function_space/polynomial_reconstruction.cpp +++ b/src/pcms/field/function_space/polynomial_reconstruction.cpp @@ -1,20 +1,20 @@ #include "pcms/field/function_space/polynomial_reconstruction.hpp" -#include "pcms/field/layout/omega_h_entity.h" -#include "pcms/field/layout/point_cloud.h" -#include "pcms/field/evaluator/point_cloud.h" -#include "pcms/field/data/simple.h" -#include "pcms/discretization/discretization/omega_h.hpp" -#include "pcms/utility/assert.h" -#include "pcms/utility/common.h" -#include "pcms/utility/mesh_geometry.h" -#include "pcms/localization/point_cloud_localization.h" -#include "pcms/localization/mesh_localization.h" +#include "pcms/backends/omega_h/entity_layout.hpp" +#include "pcms/backends/point_cloud/layout.hpp" +#include "pcms/backends/point_cloud/evaluator.hpp" +#include "pcms/field/simple_field_data.hpp" +#include "pcms/backends/omega_h/discretization.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/detail/common.hpp" +#include "pcms/utility/mesh_geometry.hpp" +#include "pcms/backends/point_cloud/localization.hpp" +#include "pcms/localization/mesh_localization.hpp" #include #include #include -namespace pcms +namespace pcms::field { PolynomialReconstructionFunctionSpace::PolynomialReconstructionFunctionSpace( @@ -35,12 +35,15 @@ PolynomialReconstructionFunctionSpace::Create( auto device_view = Kokkos::View("device_view", host_view.extent(0), host_view.extent(1)); DeepCopyMismatchLayouts(device_view, host_view); - auto pc_layout = std::make_shared( - dim, device_view, coords.GetCoordinateSystem()); + auto pc_layout = + std::make_shared( + dim, device_view, coords.GetCoordinateSystem()); auto localization = - std::make_shared(pc_layout, options); - auto eval_factory = std::make_shared( - pc_layout, localization, options); + std::make_shared( + pc_layout, options); + auto eval_factory = + std::make_shared( + pc_layout, localization, options); return std::make_shared( Key{}, pc_layout, std::move(eval_factory)); } @@ -56,8 +59,9 @@ PolynomialReconstructionFunctionSpace::FromMesh( "out of range"); } - auto mesh_layout = std::make_shared( - mesh, source_entity_dim, 1, std::move(coordinate_system)); + auto mesh_layout = + std::make_shared( + mesh, source_entity_dim, 1, std::move(coordinate_system)); // MLS assumes unweighted Euclidean in distance calculation if (!HasIdentityMetric(*mesh_layout->GetCoordinateSystem())) { throw pcms_error( @@ -65,10 +69,12 @@ PolynomialReconstructionFunctionSpace::FromMesh( "coordinate system whose metric is the identity; got '" + std::string(mesh_layout->GetCoordinateSystem()->Kind()) + "'"); } - auto localization = std::make_shared( - mesh, source_entity_dim, options); - auto eval_factory = std::make_shared( - mesh_layout, localization, options); + auto localization = + std::make_shared( + mesh, source_entity_dim, options); + auto eval_factory = + std::make_shared( + mesh_layout, localization, options); return std::make_shared( Key{}, mesh_layout, std::move(eval_factory)); } @@ -112,7 +118,7 @@ FieldVariant PolynomialReconstructionFunctionSpace::CreateFieldImpl( "SimpleFieldData"); } if (fd->GetDOFAccess()->GetOwnedValues().size() != - detail::ExpectedFlatFieldDataSize(*layout_)) { + pcms::detail::ExpectedFlatFieldDataSize(*layout_)) { throw pcms_error( "PolynomialReconstructionFunctionSpace::CreateField: field data size " "does not match layout"); @@ -133,4 +139,4 @@ PolynomialReconstructionFunctionSpace::CreatePointEvaluatorImpl( return evaluator_factory_->CreatePointEvaluator(request); } -} // namespace pcms +} // namespace pcms::field diff --git a/src/pcms/field/function_space/polynomial_reconstruction.hpp b/src/pcms/field/function_space/polynomial_reconstruction.hpp index 71e6646fc..056b90daa 100644 --- a/src/pcms/field/function_space/polynomial_reconstruction.hpp +++ b/src/pcms/field/function_space/polynomial_reconstruction.hpp @@ -1,21 +1,21 @@ -#ifndef PCMS_POLYNOMIAL_RECONSTRUCTION_FUNCTION_SPACE_H -#define PCMS_POLYNOMIAL_RECONSTRUCTION_FUNCTION_SPACE_H +#ifndef PCMS_FIELD_FUNCTION_SPACE_POLYNOMIAL_RECONSTRUCTION_HPP +#define PCMS_FIELD_FUNCTION_SPACE_POLYNOMIAL_RECONSTRUCTION_HPP -#include "pcms/field/field.h" -#include "pcms/field/field_layout.h" -#include "pcms/field/field_data.h" +#include "pcms/field/field.hpp" +#include "pcms/field/field_layout.hpp" +#include "pcms/field/field_data.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/field/function_space.h" -#include "pcms/field/out_of_bounds_policy.h" -#include "pcms/field/coordinate_view.hpp" -#include "pcms/field/evaluator/mls_options.h" -#include "pcms/utility/arrays.h" -#include "pcms/utility/memory_spaces.h" +#include "pcms/field/function_space.hpp" +#include "pcms/field/out_of_bounds_policy.hpp" +#include "pcms/utility/coordinate_view.hpp" +#include "pcms/localization/mls_options.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/memory_spaces.hpp" #include #include -namespace pcms +namespace pcms::field { template @@ -61,6 +61,6 @@ class PolynomialReconstructionFunctionSpace : public FunctionSpace std::shared_ptr> evaluator_factory_; }; -} // namespace pcms +} // namespace pcms::field -#endif // PCMS_POLYNOMIAL_RECONSTRUCTION_FUNCTION_SPACE_H +#endif // PCMS_FIELD_FUNCTION_SPACE_POLYNOMIAL_RECONSTRUCTION_HPP diff --git a/src/pcms/field/function_space/spline.cpp b/src/pcms/field/function_space/spline.cpp index f169a9f40..d82b9904b 100644 --- a/src/pcms/field/function_space/spline.cpp +++ b/src/pcms/field/function_space/spline.cpp @@ -1,13 +1,13 @@ -#include "pcms/field/function_space/spline.h" +#include "pcms/field/function_space/spline.hpp" -#include "pcms/field/data/simple.h" -#include "pcms/field/evaluator/uniform_grid_spline.h" -#include "pcms/field/layout/uniform_grid.h" -#include "pcms/utility/common.h" +#include "pcms/field/simple_field_data.hpp" +#include "pcms/backends/uniform_grid/spline_evaluator.hpp" +#include "pcms/backends/uniform_grid/layout.hpp" +#include "pcms/utility/detail/common.hpp" #include -namespace pcms +namespace pcms::field { SplineFunctionSpace::SplineFunctionSpace( @@ -21,10 +21,11 @@ std::shared_ptr SplineFunctionSpace::FromUniformGrid( const UniformGrid<2>& grid, std::shared_ptr mesh_coordinate_system) { - auto layout = std::make_shared>( - grid, 1, std::move(mesh_coordinate_system), 1); - auto evaluator_factory = - std::make_shared(layout); + auto layout = + std::make_shared>( + grid, 1, std::move(mesh_coordinate_system), 1); + auto evaluator_factory = std::make_shared< + pcms::backend::uniform_grid::UniformGridSplineEvaluatorFactory2D>(layout); return std::make_shared(Key{}, layout, std::move(evaluator_factory)); } @@ -62,7 +63,7 @@ FieldVariant SplineFunctionSpace::CreateFieldImpl(FieldDataVariant data) const "SplineFunctionSpace::CreateField: requires SimpleFieldData"); } if (fd->GetDOFAccess()->GetOwnedValues().size() != - detail::ExpectedFlatFieldDataSize(*layout_)) { + pcms::detail::ExpectedFlatFieldDataSize(*layout_)) { throw pcms_error( "SplineFunctionSpace::CreateField: field data size does not match " "layout"); @@ -85,4 +86,4 @@ PointEvaluatorVariant SplineFunctionSpace::CreatePointEvaluatorImpl( return evaluator_factory_->CreatePointEvaluator(request); } -} // namespace pcms +} // namespace pcms::field diff --git a/src/pcms/field/function_space/spline.h b/src/pcms/field/function_space/spline.hpp similarity index 66% rename from src/pcms/field/function_space/spline.h rename to src/pcms/field/function_space/spline.hpp index 531505e8a..1a0e0af14 100644 --- a/src/pcms/field/function_space/spline.h +++ b/src/pcms/field/function_space/spline.hpp @@ -1,22 +1,22 @@ -#ifndef PCMS_SPLINE_FUNCTION_SPACE_H -#define PCMS_SPLINE_FUNCTION_SPACE_H +#ifndef PCMS_FIELD_FUNCTION_SPACE_SPLINE_HPP +#define PCMS_FIELD_FUNCTION_SPACE_SPLINE_HPP -#include "pcms/field/field.h" -#include "pcms/field/field_data.h" -#include "pcms/field/field_evaluator_factory.h" -#include "pcms/field/field_layout.h" +#include "pcms/field/field.hpp" +#include "pcms/field/field_data.hpp" +#include "pcms/field/field_evaluator_factory.hpp" +#include "pcms/field/field_layout.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/field/function_space.h" -#include "pcms/field/out_of_bounds_policy.h" -#include "pcms/field/point_evaluator.h" -#include "pcms/utility/arrays.h" -#include "pcms/utility/eqdsk.h" -#include "pcms/utility/memory_spaces.h" -#include "pcms/utility/uniform_grid.h" +#include "pcms/field/function_space.hpp" +#include "pcms/field/out_of_bounds_policy.hpp" +#include "pcms/field/point_evaluator.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/eqdsk.hpp" +#include "pcms/utility/memory_spaces.hpp" +#include "pcms/utility/uniform_grid.hpp" #include -namespace pcms +namespace pcms::field { class SplineFunctionSpace : public FunctionSpace @@ -55,6 +55,6 @@ class SplineFunctionSpace : public FunctionSpace std::shared_ptr> evaluator_factory_; }; -} // namespace pcms +} // namespace pcms::field -#endif // PCMS_SPLINE_FUNCTION_SPACE_H +#endif // PCMS_FIELD_FUNCTION_SPACE_SPLINE_HPP diff --git a/src/pcms/field/function_spaces.cpp b/src/pcms/field/function_spaces.cpp new file mode 100644 index 000000000..37a9201ee --- /dev/null +++ b/src/pcms/field/function_spaces.cpp @@ -0,0 +1,139 @@ +#include "pcms/field/function_spaces.hpp" +#include "pcms/configuration.hpp" +#include "pcms/field/function_space/polynomial_reconstruction.hpp" +#include "pcms/field/layout/empty.hpp" +#include "pcms/utility/assert.hpp" +#ifdef PCMS_ENABLE_OMEGA_H +#include "pcms/backends/omega_h/discretization.hpp" +#include "pcms/backends/uniform_grid/discretization.hpp" +#include "pcms/field/function_space/lagrange.hpp" +#include "pcms/field/function_space/spline.hpp" +#endif + +#include +#include + +namespace pcms +{ +namespace +{ +[[noreturn]] void Unsupported(const char* factory, const Discretization& d) +{ + throw pcms_error(std::string(factory) + ": unsupported discretization type " + + typeid(d).name()); +} + +void RequireDiscretization(const char* factory, + const std::shared_ptr& d) +{ + if (d == nullptr) { + throw pcms_error(std::string(factory) + ": discretization is null"); + } +} +} // namespace + +std::shared_ptr CreateLagrangeSpace( + std::shared_ptr discretization, int order, + int num_components, std::shared_ptr coordinate_system, + LagrangeOptions options) +{ + RequireDiscretization("CreateLagrangeSpace", discretization); +#ifdef PCMS_ENABLE_OMEGA_H + using backend::omega_h::OmegaHDiscretization; + using backend::uniform_grid::UniformGridDiscretization; + if (const auto* oh = + dynamic_cast(discretization.get())) { + auto impl = pcms::field::LagrangeFunctionSpace::DefaultBackend; + if (options.implementation == LagrangeImplementation::MeshFields) { + impl = pcms::field::LagrangeFunctionSpace::Backend::MeshFields; + } else if (options.implementation == LagrangeImplementation::OmegaH) { + impl = pcms::field::LagrangeFunctionSpace::Backend::OmegaH; + } + if (oh->GetOwnedMask().has_value()) { + return pcms::field::LagrangeFunctionSpace::FromMesh( + oh->GetMesh(), order, num_components, std::move(coordinate_system), + *oh->GetOwnedMask(), oh->GetGlobalIdName(), impl, + std::move(options.layout_name)); + } + return pcms::field::LagrangeFunctionSpace::FromMesh( + oh->GetMesh(), order, num_components, std::move(coordinate_system), + oh->GetGlobalIdName(), impl, std::move(options.layout_name)); + } + if (options.implementation != LagrangeImplementation::Default) { + throw pcms_error("CreateLagrangeSpace: LagrangeOptions::implementation " + "only applies to Omega_h discretizations"); + } + if (const auto* ug = dynamic_cast*>( + discretization.get())) { + return pcms::field::LagrangeFunctionSpace::FromUniformGrid( + ug->GetGrid(), num_components, std::move(coordinate_system), order, + std::move(options.layout_name)); + } + if (const auto* ug = dynamic_cast*>( + discretization.get())) { + return pcms::field::LagrangeFunctionSpace::FromUniformGrid( + ug->GetGrid(), num_components, std::move(coordinate_system), order, + std::move(options.layout_name)); + } +#else + (void)order; + (void)num_components; + (void)coordinate_system; + (void)options; +#endif + Unsupported("CreateLagrangeSpace", *discretization); +} + +std::shared_ptr CreateSplineSpace( + std::shared_ptr discretization, + std::shared_ptr coordinate_system) +{ + RequireDiscretization("CreateSplineSpace", discretization); +#ifdef PCMS_ENABLE_OMEGA_H + if (const auto* ug = dynamic_cast< + const backend::uniform_grid::UniformGridDiscretization<2>*>( + discretization.get())) { + return pcms::field::SplineFunctionSpace::FromUniformGrid( + ug->GetGrid(), std::move(coordinate_system)); + } +#else + (void)coordinate_system; +#endif + Unsupported("CreateSplineSpace", *discretization); +} + +std::shared_ptr CreatePolynomialReconstructionSpace( + CoordinateView points, MLSOptions options) +{ + return pcms::field::PolynomialReconstructionFunctionSpace::Create( + std::move(points), options); +} + +std::shared_ptr CreatePolynomialReconstructionSpace( + std::shared_ptr discretization, int source_entity_dim, + std::shared_ptr coordinate_system, MLSOptions options) +{ + RequireDiscretization("CreatePolynomialReconstructionSpace", discretization); +#ifdef PCMS_ENABLE_OMEGA_H + if (const auto* oh = + dynamic_cast( + discretization.get())) { + return pcms::field::PolynomialReconstructionFunctionSpace::FromMesh( + oh->GetMesh(), source_entity_dim, std::move(coordinate_system), options); + } +#else + (void)source_entity_dim; + (void)coordinate_system; + (void)options; +#endif + Unsupported("CreatePolynomialReconstructionSpace", *discretization); +} + +std::shared_ptr CreateEmptyLayout( + std::shared_ptr coordinate_system, int num_components) +{ + return std::make_shared( + std::move(coordinate_system), num_components); +} + +} // namespace pcms diff --git a/src/pcms/field/gid_permutation.cpp b/src/pcms/field/gid_permutation.cpp index 475216f8b..2adf35a2f 100644 --- a/src/pcms/field/gid_permutation.cpp +++ b/src/pcms/field/gid_permutation.cpp @@ -1,8 +1,8 @@ #include "pcms/field/gid_permutation.hpp" -#include "pcms/utility/assert.h" +#include "pcms/utility/assert.hpp" #include -namespace pcms +namespace pcms::field { namespace @@ -67,4 +67,4 @@ std::vector BuildSortedGidPermutation(GlobalIDView gids, return permutation; } -} // namespace pcms +} // namespace pcms::field diff --git a/src/pcms/field/gid_permutation.hpp b/src/pcms/field/gid_permutation.hpp index 0118fd31c..54d7ddb0f 100644 --- a/src/pcms/field/gid_permutation.hpp +++ b/src/pcms/field/gid_permutation.hpp @@ -1,13 +1,13 @@ #ifndef PCMS_FIELD_GID_PERMUTATION_HPP #define PCMS_FIELD_GID_PERMUTATION_HPP -#include "pcms/field/field_layout.h" +#include "pcms/field/field_layout.hpp" #include #include #include #include -namespace pcms +namespace pcms::field { // Maps a GID to its position in an exchange buffer, grouped by entity-dimension @@ -40,6 +40,6 @@ void AppendGidPermutation(GlobalIDView local_gids, std::vector BuildSortedGidPermutation(GlobalIDView gids, const EntOffsetsArray& ent_offsets); -} // namespace pcms +} // namespace pcms::field #endif // PCMS_FIELD_GID_PERMUTATION_HPP diff --git a/src/pcms/field/layout/empty.cpp b/src/pcms/field/layout/empty.cpp index cdd6dc0b4..9463be628 100644 --- a/src/pcms/field/layout/empty.cpp +++ b/src/pcms/field/layout/empty.cpp @@ -1,7 +1,7 @@ -#include "pcms/field/layout/empty.h" -#include "pcms/utility/assert.h" +#include "pcms/field/layout/empty.hpp" +#include "pcms/utility/assert.hpp" -namespace pcms +namespace pcms::field { namespace @@ -42,7 +42,8 @@ EmptyFieldLayout::EmptyFieldLayout( throw pcms_error("EmptyFieldLayout: num_components must be positive"); } SetCoordinateSystem(std::move(system)); - discretization_ = std::make_shared(); + discretization_ = + std::make_shared(); } std::shared_ptr EmptyFieldLayout::GetDiscretization() @@ -110,4 +111,4 @@ EmptyFieldLayout::GetDOFHolderClassificationIdsHost() const return make_const_array_view(classification_ids_host_); } -} // namespace pcms +} // namespace pcms::field diff --git a/src/pcms/field/layout/empty.h b/src/pcms/field/layout/empty.hpp similarity index 88% rename from src/pcms/field/layout/empty.h rename to src/pcms/field/layout/empty.hpp index c3e129701..174df1574 100644 --- a/src/pcms/field/layout/empty.h +++ b/src/pcms/field/layout/empty.hpp @@ -1,11 +1,11 @@ -#ifndef PCMS_EMPTY_FIELD_LAYOUT_H -#define PCMS_EMPTY_FIELD_LAYOUT_H +#ifndef PCMS_FIELD_LAYOUT_EMPTY_HPP +#define PCMS_FIELD_LAYOUT_EMPTY_HPP -#include "pcms/discretization/discretization/empty.hpp" -#include "pcms/field/field_layout.h" +#include "pcms/discretization/empty.hpp" +#include "pcms/field/field_layout.hpp" #include -namespace pcms +namespace pcms::field { class EmptyFieldLayout : public FieldLayout @@ -48,6 +48,6 @@ class EmptyFieldLayout : public FieldLayout int num_components_; }; -} // namespace pcms +} // namespace pcms::field -#endif // PCMS_EMPTY_FIELD_LAYOUT_H +#endif // PCMS_FIELD_LAYOUT_EMPTY_HPP diff --git a/src/pcms/localization/localization_path_selection.h b/src/pcms/field/localization_path_selection.hpp similarity index 88% rename from src/pcms/localization/localization_path_selection.h rename to src/pcms/field/localization_path_selection.hpp index e08069cbf..7cb28672c 100644 --- a/src/pcms/localization/localization_path_selection.h +++ b/src/pcms/field/localization_path_selection.hpp @@ -1,12 +1,12 @@ -#ifndef PCMS_LOCALIZATION_PATH_SELECTION_H -#define PCMS_LOCALIZATION_PATH_SELECTION_H +#ifndef PCMS_FIELD_LOCALIZATION_PATH_SELECTION_HPP +#define PCMS_FIELD_LOCALIZATION_PATH_SELECTION_HPP -#include "pcms/field/field_layout.h" -#include "pcms/utility/entity_types.h" +#include "pcms/field/field_layout.hpp" +#include "pcms/utility/entity_types.hpp" #include -namespace pcms::detail +namespace pcms::field::detail { enum class LocalizationPath @@ -81,6 +81,6 @@ inline LocalizationPath SelectLocalizationPath( return LocalizationPath::PointCloudSupports; } -} // namespace pcms::detail +} // namespace pcms::field::detail -#endif // PCMS_LOCALIZATION_PATH_SELECTION_H +#endif // PCMS_FIELD_LOCALIZATION_PATH_SELECTION_HPP diff --git a/src/pcms/field/transformed_source.cpp b/src/pcms/field/transformed_source.cpp index 15ec29178..cde02db87 100644 --- a/src/pcms/field/transformed_source.cpp +++ b/src/pcms/field/transformed_source.cpp @@ -1,5 +1,5 @@ #include "pcms/field/transformed_source.hpp" -#include "pcms/field/function_space.h" +#include "pcms/field/function_space.hpp" #include namespace pcms diff --git a/src/pcms/fortranapi/CMakeLists.txt b/src/pcms/fortranapi/CMakeLists.txt index cb2f578ed..0aff05f7e 100644 --- a/src/pcms/fortranapi/CMakeLists.txt +++ b/src/pcms/fortranapi/CMakeLists.txt @@ -1,19 +1,22 @@ -add_library(pcms_fortranapi_core pcms.f90 client_wrap.c) -target_compile_definitions(pcms_fortranapi_core PUBLIC HAVE_MPI) -add_library(pcms::fortranapi::core ALIAS pcms_fortranapi_core) -set_target_properties( - pcms_fortranapi_core - PROPERTIES Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/fortran - OUTPUT_NAME pcmsfortranapi EXPORT_NAME fortranapi::core) -target_include_directories( - pcms_fortranapi_core - PUBLIC - $> - $) -target_link_libraries( - pcms_fortranapi_core - PRIVATE pcms::capi::core - PUBLIC Kokkos::kokkos) +# the Fortran client module wraps the C API client +if(TARGET pcms_capi_core) + add_library(pcms_fortranapi_core pcms.f90 client_wrap.c) + target_compile_definitions(pcms_fortranapi_core PUBLIC HAVE_MPI) + add_library(pcms::fortranapi::core ALIAS pcms_fortranapi_core) + set_target_properties( + pcms_fortranapi_core + PROPERTIES Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/fortran + OUTPUT_NAME pcmsfortranapi EXPORT_NAME fortranapi::core) + target_include_directories( + pcms_fortranapi_core + PUBLIC + $> + $) + target_link_libraries( + pcms_fortranapi_core + PRIVATE pcms::capi::core + PUBLIC Kokkos::kokkos) +endif() add_library(pcms_fortranapi_transfer pcms_interpolator.f90 interpolator_wrap.c pcms_mesh.f90 mesh_wrap.c) add_library(pcms::fortranapi::transfer ALIAS pcms_fortranapi_transfer) @@ -24,8 +27,10 @@ target_include_directories(pcms_fortranapi_transfer PUBLIC $) target_link_libraries(pcms_fortranapi_transfer PRIVATE pcms::capi::transfer PUBLIC Kokkos::kokkos) -INSTALL(DIRECTORY $ - DESTINATION ${CMAKE_INSTALL_LIBDIR}) +if(TARGET pcms_fortranapi_core) + INSTALL(DIRECTORY $ + DESTINATION ${CMAKE_INSTALL_LIBDIR}) +endif() INSTALL(DIRECTORY $ DESTINATION ${CMAKE_INSTALL_LIBDIR}) @@ -35,7 +40,9 @@ add_library(pcms_fortranapi INTERFACE) add_library(pcms::fortranapi ALIAS pcms_fortranapi) set_target_properties(pcms_fortranapi PROPERTIES EXPORT_NAME fortranapi) # link capi libraries to a high level interface library -target_link_libraries(pcms_fortranapi INTERFACE pcms::fortranapi::core) +if(TARGET pcms_fortranapi_core) + target_link_libraries(pcms_fortranapi INTERFACE pcms::fortranapi::core) +endif() target_link_libraries(pcms_fortranapi INTERFACE pcms::fortranapi::transfer) @@ -52,22 +59,24 @@ install( install( EXPORT pcms_fortranapi-targets NAMESPACE pcms:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pcms) + DESTINATION ${PCMS_INSTALL_CMAKEDIR}) -install( - TARGETS pcms_fortranapi_core - EXPORT pcms_fortranapi_core-targets - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - INCLUDES - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/pcms/fortranapi/) +if(TARGET pcms_fortranapi_core) + install( + TARGETS pcms_fortranapi_core + EXPORT pcms_fortranapi_core-targets + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + INCLUDES + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/pcms/fortranapi/) -install( - EXPORT pcms_fortranapi_core-targets - NAMESPACE pcms:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pcms) + install( + EXPORT pcms_fortranapi_core-targets + NAMESPACE pcms:: + DESTINATION ${PCMS_INSTALL_CMAKEDIR}) +endif() install( TARGETS pcms_fortranapi_transfer @@ -82,4 +91,4 @@ install( install( EXPORT pcms_fortranapi_transfer-targets NAMESPACE pcms:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pcms) + DESTINATION ${PCMS_INSTALL_CMAKEDIR}) diff --git a/src/pcms/localization/CMakeLists.txt b/src/pcms/localization/CMakeLists.txt index 269b1b776..07515d2a8 100644 --- a/src/pcms/localization/CMakeLists.txt +++ b/src/pcms/localization/CMakeLists.txt @@ -1,18 +1,16 @@ set( PCMS_LOCALIZATION_HEADERS - point_search.h - queue_visited.hpp - adj_search.hpp - mls_support_helpers.h - localization_factory.h - point_cloud_localization.h - mesh_localization.h + point_search.hpp + support_results.hpp + mls_support_helpers.hpp + localization_factory.hpp + ../../../include/pcms/localization/mls_options.hpp + mesh_localization.hpp ) set( PCMS_LOCALIZATION_SOURCES point_search.cpp - adj_search.cpp mls_support_helpers.cpp mesh_localization.cpp ) @@ -41,7 +39,16 @@ set_target_properties( ) ## export the library -set_target_properties(pcms_localization PROPERTIES PUBLIC_HEADER "${PCMS_LOCALIZATION_HEADERS}") +# Only the public headers (include/pcms/...) are installed; the private +# headers next to the sources are private sources of the target. +set(PCMS_LOCALIZATION_HEADERS_PUBLIC ${PCMS_LOCALIZATION_HEADERS}) +list(FILTER PCMS_LOCALIZATION_HEADERS_PUBLIC INCLUDE REGEX "/include/pcms/") +set(PCMS_LOCALIZATION_HEADERS_PRIVATE ${PCMS_LOCALIZATION_HEADERS}) +list(FILTER PCMS_LOCALIZATION_HEADERS_PRIVATE EXCLUDE REGEX "/include/pcms/") +target_sources(pcms_localization + PUBLIC FILE_SET localization TYPE HEADERS BASE_DIRS ${PROJECT_SOURCE_DIR}/include/pcms + FILES ${PCMS_LOCALIZATION_HEADERS_PUBLIC} + PRIVATE ${PCMS_LOCALIZATION_HEADERS_PRIVATE}) install( TARGETS pcms_localization @@ -51,11 +58,11 @@ install( RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/pcms/localization + FILE_SET localization DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/pcms ) install( EXPORT pcms_localization-targets NAMESPACE pcms:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pcms + DESTINATION ${PCMS_INSTALL_CMAKEDIR} ) diff --git a/src/pcms/localization/adj_search.hpp b/src/pcms/localization/adj_search.hpp deleted file mode 100644 index c27b11be5..000000000 --- a/src/pcms/localization/adj_search.hpp +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef PCMS_LOCALIZATION_ADJ_SEARCH_HPP -#define PCMS_LOCALIZATION_ADJ_SEARCH_HPP - -#include -#include -#include -#include -#include - -#include - -namespace pcms -{ - -static constexpr int max_dim = 3; - -class FindSupports -{ -private: - Omega_h::Mesh& source_mesh; - Omega_h::Mesh& target_mesh; - -public: - FindSupports(Omega_h::Mesh& source_mesh_, Omega_h::Mesh& target_mesh_) - : source_mesh(source_mesh_), target_mesh(target_mesh_){}; - - FindSupports(Omega_h::Mesh& mesh_) : source_mesh(mesh_), target_mesh(mesh_){}; - - void adjBasedSearch(Omega_h::Write& supports_ptr, - Omega_h::Write& nSupports, - Omega_h::Write& support_idx, - Omega_h::Write& radii2, - bool is_build_csr_call); - - void adjBasedSearchCentroidNodes(Omega_h::Write& supports_ptr, - Omega_h::Write& nSupports, - Omega_h::Write& support_idx, - Omega_h::Write& radii2, - bool is_build_csr_call); -}; - -struct SupportResults -{ - Omega_h::LOs supports_ptr; - Omega_h::LOs supports_idx; - Omega_h::Write radii2; -}; - -SupportResults searchNeighbors(Omega_h::Mesh& source_mesh, - const Omega_h::Reals& target_coords, - Omega_h::LO n_targets, - Omega_h::Real& cutoffDistance, - Omega_h::LO min_req_support = 12, - Omega_h::LO max_allowed_support = 36, - bool adapt_radius = true); - -SupportResults searchNeighbors(Omega_h::Mesh& source_mesh, - Omega_h::Mesh& target_mesh, - Omega_h::Real& cutoffDistance, - Omega_h::LO min_req_support = 12, - Omega_h::LO max_allowed_support = 36, - bool adapt_radius = true); - -SupportResults searchNeighbors(Omega_h::Mesh& mesh, - Omega_h::Real cutoffDistance, - Omega_h::LO min_support = 12, - bool adapt_radius = true); -} // namespace pcms - -#endif // PCMS_LOCALIZATION_ADJ_SEARCH_HPP diff --git a/src/pcms/localization/localization_factory.h b/src/pcms/localization/localization_factory.hpp similarity index 60% rename from src/pcms/localization/localization_factory.h rename to src/pcms/localization/localization_factory.hpp index 889d9c64f..505267078 100644 --- a/src/pcms/localization/localization_factory.h +++ b/src/pcms/localization/localization_factory.hpp @@ -1,11 +1,11 @@ -#ifndef PCMS_LOCALIZATION_LOCALIZATION_FACTORY_H -#define PCMS_LOCALIZATION_LOCALIZATION_FACTORY_H +#ifndef PCMS_LOCALIZATION_LOCALIZATION_FACTORY_HPP +#define PCMS_LOCALIZATION_LOCALIZATION_FACTORY_HPP -#include "pcms/localization/adj_search.hpp" -#include "pcms/field/coordinate_view.hpp" -#include "pcms/utility/memory_spaces.h" +#include "pcms/localization/support_results.hpp" +#include "pcms/utility/coordinate_view.hpp" +#include "pcms/utility/memory_spaces.hpp" -namespace pcms +namespace pcms::localization { // Abstract interface for building MLS support structures. @@ -23,6 +23,6 @@ class LocalizationFactory CoordinateView target_coords) const = 0; }; -} // namespace pcms +} // namespace pcms::localization -#endif // PCMS_LOCALIZATION_LOCALIZATION_FACTORY_H +#endif // PCMS_LOCALIZATION_LOCALIZATION_FACTORY_HPP diff --git a/src/pcms/localization/mesh_localization.cpp b/src/pcms/localization/mesh_localization.cpp index d5d18f030..6e4e85679 100644 --- a/src/pcms/localization/mesh_localization.cpp +++ b/src/pcms/localization/mesh_localization.cpp @@ -1,16 +1,16 @@ -#include "pcms/localization/mesh_localization.h" -#include "pcms/localization/adj_search.hpp" -#include "pcms/localization/mls_support_helpers.h" -#include "pcms/field/coordinate_view.hpp" -#include "pcms/utility/assert.h" -#include "pcms/utility/entity_types.h" -#include "pcms/utility/mesh_geometry.h" -#include "pcms/utility/omega_h_array_utils.h" +#include "pcms/localization/mesh_localization.hpp" +#include "pcms/backends/omega_h/adj_search.hpp" +#include "pcms/localization/mls_support_helpers.hpp" +#include "pcms/utility/coordinate_view.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/entity_types.hpp" +#include "pcms/utility/mesh_geometry.hpp" +#include "pcms/utility/omega_h_array_utils.hpp" #include #include -namespace pcms +namespace pcms::localization { SupportResults AdjacencyLocalizationFactory::Build( @@ -36,19 +36,19 @@ SupportResults AdjacencyLocalizationFactory::Build( if (source_entity_dim_ == Vertex) { Omega_h::Reals target_coords_oh = - flatten_to_omega_h_reals(tgt_view, "tgt_coords"); + pcms::utility::flatten_to_omega_h_reals(tgt_view, "tgt_coords"); - return searchNeighbors( + return pcms::backend::omega_h::searchNeighbors( source_mesh_, target_coords_oh, n_tgt, radius_sq, static_cast(options_.min_req_supports), static_cast(3 * options_.min_req_supports), options_.adapt_radius); } const Omega_h::Reals src_oh = - get_entity_centroids(source_mesh_, source_entity_dim_); + pcms::utility::get_entity_centroids(source_mesh_, source_entity_dim_); Omega_h::Reals target_coords_oh = - flatten_to_omega_h_reals(tgt_view, "tgt_coords"); + pcms::utility::flatten_to_omega_h_reals(tgt_view, "tgt_coords"); return BuildPointCloudSupports(src_oh, target_coords_oh, dim, options_.radius, options_.min_req_supports, @@ -61,9 +61,9 @@ SupportResults AdjacencyLocalizationFactory::BuildSameMeshCentroidToVertex() PCMS_ALWAYS_ASSERT(source_entity_dim_ == Face); PCMS_ALWAYS_ASSERT(source_mesh_.dim() == 2); Omega_h::Real radius_sq = options_.radius * options_.radius; - return searchNeighbors(source_mesh_, radius_sq, - static_cast(options_.min_req_supports), - options_.adapt_radius); + return pcms::backend::omega_h::searchNeighbors( + source_mesh_, radius_sq, + static_cast(options_.min_req_supports), options_.adapt_radius); } -} // namespace pcms +} // namespace pcms::localization diff --git a/src/pcms/localization/mesh_localization.h b/src/pcms/localization/mesh_localization.hpp similarity index 75% rename from src/pcms/localization/mesh_localization.h rename to src/pcms/localization/mesh_localization.hpp index f685b98dc..921ed96a8 100644 --- a/src/pcms/localization/mesh_localization.h +++ b/src/pcms/localization/mesh_localization.hpp @@ -1,12 +1,12 @@ -#ifndef PCMS_LOCALIZATION_ADJACENCY_LOCALIZATION_H -#define PCMS_LOCALIZATION_ADJACENCY_LOCALIZATION_H +#ifndef PCMS_LOCALIZATION_MESH_LOCALIZATION_HPP +#define PCMS_LOCALIZATION_MESH_LOCALIZATION_HPP -#include "pcms/localization/localization_factory.h" -#include "pcms/field/evaluator/mls_options.h" +#include "pcms/localization/localization_factory.hpp" +#include "pcms/localization/mls_options.hpp" #include -namespace pcms +namespace pcms::localization { // LocalizationFactory implementation using mesh-adjacency BFS search. @@ -39,6 +39,6 @@ class AdjacencyLocalizationFactory : public LocalizationFactory MLSOptions options_; }; -} // namespace pcms +} // namespace pcms::localization -#endif // PCMS_LOCALIZATION_ADJACENCY_LOCALIZATION_H +#endif // PCMS_LOCALIZATION_MESH_LOCALIZATION_HPP diff --git a/src/pcms/localization/mls_support_helpers.cpp b/src/pcms/localization/mls_support_helpers.cpp index e94d7a01e..b7c2c0fbb 100644 --- a/src/pcms/localization/mls_support_helpers.cpp +++ b/src/pcms/localization/mls_support_helpers.cpp @@ -1,11 +1,11 @@ -#include "pcms/localization/mls_support_helpers.h" -#include "pcms/localization/adj_search.hpp" -#include "pcms/utility/assert.h" -#include "pcms/utility/print.h" +#include "pcms/localization/mls_support_helpers.hpp" +#include "pcms/backends/omega_h/adj_search.hpp" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/print.hpp" #include -namespace pcms +namespace pcms::localization { // replace with Kokkos::minmax_element when out of experimental @@ -226,4 +226,4 @@ SupportResults BuildPointCloudSupports(const Omega_h::Reals& source_coords, radii2}; } -} // namespace pcms +} // namespace pcms::localization diff --git a/src/pcms/localization/mls_support_helpers.h b/src/pcms/localization/mls_support_helpers.hpp similarity index 88% rename from src/pcms/localization/mls_support_helpers.h rename to src/pcms/localization/mls_support_helpers.hpp index 1410f3df6..8832b5837 100644 --- a/src/pcms/localization/mls_support_helpers.h +++ b/src/pcms/localization/mls_support_helpers.hpp @@ -1,9 +1,9 @@ -#ifndef PCMS_LOCALIZATION_MLS_SUPPORT_HELPERS_H -#define PCMS_LOCALIZATION_MLS_SUPPORT_HELPERS_H +#ifndef PCMS_LOCALIZATION_MLS_SUPPORT_HELPERS_HPP +#define PCMS_LOCALIZATION_MLS_SUPPORT_HELPERS_HPP #include -namespace pcms +namespace pcms::localization { struct SupportResults; @@ -39,5 +39,5 @@ SupportResults BuildPointCloudSupports(const Omega_h::Reals& source_coords, bool adapt_radius, unsigned max_iterations = 100); -} // namespace pcms -#endif // PCMS_LOCALIZATION_MLS_SUPPORT_HELPERS_H +} // namespace pcms::localization +#endif // PCMS_LOCALIZATION_MLS_SUPPORT_HELPERS_HPP diff --git a/src/pcms/localization/point_search.cpp b/src/pcms/localization/point_search.cpp index da74f055a..2200e590b 100644 --- a/src/pcms/localization/point_search.cpp +++ b/src/pcms/localization/point_search.cpp @@ -1,4 +1,4 @@ -#include "point_search.h" +#include "pcms/localization/point_search.hpp" #include #include #include @@ -77,7 +77,7 @@ KOKKOS_INLINE_FUNCTION BarycentricWithScales barycentric_with_scales( return result; } -namespace pcms +namespace pcms::localization { LO GetOwningElementId(Omega_h::Mesh& mesh, int mesh_dim, int entity_dim, @@ -816,7 +816,7 @@ GridPointSearch2D::GridPointSearch2D(Omega_h::Mesh& mesh, LO Nx, LO Ny, LO GridPointSearch2D::GetOwningElementId(const Result& result) { - return pcms::GetOwningElementId( + return pcms::localization::GetOwningElementId( mesh_, 2, static_cast(result.dimensionality), result.EntityId()); } @@ -963,7 +963,7 @@ GridPointSearch3D::GridPointSearch3D(Omega_h::Mesh& mesh, LO Nx, LO Ny, LO Nz, LO GridPointSearch3D::GetOwningElementId(const Result& result) { - return pcms::GetOwningElementId( + return pcms::localization::GetOwningElementId( mesh_, 3, static_cast(result.dimensionality), result.EntityId()); } @@ -1004,4 +1004,4 @@ Kokkos::View GridPointSearch3D::GetOwningElementIds( }); return owners; } -} // namespace pcms +} // namespace pcms::localization diff --git a/src/pcms/localization/point_search.h b/src/pcms/localization/point_search.hpp similarity index 96% rename from src/pcms/localization/point_search.h rename to src/pcms/localization/point_search.hpp index 602c99fb3..ab7729623 100644 --- a/src/pcms/localization/point_search.h +++ b/src/pcms/localization/point_search.hpp @@ -1,5 +1,5 @@ -#ifndef PCMS_COUPLING_POINT_SEARCH_H -#define PCMS_COUPLING_POINT_SEARCH_H +#ifndef PCMS_LOCALIZATION_POINT_SEARCH_HPP +#define PCMS_LOCALIZATION_POINT_SEARCH_HPP #include #include @@ -9,11 +9,11 @@ #include #include -#include "pcms/utility/types.h" -#include "pcms/utility/uniform_grid.h" -#include "pcms/utility/bounding_box.h" +#include "pcms/utility/types.hpp" +#include "pcms/utility/uniform_grid.hpp" +#include "pcms/utility/bounding_box.hpp" -namespace pcms +namespace pcms::localization { /** @@ -254,5 +254,5 @@ class GridPointSearch3D : public PointLocalizationSearch3D using GridPointSearchVariant = std::variant; -} // namespace pcms -#endif // PCMS_COUPLING_POINT_SEARCH_H +} // namespace pcms::localization +#endif // PCMS_LOCALIZATION_POINT_SEARCH_HPP diff --git a/src/pcms/localization/support_results.hpp b/src/pcms/localization/support_results.hpp new file mode 100644 index 000000000..2cc419541 --- /dev/null +++ b/src/pcms/localization/support_results.hpp @@ -0,0 +1,18 @@ +#ifndef PCMS_LOCALIZATION_SUPPORT_RESULTS_HPP +#define PCMS_LOCALIZATION_SUPPORT_RESULTS_HPP + +#include + +namespace pcms::localization +{ + +struct SupportResults +{ + Omega_h::LOs supports_ptr; + Omega_h::LOs supports_idx; + Omega_h::Write radii2; +}; + +} // namespace pcms::localization + +#endif // PCMS_LOCALIZATION_SUPPORT_RESULTS_HPP diff --git a/src/pcms/pythonapi/CMakeLists.txt b/src/pcms/pythonapi/CMakeLists.txt index 2e0758f89..23dde4ce8 100644 --- a/src/pcms/pythonapi/CMakeLists.txt +++ b/src/pcms/pythonapi/CMakeLists.txt @@ -16,7 +16,7 @@ pybind11_add_module(pcms bind_mesh_utilities.cpp ) target_compile_features(pcms PUBLIC cxx_std_20) -target_link_libraries(pcms PRIVATE Kokkos::kokkos pybind11::module MPI::MPI_C pcms::core pcms::transfer) +target_link_libraries(pcms PRIVATE Kokkos::kokkos pybind11::module MPI::MPI_C pcms::coupler pcms::transfer) # The conservative/Monte Carlo projection bindings include transfer headers # that transitively pull in PETSc (petscvec.h). PETSc is linked PRIVATE into diff --git a/src/pcms/pythonapi/bind_coordinate_map.cpp b/src/pcms/pythonapi/bind_coordinate_map.cpp index 523d06a3e..04221eb9a 100644 --- a/src/pcms/pythonapi/bind_coordinate_map.cpp +++ b/src/pcms/pythonapi/bind_coordinate_map.cpp @@ -7,7 +7,7 @@ #include "pcms/field/point_evaluator_factory.hpp" #include "pcms/field/transformed_source.hpp" #include "pcms/field/value_view.hpp" -#include "py_value_types.h" +#include "pcms/pythonapi/py_value_types.hpp" namespace py = pybind11; diff --git a/src/pcms/pythonapi/bind_coordinate_system.cpp b/src/pcms/pythonapi/bind_coordinate_system.cpp index e50a36b30..26d991c39 100644 --- a/src/pcms/pythonapi/bind_coordinate_system.cpp +++ b/src/pcms/pythonapi/bind_coordinate_system.cpp @@ -5,12 +5,12 @@ #include #include -#include "pcms/field/coordinate_system.hpp" -#include "pcms/field/coordinate_systems/cartesian.hpp" -#include "pcms/field/coordinate_systems/cylindrical.hpp" -#include "pcms/field/coordinate_view.hpp" -#include "numpy_view.h" -#include "py_value_types.h" +#include "pcms/utility/coordinate_system.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_systems/cylindrical.hpp" +#include "pcms/utility/coordinate_view.hpp" +#include "pcms/pythonapi/numpy_view.hpp" +#include "pcms/pythonapi/py_value_types.hpp" namespace py = pybind11; diff --git a/src/pcms/pythonapi/bind_field_base.cpp b/src/pcms/pythonapi/bind_field_base.cpp index b38c8fbfc..35da47bd4 100644 --- a/src/pcms/pythonapi/bind_field_base.cpp +++ b/src/pcms/pythonapi/bind_field_base.cpp @@ -6,25 +6,24 @@ #include #include -#include "pcms/discretization/discretization/omega_h.hpp" -#include "pcms/field/coordinate_system.hpp" -#include "pcms/field/coordinate_systems/cartesian.hpp" -#include "pcms/field/coordinate_view.hpp" -#include "pcms/field/evaluation_request.h" -#include "pcms/field/evaluator/mls_options.h" -#include "pcms/field/field.h" -#include "pcms/field/field_data.h" -#include "pcms/field/field_layout.h" -#include "pcms/field/function_space.h" -#include "pcms/field/function_space/lagrange.h" -#include "pcms/field/function_space/polynomial_reconstruction.hpp" +#include "pcms/utility/coordinate_system.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_view.hpp" +#include "pcms/field/evaluation_request.hpp" +#include "pcms/localization/mls_options.hpp" +#include "pcms/field/field.hpp" +#include "pcms/field/field_data.hpp" +#include "pcms/field/field_layout.hpp" +#include "pcms/field/function_space.hpp" +#include "pcms/backends/omega_h/omega_h.hpp" +#include "pcms/discretization/discretization.hpp" +#include "pcms/field/function_spaces.hpp" #include "pcms/field/point_evaluator_factory.hpp" -#include "pcms/field/uniform_grid_binary_field.h" #include "pcms/field/value_view.hpp" -#include "pcms/utility/arrays.h" -#include "pcms/utility/uniform_grid.h" -#include "numpy_array_transform.h" -#include "py_value_types.h" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/uniform_grid.hpp" +#include "pcms/pythonapi/numpy_array_transform.hpp" +#include "pcms/pythonapi/py_value_types.hpp" namespace py = pybind11; @@ -207,75 +206,76 @@ void bind_create_field_module(py::module& m) .def("get_layout", [](const FunctionSpace& self) { return ToPyHolder(self.GetLayout()); }) .def( - "mesh", - [](const FunctionSpace& self) -> Omega_h::Mesh& { - auto disc = std::dynamic_pointer_cast( - self.GetDiscretization()); - if (!disc) { - throw std::runtime_error( - "FunctionSpace::mesh: this function space is not backed by an " - "Omega_h mesh"); - } - return disc->GetMesh(); + "get_discretization", + [](const FunctionSpace& self) { + return ToPyHolder(self.GetDiscretization()); }, - py::return_value_policy::reference, - "The Omega_h mesh this function space is defined on (Omega_h backend " - "only)."); + "The discretization this function space is defined on"); - py::class_> - lagrange_space(m, "LagrangeFunctionSpace"); + py::class_>( + m, "Discretization", "The entities (mesh, grid, points) a space lives on") + .def("get_dimension", &Discretization::GetDimension) + .def("get_num_entities", &Discretization::GetNumEntities, + py::arg("entity_dim")); - // Backend selecting the underlying field layout. The conservative-projection - // transfer operators require the native Omega_h backend. - py::enum_(lagrange_space, "Backend") - .value("MeshFields", LagrangeFunctionSpace::Backend::MeshFields, - "MeshFields-backed layout (default when MeshFields is enabled)") - .value("OmegaH", LagrangeFunctionSpace::Backend::OmegaH, + m.def( + "create_uniform_grid_discretization", + [](const UniformGrid<2>& grid) { + return ToPyHolder(CreateUniformGridDiscretization(grid)); + }, + py::arg("grid"), "Discretization of a 2D uniform grid"); + m.def( + "create_uniform_grid_discretization", + [](const UniformGrid<3>& grid) { + return ToPyHolder(CreateUniformGridDiscretization(grid)); + }, + py::arg("grid"), "Discretization of a 3D uniform grid"); + m.def( + "create_empty_discretization", + []() { return ToPyHolder(CreateEmptyDiscretization()); }, + "Discretization without entities, for evaluation-only spaces"); + + // Which implementation evaluates Lagrange fields on Omega_h meshes. The + // conservative-projection transfer operators require OmegaH. + py::enum_(m, "LagrangeImplementation") + .value("Default", LagrangeImplementation::Default, + "MeshFields when PCMS is built with MeshFields, OmegaH otherwise") + .value("MeshFields", LagrangeImplementation::MeshFields, + "MeshFields-backed layout") + .value("OmegaH", LagrangeImplementation::OmegaH, "Native Omega_h Lagrange layout (required by the conservative and " "Monte Carlo projection transfer operators)") .export_values(); - // The mesh-backed spaces refer to the mesh, so it is kept alive with them. - lagrange_space - .def_static( - "from_mesh", - [](Omega_h::Mesh& mesh, int order, int num_components, - const SystemHolder& mesh_coordinate_system, std::string global_id_name, - LagrangeFunctionSpace::Backend backend) { - return LagrangeFunctionSpace::FromMesh( - mesh, order, num_components, CartesianIfNone(mesh_coordinate_system), - std::move(global_id_name), backend); - }, - py::arg("mesh"), py::arg("order"), py::arg("num_components"), - py::arg("mesh_coordinate_system") = py::none(), - py::arg("global_id_name") = "global", - py::arg("backend") = LagrangeFunctionSpace::DefaultBackend, - py::keep_alive<0, 1>(), - "Create a LagrangeFunctionSpace from an Omega_h mesh. The coordinate " - "system defaults to Cartesian.") - .def_static( - "from_uniform_grid", - [](const UniformGrid<2>& grid, int num_components, - const SystemHolder& mesh_coordinate_system, int order) { - return LagrangeFunctionSpace::FromUniformGrid( - grid, num_components, CartesianIfNone(mesh_coordinate_system), order); - }, - py::arg("grid"), py::arg("num_components"), - py::arg("mesh_coordinate_system") = py::none(), py::arg("order") = 1, - "Create a LagrangeFunctionSpace from a 2D uniform grid. The coordinate " - "system defaults to Cartesian.") - .def_static( - "from_uniform_grid", - [](const UniformGrid<3>& grid, int num_components, - const SystemHolder& mesh_coordinate_system, int order) { - return LagrangeFunctionSpace::FromUniformGrid( - grid, num_components, CartesianIfNone(mesh_coordinate_system), order); - }, - py::arg("grid"), py::arg("num_components"), - py::arg("mesh_coordinate_system") = py::none(), py::arg("order") = 1, - "Create a LagrangeFunctionSpace from a 3D uniform grid. The coordinate " - "system defaults to Cartesian."); + // A space refers to its discretization (and through it to the mesh), so + // the discretization is kept alive with the space. + m.def( + "create_lagrange_space", + [](std::shared_ptr discretization, int order, + int num_components, const SystemHolder& coordinate_system, + LagrangeImplementation implementation, std::string layout_name) { + return CreateLagrangeSpace( + std::move(discretization), order, num_components, + CartesianIfNone(coordinate_system), + LagrangeOptions{implementation, std::move(layout_name)}); + }, + py::arg("discretization"), py::arg("order"), py::arg("num_components"), + py::arg("coordinate_system") = py::none(), + py::arg("implementation") = LagrangeImplementation::Default, + py::arg("layout_name") = "", py::keep_alive<0, 1>(), + "Lagrange space on an Omega_h or uniform-grid discretization. The " + "coordinate system defaults to Cartesian."); + + m.def( + "create_spline_space", + [](std::shared_ptr discretization, + const SystemHolder& coordinate_system) { + return CreateSplineSpace(std::move(discretization), + CartesianIfNone(coordinate_system)); + }, + py::arg("discretization"), py::arg("coordinate_system") = py::none(), + py::keep_alive<0, 1>(), + "Bicubic spline space on a 2D uniform-grid discretization"); // Configuration for PolynomialReconstructionFunctionSpace MLS evaluation. py::class_(m, "MLSOptions") @@ -289,57 +289,78 @@ void bind_create_field_module(py::module& m) .def_readwrite("decay_factor", &MLSOptions::decay_factor) .def_readwrite("basis", &MLSOptions::basis); - py::class_>( - m, "PolynomialReconstructionFunctionSpace") - .def_static( - "create", - [](const PyCoordinateView& coords, MLSOptions options) { - auto values = NumpyInput::ensure(coords.values); - return PolynomialReconstructionFunctionSpace::Create( - CoordinateView(coords.system, - NumpyToHostView<2, Real>(values)), - options); - }, - py::arg("coords"), py::arg("options") = MLSOptions{}, - "Create a PolynomialReconstructionFunctionSpace over the source points " - "of a CoordinateView") - .def_static( - "from_mesh", - [](Omega_h::Mesh& mesh, int source_entity_dim, - const SystemHolder& coordinate_system, MLSOptions options) { - return PolynomialReconstructionFunctionSpace::FromMesh( - mesh, source_entity_dim, CartesianIfNone(coordinate_system), options); - }, - py::arg("mesh"), py::arg("source_entity_dim"), - py::arg("coordinate_system") = py::none(), - py::arg("options") = MLSOptions{}, py::keep_alive<0, 1>(), - "Create a PolynomialReconstructionFunctionSpace from mesh entity " - "coordinates."); - m.def( + "create_polynomial_reconstruction_space", + [](const PyCoordinateView& coords, MLSOptions options) { + auto values = NumpyInput::ensure(coords.values); + return CreatePolynomialReconstructionSpace( + CoordinateView(coords.system, + NumpyToHostView<2, Real>(values)), + options); + }, + py::arg("coords"), py::arg("options") = MLSOptions{}, + "Polynomial-reconstruction (MLS) space over the points of a " + "CoordinateView"); + m.def( + "create_polynomial_reconstruction_space", + [](std::shared_ptr discretization, int source_entity_dim, + const SystemHolder& coordinate_system, MLSOptions options) { + return CreatePolynomialReconstructionSpace( + std::move(discretization), source_entity_dim, + CartesianIfNone(coordinate_system), options); + }, + py::arg("discretization"), py::arg("source_entity_dim"), + py::arg("coordinate_system") = py::none(), + py::arg("options") = MLSOptions{}, py::keep_alive<0, 1>(), + "Polynomial-reconstruction (MLS) space over the entities of dimension " + "source_entity_dim of an Omega_h discretization"); + + // Omega_h backend entry points + auto omega_h_module = + m.def_submodule("backend", "Backend-specific entry points") + .def_submodule("omega_h", "Omega_h backend"); + omega_h_module.def( + "create_discretization", + [](Omega_h::Mesh& mesh, std::string global_id_name) { + return ToPyHolder(pcms::backend::omega_h::CreateDiscretization( + mesh, std::move(global_id_name))); + }, + py::arg("mesh"), py::arg("global_id_name") = "global", + py::keep_alive<0, 1>(), + "Discretization on an Omega_h mesh (the mesh is kept alive with it)"); + omega_h_module.def( + "get_mesh", + [](const Discretization& discretization) -> Omega_h::Mesh& { + return pcms::backend::omega_h::GetMesh(discretization); + }, + py::arg("discretization"), py::return_value_policy::reference, + py::keep_alive<0, 1>(), "The Omega_h mesh of an Omega_h discretization"); + omega_h_module.def( + "create_uniform_grid_binary_field", + [](Omega_h::Mesh& mesh, const std::array& divisions) { + return pcms::backend::omega_h::CreateUniformGridBinaryField(mesh, + divisions); + }, + py::arg("mesh"), py::arg("divisions"), + "Create a 2D vertex mask field indicating inside/outside mesh"); + + omega_h_module.def( "create_uniform_grid_from_mesh", [](Omega_h::Mesh& mesh, const std::array& divisions) { - return CreateUniformGridFromMesh<2>(mesh, divisions); + return pcms::backend::omega_h::CreateUniformGridFromMesh<2>(mesh, + divisions); }, py::arg("mesh"), py::arg("divisions"), "Create a 2D uniform grid from an Omega_h mesh"); - m.def( + omega_h_module.def( "create_uniform_grid_from_mesh", [](Omega_h::Mesh& mesh, const std::array& divisions) { - return CreateUniformGridFromMesh<3>(mesh, divisions); + return pcms::backend::omega_h::CreateUniformGridFromMesh<3>(mesh, + divisions); }, py::arg("mesh"), py::arg("divisions"), "Create a 3D uniform grid from an Omega_h mesh"); - - m.def( - "create_uniform_grid_binary_field", - [](Omega_h::Mesh& mesh, const std::array& divisions) { - return CreateUniformGridBinaryField<2>(mesh, divisions).second; - }, - py::arg("mesh"), py::arg("divisions"), - "Create a 2D vertex mask field indicating inside/outside mesh"); } } // namespace pcms diff --git a/src/pcms/pythonapi/bind_mesh_utilities.cpp b/src/pcms/pythonapi/bind_mesh_utilities.cpp index 0f03c38a1..72aa20695 100644 --- a/src/pcms/pythonapi/bind_mesh_utilities.cpp +++ b/src/pcms/pythonapi/bind_mesh_utilities.cpp @@ -3,9 +3,9 @@ #include #include #include -#include -#include -#include "numpy_array_transform.h" +#include +#include +#include "pcms/pythonapi/numpy_array_transform.hpp" namespace py = pybind11; @@ -49,7 +49,7 @@ py::array ShapeLike(py::array_t vertex_values, py::array compute_entity_centroids(Omega_h::Mesh& mesh, Omega_h::Int entity_dim) { const py::ssize_t dim = mesh.dim(); - return ToNumpy(pcms::get_entity_centroids(mesh, entity_dim)) + return ToNumpy(pcms::utility::get_entity_centroids(mesh, entity_dim)) .reshape(std::vector{mesh.nents(entity_dim), dim}); } @@ -128,7 +128,8 @@ py::array map_entity_field_to_vertices_mls( const Omega_h::LO ncomps = EntityComponents(entity_field_values, nentities); // Source coordinates are the entity centroids - auto source_coordinates = pcms::get_entity_centroids(mesh, entity_dim); + auto source_coordinates = + pcms::utility::get_entity_centroids(mesh, entity_dim); // Get target coordinates (vertex coordinates) auto target_coordinates = mesh.coords(); @@ -148,7 +149,8 @@ py::array map_entity_field_to_vertices_mls( Omega_h::Write radii2_write(num_vertices, 1.0); // Create SupportResults - SupportResults support{supports_ptr, supports_idx, radii2_write}; + pcms::localization::SupportResults support{supports_ptr, supports_idx, + radii2_write}; // Convert entity field values to Omega_h array auto entity_field_omega_h = NumpyToOmegaHRead(entity_field_values); @@ -162,7 +164,7 @@ py::array map_entity_field_to_vertices_mls( component_values[i] = entity_field_omega_h[i * ncomps + c]; }); - auto interpolated_values = pcms::mls_interpolation( + auto interpolated_values = pcms::field::mls_interpolation( Omega_h::read(component_values), source_coordinates, target_coordinates, support, dim, interp_degree, pcms::RadialBasisFunction::NO_OP, lambda_reg, 1e-6, // tol @@ -181,24 +183,21 @@ py::array map_entity_field_to_vertices_mls( void bind_mesh_utilities_module(py::module& m) { - m.def("compute_entity_centroids", &compute_entity_centroids, py::arg("mesh"), - py::arg("entity_dim"), - "Compute centroids of mesh entities (faces or elements). " - "Returns an array of shape (nentities, dim)."); - - // Backward compatibility alias - m.def("compute_entity_centroids_few", &compute_entity_centroids, - py::arg("mesh"), py::arg("entity_dim"), - "Compute entity centroids using gather_verts/gather_vectors/average. " - "Returns an array of shape (nentities, dim). " - "Note: This is an alias for compute_entity_centroids."); - m.def( "patch_size_for_degree", &patch_size_for_degree, py::arg("interp_degree"), "Get recommended minimum patch size for given MLS interpolation degree. " "Returns 4 for degree 1, 10 for degree 2, and 12 for degree 3."); - m.def( + // Omega_h backend entry points (the submodule is created in + // bind_create_field_module, which runs first) + auto omega_h_module = m.attr("backend").attr("omega_h").cast(); + + omega_h_module.def("compute_entity_centroids", &compute_entity_centroids, + py::arg("mesh"), py::arg("entity_dim"), + "Compute centroids of mesh entities (faces or elements). " + "Returns an array of shape (nentities, dim)."); + + omega_h_module.def( "map_entity_field_to_vertices_average", &map_entity_field_to_vertices_average, py::arg("mesh"), py::arg("entity_field_values"), py::arg("entity_dim"), @@ -214,7 +213,7 @@ void bind_mesh_utilities_module(py::module& m) " numpy array of field values at vertices (shape: (nverts,) or " "(nverts, ncomps), matching entity_field_values)"); - m.def( + omega_h_module.def( "map_entity_field_to_vertices_mls", &map_entity_field_to_vertices_mls, py::arg("mesh"), py::arg("entity_field_values"), py::arg("entity_dim"), py::arg("interp_degree") = 1, py::arg("min_support") = -1, diff --git a/src/pcms/pythonapi/bind_omega_h_field.cpp b/src/pcms/pythonapi/bind_omega_h_field.cpp index 33c0ab633..ee1d8d230 100644 --- a/src/pcms/pythonapi/bind_omega_h_field.cpp +++ b/src/pcms/pythonapi/bind_omega_h_field.cpp @@ -1,6 +1,6 @@ #include -#include "pcms/utility/arrays.h" -#include "pcms/field/out_of_bounds_policy.h" +#include "pcms/utility/arrays.hpp" +#include "pcms/field/out_of_bounds_policy.hpp" namespace py = pybind11; diff --git a/src/pcms/pythonapi/bind_runtime.cpp b/src/pcms/pythonapi/bind_runtime.cpp index 4c72de686..1debed151 100644 --- a/src/pcms/pythonapi/bind_runtime.cpp +++ b/src/pcms/pythonapi/bind_runtime.cpp @@ -1,6 +1,6 @@ -#include "pcms/configuration.h" +#include "pcms/configuration.hpp" #include -#include "pcms/utility/assert.h" +#include "pcms/utility/assert.hpp" #include #if defined(PCMS_ENABLE_PETSC) && defined(PCMS_ENABLE_MESHFIELDS) #include diff --git a/src/pcms/pythonapi/bind_transfer_field.cpp b/src/pcms/pythonapi/bind_transfer_field.cpp index cc55b28f5..970051d7c 100644 --- a/src/pcms/pythonapi/bind_transfer_field.cpp +++ b/src/pcms/pythonapi/bind_transfer_field.cpp @@ -1,22 +1,21 @@ #include #include #include -#include "pcms/configuration.h" -#include "pcms/transfer/copy.h" -#include "pcms/field/field.h" -#include "pcms/field/function_space.h" -#include "pcms/field/point_evaluator.h" -#include "../transfer/interpolator.h" -#include "pcms/field/out_of_bounds_policy.h" -#include "numpy_array_transform.h" -#include "py_value_types.h" +#include "pcms/configuration.hpp" +#include "pcms/transfer/copy.hpp" +#include "pcms/field/field.hpp" +#include "pcms/field/function_space.hpp" +#include "pcms/field/point_evaluator.hpp" +#include "pcms/transfer/interpolator.hpp" +#include "pcms/field/out_of_bounds_policy.hpp" +#include "pcms/pythonapi/numpy_array_transform.hpp" +#include "pcms/pythonapi/py_value_types.hpp" #include "pcms/field/point_evaluator_factory.hpp" #include "pcms/transfer/transfer_operator.hpp" -#include "pcms/utility/types.h" +#include "pcms/utility/types.hpp" #if defined(PCMS_ENABLE_PETSC) && defined(PCMS_ENABLE_MESHFIELDS) #include "pcms/transfer/mass_matrix_type.hpp" -#include "pcms/transfer/omega_h_conservative_projection.hpp" -#include "pcms/transfer/omega_h_control_variate_projection.hpp" +#include "pcms/transfer/projection.hpp" #include "pcms/transfer/omega_h_mc_rhs_integrator.hpp" #include #endif @@ -120,20 +119,20 @@ void bind_transfer_field_module(py::module& m) // Conservative L2 (Galerkin) projection between order-1 Lagrange spaces on // Omega_h 2D simplex meshes. The RHS is integrated exactly over the // intersection of the source and target meshes. - py::class_>( - m, "OmegaHConservativeProjection") - .def(py::init([](const FunctionSpace& source_space, - const FunctionSpace& target_space, - MassMatrixType mass_matrix_type) { - return std::make_unique( - source_space, target_space, mass_matrix_type); - }), - py::arg("source_space"), py::arg("target_space"), - py::arg("mass_matrix_type") = MassMatrixType::Consistent, - py::keep_alive<1, 2>(), py::keep_alive<1, 3>(), - "Construct a mesh-intersection conservative projection. Mesh " - "intersection, quadrature setup, and mass-matrix factorization happen " - "here and are cached; call apply() repeatedly."); + m.def( + "create_conservative_projection", + [](const FunctionSpace& source_space, const FunctionSpace& target_space, + MassMatrixType mass_matrix_type) { + return CreateConservativeProjection( + source_space, target_space, + ConservativeProjectionOptions{mass_matrix_type}); + }, + py::arg("source_space"), py::arg("target_space"), + py::arg("mass_matrix_type") = MassMatrixType::Consistent, + py::keep_alive<0, 1>(), py::keep_alive<0, 2>(), + "Mesh-intersection conservative projection. Mesh intersection, " + "quadrature setup, and mass-matrix factorization happen here and are " + "cached; call apply() repeatedly."); // Sampling strategy for the Monte Carlo RHS integrator. py::enum_(m, "MonteCarloSampling") @@ -145,25 +144,25 @@ void bind_transfer_field_module(py::module& m) // first interpolated onto the target space as a control variate; only the // residual is integrated stochastically, so sampling noise is small (and // exactly zero when the source already lives in the target space). - py::class_>( - m, "OmegaHControlVariateProjection") - .def(py::init([](const FunctionSpace& source_space, - const FunctionSpace& target_space, int samples_per_element, - MonteCarloSampling sampling, std::uint64_t seed, - MassMatrixType mass_matrix_type) { - return std::make_unique( - source_space, target_space, samples_per_element, sampling, seed, - mass_matrix_type); - }), - py::arg("source_space"), py::arg("target_space"), - py::arg("samples_per_element"), - py::arg("sampling") = MonteCarloSampling::UniformRandom, - py::arg("seed") = std::uint64_t(8675309), - py::arg("mass_matrix_type") = MassMatrixType::Consistent, - py::keep_alive<1, 2>(), py::keep_alive<1, 3>(), - "Construct a Monte Carlo (control-variate) conservative projection. " - "Sample-point generation, the control-variate interpolator, and the " - "mass-matrix factorization are cached; call apply() repeatedly."); + m.def( + "create_control_variate_projection", + [](const FunctionSpace& source_space, const FunctionSpace& target_space, + int samples_per_element, MonteCarloSampling sampling, std::uint64_t seed, + MassMatrixType mass_matrix_type) { + return CreateControlVariateProjection( + source_space, target_space, + ControlVariateProjectionOptions{samples_per_element, sampling, seed, + mass_matrix_type}); + }, + py::arg("source_space"), py::arg("target_space"), + py::arg("samples_per_element"), + py::arg("sampling") = MonteCarloSampling::UniformRandom, + py::arg("seed") = std::uint64_t(8675309), + py::arg("mass_matrix_type") = MassMatrixType::Consistent, + py::keep_alive<0, 1>(), py::keep_alive<0, 2>(), + "Monte Carlo (control-variate) conservative projection. Sample-point " + "generation, the control-variate interpolator, and the mass-matrix " + "factorization are cached; call apply() repeatedly."); #endif } diff --git a/src/pcms/pythonapi/bind_uniform_grid_field_layout.cpp b/src/pcms/pythonapi/bind_uniform_grid_field_layout.cpp index e4210c450..91c91aee6 100644 --- a/src/pcms/pythonapi/bind_uniform_grid_field_layout.cpp +++ b/src/pcms/pythonapi/bind_uniform_grid_field_layout.cpp @@ -1,9 +1,10 @@ #include #include #include -#include "numpy_array_transform.h" -#include "pcms/field/layout/uniform_grid.h" -#include "pcms/utility/uniform_grid.h" +#include "pcms/pythonapi/numpy_array_transform.hpp" +#include "pcms/backends/uniform_grid/layout.hpp" +#include "pcms/utility/uniform_grid.hpp" +#include namespace py = pybind11; diff --git a/src/pcms/pythonapi/bind_value_view.cpp b/src/pcms/pythonapi/bind_value_view.cpp index 7ab4531c1..b8f6131bb 100644 --- a/src/pcms/pythonapi/bind_value_view.cpp +++ b/src/pcms/pythonapi/bind_value_view.cpp @@ -6,9 +6,9 @@ #include #include -#include "pcms/field/coordinate_system.hpp" +#include "pcms/utility/coordinate_system.hpp" #include "pcms/field/value_view.hpp" -#include "py_value_types.h" +#include "pcms/pythonapi/py_value_types.hpp" namespace py = pybind11; diff --git a/src/pcms/pythonapi/numpy_array_transform.h b/src/pcms/pythonapi/numpy_array_transform.hpp similarity index 91% rename from src/pcms/pythonapi/numpy_array_transform.h rename to src/pcms/pythonapi/numpy_array_transform.hpp index 407d0c36c..22e4ef335 100644 --- a/src/pcms/pythonapi/numpy_array_transform.h +++ b/src/pcms/pythonapi/numpy_array_transform.hpp @@ -1,10 +1,13 @@ +#ifndef PCMS_PYTHONAPI_NUMPY_ARRAY_TRANSFORM_HPP +#define PCMS_PYTHONAPI_NUMPY_ARRAY_TRANSFORM_HPP + #include #include #include #include -#include "pcms/utility/arrays.h" -#include "pcms/utility/types.h" -#include "numpy_view.h" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/types.hpp" +#include "pcms/pythonapi/numpy_view.hpp" namespace py = pybind11; @@ -90,3 +93,5 @@ py::array_t ToNumpy(Omega_h::Read arr) } } // namespace pcms + +#endif // PCMS_PYTHONAPI_NUMPY_ARRAY_TRANSFORM_HPP diff --git a/src/pcms/pythonapi/numpy_view.h b/src/pcms/pythonapi/numpy_view.hpp similarity index 98% rename from src/pcms/pythonapi/numpy_view.h rename to src/pcms/pythonapi/numpy_view.hpp index 760188112..b3f53f15b 100644 --- a/src/pcms/pythonapi/numpy_view.h +++ b/src/pcms/pythonapi/numpy_view.hpp @@ -1,5 +1,5 @@ -#ifndef PCMS_PYTHONAPI_NUMPY_VIEW_H -#define PCMS_PYTHONAPI_NUMPY_VIEW_H +#ifndef PCMS_PYTHONAPI_NUMPY_VIEW_HPP +#define PCMS_PYTHONAPI_NUMPY_VIEW_HPP // Conversions between numpy arrays and pcms mdspan views / Kokkos views. // @@ -38,9 +38,9 @@ #include #include -#include "pcms/utility/arrays.h" -#include "pcms/utility/memory_spaces.h" -#include "pcms/utility/types.h" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/memory_spaces.hpp" +#include "pcms/utility/types.hpp" namespace pcms { @@ -324,4 +324,4 @@ py::array_t> ViewToNumpy( } // namespace pcms -#endif // PCMS_PYTHONAPI_NUMPY_VIEW_H +#endif // PCMS_PYTHONAPI_NUMPY_VIEW_HPP diff --git a/src/pcms/pythonapi/py_value_types.h b/src/pcms/pythonapi/py_value_types.hpp similarity index 91% rename from src/pcms/pythonapi/py_value_types.h rename to src/pcms/pythonapi/py_value_types.hpp index 002cbf828..8eff5095c 100644 --- a/src/pcms/pythonapi/py_value_types.h +++ b/src/pcms/pythonapi/py_value_types.hpp @@ -1,5 +1,5 @@ -#ifndef PCMS_PYTHONAPI_PY_VALUE_TYPES_H -#define PCMS_PYTHONAPI_PY_VALUE_TYPES_H +#ifndef PCMS_PYTHONAPI_PY_VALUE_TYPES_HPP +#define PCMS_PYTHONAPI_PY_VALUE_TYPES_HPP // Python-side counterparts of the non-owning C++ view types. A C++ // CoordinateView or ValueView borrows its memory, so the Python objects pair @@ -14,15 +14,15 @@ #include #include -#include "numpy_view.h" -#include "pcms/configuration.h" -#include "pcms/field/coordinate_system.hpp" -#include "pcms/field/coordinate_systems/cartesian.hpp" -#include "pcms/field/coordinate_view.hpp" +#include "pcms/pythonapi/numpy_view.hpp" +#include "pcms/configuration.hpp" +#include "pcms/utility/coordinate_system.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_view.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/utility/arrays.h" -#include "pcms/utility/memory_spaces.h" -#include "pcms/utility/types.h" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/memory_spaces.hpp" +#include "pcms/utility/types.hpp" namespace pcms { @@ -153,4 +153,4 @@ inline void RequireScalarForPlainArray(const char* context, } // namespace pcms -#endif // PCMS_PYTHONAPI_PY_VALUE_TYPES_H +#endif // PCMS_PYTHONAPI_PY_VALUE_TYPES_HPP diff --git a/src/pcms/pythonapi/pythonapi.cpp b/src/pcms/pythonapi/pythonapi.cpp index 125f39823..b08e5ee40 100644 --- a/src/pcms/pythonapi/pythonapi.cpp +++ b/src/pcms/pythonapi/pythonapi.cpp @@ -1,6 +1,6 @@ #include -#include "pcms/configuration.h" -#include "numpy_view.h" +#include "pcms/configuration.hpp" +#include "pcms/pythonapi/numpy_view.hpp" #include namespace py = pybind11; diff --git a/src/pcms/pythonapi/uniform_grid_workflow_guide.md b/src/pcms/pythonapi/uniform_grid_workflow_guide.md index aca7bc2a1..a8fdc918c 100644 --- a/src/pcms/pythonapi/uniform_grid_workflow_guide.md +++ b/src/pcms/pythonapi/uniform_grid_workflow_guide.md @@ -102,7 +102,7 @@ Generate a structured uniform grid that covers the bounding box of the mesh. ```python # Create uniform grid with 4x4 cell divisions -grid = pcms.create_uniform_grid_from_mesh(mesh, [4, 4]) +grid = pcms.backend.omega_h.create_uniform_grid_from_mesh(mesh, [4, 4]) print(f"Created uniform grid with {grid.get_num_cells()} cells") ``` @@ -114,7 +114,7 @@ Create a mask where each uniform grid vertex is marked as 1 (inside mesh) or 0 ( ```python # Create binary mask indicating which vertices are inside the mesh -mask_field = pcms.create_uniform_grid_binary_field(mesh, [4, 4]) +mask_field = pcms.backend.omega_h.create_uniform_grid_binary_field(mesh, [4, 4]) print(f"Created mask field with {mask_field.get_layout().get_num_owned_dof_holder()} vertices") ``` @@ -135,11 +135,10 @@ mask_value = mask_data[vertex_id, 0] # Returns 0.0 or 1.0 ```python # Create a concrete FunctionSpace with linear (order=1) elements and # 1 component (scalar) -omega_h_factory = pcms.LagrangeFunctionSpace.from_mesh( - mesh, +omega_h_factory = pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(mesh), 1, - 1, -) + 1) omega_h_field = omega_h_factory.create_function() # Initialize field with f(x,y) = x + 2*y @@ -168,11 +167,13 @@ face_tag = mesh.get_tag(face_dim, tag_index) # Get tag by index face_field = mesh.get_tag(face_dim, face_tag.name()) # Convert element field to vertex field using averaging -vertex_field = pcms.map_entity_field_to_vertices_average(mesh, face_field, face_dim) +vertex_field = pcms.backend.omega_h.map_entity_field_to_vertices_average(mesh, face_field, face_dim) # Create vertex-based field and set data -omega_h_factory = pcms.LagrangeFunctionSpace.from_mesh( - mesh, 1, 1) +omega_h_factory = pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(mesh), + 1, + 1) omega_h_field = omega_h_factory.create_function() omega_h_field.set_dof_holder_data(vertex_field) @@ -186,8 +187,9 @@ Set up the data structure for storing field values on the uniform grid vertices. ```python # Create a uniform-grid FunctionSpace -ug_factory = pcms.LagrangeFunctionSpace.from_uniform_grid( - grid, +ug_factory = pcms.create_lagrange_space( + pcms.create_uniform_grid_discretization(grid), + 1, # order 1, # Number of components ) ug_field = ug_factory.create_function() @@ -242,8 +244,8 @@ np.save('field_data.npy', grid_values) ## API Reference Summary ### Grid Creation -- `create_uniform_grid_from_mesh(mesh, divisions)` - Create grid from mesh -- `create_uniform_grid_binary_field(mesh, divisions)` - Create inside/outside mask +- `backend.omega_h.create_uniform_grid_from_mesh(mesh, divisions)` - Create grid from mesh +- `backend.omega_h.create_uniform_grid_binary_field(mesh, divisions)` - Create inside/outside mask The Python names mirror the C++ API: classes keep their C++ names, C++ namespaces are submodules (`pcms.csys`, `pcms.values`), and methods are the @@ -262,9 +264,10 @@ snake_case form of the C++ method (`GetDOFHolderData` is ### Field Factories - `FunctionSpace` - abstract base class for field spaces; a `PointEvaluatorFactory` -- `LagrangeFunctionSpace.from_mesh(mesh, order, num_components, mesh_coordinate_system)` - create an Omega_h-backed FunctionSpace -- `LagrangeFunctionSpace.from_uniform_grid(grid, num_components, mesh_coordinate_system, order=1)` - create a uniform-grid-backed FunctionSpace -- `PolynomialReconstructionFunctionSpace.create(coordinate_view, options)` - MLS reconstruction over a point cloud +- `backend.omega_h.create_discretization(mesh)` - discretization on an Omega_h mesh +- `create_uniform_grid_discretization(grid)` - discretization of a uniform grid +- `create_lagrange_space(discretization, order, num_components, coordinate_system)` - Lagrange FunctionSpace on either +- `create_polynomial_reconstruction_space(coordinate_view, options)` - MLS reconstruction over a point cloud ### Field Operations - `space.create_function(name="", variance=values.Scalar, system=None, scaling=None)` - Create a real-valued `Function`; vector and tensor values are in `system`'s basis (default: the space's) @@ -283,7 +286,9 @@ snake_case form of the C++ method (`GetDOFHolderData` is - `Interpolator(source, target_space)` - Create an interpolator from a `PointEvaluatorFactory` (cached localization) - `operator.apply(source_field, target_field)` - Apply any `TransferOperator` (`Interpolator`, `Copy`, projections) - `Copy(source_space, target_space)` - Create a copy operator for compatible FunctionSpaces -- `map_entity_field_to_vertices_average(mesh, field_data, entity_dim)` - Convert element/face field to vertex field by averaging +- `backend.omega_h.map_entity_field_to_vertices_average(mesh, field_data, entity_dim)` - Convert element/face field to vertex field by averaging +- `backend.omega_h.map_entity_field_to_vertices_mls(mesh, field_data, entity_dim, interp_degree=1)` - The same with moving least squares +- `backend.omega_h.compute_entity_centroids(mesh, entity_dim)` - Centroids of the faces/elements, shape `(n_entities, dim)` ### Coordinate Transformations - `CartesianToCylindrical()`, `CylindricalToCartesian()` - `CoordinateMap`s; points map source to target, values are re-expressed the other way diff --git a/src/pcms/transfer/CMakeLists.txt b/src/pcms/transfer/CMakeLists.txt index ad62383bd..a44354814 100644 --- a/src/pcms/transfer/CMakeLists.txt +++ b/src/pcms/transfer/CMakeLists.txt @@ -1,20 +1,20 @@ set(PCMS_FIELD_TRANSFER_HEADERS - linear_interpolant.hpp - multidimarray.hpp - interpolation_base.h - interpolation_helpers.h + interpolation_base.hpp + interpolation_helpers.hpp mesh_intersection.hpp - interpolator.h - copy.h - transfer_operator.hpp - mass_matrix_type.hpp - monte_carlo_sampling.hpp + ../../../include/pcms/transfer/interpolator.hpp + ../../../include/pcms/transfer/copy.hpp + ../../../include/pcms/transfer/transfer_operator.hpp + ../../../include/pcms/transfer/mass_matrix_type.hpp + ../../../include/pcms/transfer/monte_carlo_sampling.hpp + ../../../include/pcms/transfer/projection.hpp ) set(PCMS_FIELD_TRANSFER_SOURCES mesh_intersection.cpp - interpolation_base.cpp) + interpolation_base.cpp + projection.cpp) if(PCMS_ENABLE_MESHFIELDS) @@ -50,17 +50,21 @@ add_library(pcms_transfer ${PCMS_FIELD_TRANSFER_SOURCES}) set_target_properties(pcms_transfer PROPERTIES OUTPUT_NAME pcmstransfer EXPORT_NAME transfer) -target_sources(pcms_transfer PUBLIC - FILE_SET transfer - TYPE HEADERS - BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/.. - FILES ${PCMS_FIELD_TRANSFER_HEADERS}) +# Only the public headers (include/pcms/...) are installed; the private +# headers next to the sources are private sources of the target. +set(PCMS_FIELD_TRANSFER_HEADERS_PUBLIC ${PCMS_FIELD_TRANSFER_HEADERS}) +list(FILTER PCMS_FIELD_TRANSFER_HEADERS_PUBLIC INCLUDE REGEX "/include/pcms/") +set(PCMS_FIELD_TRANSFER_HEADERS_PRIVATE ${PCMS_FIELD_TRANSFER_HEADERS}) +list(FILTER PCMS_FIELD_TRANSFER_HEADERS_PRIVATE EXCLUDE REGEX "/include/pcms/") +target_sources(pcms_transfer + PUBLIC FILE_SET transfer TYPE HEADERS BASE_DIRS ${PROJECT_SOURCE_DIR}/include/pcms + FILES ${PCMS_FIELD_TRANSFER_HEADERS_PUBLIC} + PRIVATE ${PCMS_FIELD_TRANSFER_HEADERS_PRIVATE}) add_library(pcms::transfer ALIAS pcms_transfer) target_compile_features(pcms_transfer PUBLIC cxx_std_20) target_link_libraries(pcms_transfer PUBLIC - pcms::core pcms::field pcms::localization Omega_h::omega_h) @@ -73,7 +77,7 @@ if(PCMS_ENABLE_PETSC AND PCMS_ENABLE_MESHFIELDS) target_link_libraries(pcms_transfer PRIVATE PETSc::PETSc) endif() -target_compile_definitions(pcms_transfer PUBLIC R3D_USE_KOKKOS) +target_compile_definitions(pcms_transfer PRIVATE R3D_USE_KOKKOS) target_include_directories(pcms_transfer INTERFACE $ @@ -90,4 +94,4 @@ install( install( EXPORT pcms_transfer-targets NAMESPACE pcms:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pcms) + DESTINATION ${PCMS_INSTALL_CMAKEDIR}) diff --git a/src/pcms/transfer/bilinear_form_integrator.hpp b/src/pcms/transfer/bilinear_form_integrator.hpp index df8ace693..2f6d0c701 100644 --- a/src/pcms/transfer/bilinear_form_integrator.hpp +++ b/src/pcms/transfer/bilinear_form_integrator.hpp @@ -1,9 +1,9 @@ -#ifndef PCMS_TRANSFER_BILINEAR_FORM_INTEGRATOR_H -#define PCMS_TRANSFER_BILINEAR_FORM_INTEGRATOR_H +#ifndef PCMS_TRANSFER_BILINEAR_FORM_INTEGRATOR_HPP +#define PCMS_TRANSFER_BILINEAR_FORM_INTEGRATOR_HPP #include -namespace pcms +namespace pcms::transfer { class BilinearFormIntegrator @@ -21,6 +21,6 @@ class BilinearFormIntegrator virtual ~BilinearFormIntegrator() noexcept = default; }; -} // namespace pcms +} // namespace pcms::transfer -#endif // PCMS_TRANSFER_BILINEAR_FORM_INTEGRATOR_H +#endif // PCMS_TRANSFER_BILINEAR_FORM_INTEGRATOR_HPP diff --git a/src/pcms/transfer/conservative_projection_solver.cpp b/src/pcms/transfer/conservative_projection_solver.cpp index 11a47d7e7..bf763dfdf 100644 --- a/src/pcms/transfer/conservative_projection_solver.cpp +++ b/src/pcms/transfer/conservative_projection_solver.cpp @@ -1,12 +1,12 @@ #include -#include "pcms/configuration.h" +#include "pcms/configuration.hpp" #include "pcms/transfer/conservative_projection_solver.hpp" -#include "pcms/utility/arrays.h" +#include "pcms/utility/arrays.hpp" #include "pcms/transfer/petsc_utils.hpp" #include -namespace pcms +namespace pcms::transfer { static Omega_h::Reals vecToOmegaHReals(Vec vec) @@ -114,4 +114,4 @@ Omega_h::Reals GalerkinProjectionSolver::Solve( return result; } -} // namespace pcms +} // namespace pcms::transfer diff --git a/src/pcms/transfer/conservative_projection_solver.hpp b/src/pcms/transfer/conservative_projection_solver.hpp index f0f2df0ea..77e73ee5c 100644 --- a/src/pcms/transfer/conservative_projection_solver.hpp +++ b/src/pcms/transfer/conservative_projection_solver.hpp @@ -5,13 +5,13 @@ #include #include -#include -#include +#include +#include #include #include -#include +#include -namespace pcms +namespace pcms::transfer { // Cached Galerkin projection solver for M*x = f. @@ -67,6 +67,6 @@ class GalerkinProjectionSolver mutable Kokkos::View sampled_values_; }; -} // namespace pcms +} // namespace pcms::transfer #endif // PCMS_TRANSFER_CONSERVATIVE_PROJECTION_SOLVER_HPP diff --git a/src/pcms/transfer/coo_assembly_utils.cpp b/src/pcms/transfer/coo_assembly_utils.cpp index 601889bce..c4c11c442 100644 --- a/src/pcms/transfer/coo_assembly_utils.cpp +++ b/src/pcms/transfer/coo_assembly_utils.cpp @@ -1,6 +1,6 @@ #include "pcms/transfer/coo_assembly_utils.hpp" -namespace pcms +namespace pcms::transfer { namespace { @@ -90,4 +90,4 @@ PetscErrorCode build_linear_triangle_coo_rows_cols(Omega_h::Mesh& mesh, PetscFunctionReturn(PETSC_SUCCESS); } -} // namespace pcms +} // namespace pcms::transfer diff --git a/src/pcms/transfer/coo_assembly_utils.hpp b/src/pcms/transfer/coo_assembly_utils.hpp index 2df62fe59..8921b45e9 100644 --- a/src/pcms/transfer/coo_assembly_utils.hpp +++ b/src/pcms/transfer/coo_assembly_utils.hpp @@ -4,7 +4,7 @@ #include #include -namespace pcms +namespace pcms::transfer { // Builds COO row indices for linear triangles (3 vertices per element). @@ -23,6 +23,6 @@ PetscErrorCode build_linear_triangle_coo_rows_cols(Omega_h::Mesh& mesh, PetscInt** cols_out, PetscInt* nnz_out); -} // namespace pcms +} // namespace pcms::transfer #endif // PCMS_TRANSFER_COO_ASSEMBLY_UTILS_HPP diff --git a/src/pcms/transfer/interpolation_base.cpp b/src/pcms/transfer/interpolation_base.cpp index 836b3752b..68d1d1482 100644 --- a/src/pcms/transfer/interpolation_base.cpp +++ b/src/pcms/transfer/interpolation_base.cpp @@ -2,11 +2,11 @@ // Created by hasanm4 on 1/17/25. // -#include "interpolation_base.h" -#include "interpolation_helpers.h" -#include "pcms/utility/mesh_geometry.h" +#include "pcms/transfer/interpolation_base.hpp" +#include "pcms/transfer/interpolation_helpers.hpp" +#include "pcms/utility/mesh_geometry.hpp" -namespace pcms +namespace pcms::transfer { MLSMeshInterpolation::MLSMeshInterpolation(Omega_h::Mesh& source_mesh, @@ -29,7 +29,8 @@ MLSMeshInterpolation::MLSMeshInterpolation(Omega_h::Mesh& source_mesh, OMEGA_H_CHECK_PRINTF(source_mesh_.dim() == 2, "Only 2D meshes are supported but found %d\n", source_mesh_.dim()); - source_coords_ = pcms::get_entity_centroids(source_mesh_, Omega_h::FACE); + source_coords_ = + pcms::utility::get_entity_centroids(source_mesh_, Omega_h::FACE); source_field_ = Omega_h::HostWrite(source_mesh_.nfaces(), "source field"); @@ -135,8 +136,8 @@ struct FillSupportIdxFunctor for (int source_id = 0; source_id < n_sources; source_id++) { auto source_coord = load_point(source_coords_l, source_id, dim); - auto dist2 = - pcms::distance_squared(&source_coord[0], &target_coord[0], dim); + auto dist2 = pcms::utility::distance_squared(&source_coord[0], + &target_coord[0], dim); if (dist2 <= target_radius2) { supports_idx_l[start_ptr] = source_id; start_ptr++; @@ -216,8 +217,8 @@ struct NSquareSearchFunctor // TODO: parallel with kokkos parallel_for for (int i = 0; i < n_sources; i++) { auto source_coord = load_point(source_coords_l, i, dim); - auto dist2 = - pcms::distance_squared(&source_coord[0], &target_coord[0], dim); + auto dist2 = pcms::utility::distance_squared(&source_coord[0], + &target_coord[0], dim); if (dist2 <= target_radius2) { num_supports_l[target_id]++; // only one thread is updating } @@ -298,9 +299,9 @@ void MLSPointCloudInterpolation::find_supports(unsigned min_req_supports, unsigned max_supports_found = 0; // radius adjustment loop int loop_count = 0; - while (!within_number_of_support_range(min_supports_found, max_supports_found, - min_req_supports, - max_allowed_supports)) { + while (!pcms::localization::within_number_of_support_range( + min_supports_found, max_supports_found, min_req_supports, + max_allowed_supports)) { distance_based_pointcloud_search(radii2_l, num_supports); loop_count++; @@ -319,19 +320,20 @@ void MLSPointCloudInterpolation::find_supports(unsigned min_req_supports, } // find minimum and maximum number of supports found - minmax(num_supports, min_supports_found, max_supports_found); + pcms::localization::minmax(num_supports, min_supports_found, + max_supports_found); // increase radius if not enough supports or too many supports - if (!within_number_of_support_range(min_supports_found, max_supports_found, - min_req_supports, - max_allowed_supports)) { + if (!pcms::localization::within_number_of_support_range( + min_supports_found, max_supports_found, min_req_supports, + max_allowed_supports)) { pcms::printInfo( "Adjusting radius: Iter %d:(min: %d max: %d) Min Req: %d Max " "Allowed %d\n", loop_count, min_supports_found, max_supports_found, min_req_supports, max_allowed_supports); - adapt_radii(min_req_supports, max_allowed_supports, n_targets_, radii2_l, - num_supports); + pcms::localization::adapt_radii(min_req_supports, max_allowed_supports, + n_targets_, radii2_l, num_supports); } } pcms::printInfo("Searched %d times and supports found: min: %d max: %d\n", @@ -392,7 +394,7 @@ void MLSPointCloudInterpolation::eval( copyHostScalarArrayView2HostWrite(source_field, source_field_); // TODO: make the basis function a template or pass it as a parameter - auto target_field_write = mls_interpolation( + auto target_field_write = pcms::field::mls_interpolation( Omega_h::Reals(source_field_), source_coords_, target_coords_, supports_, dim_, degree_, pcms::RadialBasisFunction::RBF_GAUSSIAN, lambda_, 1e-6, decay_factor_); @@ -418,7 +420,7 @@ void MLSMeshInterpolation::eval( copyHostScalarArrayView2HostWrite(source_field, source_field_); // TODO: make the basis function a template or pass it as a parameter - auto target_field_write = mls_interpolation( + auto target_field_write = pcms::field::mls_interpolation( Omega_h::Reals(source_field_), source_coords_, target_coords_, supports_, source_mesh_.dim(), degree_, pcms::RadialBasisFunction::RBF_GAUSSIAN, lambda_, 1e-6, decay_factor_); @@ -431,12 +433,12 @@ void MLSMeshInterpolation::find_supports(const unsigned min_req_supports, const unsigned max_allowed_supports) { if (single_mesh_) { - supports_ = - searchNeighbors(source_mesh_, radius_, min_req_supports, adapt_radius_); + supports_ = pcms::backend::omega_h::searchNeighbors( + source_mesh_, radius_, min_req_supports, adapt_radius_); } else { // two mesh : vert to vert - supports_ = - searchNeighbors(source_mesh_, target_mesh_, radius_, min_req_supports, - max_allowed_supports, adapt_radius_); + supports_ = pcms::backend::omega_h::searchNeighbors( + source_mesh_, target_mesh_, radius_, min_req_supports, + max_allowed_supports, adapt_radius_); } #ifndef NDEBUG @@ -467,4 +469,4 @@ size_t MLSMeshInterpolation::getTargetSize() const return target_mesh_.nverts(); } } -} // namespace pcms +} // namespace pcms::transfer diff --git a/src/pcms/transfer/interpolation_base.h b/src/pcms/transfer/interpolation_base.hpp similarity index 94% rename from src/pcms/transfer/interpolation_base.h rename to src/pcms/transfer/interpolation_base.hpp index 80d946c5a..e940d44db 100644 --- a/src/pcms/transfer/interpolation_base.h +++ b/src/pcms/transfer/interpolation_base.hpp @@ -9,17 +9,17 @@ * */ -#ifndef PCMS_TRANSFER_INTERPOLATION_BASE_H -#define PCMS_TRANSFER_INTERPOLATION_BASE_H +#ifndef PCMS_TRANSFER_INTERPOLATION_BASE_HPP +#define PCMS_TRANSFER_INTERPOLATION_BASE_HPP #include "pcms/field/evaluator/mls_interpolation.hpp" -#include "pcms/localization/adj_search.hpp" -#include "interpolation_helpers.h" +#include "pcms/backends/omega_h/adj_search.hpp" +#include "pcms/transfer/interpolation_helpers.hpp" #include -#include "pcms/utility/arrays.h" +#include "pcms/utility/arrays.hpp" #include -namespace pcms +namespace pcms::transfer { /** * @brief Pure virtual base class for interpolation methods @@ -144,7 +144,7 @@ class MLSPointCloudInterpolation final : public InterpolationBase pcms::Rank1View source_field, pcms::Rank1View target_field) override; - SupportResults getSupports() { return supports_; } + pcms::localization::SupportResults getSupports() { return supports_; } size_t getSourceSize() const override { return source_coords_.size() / dim_; } size_t getTargetSize() const override { return target_coords_.size() / dim_; } @@ -166,7 +166,8 @@ class MLSPointCloudInterpolation final : public InterpolationBase Omega_h::Reals source_coords_; /*!< Source point coordinates */ Omega_h::Reals target_coords_; /*!< Target point coordinates */ - SupportResults supports_; /*!< Support structure for MLS interpolation */ + pcms::localization::SupportResults + supports_; /*!< Support structure for MLS interpolation */ Omega_h::HostWrite target_field_; /*!< Target field storage */ Omega_h::HostWrite source_field_; /*!< Provided source field */ @@ -258,7 +259,7 @@ class MLSMeshInterpolation final : public InterpolationBase size_t getSourceSize() const override; size_t getTargetSize() const override; - SupportResults getSupports() { return supports_; } + pcms::localization::SupportResults getSupports() { return supports_; } private: double radius_; /*!< Cutoff radius for the MLS interpolation */ @@ -280,7 +281,8 @@ class MLSMeshInterpolation final : public InterpolationBase Omega_h::Reals source_coords_; /*!< Source point coordinates */ Omega_h::Reals target_coords_; /*!< Target point coordinates */ - SupportResults supports_; /*!< Support structure for MLS interpolation */ + pcms::localization::SupportResults + supports_; /*!< Support structure for MLS interpolation */ Omega_h::HostWrite target_field_; /*!< Target field storage */ Omega_h::HostWrite source_field_; /*!< Provided source field */ @@ -295,6 +297,6 @@ class MLSMeshInterpolation final : public InterpolationBase void find_supports(unsigned min_req_supports = 10, unsigned max_allowed_supports = 30); }; -} // namespace pcms +} // namespace pcms::transfer -#endif // PCMS_TRANSFER_INTERPOLATION_BASE_H +#endif // PCMS_TRANSFER_INTERPOLATION_BASE_HPP diff --git a/src/pcms/transfer/interpolation_helpers.h b/src/pcms/transfer/interpolation_helpers.hpp similarity index 60% rename from src/pcms/transfer/interpolation_helpers.h rename to src/pcms/transfer/interpolation_helpers.hpp index 2502bd1bf..b72aeb0b8 100644 --- a/src/pcms/transfer/interpolation_helpers.h +++ b/src/pcms/transfer/interpolation_helpers.hpp @@ -1,12 +1,12 @@ -#ifndef PCMS_TRANSFER_INTERPOLATION_HELPERS_H -#define PCMS_TRANSFER_INTERPOLATION_HELPERS_H +#ifndef PCMS_TRANSFER_INTERPOLATION_HELPERS_HPP +#define PCMS_TRANSFER_INTERPOLATION_HELPERS_HPP -#include "pcms/utility/arrays.h" -#include "pcms/utility/memory_spaces.h" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/memory_spaces.hpp" #include #include -namespace pcms +namespace pcms::transfer { // FIXME, evaluate if this is needed. If so, move to utility library @@ -18,5 +18,5 @@ void copyHostWrite2ScalarArrayView( const Omega_h::HostWrite& source, pcms::Rank1View target); -} // namespace pcms -#endif // PCMS_TRANSFER_INTERPOLATION_HELPERS_H +} // namespace pcms::transfer +#endif // PCMS_TRANSFER_INTERPOLATION_HELPERS_HPP diff --git a/src/pcms/transfer/linear_form_integrator.hpp b/src/pcms/transfer/linear_form_integrator.hpp index 05bacbb0e..897461c8d 100644 --- a/src/pcms/transfer/linear_form_integrator.hpp +++ b/src/pcms/transfer/linear_form_integrator.hpp @@ -1,11 +1,11 @@ -#ifndef PCMS_TRANSFER_LINEAR_FORM_INTEGRATOR_H -#define PCMS_TRANSFER_LINEAR_FORM_INTEGRATOR_H +#ifndef PCMS_TRANSFER_LINEAR_FORM_INTEGRATOR_HPP +#define PCMS_TRANSFER_LINEAR_FORM_INTEGRATOR_HPP -#include "pcms/field/coordinate_view.hpp" -#include "pcms/utility/arrays.h" +#include "pcms/utility/coordinate_view.hpp" +#include "pcms/utility/arrays.hpp" #include -namespace pcms +namespace pcms::transfer { class LinearFormIntegrator @@ -29,6 +29,6 @@ class LinearFormIntegrator virtual ~LinearFormIntegrator() noexcept = default; }; -} // namespace pcms +} // namespace pcms::transfer -#endif // PCMS_TRANSFER_LINEAR_FORM_INTEGRATOR_H +#endif // PCMS_TRANSFER_LINEAR_FORM_INTEGRATOR_HPP diff --git a/src/pcms/transfer/mass_matrix_integrator.hpp b/src/pcms/transfer/mass_matrix_integrator.hpp index 472a540fc..00b04df64 100644 --- a/src/pcms/transfer/mass_matrix_integrator.hpp +++ b/src/pcms/transfer/mass_matrix_integrator.hpp @@ -11,7 +11,7 @@ #include #include -namespace pcms +namespace pcms::transfer { // computes the mass matrix for each element template @@ -93,5 +93,5 @@ Kokkos::View buildElementMassMatrix(Omega_h::Mesh& mesh, mmi.process(coordFe); return mmi.elmMassMatrix; } -} // namespace pcms +} // namespace pcms::transfer #endif // PCMS_TRANSFER_MASS_MATRIX_INTEGRATOR_HPP diff --git a/src/pcms/transfer/mesh_intersection.cpp b/src/pcms/transfer/mesh_intersection.cpp index fb2ea5819..3be0331fd 100644 --- a/src/pcms/transfer/mesh_intersection.cpp +++ b/src/pcms/transfer/mesh_intersection.cpp @@ -1,9 +1,9 @@ #include "pcms/transfer/mesh_intersection.hpp" -#include "pcms/utility/assert.h" -#include "pcms/utility/mesh_geometry.h" -#include "pcms/utility/omega_h_array_utils.h" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/mesh_geometry.hpp" +#include "pcms/utility/omega_h_array_utils.hpp" -namespace pcms +namespace pcms::transfer { namespace { @@ -14,9 +14,9 @@ auto MakeGridPointSearch(Omega_h::Mesh& source_mesh) { const auto n = pcms::DivisionsPerAxisForMesh(source_mesh.nelems()); if constexpr (Dim == 3) { - return pcms::GridPointSearch3D(source_mesh, n, n, n); + return pcms::localization::GridPointSearch3D(source_mesh, n, n, n); } else { - return pcms::GridPointSearch2D(source_mesh, n, n); + return pcms::localization::GridPointSearch2D(source_mesh, n, n); } } @@ -24,11 +24,14 @@ auto MakeGridPointSearch(Omega_h::Mesh& source_mesh) // the BFS over the source dual graph starts. template Kokkos::View LocateTargetCentroids( - Omega_h::Mesh& target_mesh, const PointLocalizationSearch& source_search) + Omega_h::Mesh& target_mesh, + const pcms::localization::PointLocalizationSearch& source_search) { - const auto flat_centroids = pcms::get_entity_centroids(target_mesh, Dim); + const auto flat_centroids = + pcms::utility::get_entity_centroids(target_mesh, Dim); // Convert layout_right 1D Omega_h array to 2D Kokkos view with correct layout - auto centroids = ConvertCoordsTo2D(flat_centroids, target_mesh.nelems(), Dim); + auto centroids = + pcms::utility::ConvertCoordsTo2D(flat_centroids, target_mesh.nelems(), Dim); auto results = source_search(centroids); return source_search.GetOwningElementIds(results); } @@ -61,8 +64,8 @@ void FindIntersections::adjBasedIntersectSearch( Omega_h::parallel_for( nelems_target, OMEGA_H_LAMBDA(const Omega_h::LO id) { - Queue queue; - Track visited; + pcms::backend::omega_h::Queue queue; + pcms::backend::omega_h::Track visited; auto current_cell_id = start_elements(id); auto current_tgt_elm_measure = tgt_elem_measures[id]; @@ -185,7 +188,8 @@ namespace template IntersectionResults intersectTargetsImpl( Omega_h::Mesh& source_mesh, Omega_h::Mesh& target_mesh, - const PointLocalizationSearch& source_search, bool use_prefilter) + const pcms::localization::PointLocalizationSearch& source_search, + bool use_prefilter) { FindIntersections intersect(source_mesh, target_mesh); @@ -222,11 +226,12 @@ IntersectionResults intersectTargetsImpl( } template -const PointLocalizationSearch& RequireSearchDimension( - const GridPointSearchVariant& source_search) +const pcms::localization::PointLocalizationSearch& RequireSearchDimension( + const pcms::localization::GridPointSearchVariant& source_search) { using SearchT = - std::conditional_t; + std::conditional_t; const auto* search = std::get_if(&source_search); if (search == nullptr) { throw pcms_error("intersectTargets: the supplied source search has a " @@ -253,7 +258,8 @@ IntersectionResults intersectTargets(Omega_h::Mesh& source_mesh, IntersectionResults intersectTargets( Omega_h::Mesh& source_mesh, Omega_h::Mesh& target_mesh, - const GridPointSearchVariant& source_search, bool use_prefilter) + const pcms::localization::GridPointSearchVariant& source_search, + bool use_prefilter) { OMEGA_H_CHECK(source_mesh.dim() == target_mesh.dim()); if (source_mesh.dim() == 3) { @@ -265,4 +271,4 @@ IntersectionResults intersectTargets( RequireSearchDimension<2>(source_search), use_prefilter); } -} // namespace pcms +} // namespace pcms::transfer diff --git a/src/pcms/transfer/mesh_intersection.hpp b/src/pcms/transfer/mesh_intersection.hpp index 9d5ead08d..46cd5777b 100644 --- a/src/pcms/transfer/mesh_intersection.hpp +++ b/src/pcms/transfer/mesh_intersection.hpp @@ -1,17 +1,23 @@ #ifndef PCMS_TRANSFER_MESH_INTERSECTION_HPP #define PCMS_TRANSFER_MESH_INTERSECTION_HPP -#include -#include -#include +#include +#include +#include #include #include +// r3d's kernels are called from Kokkos kernels: R3D_USE_KOKKOS makes them +// KOKKOS_INLINE_FUNCTION. Defined here instead of as a public compile +// definition of pcms::transfer; this is the only header that includes r3d. +#ifndef R3D_USE_KOKKOS +#define R3D_USE_KOKKOS +#endif #include #include #include #include -namespace pcms +namespace pcms::transfer { // Gather the vertex coordinates of a simplex element (triangle for Dim==2, // tetrahedron for Dim==3) into an r3d simplex, ready for @@ -201,6 +207,7 @@ IntersectionResults intersectTargets(Omega_h::Mesh& source_mesh, */ IntersectionResults intersectTargets( Omega_h::Mesh& source_mesh, Omega_h::Mesh& target_mesh, - const GridPointSearchVariant& source_search, bool use_prefilter = true); -} // namespace pcms + const pcms::localization::GridPointSearchVariant& source_search, + bool use_prefilter = true); +} // namespace pcms::transfer #endif // PCMS_TRANSFER_MESH_INTERSECTION_HPP diff --git a/src/pcms/transfer/omega_h_conservative_projection.cpp b/src/pcms/transfer/omega_h_conservative_projection.cpp index 45a0c1b64..f0e21fd34 100644 --- a/src/pcms/transfer/omega_h_conservative_projection.cpp +++ b/src/pcms/transfer/omega_h_conservative_projection.cpp @@ -2,19 +2,20 @@ #include "pcms/transfer/conservative_projection_solver.hpp" #include "pcms/transfer/omega_h_intersection_rhs_integrator.hpp" #include "pcms/transfer/omega_h_mass_integrator.hpp" -#include "pcms/utility/arrays.h" +#include "pcms/utility/arrays.hpp" #include #include -namespace pcms +namespace pcms::transfer { namespace { -void CheckApplyCompatible(const Field& source, const Field& target, - const OmegaHLagrangeLayout& source_layout, - const OmegaHLagrangeLayout& target_layout) +void CheckApplyCompatible( + const Field& source, const Field& target, + const pcms::backend::omega_h::OmegaHLagrangeLayout& source_layout, + const pcms::backend::omega_h::OmegaHLagrangeLayout& target_layout) { if (&source.GetLayout() != &source_layout) { throw pcms_error( @@ -37,9 +38,11 @@ void CheckApplyCompatible(const Field& source, const Field& target, OmegaHConservativeProjection::OmegaHConservativeProjection( const FunctionSpace& source_space, const FunctionSpace& target_space, MassMatrixType mass_matrix_type) - : source_layout_(std::dynamic_pointer_cast( + : source_layout_(std::dynamic_pointer_cast< + const pcms::backend::omega_h::OmegaHLagrangeLayout>( source_space.GetLayout())), - target_layout_(std::dynamic_pointer_cast( + target_layout_(std::dynamic_pointer_cast< + const pcms::backend::omega_h::OmegaHLagrangeLayout>( target_space.GetLayout())) { // The space-based constructor lets the integrator reuse the source space's @@ -95,4 +98,4 @@ void OmegaHConservativeProjection::Apply(const Field& source, target.SetDOFHolderDataUnchecked(MakeConstRank2View(target_values_)); } -} // namespace pcms +} // namespace pcms::transfer diff --git a/src/pcms/transfer/omega_h_conservative_projection.hpp b/src/pcms/transfer/omega_h_conservative_projection.hpp index 2b2abf3d4..7ec8dd80a 100644 --- a/src/pcms/transfer/omega_h_conservative_projection.hpp +++ b/src/pcms/transfer/omega_h_conservative_projection.hpp @@ -1,15 +1,15 @@ -#ifndef PCMS_TRANSFER_OMEGA_H_CONSERVATIVE_PROJECTION_H -#define PCMS_TRANSFER_OMEGA_H_CONSERVATIVE_PROJECTION_H +#ifndef PCMS_TRANSFER_OMEGA_H_CONSERVATIVE_PROJECTION_HPP +#define PCMS_TRANSFER_OMEGA_H_CONSERVATIVE_PROJECTION_HPP -#include "pcms/field/function_space.h" -#include "pcms/field/layout/omega_h_lagrange.h" -#include "pcms/field/point_evaluator.h" +#include "pcms/field/function_space.hpp" +#include "pcms/backends/omega_h/lagrange_layout.hpp" +#include "pcms/field/point_evaluator.hpp" #include "pcms/transfer/mass_matrix_type.hpp" #include "pcms/transfer/transfer_operator.hpp" #include #include -namespace pcms +namespace pcms::transfer { class GalerkinProjectionSolver; @@ -45,14 +45,16 @@ class OmegaHConservativeProjection : public TransferOperator void Apply(const Field& source, Field& target) const override; private: - std::shared_ptr source_layout_; - std::shared_ptr target_layout_; + std::shared_ptr + source_layout_; + std::shared_ptr + target_layout_; std::unique_ptr rhs_integrator_; std::unique_ptr> evaluator_; std::unique_ptr solver_; mutable Kokkos::View target_values_; }; -} // namespace pcms +} // namespace pcms::transfer -#endif // PCMS_TRANSFER_OMEGA_H_CONSERVATIVE_PROJECTION_H +#endif // PCMS_TRANSFER_OMEGA_H_CONSERVATIVE_PROJECTION_HPP diff --git a/src/pcms/transfer/omega_h_control_variate_projection.cpp b/src/pcms/transfer/omega_h_control_variate_projection.cpp index d8c4e1aa1..f954c89d3 100644 --- a/src/pcms/transfer/omega_h_control_variate_projection.cpp +++ b/src/pcms/transfer/omega_h_control_variate_projection.cpp @@ -2,18 +2,19 @@ #include "pcms/transfer/conservative_projection_solver.hpp" #include "pcms/transfer/omega_h_mass_integrator.hpp" #include "pcms/transfer/omega_h_mc_rhs_integrator.hpp" -#include "pcms/utility/arrays.h" +#include "pcms/utility/arrays.hpp" #include #include -namespace pcms +namespace pcms::transfer { OmegaHControlVariateProjection::OmegaHControlVariateProjection( const PointEvaluatorFactory& source, const FunctionSpace& target_space, int samples_per_element, MonteCarloSampling sampling, uint64_t seed, MassMatrixType mass_matrix_type) - : target_layout_(std::dynamic_pointer_cast( + : target_layout_(std::dynamic_pointer_cast< + const pcms::backend::omega_h::OmegaHLagrangeLayout>( target_space.GetLayout())), rhs_integrator_(std::make_unique( target_layout_, target_space.GetCoordinateSystem(), samples_per_element, @@ -104,4 +105,4 @@ void OmegaHControlVariateProjection::Apply(const Field& source, target.SetDOFHolderDataUnchecked(MakeConstRank2View(target_values_)); } -} // namespace pcms +} // namespace pcms::transfer diff --git a/src/pcms/transfer/omega_h_control_variate_projection.hpp b/src/pcms/transfer/omega_h_control_variate_projection.hpp index 29e5c6d03..5216b6614 100644 --- a/src/pcms/transfer/omega_h_control_variate_projection.hpp +++ b/src/pcms/transfer/omega_h_control_variate_projection.hpp @@ -1,12 +1,12 @@ #ifndef PCMS_TRANSFER_OMEGA_H_CONTROL_VARIATE_PROJECTION_HPP #define PCMS_TRANSFER_OMEGA_H_CONTROL_VARIATE_PROJECTION_HPP -#include "pcms/field/field.h" -#include "pcms/field/function_space.h" -#include "pcms/field/layout/omega_h_lagrange.h" -#include "pcms/field/point_evaluator.h" +#include "pcms/field/field.hpp" +#include "pcms/field/function_space.hpp" +#include "pcms/backends/omega_h/lagrange_layout.hpp" +#include "pcms/field/point_evaluator.hpp" #include "pcms/field/point_evaluator_factory.hpp" -#include "pcms/transfer/interpolator.h" +#include "pcms/transfer/interpolator.hpp" #include "pcms/transfer/mass_matrix_type.hpp" #include "pcms/transfer/monte_carlo_sampling.hpp" #include "pcms/transfer/transfer_operator.hpp" @@ -14,7 +14,7 @@ #include #include -namespace pcms +namespace pcms::transfer { class GalerkinProjectionSolver; @@ -52,7 +52,8 @@ class OmegaHControlVariateProjection : public TransferOperator void Apply(const Field& source, Field& target) const override; private: - std::shared_ptr target_layout_; + std::shared_ptr + target_layout_; std::unique_ptr rhs_integrator_; Interpolator interpolator_; // Scratch field on the target space holding the interpolated control @@ -67,6 +68,6 @@ class OmegaHControlVariateProjection : public TransferOperator mutable Kokkos::View residual_; }; -} // namespace pcms +} // namespace pcms::transfer #endif // PCMS_TRANSFER_OMEGA_H_CONTROL_VARIATE_PROJECTION_HPP diff --git a/src/pcms/transfer/omega_h_form_integrator_utils.hpp b/src/pcms/transfer/omega_h_form_integrator_utils.hpp index 0f167bde1..199ff66b2 100644 --- a/src/pcms/transfer/omega_h_form_integrator_utils.hpp +++ b/src/pcms/transfer/omega_h_form_integrator_utils.hpp @@ -1,18 +1,18 @@ #ifndef PCMS_TRANSFER_OMEGA_H_FORM_INTEGRATOR_UTILS_HPP #define PCMS_TRANSFER_OMEGA_H_FORM_INTEGRATOR_UTILS_HPP -#include "pcms/field/function_space.h" -#include "pcms/field/layout/omega_h_lagrange.h" -#include "pcms/field/coordinate_systems/cartesian.hpp" +#include "pcms/field/function_space.hpp" +#include "pcms/backends/omega_h/lagrange_layout.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" #include "pcms/transfer/mesh_intersection.hpp" -#include "pcms/utility/assert.h" +#include "pcms/utility/assert.hpp" #include #include #include #include #include -namespace pcms::detail +namespace pcms::transfer::detail { // Shared checks for a scalar Cartesian Lagrange space on a simplex mesh @@ -20,7 +20,8 @@ namespace pcms::detail // separately by the callers below. inline void CheckOmegaHScalarSimplexLayout( std::shared_ptr coordinate_system, - const std::shared_ptr& layout, + const std::shared_ptr& + layout, const char* context, const char* role) { if (layout == nullptr) { @@ -51,7 +52,8 @@ inline void CheckOmegaHScalarSimplexLayout( // Strict order-1 check (used where only P1 is supported, e.g. Monte-Carlo RHS). inline void CheckOmegaHScalarP1Layout( std::shared_ptr coordinate_system, - const std::shared_ptr& layout, + const std::shared_ptr& + layout, const char* context, const char* role) { CheckOmegaHScalarSimplexLayout(coordinate_system, layout, context, role); @@ -66,7 +68,8 @@ inline void CheckOmegaHScalarP1Layout( // this replaces the strict P1 requirement on those paths. inline void CheckOmegaHScalarLagrangeLayout( std::shared_ptr coordinate_system, - const std::shared_ptr& layout, + const std::shared_ptr& + layout, const char* context, const char* role) { CheckOmegaHScalarSimplexLayout(coordinate_system, layout, context, role); @@ -405,6 +408,6 @@ struct TargetSimplexBasis } }; -} // namespace pcms::detail +} // namespace pcms::transfer::detail #endif // PCMS_TRANSFER_OMEGA_H_FORM_INTEGRATOR_UTILS_HPP diff --git a/src/pcms/transfer/omega_h_intersection_rhs_integrator.cpp b/src/pcms/transfer/omega_h_intersection_rhs_integrator.cpp index 974f3d0ea..20a662906 100644 --- a/src/pcms/transfer/omega_h_intersection_rhs_integrator.cpp +++ b/src/pcms/transfer/omega_h_intersection_rhs_integrator.cpp @@ -1,17 +1,17 @@ #include "pcms/transfer/omega_h_intersection_rhs_integrator.hpp" -#include "pcms/field/element_dispatch.h" -#include "pcms/field/evaluator/omega_h_lagrange.h" -#include "pcms/field/function_space/lagrange.h" +#include "pcms/field/element_dispatch.hpp" +#include "pcms/backends/omega_h/lagrange_evaluator.hpp" +#include "pcms/field/function_space/lagrange.hpp" #include "pcms/transfer/omega_h_form_integrator_utils.hpp" #include "pcms/transfer/petsc_utils.hpp" -#include "pcms/utility/assert.h" +#include "pcms/utility/assert.hpp" #include #include #include #include -#include "pcms/field/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" -namespace pcms +namespace pcms::transfer { namespace @@ -29,29 +29,36 @@ struct Data }; template -Data BuildDataImpl(const OmegaHLagrangeLayout& source_layout, - const OmegaHLagrangeLayout& target_layout, int quad_order, - const GridPointSearchVariant* source_search); +Data BuildDataImpl( + const pcms::backend::omega_h::OmegaHLagrangeLayout& source_layout, + const pcms::backend::omega_h::OmegaHLagrangeLayout& target_layout, + int quad_order, + const pcms::localization::GridPointSearchVariant* source_search); // The source space's point search, if the space is an Omega_h Lagrange space // and so owns one the intersection can reuse; null otherwise. -const GridPointSearchVariant* SourceSearchFromSpace(const FunctionSpace& space) +const pcms::localization::GridPointSearchVariant* SourceSearchFromSpace( + const FunctionSpace& space) { - const auto* lagrange = dynamic_cast(&space); + const auto* lagrange = + dynamic_cast(&space); if (lagrange == nullptr) { return nullptr; } - const auto* factory = - dynamic_cast*>( - lagrange->GetEvaluatorFactory().get()); + const auto* factory = dynamic_cast< + const pcms::backend::omega_h::OmegaHLagrangeEvaluatorFactory*>( + lagrange->GetEvaluatorFactory().get()); return factory ? &factory->GetSearch() : nullptr; } -Data BuildData(const std::shared_ptr& source_layout, - std::shared_ptr source_coordinate_system, - const std::shared_ptr& target_layout, - std::shared_ptr target_coordinate_system, - const GridPointSearchVariant* source_search) +Data BuildData( + const std::shared_ptr& + source_layout, + std::shared_ptr source_coordinate_system, + const std::shared_ptr& + target_layout, + std::shared_ptr target_coordinate_system, + const pcms::localization::GridPointSearchVariant* source_search) { detail::CheckOmegaHScalarLagrangeLayout( source_coordinate_system, source_layout, "OmegaHIntersectionRHSIntegrator", @@ -72,21 +79,24 @@ Data BuildData(const std::shared_ptr& source_layout, const int quad_order = std::max(1, source_layout->GetOrder() + target_layout->GetOrder()); - return detail::DispatchByOrder(target_layout->GetOrder(), [&](auto order_c) { - constexpr int TgtOrder = decltype(order_c)::value; - if (dim == 3) { - return BuildDataImpl<3, TgtOrder>(*source_layout, *target_layout, + return pcms::field::detail::DispatchByOrder( + target_layout->GetOrder(), [&](auto order_c) { + constexpr int TgtOrder = decltype(order_c)::value; + if (dim == 3) { + return BuildDataImpl<3, TgtOrder>(*source_layout, *target_layout, + quad_order, source_search); + } + return BuildDataImpl<2, TgtOrder>(*source_layout, *target_layout, quad_order, source_search); - } - return BuildDataImpl<2, TgtOrder>(*source_layout, *target_layout, - quad_order, source_search); - }); + }); } template -Data BuildDataImpl(const OmegaHLagrangeLayout& source_layout, - const OmegaHLagrangeLayout& target_layout, int quad_order, - const GridPointSearchVariant* source_search) +Data BuildDataImpl( + const pcms::backend::omega_h::OmegaHLagrangeLayout& source_layout, + const pcms::backend::omega_h::OmegaHLagrangeLayout& target_layout, + int quad_order, + const pcms::localization::GridPointSearchVariant* source_search) { using Basis = detail::TargetSimplexBasis; constexpr int ndof = Basis::ndof; @@ -211,19 +221,23 @@ Data BuildDataImpl(const OmegaHLagrangeLayout& source_layout, OmegaHIntersectionRHSIntegrator::OmegaHIntersectionRHSIntegrator( const FunctionSpace& source_space, const FunctionSpace& target_space) : OmegaHIntersectionRHSIntegrator( - std::dynamic_pointer_cast( + std::dynamic_pointer_cast< + const pcms::backend::omega_h::OmegaHLagrangeLayout>( source_space.GetLayout()), source_space.GetCoordinateSystem(), - std::dynamic_pointer_cast( + std::dynamic_pointer_cast< + const pcms::backend::omega_h::OmegaHLagrangeLayout>( target_space.GetLayout()), target_space.GetCoordinateSystem(), SourceSearchFromSpace(source_space)) { } OmegaHIntersectionRHSIntegrator::OmegaHIntersectionRHSIntegrator( - std::shared_ptr source_layout, + std::shared_ptr + source_layout, std::shared_ptr source_coordinate_system, - std::shared_ptr target_layout, + std::shared_ptr + target_layout, std::shared_ptr target_coordinate_system) : OmegaHIntersectionRHSIntegrator( std::move(source_layout), std::move(source_coordinate_system), @@ -232,11 +246,13 @@ OmegaHIntersectionRHSIntegrator::OmegaHIntersectionRHSIntegrator( } OmegaHIntersectionRHSIntegrator::OmegaHIntersectionRHSIntegrator( - std::shared_ptr source_layout, + std::shared_ptr + source_layout, std::shared_ptr source_coordinate_system, - std::shared_ptr target_layout, + std::shared_ptr + target_layout, std::shared_ptr target_coordinate_system, - const GridPointSearchVariant* source_search) + const pcms::localization::GridPointSearchVariant* source_search) { Data data = BuildData(source_layout, source_coordinate_system, target_layout, target_coordinate_system, source_search); @@ -323,4 +339,4 @@ std::unique_ptr BuildOmegaHConservativeRHSIntegrator( target_space); } -} // namespace pcms +} // namespace pcms::transfer diff --git a/src/pcms/transfer/omega_h_intersection_rhs_integrator.hpp b/src/pcms/transfer/omega_h_intersection_rhs_integrator.hpp index 808ba272f..08535e76b 100644 --- a/src/pcms/transfer/omega_h_intersection_rhs_integrator.hpp +++ b/src/pcms/transfer/omega_h_intersection_rhs_integrator.hpp @@ -1,15 +1,15 @@ #ifndef PCMS_TRANSFER_OMEGA_H_INTERSECTION_RHS_INTEGRATOR_HPP #define PCMS_TRANSFER_OMEGA_H_INTERSECTION_RHS_INTEGRATOR_HPP -#include "pcms/field/coordinate_view.hpp" -#include "pcms/field/function_space.h" -#include "pcms/field/layout/omega_h_lagrange.h" +#include "pcms/utility/coordinate_view.hpp" +#include "pcms/field/function_space.hpp" +#include "pcms/backends/omega_h/lagrange_layout.hpp" #include "pcms/transfer/linear_form_integrator.hpp" #include "pcms/transfer/mesh_intersection.hpp" #include #include -namespace pcms +namespace pcms::transfer { // Conservative-projection RHS integrator for Lagrange spaces on Omega_h 2D @@ -37,9 +37,11 @@ class OmegaHIntersectionRHSIntegrator : public LinearFormIntegrator OmegaHIntersectionRHSIntegrator(const FunctionSpace& source_space, const FunctionSpace& target_space); OmegaHIntersectionRHSIntegrator( - std::shared_ptr source_layout, + std::shared_ptr + source_layout, std::shared_ptr source_coordinate_system, - std::shared_ptr target_layout, + std::shared_ptr + target_layout, std::shared_ptr target_coordinate_system); ~OmegaHIntersectionRHSIntegrator(); @@ -55,11 +57,13 @@ class OmegaHIntersectionRHSIntegrator : public LinearFormIntegrator // Both public constructors delegate here; `source_search` may be null, in // which case the intersection builds its own search over the source mesh. OmegaHIntersectionRHSIntegrator( - std::shared_ptr source_layout, + std::shared_ptr + source_layout, std::shared_ptr source_coordinate_system, - std::shared_ptr target_layout, + std::shared_ptr + target_layout, std::shared_ptr target_coordinate_system, - const GridPointSearchVariant* source_search); + const pcms::localization::GridPointSearchVariant* source_search); Vec vec_ = nullptr; Kokkos::View @@ -76,6 +80,6 @@ class OmegaHIntersectionRHSIntegrator : public LinearFormIntegrator std::unique_ptr BuildOmegaHConservativeRHSIntegrator( const FunctionSpace& source_space, const FunctionSpace& target_space); -} // namespace pcms +} // namespace pcms::transfer #endif // PCMS_TRANSFER_OMEGA_H_INTERSECTION_RHS_INTEGRATOR_HPP diff --git a/src/pcms/transfer/omega_h_mass_integrator.cpp b/src/pcms/transfer/omega_h_mass_integrator.cpp index c34dd529b..b8931c572 100644 --- a/src/pcms/transfer/omega_h_mass_integrator.cpp +++ b/src/pcms/transfer/omega_h_mass_integrator.cpp @@ -2,8 +2,8 @@ #include "pcms/transfer/mass_matrix_integrator.hpp" #include "pcms/transfer/omega_h_form_integrator_utils.hpp" #include "pcms/transfer/petsc_utils.hpp" -#include "pcms/utility/assert.h" -#include "pcms/utility/memory_spaces.h" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/memory_spaces.hpp" #include #include #include @@ -11,7 +11,7 @@ #include #include -namespace pcms +namespace pcms::transfer { namespace @@ -88,9 +88,10 @@ void FillP1MassCooPattern( // Assembles the target-space mass matrix for spatial dimension Dim (triangles // for Dim==2, tetrahedra for Dim==3) and returns the owned PETSc matrix. template -Mat BuildOmegaHMassMatrixImpl(Omega_h::Mesh& mesh, - const OmegaHLagrangeLayout& target_layout, - MassMatrixType mass_type) +Mat BuildOmegaHMassMatrixImpl( + Omega_h::Mesh& mesh, + const pcms::backend::omega_h::OmegaHLagrangeLayout& target_layout, + MassMatrixType mass_type) { const auto global_to_local = target_layout.GetGlobalToLocalPermutation(); const PetscInt num_dofs = @@ -178,14 +179,16 @@ Mat BuildOmegaHMassMatrixImpl(Omega_h::Mesh& mesh, OmegaHMassIntegrator::OmegaHMassIntegrator(const FunctionSpace& target_space, MassMatrixType mass_type) - : OmegaHMassIntegrator(std::dynamic_pointer_cast( + : OmegaHMassIntegrator(std::dynamic_pointer_cast< + const pcms::backend::omega_h::OmegaHLagrangeLayout>( target_space.GetLayout()), target_space.GetCoordinateSystem(), mass_type) { } OmegaHMassIntegrator::OmegaHMassIntegrator( - std::shared_ptr target_layout, + std::shared_ptr + target_layout, std::shared_ptr coordinate_system, MassMatrixType mass_type) { @@ -225,4 +228,4 @@ std::unique_ptr BuildOmegaHMassIntegrator( return std::make_unique(target_space, mass_type); } -} // namespace pcms +} // namespace pcms::transfer diff --git a/src/pcms/transfer/omega_h_mass_integrator.hpp b/src/pcms/transfer/omega_h_mass_integrator.hpp index 8da8c47e9..027dda735 100644 --- a/src/pcms/transfer/omega_h_mass_integrator.hpp +++ b/src/pcms/transfer/omega_h_mass_integrator.hpp @@ -1,14 +1,14 @@ #ifndef PCMS_TRANSFER_OMEGA_H_MASS_INTEGRATOR_HPP #define PCMS_TRANSFER_OMEGA_H_MASS_INTEGRATOR_HPP -#include "pcms/field/function_space.h" -#include "pcms/field/layout/omega_h_lagrange.h" +#include "pcms/field/function_space.hpp" +#include "pcms/backends/omega_h/lagrange_layout.hpp" #include "pcms/transfer/bilinear_form_integrator.hpp" #include "pcms/transfer/mass_matrix_type.hpp" #include #include -namespace pcms +namespace pcms::transfer { // Mass-matrix bilinear form integrator for Lagrange spaces on Omega_h 2D @@ -29,7 +29,8 @@ class OmegaHMassIntegrator : public BilinearFormIntegrator const FunctionSpace& target_space, MassMatrixType mass_type = MassMatrixType::Consistent); OmegaHMassIntegrator( - std::shared_ptr target_layout, + std::shared_ptr + target_layout, std::shared_ptr coordinate_system, MassMatrixType mass_type = MassMatrixType::Consistent); ~OmegaHMassIntegrator(); @@ -49,6 +50,6 @@ std::unique_ptr BuildOmegaHMassIntegrator( const FunctionSpace& target_space, MassMatrixType mass_type = MassMatrixType::Consistent); -} // namespace pcms +} // namespace pcms::transfer #endif // PCMS_TRANSFER_OMEGA_H_MASS_INTEGRATOR_HPP diff --git a/src/pcms/transfer/omega_h_mc_rhs_integrator.cpp b/src/pcms/transfer/omega_h_mc_rhs_integrator.cpp index 497efe9ea..d7af54fd7 100644 --- a/src/pcms/transfer/omega_h_mc_rhs_integrator.cpp +++ b/src/pcms/transfer/omega_h_mc_rhs_integrator.cpp @@ -1,13 +1,13 @@ #include "pcms/transfer/omega_h_mc_rhs_integrator.hpp" #include "pcms/transfer/omega_h_form_integrator_utils.hpp" #include "pcms/transfer/petsc_utils.hpp" -#include "pcms/utility/assert.h" +#include "pcms/utility/assert.hpp" #include #include #include -#include "pcms/field/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" -namespace pcms +namespace pcms::transfer { namespace @@ -141,14 +141,16 @@ OmegaHMonteCarloRHSIntegrator::OmegaHMonteCarloRHSIntegrator( const FunctionSpace& target_space, int samples_per_element, MonteCarloSampling sampling, uint64_t seed) : OmegaHMonteCarloRHSIntegrator( - std::dynamic_pointer_cast( + std::dynamic_pointer_cast< + const pcms::backend::omega_h::OmegaHLagrangeLayout>( target_space.GetLayout()), target_space.GetCoordinateSystem(), samples_per_element, sampling, seed) { } OmegaHMonteCarloRHSIntegrator::OmegaHMonteCarloRHSIntegrator( - std::shared_ptr target_layout, + std::shared_ptr + target_layout, std::shared_ptr target_coordinate_system, int samples_per_element, MonteCarloSampling /*sampling*/, uint64_t seed) { @@ -255,4 +257,4 @@ void OmegaHMonteCarloRHSIntegrator::Assemble( CHKERRABORT(PETSC_COMM_SELF, ierr); } -} // namespace pcms +} // namespace pcms::transfer diff --git a/src/pcms/transfer/omega_h_mc_rhs_integrator.hpp b/src/pcms/transfer/omega_h_mc_rhs_integrator.hpp index f652e380a..cc1c7430a 100644 --- a/src/pcms/transfer/omega_h_mc_rhs_integrator.hpp +++ b/src/pcms/transfer/omega_h_mc_rhs_integrator.hpp @@ -1,16 +1,16 @@ #ifndef PCMS_TRANSFER_OMEGA_H_MC_RHS_INTEGRATOR_HPP #define PCMS_TRANSFER_OMEGA_H_MC_RHS_INTEGRATOR_HPP -#include "pcms/field/coordinate_view.hpp" -#include "pcms/field/function_space.h" -#include "pcms/field/layout/omega_h_lagrange.h" +#include "pcms/utility/coordinate_view.hpp" +#include "pcms/field/function_space.hpp" +#include "pcms/backends/omega_h/lagrange_layout.hpp" #include "pcms/transfer/linear_form_integrator.hpp" #include "pcms/transfer/monte_carlo_sampling.hpp" #include #include #include -namespace pcms +namespace pcms::transfer { // Monte Carlo RHS integrator for conservative L2 projection onto order-1 @@ -35,7 +35,8 @@ class OmegaHMonteCarloRHSIntegrator : public LinearFormIntegrator MonteCarloSampling sampling, uint64_t seed = 8675309); OmegaHMonteCarloRHSIntegrator( - std::shared_ptr target_layout, + std::shared_ptr + target_layout, std::shared_ptr target_coordinate_system, int samples_per_element, MonteCarloSampling sampling, uint64_t seed = 8675309); @@ -62,6 +63,6 @@ class OmegaHMonteCarloRHSIntegrator : public LinearFormIntegrator int nbary_ = 3; // barycentric DOFs per sample (Dim+1): 3 in 2D, 4 in 3D }; -} // namespace pcms +} // namespace pcms::transfer #endif // PCMS_TRANSFER_OMEGA_H_MC_RHS_INTEGRATOR_HPP diff --git a/src/pcms/transfer/petsc_utils.cpp b/src/pcms/transfer/petsc_utils.cpp index fe51a4f5c..f76fa3657 100644 --- a/src/pcms/transfer/petsc_utils.cpp +++ b/src/pcms/transfer/petsc_utils.cpp @@ -6,7 +6,7 @@ #include "pcms/transfer/petsc_utils.hpp" -namespace pcms +namespace pcms::transfer { PetscErrorCode createSeqAIJMat(MPI_Comm comm, PetscInt m, PetscInt n, PetscInt nz, const PetscInt nnz[], Mat* mat) @@ -30,4 +30,4 @@ PetscErrorCode createSeqVec(MPI_Comm comm, PetscInt n, Vec* vec) #endif PetscFunctionReturn(PETSC_SUCCESS); } -} // namespace pcms +} // namespace pcms::transfer diff --git a/src/pcms/transfer/petsc_utils.hpp b/src/pcms/transfer/petsc_utils.hpp index 77b12bb1e..3aecf9942 100644 --- a/src/pcms/transfer/petsc_utils.hpp +++ b/src/pcms/transfer/petsc_utils.hpp @@ -14,7 +14,7 @@ (configure with --with-kokkos)" #endif -namespace pcms +namespace pcms::transfer { // Creates a sequential AIJ matrix using the Kokkos backend when available, // falling back to standard sequential AIJ on CPU-only builds. @@ -25,6 +25,6 @@ PetscErrorCode createSeqAIJMat(MPI_Comm comm, PetscInt m, PetscInt n, // Creates a sequential vector using the Kokkos backend when available, // falling back to standard sequential vector on CPU-only builds. PetscErrorCode createSeqVec(MPI_Comm comm, PetscInt n, Vec* vec); -} // namespace pcms +} // namespace pcms::transfer #endif // PCMS_TRANSFER_PETSC_UTILS_HPP diff --git a/src/pcms/transfer/projection.cpp b/src/pcms/transfer/projection.cpp new file mode 100644 index 000000000..83cf79b8d --- /dev/null +++ b/src/pcms/transfer/projection.cpp @@ -0,0 +1,47 @@ +#include "pcms/transfer/projection.hpp" +#include "pcms/configuration.hpp" +#include "pcms/utility/assert.hpp" +#if defined(PCMS_ENABLE_PETSC) && defined(PCMS_ENABLE_MESHFIELDS) +#include "pcms/transfer/omega_h_conservative_projection.hpp" +#include "pcms/transfer/omega_h_control_variate_projection.hpp" +#endif + +namespace pcms +{ + +std::unique_ptr> CreateConservativeProjection( + const FunctionSpace& source_space, const FunctionSpace& target_space, + ConservativeProjectionOptions options) +{ +#if defined(PCMS_ENABLE_PETSC) && defined(PCMS_ENABLE_MESHFIELDS) + return std::make_unique( + source_space, target_space, options.mass_matrix_type); +#else + (void)source_space; + (void)target_space; + (void)options; + throw pcms_error( + "CreateConservativeProjection: not available in this " + "build (needs PCMS_ENABLE_PETSC and PCMS_ENABLE_MESHFIELDS)"); +#endif +} + +std::unique_ptr> CreateControlVariateProjection( + const PointEvaluatorFactory& source, const FunctionSpace& target_space, + ControlVariateProjectionOptions options) +{ +#if defined(PCMS_ENABLE_PETSC) && defined(PCMS_ENABLE_MESHFIELDS) + return std::make_unique( + source, target_space, options.samples_per_element, options.sampling, + options.seed, options.mass_matrix_type); +#else + (void)source; + (void)target_space; + (void)options; + throw pcms_error( + "CreateControlVariateProjection: not available in this " + "build (needs PCMS_ENABLE_PETSC and PCMS_ENABLE_MESHFIELDS)"); +#endif +} + +} // namespace pcms diff --git a/src/pcms/transient/CMakeLists.txt b/src/pcms/transient/CMakeLists.txt index c64c9e36d..47ea24e5f 100644 --- a/src/pcms/transient/CMakeLists.txt +++ b/src/pcms/transient/CMakeLists.txt @@ -1,4 +1,4 @@ -set(PCMS_TRANSIENT_HEADERS timestepper.hpp) +set(PCMS_TRANSIENT_HEADERS ../../../include/pcms/transient/timestepper.hpp) set(PCMS_TRANSIENT_SOURCES timestepper.cpp) add_library(pcms_transient ${PCMS_TRANSIENT_SOURCES}) @@ -9,7 +9,7 @@ target_sources( pcms_transient PUBLIC FILE_SET transient TYPE HEADERS - BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/.. + BASE_DIRS ${PROJECT_SOURCE_DIR}/include/pcms FILES ${PCMS_TRANSIENT_HEADERS}) target_compile_features(pcms_transient PUBLIC cxx_std_20) target_link_libraries(pcms_transient PUBLIC pcms::utility) @@ -30,4 +30,4 @@ install( install( EXPORT pcms_transient-targets NAMESPACE pcms:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pcms) + DESTINATION ${PCMS_INSTALL_CMAKEDIR}) diff --git a/src/pcms/utility/CMakeLists.txt b/src/pcms/utility/CMakeLists.txt index 0016de28f..585989d5e 100644 --- a/src/pcms/utility/CMakeLists.txt +++ b/src/pcms/utility/CMakeLists.txt @@ -1,26 +1,31 @@ set( PCMS_UTILITY_HEADERS - arrays.h - assert.h - bounding_box.h - common.h - entity_types.h - eqdsk.h - mesh_geometry.h - memory_spaces.h - mpi_type.h - omega_h_array_utils.h - types.h - array_mask.h - inclusive_scan.h - profile.h - print.h - uniform_grid.h + ../../../include/pcms/utility/arrays.hpp + ../../../include/pcms/utility/coordinate_system.hpp + ../../../include/pcms/utility/coordinate_view.hpp + ../../../include/pcms/utility/coordinate_systems/cartesian.hpp + ../../../include/pcms/utility/coordinate_systems/cylindrical.hpp + ../../../include/pcms/utility/assert.hpp + ../../../include/pcms/utility/bounding_box.hpp + ../../../include/pcms/utility/detail/common.hpp + ../../../include/pcms/utility/entity_types.hpp + ../../../include/pcms/utility/eqdsk.hpp + mesh_geometry.hpp + ../../../include/pcms/utility/memory_spaces.hpp + mpi_type.hpp + omega_h_array_utils.hpp + ../../../include/pcms/utility/types.hpp + array_mask.hpp + ../../../include/pcms/utility/detail/inclusive_scan.hpp + ../../../include/pcms/utility/detail/profile.hpp + ../../../include/pcms/utility/print.hpp + ../../../include/pcms/utility/uniform_grid.hpp ) set( PCMS_UTILITY_SOURCES assert.cpp + coordinate_system.cpp eqdsk.cpp print.cpp ) @@ -30,6 +35,8 @@ target_include_directories( pcms_utility PUBLIC # include path should be pcms/utility/ + # public headers (include/pcms/...) + "$" "$" # include path to search for pcms/config.h "$" @@ -46,11 +53,16 @@ set_target_properties( ) ## export the library -target_sources(pcms_utility PUBLIC - FILE_SET utilities - TYPE HEADERS - BASE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../ - FILES ${PCMS_UTILITY_HEADERS}) +# Only the public headers (include/pcms/...) are installed; the private +# headers next to the sources are private sources of the target. +set(PCMS_UTILITY_HEADERS_PUBLIC ${PCMS_UTILITY_HEADERS}) +list(FILTER PCMS_UTILITY_HEADERS_PUBLIC INCLUDE REGEX "/include/pcms/") +set(PCMS_UTILITY_HEADERS_PRIVATE ${PCMS_UTILITY_HEADERS}) +list(FILTER PCMS_UTILITY_HEADERS_PRIVATE EXCLUDE REGEX "/include/pcms/") +target_sources(pcms_utility + PUBLIC FILE_SET utilities TYPE HEADERS BASE_DIRS ${PROJECT_SOURCE_DIR}/include/pcms + FILES ${PCMS_UTILITY_HEADERS_PUBLIC} + PRIVATE ${PCMS_UTILITY_HEADERS_PRIVATE}) install( TARGETS pcms_utility EXPORT pcms_utility-targets @@ -65,5 +77,5 @@ install( install( EXPORT pcms_utility-targets NAMESPACE pcms:: - DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/pcms + DESTINATION ${PCMS_INSTALL_CMAKEDIR} ) diff --git a/src/pcms/utility/array_mask.h b/src/pcms/utility/array_mask.hpp similarity index 96% rename from src/pcms/utility/array_mask.h rename to src/pcms/utility/array_mask.hpp index b51f5c5cc..9de04158d 100644 --- a/src/pcms/utility/array_mask.h +++ b/src/pcms/utility/array_mask.hpp @@ -1,9 +1,9 @@ -#ifndef PCMS_COUPLING_ARRAY_MASK_H -#define PCMS_COUPLING_ARRAY_MASK_H -#include "pcms/utility/arrays.h" -#include "pcms/utility/assert.h" +#ifndef PCMS_UTILITY_ARRAY_MASK_HPP +#define PCMS_UTILITY_ARRAY_MASK_HPP +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/assert.hpp" #include -namespace pcms +namespace pcms::utility { namespace detail @@ -162,6 +162,6 @@ class ArrayMask Kokkos::View mask_; LO num_active_entries_; }; -} // namespace pcms +} // namespace pcms::utility -#endif // PCMS_COUPLING_ARRAY_MASK_H +#endif // PCMS_UTILITY_ARRAY_MASK_HPP diff --git a/src/pcms/utility/assert.cpp b/src/pcms/utility/assert.cpp index 306dbf4cb..b9f1eb047 100644 --- a/src/pcms/utility/assert.cpp +++ b/src/pcms/utility/assert.cpp @@ -1,4 +1,4 @@ -#include "pcms/utility/print.h" +#include "pcms/utility/print.hpp" namespace pcms { diff --git a/src/pcms/field/coordinate_system.cpp b/src/pcms/utility/coordinate_system.cpp similarity index 87% rename from src/pcms/field/coordinate_system.cpp rename to src/pcms/utility/coordinate_system.cpp index 1e57dae66..f7374a8a8 100644 --- a/src/pcms/field/coordinate_system.cpp +++ b/src/pcms/utility/coordinate_system.cpp @@ -1,6 +1,6 @@ -#include "pcms/field/coordinate_system.hpp" -#include "pcms/field/coordinate_systems/cartesian.hpp" -#include "pcms/utility/assert.h" +#include "pcms/utility/coordinate_system.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" +#include "pcms/utility/assert.hpp" #include namespace pcms diff --git a/src/pcms/utility/eqdsk.cpp b/src/pcms/utility/eqdsk.cpp index c4b7f7198..17ddc924e 100644 --- a/src/pcms/utility/eqdsk.cpp +++ b/src/pcms/utility/eqdsk.cpp @@ -1,5 +1,6 @@ -#include "pcms/utility/eqdsk.h" -#include "pcms/utility/assert.h" +#include "pcms/utility/eqdsk.hpp" +#include "pcms/utility/assert.hpp" +#include #include #include #include diff --git a/src/pcms/utility/mesh_geometry.h b/src/pcms/utility/mesh_geometry.hpp similarity index 96% rename from src/pcms/utility/mesh_geometry.h rename to src/pcms/utility/mesh_geometry.hpp index 4c74595f4..6735370f9 100644 --- a/src/pcms/utility/mesh_geometry.h +++ b/src/pcms/utility/mesh_geometry.hpp @@ -1,12 +1,12 @@ -#ifndef PCMS_UTILITY_MESH_GEOMETRY_H -#define PCMS_UTILITY_MESH_GEOMETRY_H +#ifndef PCMS_UTILITY_MESH_GEOMETRY_HPP +#define PCMS_UTILITY_MESH_GEOMETRY_HPP #include #include #include #include -namespace pcms +namespace pcms::utility { KOKKOS_INLINE_FUNCTION @@ -123,6 +123,6 @@ inline void EnsureClassification(Omega_h::Mesh& mesh) } } -} // namespace pcms +} // namespace pcms::utility -#endif // PCMS_UTILITY_MESH_GEOMETRY_H +#endif // PCMS_UTILITY_MESH_GEOMETRY_HPP diff --git a/src/pcms/utility/mpi_type.h b/src/pcms/utility/mpi_type.hpp similarity index 90% rename from src/pcms/utility/mpi_type.h rename to src/pcms/utility/mpi_type.hpp index 4c133f68f..0b6d07a38 100644 --- a/src/pcms/utility/mpi_type.h +++ b/src/pcms/utility/mpi_type.hpp @@ -1,11 +1,11 @@ -#ifndef PCMS_MPI_TYPE_H -#define PCMS_MPI_TYPE_H +#ifndef PCMS_UTILITY_MPI_TYPE_HPP +#define PCMS_UTILITY_MPI_TYPE_HPP -#include "pcms/utility/types.h" +#include "pcms/utility/types.hpp" #include #include -namespace pcms +namespace pcms::utility { template @@ -66,12 +66,12 @@ template } else if constexpr (std::is_same_v>) { return MPI_CXX_LONG_DOUBLE_COMPLEX; } else { - static_assert(detail::dependent_always_false::value, + static_assert(pcms::detail::dependent_always_false::value, "type has unknown map to MPI_Datatype"); return {}; } } -} // namespace pcms +} // namespace pcms::utility -#endif // PCMS_MPI_TYPE_H +#endif // PCMS_UTILITY_MPI_TYPE_HPP diff --git a/src/pcms/utility/omega_h_array_utils.h b/src/pcms/utility/omega_h_array_utils.hpp similarity index 89% rename from src/pcms/utility/omega_h_array_utils.h rename to src/pcms/utility/omega_h_array_utils.hpp index 9b76d97a3..28666b521 100644 --- a/src/pcms/utility/omega_h_array_utils.h +++ b/src/pcms/utility/omega_h_array_utils.hpp @@ -1,10 +1,10 @@ -#ifndef PCMS_UTILITY_OMEGA_H_ARRAY_UTILS_H -#define PCMS_UTILITY_OMEGA_H_ARRAY_UTILS_H +#ifndef PCMS_UTILITY_OMEGA_H_ARRAY_UTILS_HPP +#define PCMS_UTILITY_OMEGA_H_ARRAY_UTILS_HPP #include -#include "pcms/utility/memory_spaces.h" +#include "pcms/utility/memory_spaces.hpp" -namespace pcms +namespace pcms::utility { template @@ -65,6 +65,6 @@ inline Kokkos::View ConvertCoordsTo2D( return coords_2d; } -} // namespace pcms +} // namespace pcms::utility -#endif // PCMS_UTILITY_OMEGA_H_ARRAY_UTILS_H +#endif // PCMS_UTILITY_OMEGA_H_ARRAY_UTILS_HPP diff --git a/src/pcms/utility/print.cpp b/src/pcms/utility/print.cpp index 0f1747ff7..39bb01278 100644 --- a/src/pcms/utility/print.cpp +++ b/src/pcms/utility/print.cpp @@ -1,4 +1,4 @@ -#include "pcms/utility/print.h" +#include "pcms/utility/print.hpp" #include #include diff --git a/src/pcms/version.h.in b/src/pcms/version.hpp.in similarity index 76% rename from src/pcms/version.h.in rename to src/pcms/version.hpp.in index f76334b57..50c7e7fad 100644 --- a/src/pcms/version.h.in +++ b/src/pcms/version.hpp.in @@ -1,4 +1,5 @@ -#pragma once +#ifndef PCMS_VERSION_HPP +#define PCMS_VERSION_HPP #define PCMS_VERSION_MAJOR @CMAKE_PROJECT_VERSION_MAJOR@ #define PCMS_VERSION_MINOR @CMAKE_PROJECT_VERSION_MINOR@ @@ -8,4 +9,6 @@ namespace pcms { const char* pcms_version() { return "@CMAKE_PROJECT_VERSION@"; } -} \ No newline at end of file +} + +#endif // PCMS_VERSION_HPP diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 97eee9023..7eca1effc 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -6,7 +6,8 @@ message("TESTING ON SYSTEM WITH ${HOST_NPROC} CPU Cores") set(rendezvous 1) set(notRendezvous 0) -if(PCMS_ENABLE_OMEGA_H) +# coupling tests need the coupler (redev/ADIOS2) +if(PCMS_ENABLE_OMEGA_H AND TARGET pcms::coupler) add_exe(test_ohClassPtn) set(cyclone1p ${PCMS_TEST_DATA_DIR}/cyclone/23elements/mesh.osh/) if(HOST_NPROC GREATER_EQUAL 3) @@ -168,7 +169,7 @@ if(PCMS_ENABLE_OMEGA_H) ignored) endif() add_executable(field_communication test_field_communication.cpp) - target_link_libraries(field_communication PUBLIC pcms::core test_support) + target_link_libraries(field_communication PUBLIC pcms::pcms test_support) if(HOST_NPROC GREATER_EQUAL 4) tri_mpi_test( TESTNAME @@ -207,7 +208,7 @@ if(PCMS_ENABLE_OMEGA_H) ignored) endif() add_executable(proxy_coupling test_proxy_coupling.cpp) - target_link_libraries(proxy_coupling PUBLIC pcms::core test_support) + target_link_libraries(proxy_coupling PUBLIC pcms::pcms test_support) if(HOST_NPROC GREATER_EQUAL 4) tri_mpi_test( TESTNAME @@ -401,10 +402,22 @@ if(Catch2_FOUND) STATUS "Found Catch2: ${Catch2_DIR} (found version ${Catch2_VERSION})") set(PCMS_UNIT_TEST_SOURCES unit_test_main.cpp test_coordinate_transformation.cpp - test_bounding_box.cpp test_field_serializer.cpp) + test_bounding_box.cpp) if(PCMS_ENABLE_XGC) - list(APPEND PCMS_UNIT_TEST_SOURCES test_xgc_reverse_classification.cpp - test_xgc_field_data.cpp) + list(APPEND PCMS_UNIT_TEST_SOURCES test_xgc_reverse_classification.cpp) + endif() + # unit tests that use the coupler + if(TARGET pcms::coupler) + list(APPEND PCMS_UNIT_TEST_SOURCES test_field_serializer.cpp) + if(PCMS_ENABLE_XGC) + list(APPEND PCMS_UNIT_TEST_SOURCES test_xgc_field_data.cpp) + endif() + if(PCMS_ENABLE_OMEGA_H) + list(APPEND PCMS_UNIT_TEST_SOURCES test_field_exchange_planner.cpp) + endif() + if(PCMS_ENABLE_MFEM) + list(APPEND PCMS_UNIT_TEST_SOURCES test_mfem_adapter.cpp) + endif() endif() if(PCMS_ENABLE_OMEGA_H) @@ -417,7 +430,6 @@ if(Catch2_FOUND) test_field_evaluation.cpp test_field_interpolation.cpp test_field_copy.cpp - test_field_exchange_planner.cpp test_point_search.cpp test_mls_basis.cpp test_rbf_interp.cpp @@ -438,10 +450,6 @@ if(Catch2_FOUND) test_evaluation_only_space.cpp) endif() - if(PCMS_ENABLE_MFEM) - list(APPEND PCMS_UNIT_TEST_SOURCES test_mfem_adapter.cpp) - endif() - if(PCMS_ENABLE_MESHFIELDS) list(APPEND PCMS_UNIT_TEST_SOURCES test_omega_h_form_integrator_utils.cpp) @@ -470,7 +478,7 @@ if(Catch2_FOUND) target_link_libraries(unit_tests PUBLIC mfem) endif() - target_link_libraries(unit_tests PUBLIC Catch2::Catch2 pcms::core + target_link_libraries(unit_tests PUBLIC Catch2::Catch2 pcms::pcms pcms::transfer Kokkos::kokkoskernels) target_include_directories(unit_tests PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) @@ -480,7 +488,7 @@ if(Catch2_FOUND) add_executable(test_interpolation_on_ltx_mesh test_interpolation_on_ltx_mesh.cpp) target_link_libraries(test_interpolation_on_ltx_mesh PUBLIC Catch2::Catch2WithMain - pcms::core + pcms::pcms pcms::transfer) target_include_directories(test_interpolation_on_ltx_mesh PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) add_test(NAME test_interpolation_on_ltx_mesh @@ -502,9 +510,9 @@ else() message(WARNING "Catch2 not found. Disabling Unit Tests") endif() -if(PCMS_ENABLE_MFEM) +if(PCMS_ENABLE_MFEM AND TARGET pcms::coupler) add_executable(test_mfem_coupling test_mfem_coupling.cpp) - target_link_libraries(test_mfem_coupling PUBLIC pcms::core mfem) + target_link_libraries(test_mfem_coupling PUBLIC pcms::pcms mfem) if(HOST_NPROC GREATER_EQUAL 2) dual_mpi_test( TESTNAME @@ -532,7 +540,7 @@ endif() if(PCMS_ENABLE_C) find_package(Kokkos REQUIRED) - if(PCMS_ENABLE_XGC) + if(PCMS_ENABLE_XGC AND TARGET pcms::capi::core) add_executable(test_proxy_couple_xgc_c_interface test_proxy_coupling_xgc_client.c) target_link_libraries(test_proxy_couple_xgc_c_interface @@ -541,12 +549,12 @@ if(PCMS_ENABLE_C) add_executable(test_proxy_couple_xgc_cpp_interface test_proxy_coupling_xgc_server.cpp) target_link_libraries(test_proxy_couple_xgc_cpp_interface - PUBLIC pcms::core MPI::MPI_C test_support) + PUBLIC pcms::pcms MPI::MPI_C test_support) # New test with proper overlap mask feature (no hacky ownership modification) add_executable(test_proxy_couple_xgc_overlap_interface test_proxy_coupling_xgc_server_overlap.cpp) target_link_libraries(test_proxy_couple_xgc_overlap_interface - PUBLIC pcms::core MPI::MPI_C test_support) + PUBLIC pcms::pcms MPI::MPI_C test_support) if(HOST_NPROC GREATER_EQUAL 3) dual_mpi_test( TESTNAME @@ -648,13 +656,15 @@ if(PCMS_ENABLE_C) endif() endif() endif() -if(PCMS_ENABLE_Fortran) - add_executable(test_proxy_coupling_xgc_client_fortran - test_proxy_coupling_xgc_client_fortran.f90) - target_link_libraries(test_proxy_coupling_xgc_client_fortran - PUBLIC pcms::fortranapi MPI::MPI_Fortran) - set_target_properties(test_proxy_coupling_xgc_client_fortran - PROPERTIES LINKER_LANGUAGE Fortran) +if(PCMS_ENABLE_FORTRAN) + if(TARGET pcms::fortranapi::core) + add_executable(test_proxy_coupling_xgc_client_fortran + test_proxy_coupling_xgc_client_fortran.f90) + target_link_libraries(test_proxy_coupling_xgc_client_fortran + PUBLIC pcms::fortranapi MPI::MPI_Fortran) + set_target_properties(test_proxy_coupling_xgc_client_fortran + PROPERTIES LINKER_LANGUAGE Fortran) + endif() add_executable(test_interpolation_fortran_api test_interpolation.f90) @@ -668,7 +678,7 @@ if(PCMS_ENABLE_Fortran) $ ${PCMS_TEST_DATA_DIR}/cyclone/23elements/mesh.osh 23 19 ) - if(HOST_NPROC GREATER_EQUAL 4) + if(HOST_NPROC GREATER_EQUAL 4 AND TARGET pcms::fortranapi::core) dual_mpi_test( TESTNAME xgc_fortran_proxy_to_omega @@ -697,5 +707,19 @@ endif() find_package(KokkosKernels REQUIRED) -add_executable(xgc_n0_server xgc_n0_coupling_server.cpp) -target_link_libraries(xgc_n0_server PUBLIC pcms::core test_support) +if(TARGET pcms::coupler) + add_executable(xgc_n0_server xgc_n0_coupling_server.cpp) + target_link_libraries(xgc_n0_server PUBLIC pcms::pcms test_support) +endif() + +# every installed public header compiles on its own +add_subdirectory(public_headers) + +# installed core headers must not include backend libraries +find_package(Python3 COMPONENTS Interpreter) +if(Python3_Interpreter_FOUND) + add_test(NAME public_header_includes + COMMAND ${Python3_EXECUTABLE} + ${PROJECT_SOURCE_DIR}/tools/check-public-includes.py + ${PROJECT_SOURCE_DIR}) +endif() diff --git a/test/field_test_utils.h b/test/field_test_utils.hpp similarity index 94% rename from test/field_test_utils.h rename to test/field_test_utils.hpp index fd81add9b..ee50264f0 100644 --- a/test/field_test_utils.h +++ b/test/field_test_utils.hpp @@ -1,24 +1,24 @@ -#ifndef PCMS_TEST_FIELD_TEST_UTILS_H -#define PCMS_TEST_FIELD_TEST_UTILS_H +#ifndef PCMS_TEST_FIELD_TEST_UTILS_HPP +#define PCMS_TEST_FIELD_TEST_UTILS_HPP #include #include -#include "pcms/configuration.h" -#include "pcms/field/field.h" -#include "pcms/field/field_data.h" -#include "pcms/field/field_evaluator_factory.h" -#include "pcms/field/evaluation_request.h" -#include "pcms/field/point_evaluator.h" -#include "pcms/field/out_of_bounds_policy.h" -#include "pcms/field/coordinate_view.hpp" -#include "pcms/utility/arrays.h" -#include "pcms/utility/memory_spaces.h" +#include "pcms/configuration.hpp" +#include "pcms/field/field.hpp" +#include "pcms/field/field_data.hpp" +#include "pcms/field/field_evaluator_factory.hpp" +#include "pcms/field/evaluation_request.hpp" +#include "pcms/field/point_evaluator.hpp" +#include "pcms/field/out_of_bounds_policy.hpp" +#include "pcms/utility/coordinate_view.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/memory_spaces.hpp" #ifdef PCMS_ENABLE_OMEGA_H #include #include #include -#include "pcms/field/function_space/lagrange.h" -#include "pcms/localization/adj_search.hpp" +#include "pcms/field/function_space/lagrange.hpp" +#include "pcms/backends/omega_h/adj_search.hpp" #endif #if defined(PCMS_ENABLE_PETSC) && defined(PCMS_ENABLE_MESHFIELDS) #include "pcms/transfer/linear_form_integrator.hpp" @@ -30,7 +30,7 @@ #include #include #include -#include "pcms/field/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" // Shared utilities for field tests that apply equally to MeshFields-backed // and native OmegaH-backed field implementations. @@ -150,19 +150,20 @@ inline Omega_h::Mesh BuildReferenceTet(Omega_h::Library& lib) })); } -inline std::shared_ptr MakeP1Space( +inline std::shared_ptr MakeP1Space( Omega_h::Mesh& mesh, const std::string& global_id_name = "global") { - return LagrangeFunctionSpace::FromMesh( + return pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, csys::Cartesian::Deferred(), global_id_name, - LagrangeFunctionSpace::Backend::OmegaH); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); } -inline std::shared_ptr MakeP0Space(Omega_h::Mesh& mesh) +inline std::shared_ptr MakeP0Space( + Omega_h::Mesh& mesh) { - return LagrangeFunctionSpace::FromMesh( + return pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 0, 1, csys::Cartesian::Deferred(), "global", - LagrangeFunctionSpace::Backend::OmegaH); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); } inline bool AreArraysEqualUnordered( @@ -177,8 +178,9 @@ inline bool AreArraysEqualUnordered( return freq1 == freq2; } -inline void CheckSupportResultsEquivalent(const SupportResults& actual, - const SupportResults& expected) +inline void CheckSupportResultsEquivalent( + const pcms::localization::SupportResults& actual, + const pcms::localization::SupportResults& expected) { auto actual_ptr = Omega_h::HostRead(actual.supports_ptr); auto actual_idx = Omega_h::HostRead(actual.supports_idx); @@ -599,7 +601,7 @@ void CheckEvaluationWithFill(const Factory& factory, const Field& field, // Evaluates source_field at the integrator's sample points and assembles the // load vector. inline void EvaluateAndAssemble( - LinearFormIntegrator& integrator, + pcms::transfer::LinearFormIntegrator& integrator, const std::shared_ptr& source_space, const Field& source_field) { @@ -615,4 +617,4 @@ inline void EvaluateAndAssemble( } // namespace pcms::test -#endif // PCMS_TEST_FIELD_TEST_UTILS_H +#endif // PCMS_TEST_FIELD_TEST_UTILS_HPP diff --git a/test/public_headers/CMakeLists.txt b/test/public_headers/CMakeLists.txt new file mode 100644 index 000000000..eda576f44 --- /dev/null +++ b/test/public_headers/CMakeLists.txt @@ -0,0 +1,66 @@ +# Self-containment check: every installed public header must compile on its +# own (only its own includes, nothing before it). One translation unit is +# generated per header and compiled into an object library; the test +# "public_headers_self_contained" builds that library. + +file(GLOB_RECURSE pcms_public_headers RELATIVE "${PROJECT_SOURCE_DIR}/include" + CONFIGURE_DEPENDS "${PROJECT_SOURCE_DIR}/include/pcms/*.hpp" + "${PROJECT_SOURCE_DIR}/include/pcms/*.h") + +# headers whose library is not part of this build +set(pcms_skipped_header_regex "") +if(NOT TARGET pcms::coupler) + list(APPEND pcms_skipped_header_regex "^pcms/coupler/") +endif() +if(NOT TARGET pcms::transient) + list(APPEND pcms_skipped_header_regex "^pcms/transient/") +endif() +if(NOT PCMS_ENABLE_C) + list(APPEND pcms_skipped_header_regex "^pcms/capi/") +endif() +if(NOT TARGET pcms::capi::core) + list(APPEND pcms_skipped_header_regex "^pcms/capi/client\\.h$") +endif() +if(NOT PCMS_ENABLE_OMEGA_H) + list(APPEND pcms_skipped_header_regex "^pcms/backends/omega_h/" + "^pcms/field/eqdsk_field\\.hpp$") +endif() +if(NOT PCMS_ENABLE_MFEM) + list(APPEND pcms_skipped_header_regex "^pcms/backends/mfem/") +endif() +if(NOT PCMS_ENABLE_XGC) + list(APPEND pcms_skipped_header_regex "^pcms/backends/xgc/xgc\\.hpp$") +endif() + +set(pcms_header_check_sources "") +foreach(header IN LISTS pcms_public_headers) + set(skip FALSE) + foreach(regex IN LISTS pcms_skipped_header_regex) + if(header MATCHES "${regex}") + set(skip TRUE) + endif() + endforeach() + if(skip) + continue() + endif() + string(MAKE_C_IDENTIFIER "${header}" name) + if(header MATCHES "\\.h$") + set(source "${CMAKE_CURRENT_BINARY_DIR}/${name}.c") + else() + set(source "${CMAKE_CURRENT_BINARY_DIR}/${name}.cpp") + endif() + file(CONFIGURE OUTPUT "${source}" CONTENT "#include <${header}>\n") + list(APPEND pcms_header_check_sources "${source}") +endforeach() + +add_library(pcms_public_header_check OBJECT EXCLUDE_FROM_ALL + ${pcms_header_check_sources}) +target_link_libraries(pcms_public_header_check PRIVATE pcms::pcms) +if(TARGET mfem) + target_link_libraries(pcms_public_header_check PRIVATE mfem) +endif() + +add_test( + NAME public_headers_self_contained + COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR} --target + pcms_public_header_check) diff --git a/test/python/test_coordinate_transformations.py b/test/python/test_coordinate_transformations.py index 1db5c0944..e6c38f6ba 100644 --- a/test/python/test_coordinate_transformations.py +++ b/test/python/test_coordinate_transformations.py @@ -34,9 +34,12 @@ def cylindrical_space(world): """P1 vector space on a box whose coordinates are (r, theta, z).""" mesh = omega_h.build_box(world, omega_h.Family.SIMPLEX, 2.0, 1.6, 1.1, 6, 6, 4, False) - return pcms.LagrangeFunctionSpace.from_mesh( - mesh, 1, 3, pcms.csys.CylindricalRThetaZ.create(), - backend=pcms.LagrangeFunctionSpace.Backend.OmegaH) + return pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(mesh), + 1, + 3, + pcms.csys.CylindricalRThetaZ.create(), + implementation=pcms.LagrangeImplementation.OmegaH) @pytest.fixture @@ -44,9 +47,12 @@ def cartesian_space(world): """P1 vector space on the Cartesian unit cube.""" mesh = omega_h.build_box(world, omega_h.Family.SIMPLEX, 1.0, 1.0, 1.0, 3, 3, 3, False) - return pcms.LagrangeFunctionSpace.from_mesh( - mesh, 1, 3, pcms.csys.Cartesian.create(3), - backend=pcms.LagrangeFunctionSpace.Backend.OmegaH) + return pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(mesh), + 1, + 3, + pcms.csys.Cartesian.create(3), + implementation=pcms.LagrangeImplementation.OmegaH) def _coordinates_of(space): @@ -98,7 +104,7 @@ def test_equality_is_by_value(self): def test_space_defaults_to_cartesian_of_mesh_dimension(self, world): mesh = omega_h.build_box(world, omega_h.Family.SIMPLEX, 1.0, 1.0, 0.0, 4, 4, 0, False) - space = pcms.LagrangeFunctionSpace.from_mesh(mesh, 1, 1) + space = pcms.create_lagrange_space(pcms.backend.omega_h.create_discretization(mesh), 1, 1) assert (space.get_layout().get_coordinate_system() == pcms.csys.Cartesian.create(2)) @@ -392,8 +398,11 @@ class TestLifetimes: def test_space_keeps_its_mesh_alive(self, world): mesh = omega_h.build_box(world, omega_h.Family.SIMPLEX, 1.0, 1.0, 0.0, 4, 4, 0, False) - space = pcms.LagrangeFunctionSpace.from_mesh( - mesh, 1, 1, backend=pcms.LagrangeFunctionSpace.Backend.OmegaH) + space = pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(mesh), + 1, + 1, + implementation=pcms.LagrangeImplementation.OmegaH) del mesh gc.collect() f = space.create_function() diff --git a/test/python/test_examples.py b/test/python/test_examples.py index 6cb40c8e2..a1195a4ec 100644 --- a/test/python/test_examples.py +++ b/test/python/test_examples.py @@ -47,7 +47,7 @@ def _run_example(script, *args): def test_conservative_transfer_example(): - if not hasattr(pcms, "OmegaHConservativeProjection"): + if not hasattr(pcms, "create_conservative_projection"): _skip_or_fail("pcms was built without PETSc/MeshFields") stdout = _run_example("example_conservative_transfer.py") assert "Field transfer completed" in stdout diff --git a/test/python/test_field_copy.py b/test/python/test_field_copy.py index fa616aa28..ff2ef9fbd 100644 --- a/test/python/test_field_copy.py +++ b/test/python/test_field_copy.py @@ -29,8 +29,10 @@ def test_copy(self, world, dim, order, num_components): ) # Create factory and layout - factory = pcms.LagrangeFunctionSpace.from_mesh( - mesh, order, num_components) + factory = pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(mesh), + order, + num_components) # Create original field and set data original = factory.create_function() diff --git a/test/python/test_mls_interpolation.py b/test/python/test_mls_interpolation.py index c09451e3a..8c07706a4 100644 --- a/test/python/test_mls_interpolation.py +++ b/test/python/test_mls_interpolation.py @@ -58,10 +58,9 @@ def test_polynomial_reproduction(self): opts.adapt_radius = False opts.basis = pcms.RadialBasisFunction.NO_OP - factory = pcms.PolynomialReconstructionFunctionSpace.create( + factory = pcms.create_polynomial_reconstruction_space( pcms.CoordinateView(source_xy), - opts, - ) + opts) field = factory.create_function() request = pcms.EvaluationRequest.from_coordinates( pcms.CoordinateView(target_xy)) diff --git a/test/python/test_numpy_conversion.py b/test/python/test_numpy_conversion.py index 4d65a75d2..8c73a0b5f 100644 --- a/test/python/test_numpy_conversion.py +++ b/test/python/test_numpy_conversion.py @@ -25,8 +25,10 @@ def mesh(world): @pytest.fixture def p1_space(mesh): - return pcms.LagrangeFunctionSpace.from_mesh( - mesh, 1, 1) + return pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(mesh), + 1, + 1) def _coordinates(field): @@ -46,8 +48,10 @@ def _linear_field(space): class TestFieldData: def test_shape_matches_layout(self, mesh, world): - space = pcms.LagrangeFunctionSpace.from_mesh( - mesh, 1, 2) + space = pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(mesh), + 1, + 2) field = space.create_function() n = _num_dof_holders(field) data = np.arange(2 * n, dtype=np.float64).reshape(n, 2) @@ -97,8 +101,10 @@ def test_set_rejects_wrong_shape(self, p1_space, shape): field.set_dof_holder_data(np.zeros(shape(_num_dof_holders(field)))) def test_vector_field_rejects_1d(self, mesh): - space = pcms.LagrangeFunctionSpace.from_mesh( - mesh, 1, 2) + space = pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(mesh), + 1, + 2) field = space.create_function() n = _num_dof_holders(field) for shape in [(n,), (2 * n,)]: @@ -255,24 +261,24 @@ def test_average_from_strided_input(self, mesh): nfaces = mesh.nfaces() values = np.arange(nfaces, dtype=np.float64) wide = np.stack([values, -values], axis=1) - contiguous = pcms.map_entity_field_to_vertices_average(mesh, values, 2) - strided = pcms.map_entity_field_to_vertices_average(mesh, wide[:, 0], + contiguous = pcms.backend.omega_h.map_entity_field_to_vertices_average(mesh, values, 2) + strided = pcms.backend.omega_h.map_entity_field_to_vertices_average(mesh, wide[:, 0], 2) np.testing.assert_array_equal(strided, contiguous) def test_average_of_constant_is_constant(self, mesh): values = np.full(mesh.nfaces(), 3.5) - result = pcms.map_entity_field_to_vertices_average(mesh, values, 2) + result = pcms.backend.omega_h.map_entity_field_to_vertices_average(mesh, values, 2) assert result.shape == (mesh.nverts(),) assert not result.flags.writeable np.testing.assert_allclose(result, 3.5) @pytest.mark.parametrize("mapping", [ - lambda mesh, v: pcms.map_entity_field_to_vertices_average(mesh, v, 2), - lambda mesh, v: pcms.map_entity_field_to_vertices_mls(mesh, v, 2), + lambda mesh, v: pcms.backend.omega_h.map_entity_field_to_vertices_average(mesh, v, 2), + lambda mesh, v: pcms.backend.omega_h.map_entity_field_to_vertices_mls(mesh, v, 2), ], ids=["average", "mls"]) def test_multicomponent_matches_per_component(self, mesh, mapping): - centroids = pcms.compute_entity_centroids(mesh, 2) + centroids = pcms.backend.omega_h.compute_entity_centroids(mesh, 2) values = np.stack([_linear(centroids[:, 0], centroids[:, 1]), centroids[:, 0] - centroids[:, 1]], axis=1) result = mapping(mesh, values) @@ -283,7 +289,7 @@ def test_multicomponent_matches_per_component(self, mesh, mapping): def test_single_component_2d_keeps_rank(self, mesh): values = np.full((mesh.nfaces(), 1), 3.5) - result = pcms.map_entity_field_to_vertices_average(mesh, values, 2) + result = pcms.backend.omega_h.map_entity_field_to_vertices_average(mesh, values, 2) assert result.shape == (mesh.nverts(), 1) np.testing.assert_allclose(result, 3.5) @@ -293,11 +299,11 @@ def test_single_component_2d_keeps_rank(self, mesh): ], ids=["1d-wrong-entities", "2d-wrong-entities", "no-components", "3d"]) def test_rejects_wrong_shape(self, mesh, shape): with pytest.raises(ValueError): - pcms.map_entity_field_to_vertices_average( + pcms.backend.omega_h.map_entity_field_to_vertices_average( mesh, np.zeros(shape(mesh.nfaces())), 2) def test_centroids_survive_garbage_collection(self, mesh): - centroids = pcms.compute_entity_centroids(mesh, 2) + centroids = pcms.backend.omega_h.compute_entity_centroids(mesh, 2) expected = centroids.copy() gc.collect() np.testing.assert_array_equal(centroids, expected) @@ -306,13 +312,13 @@ def test_centroids_survive_garbage_collection(self, mesh): class TestUniformGrid: def test_closest_cell_id_accepts_sequences(self, mesh): - grid = pcms.create_uniform_grid_from_mesh(mesh, [4, 4]) + grid = pcms.backend.omega_h.create_uniform_grid_from_mesh(mesh, [4, 4]) expected = grid.closest_cell_id(np.array([0.3, 0.6])) assert grid.closest_cell_id([0.3, 0.6]) == expected assert grid.closest_cell_id(np.array([0.3, 0.6], np.float32)) == \ expected def test_closest_cell_id_rejects_wrong_dimension(self, mesh): - grid = pcms.create_uniform_grid_from_mesh(mesh, [4, 4]) + grid = pcms.backend.omega_h.create_uniform_grid_from_mesh(mesh, [4, 4]) with pytest.raises(ValueError): grid.closest_cell_id(np.array([0.3, 0.6, 0.1])) diff --git a/test/python/test_omega_h_field.py b/test/python/test_omega_h_field.py index 09d432aae..5d7a13533 100644 --- a/test/python/test_omega_h_field.py +++ b/test/python/test_omega_h_field.py @@ -25,8 +25,10 @@ def _build_mesh(world, dim, nx=10): def test_field_methods(self, world, dim, order, num_components): """Create an Omega_h-backed Field and exercise the public Field API.""" mesh = self._build_mesh(world, dim) - factory = pcms.LagrangeFunctionSpace.from_mesh( - mesh, order, num_components) + factory = pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(mesh), + order, + num_components) field = factory.create_function() assert field.get_layout().get_num_components() == num_components @@ -54,10 +56,14 @@ def test_field_transfer(self, world, dim, order, num_components): pytest.skip("Multi-component transfer not yet supported") mesh = self._build_mesh(world, dim) - source_space = pcms.LagrangeFunctionSpace.from_mesh( - mesh, order, num_components) - target_space = pcms.LagrangeFunctionSpace.from_mesh( - mesh, order, num_components) + source_space = pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(mesh), + order, + num_components) + target_space = pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(mesh), + order, + num_components) source = source_space.create_function() target = target_space.create_function() @@ -80,8 +86,10 @@ def test_field_transfer(self, world, dim, order, num_components): def test_field_evaluation(self, world, dim, order, num_components): """Evaluate an Omega_h-backed field at explicit query points.""" mesh = self._build_mesh(world, dim) - factory = pcms.LagrangeFunctionSpace.from_mesh( - mesh, order, num_components) + factory = pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(mesh), + order, + num_components) field = factory.create_function() mesh_coords = mesh.coords() @@ -143,8 +151,10 @@ def test_func(x, y, z, component): def test_evaluate_rejects_wrong_output_shape(self, world, shape): """A wrongly shaped output buffer raises instead of aborting.""" mesh = self._build_mesh(world, 2) - factory = pcms.LagrangeFunctionSpace.from_mesh( - mesh, 1, 1) + factory = pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(mesh), + 1, + 1) field = factory.create_function() eval_coords = np.full((5, 2), 0.5) evaluator = factory.create_point_evaluator( diff --git a/test/python/test_uniform_grid_field.py b/test/python/test_uniform_grid_field.py index 286297be0..469c8f15b 100644 --- a/test/python/test_uniform_grid_field.py +++ b/test/python/test_uniform_grid_field.py @@ -26,8 +26,10 @@ def test_field_creation(self): grid.edge_length = [10.0, 10.0] grid.divisions = [4, 4] - factory = pcms.LagrangeFunctionSpace.from_uniform_grid( - grid, 1) + factory = pcms.create_lagrange_space( + pcms.create_uniform_grid_discretization(grid), + 1, + 1) field = factory.create_function() expected = (grid.divisions[0] + 1) * (grid.divisions[1] + 1) assert field.get_layout().get_num_components() == 1 @@ -40,8 +42,10 @@ def test_data_operations(self): grid.edge_length = [10.0, 10.0] grid.divisions = [2, 2] - factory = pcms.LagrangeFunctionSpace.from_uniform_grid( - grid, 1) + factory = pcms.create_lagrange_space( + pcms.create_uniform_grid_discretization(grid), + 1, + 1) field = factory.create_function() data = np.arange(_num_dof_holders(field), dtype=np.float64).reshape(-1, 1) @@ -58,8 +62,10 @@ def test_coordinates_2d(self): grid.edge_length = [10.0, 10.0] grid.divisions = [2, 3] - factory = pcms.LagrangeFunctionSpace.from_uniform_grid( - grid, 1) + factory = pcms.create_lagrange_space( + pcms.create_uniform_grid_discretization(grid), + 1, + 1) field = factory.create_function() coords = _coordinates(field) expected = (grid.divisions[0] + 1) * (grid.divisions[1] + 1) @@ -88,8 +94,10 @@ def test_coordinates_3d(self): grid.edge_length = [10.0, 10.0, 10.0] grid.divisions = [2, 2, 2] - factory = pcms.LagrangeFunctionSpace.from_uniform_grid( - grid, 1) + factory = pcms.create_lagrange_space( + pcms.create_uniform_grid_discretization(grid), + 1, + 1) field = factory.create_function() coords = _coordinates(field) expected = ( @@ -113,8 +121,10 @@ def test_field_evaluation(self): grid.edge_length = [1.0, 1.0] grid.divisions = [10, 10] - factory = pcms.LagrangeFunctionSpace.from_uniform_grid( - grid, 1) + factory = pcms.create_lagrange_space( + pcms.create_uniform_grid_discretization(grid), + 1, + 1) field = factory.create_function() coords = _coordinates(field) num_dofs = _num_dof_holders(field) @@ -150,13 +160,15 @@ def test_uniform_grid_to_omega_h_workflow(self, world): world, omega_h.Family.SIMPLEX, 1.0, 1.0, 0.0, 4, 4, 0, False, ) - grid = pcms.create_uniform_grid_from_mesh(mesh, [4, 4]) - mask_field = pcms.create_uniform_grid_binary_field(mesh, [4, 4]) + grid = pcms.backend.omega_h.create_uniform_grid_from_mesh(mesh, [4, 4]) + mask_field = pcms.backend.omega_h.create_uniform_grid_binary_field(mesh, [4, 4]) mask_data = mask_field.get_dof_holder_data().get_values() # Build a mesh-backed source field: f(x,y) = x + 2y. - omega_h_factory = pcms.LagrangeFunctionSpace.from_mesh( - mesh, 1, 1) + omega_h_factory = pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(mesh), + 1, + 1) omega_h_field = omega_h_factory.create_function() coords = _coordinates(omega_h_field) omega_h_data = np.zeros(_num_dof_holders(omega_h_field), @@ -165,8 +177,10 @@ def test_uniform_grid_to_omega_h_workflow(self, world): omega_h_data[i] = coords[i, 0] + 2.0 * coords[i, 1] omega_h_field.set_dof_holder_data(omega_h_data) - ug_factory = pcms.LagrangeFunctionSpace.from_uniform_grid( - grid, 1) + ug_factory = pcms.create_lagrange_space( + pcms.create_uniform_grid_discretization(grid), + 1, + 1) ug_field = ug_factory.create_function() # Transfer from unstructured mesh to uniform grid. @@ -194,10 +208,14 @@ def test_omega_h_to_omega_h_transfer(self, world): world, omega_h.Family.SIMPLEX, 1.0, 1.0, 0.0, 8, 8, 0, False, ) - src_factory = pcms.LagrangeFunctionSpace.from_mesh( - src_mesh, 1, 1) - tgt_factory = pcms.LagrangeFunctionSpace.from_mesh( - tgt_mesh, 1, 1) + src_factory = pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(src_mesh), + 1, + 1) + tgt_factory = pcms.create_lagrange_space( + pcms.backend.omega_h.create_discretization(tgt_mesh), + 1, + 1) src_field = src_factory.create_function() tgt_field = tgt_factory.create_function() diff --git a/test/test_GDI.cpp b/test/test_GDI.cpp index c2621501e..6abe66489 100644 --- a/test/test_GDI.cpp +++ b/test/test_GDI.cpp @@ -1,8 +1,8 @@ #include #include -#include "test_support.h" +#include "test_support.hpp" #include "pcms/coupler/coupler.hpp" -#include +#include #include static constexpr bool done = true; diff --git a/test/test_bounding_box.cpp b/test/test_bounding_box.cpp index f29f9567a..dc83280ba 100644 --- a/test/test_bounding_box.cpp +++ b/test/test_bounding_box.cpp @@ -1,5 +1,5 @@ #include -#include +#include using pcms::AABBox; using pcms::intersects; diff --git a/test/test_coordinate_transformation.cpp b/test/test_coordinate_transformation.cpp index c1fb509e0..0fa87f88e 100644 --- a/test/test_coordinate_transformation.cpp +++ b/test/test_coordinate_transformation.cpp @@ -2,15 +2,15 @@ #include #include #include -#include +#include #include -#include +#include #include #include #include -#include "pcms/field/coordinate_systems/cartesian.hpp" -#include "pcms/field/coordinate_systems/cylindrical.hpp" -#include "field_test_utils.h" +#include "pcms/utility/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_systems/cylindrical.hpp" +#include "field_test_utils.hpp" using Catch::Matchers::ContainsSubstring; using Catch::Matchers::WithinAbs; diff --git a/test/test_eqdsk.cpp b/test/test_eqdsk.cpp index 7096c9096..fdafca984 100644 --- a/test/test_eqdsk.cpp +++ b/test/test_eqdsk.cpp @@ -1,16 +1,16 @@ -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include #include -#include "field_test_utils.h" +#include "field_test_utils.hpp" #include #include -#include "pcms/field/coordinate_systems/cylindrical.hpp" +#include "pcms/utility/coordinate_systems/cylindrical.hpp" using Catch::Approx; using pcms::CoordinateSystem; diff --git a/test/test_error_handling.cpp b/test/test_error_handling.cpp index 000f511a1..79791d228 100644 --- a/test/test_error_handling.cpp +++ b/test/test_error_handling.cpp @@ -1,6 +1,6 @@ #include -#include "pcms/utility/assert.h" -#include "pcms/utility/print.h" +#include "pcms/utility/assert.hpp" +#include "pcms/utility/print.hpp" #include int raise_error(int code) diff --git a/test/test_evaluation_only_space.cpp b/test/test_evaluation_only_space.cpp index e76f2e1e6..b97ab57e6 100644 --- a/test/test_evaluation_only_space.cpp +++ b/test/test_evaluation_only_space.cpp @@ -5,13 +5,13 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include -#include -#include "field_test_utils.h" +#include +#include "field_test_utils.hpp" using Catch::Matchers::ContainsSubstring; using Catch::Matchers::WithinAbs; @@ -127,20 +127,20 @@ class MockSpace final : public pcms::FunctionSpace private: explicit MockSpace(int num_components) - : layout_(std::make_shared( + : layout_(std::make_shared( pcms::csys::CylindricalRThetaZ::Create(), num_components)) { } - std::shared_ptr layout_; + std::shared_ptr layout_; }; -std::shared_ptr MakePoloidalTarget( +std::shared_ptr MakePoloidalTarget( Omega_h::Mesh& mesh, int num_components) { - return pcms::LagrangeFunctionSpace::FromMesh( + return pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, num_components, pcms::csys::CylindricalRZ::Create(), "global", - pcms::LagrangeFunctionSpace::Backend::OmegaH); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); } } // namespace diff --git a/test/test_field_communication.cpp b/test/test_field_communication.cpp index 2a74e0602..664fdb2fe 100644 --- a/test/test_field_communication.cpp +++ b/test/test_field_communication.cpp @@ -8,13 +8,13 @@ #include #include #include -#include "pcms/coupler/field_communicator.hpp" +#include "pcms/coupler/detail/field_communicator.hpp" #include "pcms/coupler/coupler.hpp" -#include "pcms/field/function_space/lagrange.h" +#include "pcms/field/function_space/lagrange.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/field/data/simple.h" -#include "test_support.h" -#include "pcms/field/coordinate_systems/cartesian.hpp" +#include "pcms/field/simple_field_data.hpp" +#include "test_support.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" namespace ts = test_support; using pcms::Real; @@ -78,9 +78,9 @@ static void test_shared_layout(Omega_h::Library& lib, pcms::CouplerComm cpl("shared_layout_server", mpi_comm, true, redev::Partition{partition}); auto* app = cpl.AddApplication("shared_layout"); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::DefaultBackend, "shared"); + pcms::field::LagrangeFunctionSpace::DefaultBackend, "shared"); auto f1 = app->AddField(factory->CreateFunction("field_a")); PCMS_ALWAYS_ASSERT(app->GetLayoutCommunicatorCount() == 1); auto f2 = app->AddField(factory->CreateFunction("field_b")); @@ -97,9 +97,9 @@ static void test_shared_layout(Omega_h::Library& lib, pcms::CouplerComm cpl("shared_layout_client", mpi_comm, false, redev::Partition{}); auto* app = cpl.AddApplication("shared_layout"); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::DefaultBackend, "shared"); + pcms::field::LagrangeFunctionSpace::DefaultBackend, "shared"); auto f1 = app->AddField(factory->CreateFunction("field_a")); auto f2 = app->AddField(factory->CreateFunction("field_b")); app->SendPhase([&]() { @@ -120,7 +120,7 @@ void client1(MPI_Comm comm, Omega_h::Mesh& mesh, std::string comm_name, auto channel = rdv.CreateAdiosChannel("field2_chan1", params, redev::TransportType::BP4); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, order, 1, pcms::csys::Cartesian::Deferred()); auto layout = factory->GetLayout(); auto gids = layout->GetGidsHost(); @@ -135,10 +135,10 @@ void client1(MPI_Comm comm, Omega_h::Mesh& mesh, std::string comm_name, field.SetDOFHolderDataUncheckedHost( pcms::Rank2View(ids.data(), n, 1)); - pcms::FieldLayoutCommunicator layout_comm(comm_name + "1", comm, rdv, channel, - *layout); - pcms::FieldCommunicator field_comm(layout_comm.GetName(), - layout_comm, field); + pcms::coupler::FieldLayoutCommunicator layout_comm(comm_name + "1", comm, rdv, + channel, *layout); + pcms::coupler::FieldCommunicator field_comm(layout_comm.GetName(), + layout_comm, field); channel.BeginSendCommunicationPhase(); field_comm.Send(); @@ -152,17 +152,17 @@ void client2(MPI_Comm comm, Omega_h::Mesh& mesh, std::string comm_name, auto channel = rdv.CreateAdiosChannel("field2_chan2", params, redev::TransportType::BP4); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, order, 1, pcms::csys::Cartesian::Deferred()); auto layout = factory->GetLayout(); auto gids = layout->GetGidsHost(); const auto n = layout->GetNumOwnedDofHolder(); auto field = factory->CreateFunction(); - pcms::FieldLayoutCommunicator layout_comm(comm_name + "2", comm, rdv, channel, - *layout); - pcms::FieldCommunicator field_comm(layout_comm.GetName(), - layout_comm, field); + pcms::coupler::FieldLayoutCommunicator layout_comm(comm_name + "2", comm, rdv, + channel, *layout); + pcms::coupler::FieldCommunicator field_comm(layout_comm.GetName(), + layout_comm, field); channel.BeginReceiveCommunicationPhase(); field_comm.Receive(); @@ -213,7 +213,7 @@ void server(MPI_Comm comm, Omega_h::Mesh& mesh, std::string comm_name, auto channel2 = rdv.CreateAdiosChannel("field2_chan2", params, redev::TransportType::BP4); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, order, 1, pcms::csys::Cartesian::Deferred()); auto layout = factory->GetLayout(); const auto n = layout->GetNumOwnedDofHolder(); @@ -223,14 +223,14 @@ void server(MPI_Comm comm, Omega_h::Mesh& mesh, std::string comm_name, [=](int i) { ids[i] = 0; }); auto field = factory->CreateFunction(); - pcms::FieldLayoutCommunicator layout_comm1(comm_name + "1", comm, rdv, - channel1, *layout); - pcms::FieldLayoutCommunicator layout_comm2(comm_name + "2", comm, rdv, - channel2, *layout); - pcms::FieldCommunicator field_comm1(layout_comm1.GetName(), - layout_comm1, field); - pcms::FieldCommunicator field_comm2(layout_comm2.GetName(), - layout_comm2, field); + pcms::coupler::FieldLayoutCommunicator layout_comm1(comm_name + "1", comm, + rdv, channel1, *layout); + pcms::coupler::FieldLayoutCommunicator layout_comm2(comm_name + "2", comm, + rdv, channel2, *layout); + pcms::coupler::FieldCommunicator field_comm1( + layout_comm1.GetName(), layout_comm1, field); + pcms::coupler::FieldCommunicator field_comm2( + layout_comm2.GetName(), layout_comm2, field); channel1.BeginReceiveCommunicationPhase(); field_comm1.Receive(); diff --git a/test/test_field_copy.cpp b/test/test_field_copy.cpp index 754371c61..472e0d7d1 100644 --- a/test/test_field_copy.cpp +++ b/test/test_field_copy.cpp @@ -3,12 +3,12 @@ #include #include #include -#include "pcms/transfer/copy.h" -#include "pcms/field/function_space/lagrange.h" +#include "pcms/transfer/copy.hpp" +#include "pcms/field/function_space/lagrange.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/utility/assert.h" +#include "pcms/utility/assert.hpp" #include -#include "pcms/field/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" using pcms::Real; @@ -20,9 +20,9 @@ void test_copy(Omega_h::CommPtr world, int dim, int order, int num_components) auto mesh = Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1, 1, 1, nx, ny, nz, false); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, order, num_components, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::OmegaH); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); auto layout = factory->GetLayout(); int ndata = layout->GetNumOwnedDofHolder() * num_components; Omega_h::HostWrite ids(ndata); @@ -59,8 +59,8 @@ TEST_CASE("copy omega_h_field2 data") test_copy(lib.world(), 2, 1, 1); auto mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1, 1, 1, 100, 100, 0, false); - REQUIRE_THROWS_AS(pcms::LagrangeFunctionSpace::FromMesh( + REQUIRE_THROWS_AS(pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 2, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::OmegaH), + pcms::field::LagrangeFunctionSpace::Backend::OmegaH), pcms::pcms_error); } diff --git a/test/test_field_evaluation.cpp b/test/test_field_evaluation.cpp index 85a05a96e..5bd4c6e5a 100644 --- a/test/test_field_evaluation.cpp +++ b/test/test_field_evaluation.cpp @@ -2,14 +2,14 @@ #include #include #include -#include "pcms/field/function_space/lagrange.h" +#include "pcms/field/function_space/lagrange.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/utility/assert.h" -#include "field_test_utils.h" +#include "pcms/utility/assert.hpp" +#include "field_test_utils.hpp" #include #include #include -#include "pcms/field/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" using pcms::Real; @@ -31,7 +31,7 @@ TEST_CASE("evaluate linear 2d omega_h_field") auto lib = Omega_h::Library{}; auto mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1, 1, 0, 100, 100, 0, false); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred()); auto field = factory->CreateFunction(); @@ -49,9 +49,9 @@ TEST_CASE("evaluate quadratic 2d meshfields_field") auto lib = Omega_h::Library{}; auto mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1, 1, 0, 100, 100, 0, false); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 2, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::MeshFields); + pcms::field::LagrangeFunctionSpace::Backend::MeshFields); // Quadratic DOF holders span vertices and edge midpoints; the layout's DOF // coordinates cover both, so SetField samples sin_f at every holder. @@ -115,9 +115,9 @@ static void CheckMeshFieldsDofHolderCoordsAgainstManual(Omega_h::Library& lib, else if (order == 2) nodes_per_dim = {1, 1, 0, 0}; - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, order, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::MeshFields); + pcms::field::LagrangeFunctionSpace::Backend::MeshFields); auto layout = factory->GetLayout(); // Sanity-check the block layout: vertices then edges. @@ -167,8 +167,8 @@ TEST_CASE("evaluate quadratic 2d omega_h_field throws") auto mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1, 1, 0, 100, 100, 0, false); - REQUIRE_THROWS_AS(pcms::LagrangeFunctionSpace::FromMesh( + REQUIRE_THROWS_AS(pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 2, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::OmegaH), + pcms::field::LagrangeFunctionSpace::Backend::OmegaH), pcms::pcms_error); } diff --git a/test/test_field_exchange_planner.cpp b/test/test_field_exchange_planner.cpp index 1ebdd6fff..b3771babc 100644 --- a/test/test_field_exchange_planner.cpp +++ b/test/test_field_exchange_planner.cpp @@ -1,14 +1,15 @@ #include -#include -#include -#include "pcms/field/coordinate_systems/cartesian.hpp" +#include +#include +#include "pcms/utility/coordinate_systems/cartesian.hpp" TEST_CASE("Field exchange plans exclude GID message headers", "[field_exchange]") { Kokkos::View coords("coords", 4, 2); - pcms::PointCloudLayout layout(2, coords, pcms::csys::Cartesian::Deferred()); + pcms::backend::point_cloud::PointCloudLayout layout( + 2, coords, pcms::csys::Cartesian::Deferred()); // Two incoming messages. Each contains a five-entry entity-offset header // followed by two vertex GIDs. @@ -24,7 +25,7 @@ TEST_CASE("Field exchange plans exclude GID message headers", in.srcRanks = {0, 7}; in.offset = {0, 14}; - pcms::GenericFieldExchangePlanner planner; + pcms::coupler::GenericFieldExchangePlanner planner; const auto plan = planner.BuildReceivePlan( layout, pcms::GlobalIDView(received.data(), received.size()), @@ -40,9 +41,10 @@ TEST_CASE("GID messages insert headers around compact field payloads", "[field_exchange]") { Kokkos::View coords("coords", 4, 2); - pcms::PointCloudLayout layout(2, coords, pcms::csys::Cartesian::Deferred()); + pcms::backend::point_cloud::PointCloudLayout layout( + 2, coords, pcms::csys::Cartesian::Deferred()); - pcms::ExchangePlan plan; + pcms::coupler::ExchangePlan plan; plan.dest_ranks = {0, 1}; plan.offsets = {0, 2, 4}; plan.permutation = {0, 2, 1, 3}; @@ -51,7 +53,7 @@ TEST_CASE("GID messages insert headers around compact field payloads", Kokkos::View message( "gid_message", plan.msg_size + 2 * static_cast(pcms::ent_offsets_len)); - pcms::GenericFieldExchangePlanner planner; + pcms::coupler::GenericFieldExchangePlanner planner; planner.FillGidMessage(layout, plan, pcms::MakeRank1View(message)); const pcms::GO expected[] = { @@ -74,7 +76,8 @@ TEST_CASE("ExchangePlan permutation is negative for non-participating holders", // the received message, so holders 4 and 5 should have negative // permutation entries. Kokkos::View coords("coords", 6, 2); - pcms::PointCloudLayout layout(2, coords, pcms::csys::Cartesian::Deferred()); + pcms::backend::point_cloud::PointCloudLayout layout( + 2, coords, pcms::csys::Cartesian::Deferred()); const std::size_t header_len = static_cast(pcms::ent_offsets_len); @@ -89,7 +92,7 @@ TEST_CASE("ExchangePlan permutation is negative for non-participating holders", in.srcRanks = {0}; in.offset = {0, static_cast(msg_total)}; - pcms::GenericFieldExchangePlanner planner; + pcms::coupler::GenericFieldExchangePlanner planner; const auto plan = planner.BuildReceivePlan( layout, pcms::GlobalIDView(received.data(), received.size()), diff --git a/test/test_field_interpolation.cpp b/test/test_field_interpolation.cpp index 0a94e0594..6232c1d2f 100644 --- a/test/test_field_interpolation.cpp +++ b/test/test_field_interpolation.cpp @@ -4,14 +4,14 @@ #include #include #include -#include "pcms/transfer/interpolator.h" -#include "pcms/field/function_space/lagrange.h" +#include "pcms/transfer/interpolator.hpp" +#include "pcms/field/function_space/lagrange.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/utility/assert.h" -#include "field_test_utils.h" +#include "pcms/utility/assert.hpp" +#include "field_test_utils.hpp" #include #include -#include "pcms/field/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" using pcms::Real; @@ -26,7 +26,7 @@ TEST_CASE("interpolate linear 2d omega_h_field") auto world = lib.world(); auto mesh = Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1, 1, 0, 100, 100, 0, false); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred()); auto field = factory->CreateFunction(); auto interpolated = factory->CreateFunction(); @@ -54,9 +54,9 @@ TEST_CASE("interpolate quadratic 2d meshfields_field") auto world = lib.world(); auto mesh = Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1, 1, 0, 100, 100, 0, false); - auto factory2 = pcms::LagrangeFunctionSpace::FromMesh( + auto factory2 = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 2, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::MeshFields); + pcms::field::LagrangeFunctionSpace::Backend::MeshFields); auto field = factory2->CreateFunction(); auto interpolated = factory2->CreateFunction(); pcms::test::SetField( @@ -86,9 +86,9 @@ TEST_CASE("interpolate quadratic 2d omega_h_field throws") auto mesh = Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1, 1, 0, 100, 100, 0, false); - REQUIRE_THROWS_AS(pcms::LagrangeFunctionSpace::FromMesh( + REQUIRE_THROWS_AS(pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 2, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::OmegaH), + pcms::field::LagrangeFunctionSpace::Backend::OmegaH), pcms::pcms_error); } @@ -102,7 +102,7 @@ TEST_CASE("Interpolator: construct once, apply twice with different data") auto world = lib.world(); auto mesh = Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1, 1, 0, 100, 100, 0, false); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred()); auto source = factory->CreateFunction(); diff --git a/test/test_field_serializer.cpp b/test/test_field_serializer.cpp index 267564922..8f5bf13f7 100644 --- a/test/test_field_serializer.cpp +++ b/test/test_field_serializer.cpp @@ -1,27 +1,27 @@ #include #include -#include "pcms/configuration.h" -#include "pcms/coupler/field_serializer.h" -#include "pcms/field/coordinate_systems/cartesian.hpp" -#include "pcms/utility/arrays.h" +#include "pcms/configuration.hpp" +#include "pcms/coupler/detail/field_serializer.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" +#include "pcms/utility/arrays.hpp" #include #include #include #ifdef PCMS_ENABLE_OMEGA_H -#include "field_test_utils.h" -#include "pcms/field/function_space/lagrange.h" +#include "field_test_utils.hpp" +#include "pcms/field/function_space/lagrange.hpp" #include "pcms/field/function_space/polynomial_reconstruction.hpp" -#include "pcms/utility/uniform_grid.h" +#include "pcms/utility/uniform_grid.hpp" #include #endif #ifdef PCMS_ENABLE_XGC -#include "pcms/coupler/overlap_mask.h" -#include "pcms/field/data/xgc.h" -#include "pcms/field/function_space/xgc.h" +#include "pcms/coupler/overlap_mask.hpp" +#include "pcms/backends/xgc/field_data.hpp" +#include "pcms/backends/xgc/field_factory.hpp" #endif namespace @@ -46,7 +46,7 @@ void CheckSerializeDeserialize(pcms::Field& field) std::vector permutation(num_dof); std::iota(permutation.begin(), permutation.end(), pcms::LO{0}); - pcms::FieldSerializer serializer; + pcms::coupler::FieldSerializer serializer; REQUIRE(serializer.Serialize(field, pcms::make_array_view(buffer), pcms::make_const_array_view(permutation)) == static_cast(num_values)); @@ -71,11 +71,14 @@ void CheckSerializeDeserialize(pcms::Field& field) #endif #ifdef PCMS_ENABLE_XGC -pcms::ReverseClassificationVertex CreateDummyReverseClassification(int size) +pcms::backend::xgc::ReverseClassificationVertex +CreateDummyReverseClassification(int size) { - pcms::ReverseClassificationVertex rc; + pcms::backend::xgc::ReverseClassificationVertex rc; for (int i = 0; i < size; ++i) { - rc.Insert(i % 4 == 0 ? pcms::DimID{0, 0} : pcms::DimID{0, 1}, i); + rc.Insert(i % 4 == 0 ? pcms::backend::xgc::DimID{0, 0} + : pcms::backend::xgc::DimID{0, 1}, + i); } return rc; } @@ -93,16 +96,16 @@ TEST_CASE("Serializing an XGC field preserves inactive field entries") { static constexpr int data_size = 16; auto rc = CreateDummyReverseClassification(data_size); - pcms::XGCFieldFactory factory(rc, data_size); + pcms::backend::xgc::XGCFieldFactory factory(rc, data_size); std::vector data(data_size); std::iota(data.begin(), data.end(), 0.0); const auto original = data; auto field = factory.CreateField( - "", std::make_unique>( + "", std::make_unique>( factory.GetXGCLayout(), pcms::ValueBasis{}, pcms::make_array_view(data), MPI_COMM_SELF)); - pcms::FieldSerializer serializer; + pcms::coupler::FieldSerializer serializer; // Entries outside the overlap region are not exchanged. const pcms::OverlapMask overlap_mask(InXGCOverlap); @@ -152,7 +155,7 @@ TEST_CASE("FieldSerializer round-trips a polynomial-reconstruction field") std::vector coords{0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0}; pcms::Rank2View coords_view(coords.data(), 4, 2); - auto space = pcms::PolynomialReconstructionFunctionSpace::Create( + auto space = pcms::field::PolynomialReconstructionFunctionSpace::Create( pcms::CoordinateView( pcms::csys::Cartesian::Deferred(), coords_view)); auto field = space->CreateFunction(); @@ -171,7 +174,7 @@ TEST_CASE("FieldSerializer round-trips a uniform-grid field") grid.bot_left = {0.0, 0.0}; grid.edge_length = {10.0, 10.0}; grid.divisions = {3, 3}; - auto space = pcms::LagrangeFunctionSpace::FromUniformGrid( + auto space = pcms::field::LagrangeFunctionSpace::FromUniformGrid( grid, 1, pcms::csys::Cartesian::Deferred()); auto field = space->CreateFunction(); @@ -206,9 +209,9 @@ TEST_CASE("FieldSerializer round-trips a multi-component Omega_h field") auto lib = Omega_h::Library{}; auto mesh = pcms::test::BuildUnitSquare(lib, 0); constexpr int num_components = 3; - auto space = pcms::LagrangeFunctionSpace::FromMesh( + auto space = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, num_components, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::OmegaH); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); auto field = space->CreateFunction(); const int num_dof = field.GetLayout().GetNumOwnedDofHolder(); @@ -246,7 +249,7 @@ TEST_CASE("FieldSerializer preserves holders outside the exchange on receive") std::vector coords{0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0}; pcms::Rank2View coords_view(coords.data(), 4, 2); - auto space = pcms::PolynomialReconstructionFunctionSpace::Create( + auto space = pcms::field::PolynomialReconstructionFunctionSpace::Create( pcms::CoordinateView( pcms::csys::Cartesian::Deferred(), coords_view)); auto field = space->CreateFunction(); @@ -260,7 +263,7 @@ TEST_CASE("FieldSerializer preserves holders outside the exchange on receive") // the sender's overlap mask); they must keep their current values. std::vector permutation{0, -1, 1, -1}; std::vector buffer{50.0, 70.0}; - pcms::FieldSerializer serializer; + pcms::coupler::FieldSerializer serializer; serializer.Deserialize(field, pcms::make_const_array_view(buffer), pcms::make_const_array_view(permutation)); diff --git a/test/test_interpolation_class.cpp b/test/test_interpolation_class.cpp index 878f6288d..a9567df7d 100644 --- a/test/test_interpolation_class.cpp +++ b/test/test_interpolation_class.cpp @@ -7,10 +7,10 @@ #include #include -#include -#include -#include -#include "field_test_utils.h" +#include +#include +#include +#include "field_test_utils.hpp" #include #include @@ -106,11 +106,11 @@ TEST_CASE("Test MLSMeshInterpolation") pcms::printInfo("\n-------------------- Single Mesh Interpolation Test " "Started --------------------\n"); pcms::printInfo("Mesh based search...\n"); - auto mls_single = - pcms::MLSMeshInterpolation(source_mesh, 0.12, 15, 3, true, 0.0, 5.0); + auto mls_single = pcms::transfer::MLSMeshInterpolation( + source_mesh, 0.12, 15, 3, true, 0.0, 5.0); auto source_points_vec = pcms::test::CopyOmegaHRealsToVector( - pcms::get_entity_centroids(source_mesh, Omega_h::FACE)); + pcms::utility::get_entity_centroids(source_mesh, Omega_h::FACE)); auto source_points_view = pcms::make_array_view(source_points_vec); auto target_points_vec = @@ -118,7 +118,7 @@ TEST_CASE("Test MLSMeshInterpolation") auto target_points_view = pcms::make_array_view(target_points_vec); REQUIRE(source_mesh.dim() == 2); pcms::printInfo("Point cloud based search...\n"); - auto point_mls = pcms::MLSPointCloudInterpolation( + auto point_mls = pcms::transfer::MLSPointCloudInterpolation( source_points_view, target_points_view, 2, 0.12, 15, 3, true, 0.0, 5.0); Omega_h::Write sinxcosy_centroid(source_mesh.nfaces(), @@ -213,8 +213,8 @@ TEST_CASE("Test MLSMeshInterpolation") // translate_mesh(&target_mesh, Omega_h::Vector<2>{(1.0 - 0.999) / 2.0, // (1.0 - 0.999) / 2.0}); - auto mls_double = pcms::MLSMeshInterpolation(source_mesh, target_mesh, 0.12, - 15, 3, true, 0.0, 5.0); + auto mls_double = pcms::transfer::MLSMeshInterpolation( + source_mesh, target_mesh, 0.12, 15, 3, true, 0.0, 5.0); Omega_h::HostWrite source_data_host_write(source_sinxcosy_node); Omega_h::HostWrite interpolated_data_hwrite( @@ -272,7 +272,7 @@ TEST_CASE("MLSPointCloudInterpolation honors provided dimension in eval") auto source_values_view = pcms::make_array_view(source_values); auto output_values_view = pcms::make_array_view(output_values); - auto mls = pcms::MLSPointCloudInterpolation( + auto mls = pcms::transfer::MLSPointCloudInterpolation( source_points_view, target_points_view, 3, 2.5, 10, 1, true, 0.0, 5.0); REQUIRE_NOTHROW(mls.eval(source_values_view, output_values_view)); diff --git a/test/test_interpolation_on_ltx_mesh.cpp b/test/test_interpolation_on_ltx_mesh.cpp index 141ebfa86..d0b7af9ae 100644 --- a/test/test_interpolation_on_ltx_mesh.cpp +++ b/test/test_interpolation_on_ltx_mesh.cpp @@ -13,9 +13,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include #include @@ -78,8 +78,8 @@ TEST_CASE("Test Interpolation on LTX Mesh", "[interpolation]") // --------------------- Initialize Interpolators -------------- // const int degas2_num_elems = degas2_mesh.nelems(); - const auto degas2_mesh_centroids_host = - Omega_h::HostRead(pcms::get_entity_centroids(degas2_mesh, Omega_h::FACE)); + const auto degas2_mesh_centroids_host = Omega_h::HostRead( + pcms::utility::get_entity_centroids(degas2_mesh, Omega_h::FACE)); printf("[INFO] Degas2 Mesh loaded from %s with %d elements\n", degas2_mesh_filename.c_str(), degas2_num_elems); const auto degas2_mesh_centroids_view = @@ -91,10 +91,10 @@ TEST_CASE("Test Interpolation on LTX Mesh", "[interpolation]") ltx_mesh_base_filename.c_str(), xgc_num_nodes); const auto xgc_mesh_points_view = pcms::make_array_view(xgc_mesh_points); - auto xgc_to_degas2_interpolator = pcms::MLSPointCloudInterpolation( + auto xgc_to_degas2_interpolator = pcms::transfer::MLSPointCloudInterpolation( xgc_mesh_points_view, degas2_mesh_centroids_view, 2, 0.000001, 10, 1, true, 0.0, 50.0); - auto degas2_to_xgc_interpolator = pcms::MLSPointCloudInterpolation( + auto degas2_to_xgc_interpolator = pcms::transfer::MLSPointCloudInterpolation( degas2_mesh_centroids_view, xgc_mesh_points_view, 2, 0.01, 10, 1, true, 1e-3, 50.0); printf("[INFO] Interpolators initialized.\n"); diff --git a/test/test_intersections.cpp b/test/test_intersections.cpp index 36ccb766e..ebc9693ac 100644 --- a/test/test_intersections.cpp +++ b/test/test_intersections.cpp @@ -78,7 +78,7 @@ TEST_CASE("Mesh intersection test with source and target", "[intersection]") // ============================ // Compute intersection mapping // ============================ - auto intersection = intersectTargets(src_mesh, tgt_mesh); + auto intersection = pcms::transfer::intersectTargets(src_mesh, tgt_mesh); auto offsets = Omega_h::HostRead(intersection.tgt2src_offsets); auto indices = Omega_h::HostRead(intersection.tgt2src_indices); diff --git a/test/test_localization_factory.cpp b/test/test_localization_factory.cpp index c5de024f9..913dc9df3 100644 --- a/test/test_localization_factory.cpp +++ b/test/test_localization_factory.cpp @@ -3,28 +3,28 @@ #include #include -#include "pcms/field/layout/omega_h_entity.h" -#include "pcms/field/layout/omega_h_lagrange.h" -#include "pcms/field/layout/point_cloud.h" -#include "pcms/field/evaluator/mls_options.h" -#include "pcms/localization/adj_search.hpp" -#include "pcms/localization/localization_path_selection.h" -#include "pcms/localization/mesh_localization.h" -#include "pcms/localization/mls_support_helpers.h" -#include "pcms/localization/point_cloud_localization.h" -#include "pcms/discretization/discretization/omega_h.hpp" -#include "pcms/utility/arrays.h" -#include "pcms/utility/omega_h_array_utils.h" -#include "field_test_utils.h" -#include "pcms/field/coordinate_systems/cartesian.hpp" +#include "pcms/backends/omega_h/entity_layout.hpp" +#include "pcms/backends/omega_h/lagrange_layout.hpp" +#include "pcms/backends/point_cloud/layout.hpp" +#include "pcms/localization/mls_options.hpp" +#include "pcms/backends/omega_h/adj_search.hpp" +#include "pcms/field/localization_path_selection.hpp" +#include "pcms/localization/mesh_localization.hpp" +#include "pcms/localization/mls_support_helpers.hpp" +#include "pcms/backends/point_cloud/localization.hpp" +#include "pcms/backends/omega_h/discretization.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/omega_h_array_utils.hpp" +#include "field_test_utils.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" namespace { -std::shared_ptr MakeMeshEntityLayout( - Omega_h::Mesh& mesh, int entity_dim) +std::shared_ptr +MakeMeshEntityLayout(Omega_h::Mesh& mesh, int entity_dim) { - return std::make_shared( + return std::make_shared( mesh, entity_dim, 1, pcms::csys::Cartesian::Deferred()); } @@ -48,14 +48,16 @@ TEST_CASE( auto target_device = pcms::test::CreateDeviceCoordinateView( target_coords, pcms::csys::Cartesian::Deferred(), dim); - auto coords_dev = pcms::ConvertCoordsTo2D(source_coords, mesh.nverts(), dim); + auto coords_dev = + pcms::utility::ConvertCoordsTo2D(source_coords, mesh.nverts(), dim); - auto layout = std::make_shared( + auto layout = std::make_shared( dim, coords_dev, pcms::csys::Cartesian::Deferred()); - pcms::PointCloudLocalizationFactory factory(layout, options); + pcms::backend::point_cloud::PointCloudLocalizationFactory factory(layout, + options); auto actual = factory.Build(target_device.coordinate_view); - auto expected = pcms::BuildPointCloudSupports( + auto expected = pcms::localization::BuildPointCloudSupports( source_coords, source_coords, dim, options.radius, options.min_req_supports, options.adapt_radius); @@ -77,8 +79,8 @@ TEST_CASE("LocalizationFactory: vertex adjacency Build matches two-mesh " options.min_req_supports = 15; options.adapt_radius = true; - pcms::AdjacencyLocalizationFactory factory(source_mesh, Omega_h::VERT, - options); + pcms::localization::AdjacencyLocalizationFactory factory( + source_mesh, Omega_h::VERT, options); auto target_coords = pcms::test::CopyOmegaHRealsToVector(target_mesh.coords()); auto target_device = pcms::test::CreateDeviceCoordinateView( @@ -87,7 +89,7 @@ TEST_CASE("LocalizationFactory: vertex adjacency Build matches two-mesh " auto actual = factory.Build(target_device.coordinate_view); Omega_h::Real radius_sq = options.radius * options.radius; - auto expected = pcms::searchNeighbors( + auto expected = pcms::backend::omega_h::searchNeighbors( source_mesh, target_mesh, radius_sq, static_cast(options.min_req_supports), static_cast(3 * options.min_req_supports), @@ -103,11 +105,12 @@ TEST_CASE("Localization path selection: vertex source uses adjacency for " auto mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1, 1, 1, 8, 8, 0, false); - auto source_layout = std::make_shared( - mesh, 1, 1, pcms::csys::Cartesian::Deferred()); + auto source_layout = + std::make_shared( + mesh, 1, 1, pcms::csys::Cartesian::Deferred()); - REQUIRE(pcms::detail::SelectLocalizationPath(*source_layout) == - pcms::detail::LocalizationPath::VertexAdjacencySearch); + REQUIRE(pcms::field::detail::SelectLocalizationPath(*source_layout) == + pcms::field::detail::LocalizationPath::VertexAdjacencySearch); } TEST_CASE( @@ -118,12 +121,14 @@ TEST_CASE( Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1, 1, 1, 8, 8, 0, false); auto source_layout = MakeMeshEntityLayout(mesh, pcms::Face); - auto target_layout = std::make_shared( - mesh, 1, 1, pcms::csys::Cartesian::Deferred()); + auto target_layout = + std::make_shared( + mesh, 1, 1, pcms::csys::Cartesian::Deferred()); REQUIRE( - pcms::detail::SelectLocalizationPath(*source_layout, target_layout.get()) == - pcms::detail::LocalizationPath::CentroidToVertexAdjacencySearch); + pcms::field::detail::SelectLocalizationPath(*source_layout, + target_layout.get()) == + pcms::field::detail::LocalizationPath::CentroidToVertexAdjacencySearch); } TEST_CASE("Localization path selection: centroid source uses point-cloud " @@ -135,8 +140,8 @@ TEST_CASE("Localization path selection: centroid source uses point-cloud " auto source_layout = MakeMeshEntityLayout(mesh, pcms::Face); - REQUIRE(pcms::detail::SelectLocalizationPath(*source_layout) == - pcms::detail::LocalizationPath::PointCloudSupports); + REQUIRE(pcms::field::detail::SelectLocalizationPath(*source_layout) == + pcms::field::detail::LocalizationPath::PointCloudSupports); } TEST_CASE("LocalizationFactory: centroid-to-vertex Build correct on same-mesh " @@ -152,12 +157,13 @@ TEST_CASE("LocalizationFactory: centroid-to-vertex Build correct on same-mesh " options.adapt_radius = true; // Source: face centroids on the mesh; target: mesh vertices. - pcms::AdjacencyLocalizationFactory factory(mesh, Omega_h::FACE, options); + pcms::localization::AdjacencyLocalizationFactory factory(mesh, Omega_h::FACE, + options); auto actual = factory.BuildSameMeshCentroidToVertex(); // Reference: direct call to the single-mesh centroid-to-vertex overload. Omega_h::Real radius_sq = options.radius * options.radius; - auto expected = pcms::searchNeighbors( + auto expected = pcms::backend::omega_h::searchNeighbors( mesh, radius_sq, static_cast(options.min_req_supports), options.adapt_radius); @@ -178,8 +184,8 @@ TEST_CASE("LocalizationFactory: correct with different meshes") options.min_req_supports = 8; options.adapt_radius = true; - pcms::AdjacencyLocalizationFactory factory(source_mesh, Omega_h::FACE, - options); + pcms::localization::AdjacencyLocalizationFactory factory( + source_mesh, Omega_h::FACE, options); auto target_coords = pcms::test::CopyOmegaHRealsToVector(target_mesh.coords()); diff --git a/test/test_mesh_geometry.cpp b/test/test_mesh_geometry.cpp index 1c327b1b3..d44eeaf5d 100644 --- a/test/test_mesh_geometry.cpp +++ b/test/test_mesh_geometry.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include TEST_CASE("pcms::get_entity_centroids supports simplex mesh entities") { @@ -15,7 +15,7 @@ TEST_CASE("pcms::get_entity_centroids supports simplex mesh entities") auto mesh = Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1.0, 1.0, 1.0, 4, 4, 0, false); - auto centroids = pcms::get_entity_centroids(mesh, Omega_h::EDGE); + auto centroids = pcms::utility::get_entity_centroids(mesh, Omega_h::EDGE); REQUIRE(centroids.size() == mesh.nedges() * mesh.dim()); } @@ -24,7 +24,7 @@ TEST_CASE("pcms::get_entity_centroids supports simplex mesh entities") auto mesh = Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1.0, 1.0, 1.0, 4, 4, 0, false); - auto centroids = pcms::get_entity_centroids(mesh, Omega_h::FACE); + auto centroids = pcms::utility::get_entity_centroids(mesh, Omega_h::FACE); REQUIRE(centroids.size() == mesh.nfaces() * mesh.dim()); } @@ -33,7 +33,7 @@ TEST_CASE("pcms::get_entity_centroids supports simplex mesh entities") auto mesh = Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1.0, 1.0, 1.0, 3, 3, 3, false); - auto centroids = pcms::get_entity_centroids(mesh, Omega_h::EDGE); + auto centroids = pcms::utility::get_entity_centroids(mesh, Omega_h::EDGE); REQUIRE(centroids.size() == mesh.nedges() * mesh.dim()); } @@ -42,7 +42,7 @@ TEST_CASE("pcms::get_entity_centroids supports simplex mesh entities") auto mesh = Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1.0, 1.0, 1.0, 3, 3, 3, false); - auto centroids = pcms::get_entity_centroids(mesh, Omega_h::REGION); + auto centroids = pcms::utility::get_entity_centroids(mesh, Omega_h::REGION); REQUIRE(centroids.size() == mesh.nelems() * mesh.dim()); } @@ -51,7 +51,7 @@ TEST_CASE("pcms::get_entity_centroids supports simplex mesh entities") auto mesh = Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1.0, 1.0, 1.0, 2, 2, 0, false); - auto centroids = pcms::get_entity_centroids(mesh, Omega_h::VERT); + auto centroids = pcms::utility::get_entity_centroids(mesh, Omega_h::VERT); auto coords = mesh.coords(); REQUIRE(centroids.size() == coords.size()); } @@ -63,13 +63,13 @@ TEST_CASE("pcms::distance_squared handles 2D and 3D") { const Omega_h::Real p1[3] = {1.0, 2.0, 99.0}; const Omega_h::Real p2[3] = {4.0, 6.0, -5.0}; - REQUIRE(pcms::distance_squared(p1, p2, 2) == Catch::Approx(25.0)); + REQUIRE(pcms::utility::distance_squared(p1, p2, 2) == Catch::Approx(25.0)); } SECTION("3D distance") { const Omega_h::Real p1[3] = {1.0, 2.0, 3.0}; const Omega_h::Real p2[3] = {4.0, 6.0, 8.0}; - REQUIRE(pcms::distance_squared(p1, p2, 3) == Catch::Approx(50.0)); + REQUIRE(pcms::utility::distance_squared(p1, p2, 3) == Catch::Approx(50.0)); } } diff --git a/test/test_mesh_intersection_field_transfer.cpp b/test/test_mesh_intersection_field_transfer.cpp index 84ee7706b..689541e14 100644 --- a/test/test_mesh_intersection_field_transfer.cpp +++ b/test/test_mesh_intersection_field_transfer.cpp @@ -7,12 +7,13 @@ #include #include -#include -#include -#include "field_test_utils.h" +#include +#include +#include "field_test_utils.hpp" #include #include +#include "pcms/backends/omega_h/omega_h.hpp" namespace { @@ -53,7 +54,8 @@ TEST_CASE("OmegaHConservativeProjection reproduces constant and linear fields", auto source = source_space->CreateFunction(); auto target = target_space->CreateFunction(); - pcms::OmegaHConservativeProjection projection(*source_space, *target_space); + pcms::transfer::OmegaHConservativeProjection projection(*source_space, + *target_space); SECTION("constant field is preserved and conserved") { @@ -85,7 +87,7 @@ TEST_CASE("OmegaHConservativeProjection reproduces constant and linear fields", const auto target_values = pcms::FlattenToRank1View(target.GetDOFHolderDataHost().GetValues()); const auto tgt_coords_h = pcms::test::CopyCoordinatesToHost( - pcms::MakeConstRank2View(target_mesh.coords(), 2)); + pcms::backend::omega_h::MakeConstRank2View(target_mesh.coords(), 2)); for (Omega_h::LO i = 0; i < target_mesh.nverts(); ++i) { const double expected = tgt_coords_h(i, 0) + tgt_coords_h(i, 1); REQUIRE(target_values[i] == Catch::Approx(expected).margin(1e-9)); @@ -116,8 +118,8 @@ TEST_CASE("OmegaHConservativeProjection conserves the integral", GENERATE(pcms::MassMatrixType::Consistent, pcms::MassMatrixType::Lumped); CAPTURE(static_cast(mass_type)); - pcms::OmegaHConservativeProjection projection(*source_space, *target_space, - mass_type); + pcms::transfer::OmegaHConservativeProjection projection( + *source_space, *target_space, mass_type); pcms::test::SetField( source, OMEGA_H_LAMBDA(pcms::Real x, pcms::Real y) { @@ -157,8 +159,8 @@ TEST_CASE("OmegaHConservativeProjection with lumped mass reproduces constants, " auto source = source_space->CreateFunction(); auto target = target_space->CreateFunction(); - pcms::OmegaHConservativeProjection projection(*source_space, *target_space, - pcms::MassMatrixType::Lumped); + pcms::transfer::OmegaHConservativeProjection projection( + *source_space, *target_space, pcms::MassMatrixType::Lumped); SECTION("constant field is preserved and conserved") { @@ -250,7 +252,8 @@ TEST_CASE("OmegaHConservativeProjection writes reordered target GIDs in local " pcms::test::SetField( source, OMEGA_H_LAMBDA(pcms::Real x, pcms::Real y) { return x + 2.0 * y; }); - pcms::OmegaHConservativeProjection projection(*source_space, *target_space); + pcms::transfer::OmegaHConservativeProjection projection(*source_space, + *target_space); projection.Apply(source, target); const auto target_values = target.GetDOFHolderDataHost().GetValues(); @@ -288,7 +291,8 @@ TEST_CASE("OmegaHConservativeProjection maps sparse target GIDs to active " pcms::test::SetField( source, OMEGA_H_LAMBDA(pcms::Real x, pcms::Real y) { return x + 2.0 * y; }); - pcms::OmegaHConservativeProjection projection(*source_space, *target_space); + pcms::transfer::OmegaHConservativeProjection projection(*source_space, + *target_space); projection.Apply(source, target); const auto target_values = target.GetDOFHolderDataHost().GetValues(); @@ -324,7 +328,8 @@ TEST_CASE("OmegaHConservativeProjection P0 source to P1 target", auto source = source_space->CreateFunction(); auto target = target_space->CreateFunction(); - pcms::OmegaHConservativeProjection projection(*source_space, *target_space); + pcms::transfer::OmegaHConservativeProjection projection(*source_space, + *target_space); SECTION("constant field is preserved and conserved") { @@ -380,7 +385,8 @@ TEST_CASE("OmegaHConservativeProjection P1 source to P0 target", auto source = source_space->CreateFunction(); auto target = target_space->CreateFunction(); - pcms::OmegaHConservativeProjection projection(*source_space, *target_space); + pcms::transfer::OmegaHConservativeProjection projection(*source_space, + *target_space); SECTION("constant field is preserved and conserved") { @@ -414,7 +420,7 @@ TEST_CASE("OmegaHConservativeProjection P1 source to P0 target", const auto target_values = pcms::FlattenToRank1View(target.GetDOFHolderDataHost().GetValues()); const auto centroids_h = Omega_h::HostRead( - pcms::get_entity_centroids(target_mesh, target_mesh.dim())); + pcms::utility::get_entity_centroids(target_mesh, target_mesh.dim())); REQUIRE(static_cast(target_values.size()) == target_mesh.nelems()); for (Omega_h::LO e = 0; e < target_mesh.nelems(); ++e) { diff --git a/test/test_mesh_intersection_prefilter.cpp b/test/test_mesh_intersection_prefilter.cpp index 2a15b8e4b..272f272b9 100644 --- a/test/test_mesh_intersection_prefilter.cpp +++ b/test/test_mesh_intersection_prefilter.cpp @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include @@ -13,8 +13,9 @@ namespace { /// Assert the two intersection maps are identical: same per-target counts and /// the same source elements in the same order. -void require_intersections_identical(const pcms::IntersectionResults& filtered, - const pcms::IntersectionResults& exact) +void require_intersections_identical( + const pcms::transfer::IntersectionResults& filtered, + const pcms::transfer::IntersectionResults& exact) { const auto filtered_offsets = Omega_h::HostRead(filtered.tgt2src_offsets); const auto exact_offsets = Omega_h::HostRead(exact.tgt2src_offsets); @@ -35,8 +36,9 @@ void require_intersections_identical(const pcms::IntersectionResults& filtered, /// ignoring order. The order of a row is seed-then-BFS, and the seed is /// whichever containing element the point search reports first; a centroid /// lying on a shared face can legitimately be located in either neighbor. -void require_intersections_equivalent(const pcms::IntersectionResults& a, - const pcms::IntersectionResults& b) +void require_intersections_equivalent( + const pcms::transfer::IntersectionResults& a, + const pcms::transfer::IntersectionResults& b) { const auto a_offsets = Omega_h::HostRead(a.tgt2src_offsets); const auto b_offsets = Omega_h::HostRead(b.tgt2src_offsets); @@ -69,7 +71,7 @@ TEST_CASE("intersection prefilter rejects degenerate overlaps", {{0, 0, 0}, {0, 1, 0}, {0, 0, 1}, {-1, 0, 0}}}; const r3d::Few, 4> right{ {{0, 0, 0}, {0, 1, 0}, {0, 0, 1}, {1, 0, 0}}}; - REQUIRE(pcms::simplices_have_degenerate_overlap<3>(left, right)); + REQUIRE(pcms::transfer::simplices_have_degenerate_overlap<3>(left, right)); } SECTION("3D, overlapping tets are not rejected") { @@ -78,19 +80,19 @@ TEST_CASE("intersection prefilter rejects degenerate overlaps", // Same tet shifted slightly; the overlap has positive volume. const r3d::Few, 4> b{ {{0.1, 0.1, 0.1}, {1.1, 0.1, 0.1}, {0.1, 1.1, 0.1}, {0.1, 0.1, 1.1}}}; - REQUIRE_FALSE(pcms::simplices_have_degenerate_overlap<3>(a, b)); + REQUIRE_FALSE(pcms::transfer::simplices_have_degenerate_overlap<3>(a, b)); } SECTION("2D, edge-adjacent triangles are rejected") { const r3d::Few, 3> left{{{0, 0}, {0, 1}, {-1, 0}}}; const r3d::Few, 3> right{{{0, 0}, {0, 1}, {1, 0}}}; - REQUIRE(pcms::simplices_have_degenerate_overlap<2>(left, right)); + REQUIRE(pcms::transfer::simplices_have_degenerate_overlap<2>(left, right)); } SECTION("2D, overlapping triangles are not rejected") { const r3d::Few, 3> a{{{0, 0}, {1, 0}, {0, 1}}}; const r3d::Few, 3> b{{{0.1, 0.1}, {1.1, 0.1}, {0.1, 1.1}}}; - REQUIRE_FALSE(pcms::simplices_have_degenerate_overlap<2>(a, b)); + REQUIRE_FALSE(pcms::transfer::simplices_have_degenerate_overlap<2>(a, b)); } } @@ -110,8 +112,8 @@ TEST_CASE("intersection prefilter preserves the intersection map", auto target = Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1, 1, 0, 8, 8, 0, false); require_intersections_identical( - pcms::intersectTargets(source, target, true), - pcms::intersectTargets(source, target, false)); + pcms::transfer::intersectTargets(source, target, true), + pcms::transfer::intersectTargets(source, target, false)); } SECTION("2D, nested resolutions") { @@ -120,8 +122,8 @@ TEST_CASE("intersection prefilter preserves the intersection map", auto target = Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1, 1, 0, 4, 4, 0, false); require_intersections_identical( - pcms::intersectTargets(source, target, true), - pcms::intersectTargets(source, target, false)); + pcms::transfer::intersectTargets(source, target, true), + pcms::transfer::intersectTargets(source, target, false)); } SECTION("2D, non-nested resolutions") { @@ -130,8 +132,8 @@ TEST_CASE("intersection prefilter preserves the intersection map", auto target = Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1, 1, 0, 5, 3, 0, false); require_intersections_identical( - pcms::intersectTargets(source, target, true), - pcms::intersectTargets(source, target, false)); + pcms::transfer::intersectTargets(source, target, true), + pcms::transfer::intersectTargets(source, target, false)); } SECTION("3D, identical meshes") { @@ -140,8 +142,8 @@ TEST_CASE("intersection prefilter preserves the intersection map", auto target = Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1, 1, 1, 4, 4, 4, false); require_intersections_identical( - pcms::intersectTargets(source, target, true), - pcms::intersectTargets(source, target, false)); + pcms::transfer::intersectTargets(source, target, true), + pcms::transfer::intersectTargets(source, target, false)); } SECTION("3D, nested resolutions") { @@ -150,8 +152,8 @@ TEST_CASE("intersection prefilter preserves the intersection map", auto target = Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1, 1, 1, 3, 3, 3, false); require_intersections_identical( - pcms::intersectTargets(source, target, true), - pcms::intersectTargets(source, target, false)); + pcms::transfer::intersectTargets(source, target, true), + pcms::transfer::intersectTargets(source, target, false)); } SECTION("3D, non-nested resolutions") { @@ -160,8 +162,8 @@ TEST_CASE("intersection prefilter preserves the intersection map", auto target = Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1, 1, 1, 2, 4, 3, false); require_intersections_identical( - pcms::intersectTargets(source, target, true), - pcms::intersectTargets(source, target, false)); + pcms::transfer::intersectTargets(source, target, true), + pcms::transfer::intersectTargets(source, target, false)); } } @@ -182,11 +184,11 @@ TEST_CASE("intersection map is independent of the supplied source search", Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1, 1, 0, 7, 11, 0, false); auto target = Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1, 1, 0, 5, 3, 0, false); - const pcms::GridPointSearchVariant search{ - std::in_place_type, source, 3, 3}; + const pcms::localization::GridPointSearchVariant search{ + std::in_place_type, source, 3, 3}; require_intersections_equivalent( - pcms::intersectTargets(source, target, search), - pcms::intersectTargets(source, target)); + pcms::transfer::intersectTargets(source, target, search), + pcms::transfer::intersectTargets(source, target)); } SECTION("3D, coarse caller-supplied grid") { @@ -194,11 +196,12 @@ TEST_CASE("intersection map is independent of the supplied source search", Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1, 1, 1, 5, 3, 4, false); auto target = Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1, 1, 1, 2, 4, 3, false); - const pcms::GridPointSearchVariant search{ - std::in_place_type, source, 2, 2, 2}; + const pcms::localization::GridPointSearchVariant search{ + std::in_place_type, source, 2, 2, + 2}; require_intersections_equivalent( - pcms::intersectTargets(source, target, search), - pcms::intersectTargets(source, target)); + pcms::transfer::intersectTargets(source, target, search), + pcms::transfer::intersectTargets(source, target)); } SECTION("a search of the wrong dimension is rejected") { @@ -208,9 +211,9 @@ TEST_CASE("intersection map is independent of the supplied source search", Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1, 1, 1, 2, 2, 2, false); auto flat = Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1, 1, 0, 2, 2, 0, false); - const pcms::GridPointSearchVariant search{ - std::in_place_type, flat, 2, 2}; - REQUIRE_THROWS_AS(pcms::intersectTargets(source, target, search), + const pcms::localization::GridPointSearchVariant search{ + std::in_place_type, flat, 2, 2}; + REQUIRE_THROWS_AS(pcms::transfer::intersectTargets(source, target, search), pcms::pcms_error); } } diff --git a/test/test_mfem_adapter.cpp b/test/test_mfem_adapter.cpp index ba5b869a0..9da794669 100644 --- a/test/test_mfem_adapter.cpp +++ b/test/test_mfem_adapter.cpp @@ -1,10 +1,10 @@ #include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include #include @@ -31,7 +31,8 @@ TEST_CASE("MFEM vertex-scalar field adapter", "[mfem]") SECTION("layout reports vertex-scalar properties") { - pcms::MFEMLayout layout(pmesh, pfes, pcms::csys::Cartesian::Deferred()); + pcms::backend::mfem::MFEMLayout layout(pmesh, pfes, + pcms::csys::Cartesian::Deferred()); REQUIRE(layout.GetNumComponents() == 1); REQUIRE(layout.GetDimension() == 2); @@ -63,8 +64,8 @@ TEST_CASE("MFEM vertex-scalar field adapter", "[mfem]") mfem::FunctionCoefficient coeff(LinearField); gf.ProjectCoefficient(coeff); - pcms::MFEMFieldFactory factory(pmesh, pfes, gf, - pcms::csys::Cartesian::Deferred(), "mfem"); + pcms::backend::mfem::MFEMFieldFactory factory( + pmesh, pfes, gf, pcms::csys::Cartesian::Deferred(), "mfem"); auto field = factory.CreateField("data"); const auto& layout = field.GetLayout(); @@ -109,8 +110,8 @@ TEST_CASE("MFEM vertex-scalar field adapter", "[mfem]") mfem::FunctionCoefficient coeff(LinearField); gf.ProjectCoefficient(coeff); - pcms::MFEMFieldFactory factory(pmesh, pfes, gf, - pcms::csys::Cartesian::Deferred(), "mfem"); + pcms::backend::mfem::MFEMFieldFactory factory( + pmesh, pfes, gf, pcms::csys::Cartesian::Deferred(), "mfem"); auto field = factory.CreateField("source"); const auto& layout = field.GetLayout(); @@ -123,7 +124,7 @@ TEST_CASE("MFEM vertex-scalar field adapter", "[mfem]") } Kokkos::View buffer("buffer", n); - pcms::FieldSerializer serializer; + pcms::coupler::FieldSerializer serializer; serializer.Serialize(field, pcms::make_array_view(buffer), pcms::make_const_array_view(perm)); @@ -131,7 +132,8 @@ TEST_CASE("MFEM vertex-scalar field adapter", "[mfem]") mfem::ParGridFunction gf2(&pfes); gf2 = 0.0; auto field2 = factory.CreateField( - "target", std::make_unique(pfes, gf2)); + "target", + std::make_unique(pfes, gf2)); serializer.Deserialize(field2, pcms::make_const_array_view(buffer), pcms::make_const_array_view(perm)); diff --git a/test/test_mfem_coupling.cpp b/test/test_mfem_coupling.cpp index 495495af0..d7a05f9d9 100644 --- a/test/test_mfem_coupling.cpp +++ b/test/test_mfem_coupling.cpp @@ -1,10 +1,10 @@ // Two-application coupling test for the MFEM field adapter. #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include @@ -76,12 +76,12 @@ int RunClient(MPI_Comm comm) redev::Partition{}); auto* app = cpl.AddApplication("mfem_app"); - pcms::MFEMFieldFactory factory(pmesh, pfes, gf, - pcms::csys::Cartesian::Deferred(), LayoutName); + pcms::backend::mfem::MFEMFieldFactory factory( + pmesh, pfes, gf, pcms::csys::Cartesian::Deferred(), LayoutName); auto layout = factory.GetLayout(); - auto overlap_view = - pcms::MFEMLayout::OverlapMaskFromAttribute(pmesh, TargetAttribute); + auto overlap_view = pcms::backend::mfem::MFEMLayout::OverlapMaskFromAttribute( + pmesh, TargetAttribute); app->SetLayoutOverlapMask( LayoutName, std::make_unique( @@ -114,8 +114,8 @@ int RunServer(MPI_Comm comm) MakeRCBPartition(pmesh.SpaceDimension())); auto* app = cpl.AddApplication("mfem_app"); - pcms::MFEMFieldFactory factory(pmesh, pfes, gf, - pcms::csys::Cartesian::Deferred(), LayoutName); + pcms::backend::mfem::MFEMFieldFactory factory( + pmesh, pfes, gf, pcms::csys::Cartesian::Deferred(), LayoutName); auto layout = factory.GetLayout(); auto handle = app->AddField(factory.CreateField(FieldName)); @@ -126,8 +126,8 @@ int RunServer(MPI_Comm comm) app->ReceivePhase([&]() { handle.Receive(); }); - auto overlap = - pcms::MFEMLayout::OverlapMaskFromAttribute(pmesh, TargetAttribute); + auto overlap = pcms::backend::mfem::MFEMLayout::OverlapMaskFromAttribute( + pmesh, TargetAttribute); auto gids = layout->GetGidsHost(); auto received = handle.GetField().GetDOFHolderDataHost().GetValues(); diff --git a/test/test_mls_basis.cpp b/test/test_mls_basis.cpp index 76769f990..2bbb6746f 100644 --- a/test/test_mls_basis.cpp +++ b/test/test_mls_basis.cpp @@ -15,8 +15,8 @@ TEST_CASE("basis test") const int degree = 3; Kokkos::View array("array", degree, dim); Kokkos::deep_copy(array, 0); - pcms::detail::calculate_basis_slice_lengths(array); - auto size = pcms::detail::calculate_basis_vector_size(array); + pcms::field::detail::calculate_basis_slice_lengths(array); + auto size = pcms::field::detail::calculate_basis_vector_size(array); int expected[degree][dim] = {{1, 1, 1}, {1, 2, 3}, {1, 3, 6}}; @@ -45,7 +45,7 @@ TEST_CASE("basis test") KOKKOS_LAMBDA(const pcms::member_type& team) { int i = team.league_rank(); pcms::ScratchVecView basis_vector(team.team_scratch(0), size); - pcms::detail::fill(0, team, basis_vector); + pcms::field::detail::fill(0, team, basis_vector); double target_point[MAX_DIM] = {}; @@ -53,7 +53,8 @@ TEST_CASE("basis test") target_point[j] = coords[i][j]; } - pcms::detail::eval_basis_vector(d_array, target_point, basis_vector); + pcms::field::detail::eval_basis_vector(d_array, target_point, + basis_vector); Kokkos::parallel_for(Kokkos::TeamThreadRange(team, size), [=](int j) { results(i, j) = basis_vector(j); }); @@ -107,9 +108,9 @@ TEST_CASE("basis test") const int degree = 1; Kokkos::View array("array", degree, dim); Kokkos::deep_copy(array, 0); - pcms::detail::calculate_basis_slice_lengths(array); + pcms::field::detail::calculate_basis_slice_lengths(array); - auto size = pcms::detail::calculate_basis_vector_size(array); + auto size = pcms::field::detail::calculate_basis_vector_size(array); int expected[degree][dim] = { {1, 1, 1}, @@ -149,7 +150,8 @@ TEST_CASE("basis test") target_point[j] = coords[i][j]; } - pcms::detail::eval_basis_vector(d_array, target_point, basis_vector); + pcms::field::detail::eval_basis_vector(d_array, target_point, + basis_vector); Kokkos::parallel_for(Kokkos::TeamThreadRange(team, size), [=](int j) { results(i, j) = basis_vector(j); }); @@ -185,13 +187,14 @@ TEST_CASE("basis test") Kokkos::View host_slice_length("array", degree, dim); Kokkos::deep_copy(host_slice_length, 0); - pcms::detail::calculate_basis_slice_lengths(host_slice_length); + pcms::field::detail::calculate_basis_slice_lengths(host_slice_length); pcms::IntDeviceMatView slice_length("slice array in device", degree, dim); auto slice_length_hd = Kokkos::create_mirror_view(slice_length); Kokkos::deep_copy(slice_length_hd, host_slice_length); Kokkos::deep_copy(slice_length, slice_length_hd); - auto size = pcms::detail::calculate_basis_vector_size(host_slice_length); + auto size = + pcms::field::detail::calculate_basis_vector_size(host_slice_length); int nvertices_target = 2; int nsupports = 5; Kokkos::View points("vandermonde matrix", nvertices_target, @@ -243,7 +246,7 @@ TEST_CASE("basis test") Kokkos::parallel_for( Kokkos::TeamThreadRange(team, nsupports), [=](int j) { - pcms::detail::create_vandermonde_matrix( + pcms::field::detail::create_vandermonde_matrix( local_source_points, j, slice_length, vandermonde_matrix); }); diff --git a/test/test_normalisation.cpp b/test/test_normalisation.cpp index 881350be1..228b1ab9f 100644 --- a/test/test_normalisation.cpp +++ b/test/test_normalisation.cpp @@ -2,9 +2,9 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include #include #include @@ -63,9 +63,9 @@ TEST_CASE("test_normalization_routine") int num_supports = nsupports[league_rank]; pcms::ScratchMatView local_supports(team.team_scratch(1), num_supports, dim); - pcms::detail::fill(0, team, local_supports); + pcms::field::detail::fill(0, team, local_supports); - double target_point[MAX_DIM] = {}; + double target_point[PCMS_MAX_DIM] = {}; for (int i = 0; i < dim; ++i) { target_point[i] = target_coordinates[league_rank][i]; @@ -91,7 +91,8 @@ TEST_CASE("test_normalization_routine") }); team.team_barrier(); - pcms::detail::normalize_supports(team, target_point, local_supports); + pcms::field::detail::normalize_supports(team, target_point, + local_supports); team.team_barrier(); Kokkos::parallel_for( diff --git a/test/test_ohClassPtn.cpp b/test/test_ohClassPtn.cpp index e27b494ed..0fdc3d7aa 100644 --- a/test/test_ohClassPtn.cpp +++ b/test/test_ohClassPtn.cpp @@ -4,8 +4,8 @@ #include #include #include -#include "pcms.h" -#include "test_support.h" +#include "pcms/pcms.hpp" +#include "test_support.hpp" namespace ts = test_support; diff --git a/test/test_ohClassPtn_appRibPtn.cpp b/test/test_ohClassPtn_appRibPtn.cpp index a6680ce19..cca59b51b 100644 --- a/test/test_ohClassPtn_appRibPtn.cpp +++ b/test/test_ohClassPtn_appRibPtn.cpp @@ -6,8 +6,8 @@ #include #include #include // divide_no_remainder -#include "pcms.h" -#include "test_support.h" +#include "pcms/pcms.hpp" +#include "test_support.hpp" namespace ts = test_support; diff --git a/test/test_ohOverlap.cpp b/test/test_ohOverlap.cpp index c75614b38..16c2cd7de 100644 --- a/test/test_ohOverlap.cpp +++ b/test/test_ohOverlap.cpp @@ -6,10 +6,10 @@ #include #include #include // divide_no_remainder -#include "pcms.h" -#include "test_support.h" -#include -#include "pcms/utility/types.h" +#include "pcms/pcms.hpp" +#include "test_support.hpp" +#include +#include "pcms/utility/types.hpp" namespace ts = test_support; diff --git a/test/test_omega_h_3d_analytic_mass.cpp b/test/test_omega_h_3d_analytic_mass.cpp index 4a80a634c..ab3851fad 100644 --- a/test/test_omega_h_3d_analytic_mass.cpp +++ b/test/test_omega_h_3d_analytic_mass.cpp @@ -3,12 +3,13 @@ #include #include #include -#include -#include +#include +#include #include #include -#include "field_test_utils.h" +#include "field_test_utils.hpp" #include +#include "pcms/backends/omega_h/omega_h.hpp" // Reference corner tet: // v0=(0,0,0), v1=(1,0,0), v2=(0,1,0), v3=(0,0,1) @@ -33,12 +34,11 @@ TEST_CASE("OmegaHMassIntegrator (3D): P1 mass on reference tet matches " constexpr pcms::Real M_off = V / 20.0; // 1/120 auto space = pcms::test::MakeP1Space(mesh); - auto integrator = pcms::BuildOmegaHMassIntegrator(*space); + auto integrator = pcms::transfer::BuildOmegaHMassIntegrator(*space); Mat mat = integrator->GetMatrix(); - const auto layout = - std::dynamic_pointer_cast( - space->GetLayout()); + const auto layout = std::dynamic_pointer_cast< + const pcms::backend::omega_h::OmegaHLagrangeLayout>(space->GetLayout()); REQUIRE(layout != nullptr); // PETSc rows are active indices = global_to_local(local_vertex). @@ -76,7 +76,7 @@ TEST_CASE("OmegaHMassIntegrator (3D): P0 mass on reference tet equals volume", constexpr pcms::Real V = 1.0 / 6.0; auto space = pcms::test::MakeP0Space(mesh); - auto integrator = pcms::BuildOmegaHMassIntegrator(*space); + auto integrator = pcms::transfer::BuildOmegaHMassIntegrator(*space); Mat mat = integrator->GetMatrix(); PetscInt r = 0; @@ -100,7 +100,7 @@ TEST_CASE("OmegaHConservativeProjection (3D): same-mesh reference tet is " auto space = pcms::test::MakeP1Space(mesh); auto source = space->CreateFunction(); auto target = space->CreateFunction(); - pcms::OmegaHConservativeProjection projection(*space, *space); + pcms::transfer::OmegaHConservativeProjection projection(*space, *space); SECTION("constant field") { const double c = 2.5; @@ -125,7 +125,7 @@ TEST_CASE("OmegaHConservativeProjection (3D): same-mesh reference tet is " const auto values = pcms::FlattenToRank1View(target.GetDOFHolderDataHost().GetValues()); const auto coords_h = pcms::test::CopyCoordinatesToHost( - pcms::MakeConstRank2View(mesh.coords(), 3)); + pcms::backend::omega_h::MakeConstRank2View(mesh.coords(), 3)); for (Omega_h::LO i = 0; i < 4; ++i) { const double expected = 1.0 + coords_h(i, 0) + 2.0 * coords_h(i, 1) + 3.0 * coords_h(i, 2); diff --git a/test/test_omega_h_3d_conservative_projection.cpp b/test/test_omega_h_3d_conservative_projection.cpp index 807c69701..565407abb 100644 --- a/test/test_omega_h_3d_conservative_projection.cpp +++ b/test/test_omega_h_3d_conservative_projection.cpp @@ -8,13 +8,14 @@ #include #include #include -#include -#include -#include -#include -#include "field_test_utils.h" +#include +#include +#include +#include +#include "field_test_utils.hpp" #include +#include "pcms/backends/omega_h/omega_h.hpp" TEST_CASE("OmegaHConservativeProjection (3D tets) reproduces constant and " "linear fields", @@ -32,7 +33,8 @@ TEST_CASE("OmegaHConservativeProjection (3D tets) reproduces constant and " auto source = source_space->CreateFunction(); auto target = target_space->CreateFunction(); - pcms::OmegaHConservativeProjection projection(*source_space, *target_space); + pcms::transfer::OmegaHConservativeProjection projection(*source_space, + *target_space); SECTION("constant field is preserved and conserved") { @@ -66,7 +68,7 @@ TEST_CASE("OmegaHConservativeProjection (3D tets) reproduces constant and " const auto target_values = pcms::FlattenToRank1View(target.GetDOFHolderDataHost().GetValues()); const auto tgt_coords_h = pcms::test::CopyCoordinatesToHost( - pcms::MakeConstRank2View(target_mesh.coords(), 3)); + pcms::backend::omega_h::MakeConstRank2View(target_mesh.coords(), 3)); for (Omega_h::LO i = 0; i < target_mesh.nverts(); ++i) { const double expected = 1.0 + tgt_coords_h(i, 0) + 2.0 * tgt_coords_h(i, 1) + @@ -94,7 +96,8 @@ TEST_CASE("OmegaHConservativeProjection (3D tets) conserves the integral for a " auto source = source_space->CreateFunction(); auto target = target_space->CreateFunction(); - pcms::OmegaHConservativeProjection projection(*source_space, *target_space); + pcms::transfer::OmegaHConservativeProjection projection(*source_space, + *target_space); pcms::test::SetField( source, KOKKOS_LAMBDA(pcms::Real x, pcms::Real y, pcms::Real z) { @@ -162,7 +165,7 @@ TEST_CASE("Interpolation transfer (3D tets) reproduces a linear field", const auto target_values = pcms::FlattenToRank1View(target.GetDOFHolderDataHost().GetValues()); const auto tgt_coords_h = pcms::test::CopyCoordinatesToHost( - pcms::MakeConstRank2View(target_mesh.coords(), 3)); + pcms::backend::omega_h::MakeConstRank2View(target_mesh.coords(), 3)); for (Omega_h::LO i = 0; i < target_mesh.nverts(); ++i) { const double expected = 1.0 + tgt_coords_h(i, 0) + 2.0 * tgt_coords_h(i, 1) + 3.0 * tgt_coords_h(i, 2); @@ -194,7 +197,7 @@ TEST_CASE("OmegaHControlVariateProjection (3D tets) is exact for target-space " return 1.0 + x + 2.0 * y + 3.0 * z; }); - pcms::OmegaHControlVariateProjection projection( + pcms::transfer::OmegaHControlVariateProjection projection( *source_space, *target_space, /*samples_per_element=*/8, pcms::MonteCarloSampling::UniformRandom, /*seed=*/12345); projection.Apply(source, target); @@ -202,7 +205,7 @@ TEST_CASE("OmegaHControlVariateProjection (3D tets) is exact for target-space " const auto target_values = pcms::FlattenToRank1View(target.GetDOFHolderDataHost().GetValues()); const auto tgt_coords_h = pcms::test::CopyCoordinatesToHost( - pcms::MakeConstRank2View(target_mesh.coords(), 3)); + pcms::backend::omega_h::MakeConstRank2View(target_mesh.coords(), 3)); for (Omega_h::LO i = 0; i < target_mesh.nverts(); ++i) { const double expected = 1.0 + tgt_coords_h(i, 0) + 2.0 * tgt_coords_h(i, 1) + 3.0 * tgt_coords_h(i, 2); diff --git a/test/test_omega_h_field2_outofbounds.cpp b/test/test_omega_h_field2_outofbounds.cpp index 5a909e527..89a206a22 100644 --- a/test/test_omega_h_field2_outofbounds.cpp +++ b/test/test_omega_h_field2_outofbounds.cpp @@ -3,14 +3,14 @@ #include #include #include -#include "pcms/field/function_space/lagrange.h" -#include "pcms/field/function_space/spline.h" +#include "pcms/field/function_space/lagrange.hpp" +#include "pcms/field/function_space/spline.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/utility/uniform_grid.h" -#include "field_test_utils.h" +#include "pcms/utility/uniform_grid.hpp" +#include "field_test_utils.hpp" #include #include -#include "pcms/field/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" using pcms::Real; @@ -20,7 +20,7 @@ TEST_CASE("omega_h_field2 out of bounds FILL mode") auto world = lib.world(); auto mesh = Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1, 1, 0, 10, 10, 0, false); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred()); auto field = factory->CreateFunction(); pcms::test::SetField(field, OMEGA_H_LAMBDA(Real x, Real y) { return x + y; }); @@ -50,7 +50,7 @@ TEST_CASE("uniform_grid_field out of bounds FILL mode") grid.edge_length = {1.0, 1.0}; grid.divisions = {N, N}; - auto factory = pcms::LagrangeFunctionSpace::FromUniformGrid( + auto factory = pcms::field::LagrangeFunctionSpace::FromUniformGrid( grid, 1, pcms::csys::Cartesian::Deferred(), 1); auto field = factory->CreateFunction(); pcms::test::SetField(field, OMEGA_H_LAMBDA(Real x, Real y) { return x + y; }); @@ -80,7 +80,7 @@ TEST_CASE("spline_field out of bounds FILL mode") grid.edge_length = {1.0, 1.0}; grid.divisions = {N, N}; - auto factory = pcms::SplineFunctionSpace::FromUniformGrid( + auto factory = pcms::field::SplineFunctionSpace::FromUniformGrid( grid, pcms::csys::Cartesian::Deferred()); auto field = factory->CreateFunction(); pcms::test::SetField(field, OMEGA_H_LAMBDA(Real x, Real y) { return x + y; }); diff --git a/test/test_omega_h_form_integrator_utils.cpp b/test/test_omega_h_form_integrator_utils.cpp index 6f3865cc6..625fa012e 100644 --- a/test/test_omega_h_form_integrator_utils.cpp +++ b/test/test_omega_h_form_integrator_utils.cpp @@ -42,12 +42,12 @@ std::pair DecomposeFromCentroid(const r3d::Polytope<3>& poly) double total_vol = 0.0; int ntri = 0; - pcms::detail::ForEachPolytopeFaceTriangle(poly, [&](const r3d::Vector<3>& a, - const r3d::Vector<3>& b, - const r3d::Vector<3>& c) { - total_vol += TetVolume(apex, a, b, c); - ++ntri; - }); + pcms::transfer::detail::ForEachPolytopeFaceTriangle( + poly, [&](const r3d::Vector<3>& a, const r3d::Vector<3>& b, + const r3d::Vector<3>& c) { + total_vol += TetVolume(apex, a, b, c); + ++ntri; + }); return {total_vol, ntri}; } @@ -134,7 +134,7 @@ TEST_CASE("ForEachPolytopeBoundarySimplex: a triangle yields its 3 edges once, " int nedges = 0; double shoelace = 0.0; - pcms::detail::ForEachPolytopeBoundarySimplex( + pcms::transfer::detail::ForEachPolytopeBoundarySimplex( poly, [&](const r3d::Few, 2>& e) { shoelace += 0.5 * (e[0][0] * e[1][1] - e[1][0] * e[0][1]); ++nedges; diff --git a/test/test_omega_h_intersection_coverage.cpp b/test/test_omega_h_intersection_coverage.cpp index b631d325f..fedf08763 100644 --- a/test/test_omega_h_intersection_coverage.cpp +++ b/test/test_omega_h_intersection_coverage.cpp @@ -7,15 +7,15 @@ #include #include -#include +#include #include #include -#include +#include #include #include -#include "field_test_utils.h" +#include "field_test_utils.hpp" namespace { @@ -35,8 +35,8 @@ std::vector CoveragePerTargetElement(Omega_h::Mesh& source_mesh, // Lumped: for a P0 target the mass matrix is diagonal either way, so this // is an exact division by the element volume and adds no error of its own. - pcms::OmegaHConservativeProjection projection(*source_space, *target_space, - pcms::MassMatrixType::Lumped); + pcms::transfer::OmegaHConservativeProjection projection( + *source_space, *target_space, pcms::MassMatrixType::Lumped); projection.Apply(source, target); const auto values = diff --git a/test/test_omega_h_intersection_rhs_integrator.cpp b/test/test_omega_h_intersection_rhs_integrator.cpp index aa6488c1a..9b19ac592 100644 --- a/test/test_omega_h_intersection_rhs_integrator.cpp +++ b/test/test_omega_h_intersection_rhs_integrator.cpp @@ -4,17 +4,18 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include -#include "field_test_utils.h" +#include "field_test_utils.hpp" #include #include #include #include -#include "pcms/field/coordinate_systems/cartesian.hpp" -#include "pcms/field/coordinate_systems/cylindrical.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_systems/cylindrical.hpp" +#include "pcms/backends/omega_h/omega_h.hpp" // --------------------------------------------------------------------------- // Helpers @@ -34,7 +35,8 @@ namespace // The result is keyed by global DOF id to match the PETSc row indexing of the // integrator's assembled vector. std::unordered_map ExpectedLoadByGid( - Omega_h::Mesh& target_mesh, const pcms::OmegaHLagrangeLayout& target_layout, + Omega_h::Mesh& target_mesh, + const pcms::backend::omega_h::OmegaHLagrangeLayout& target_layout, const std::vector& g_by_vert) { const auto coords_h = Omega_h::HostRead(target_mesh.coords()); @@ -67,7 +69,7 @@ std::unordered_map ExpectedLoadByGid( // per global DOF id, against the supplied expected values. void CheckAssembledLoadMatches( const std::shared_ptr& source_space, - pcms::LinearFormIntegrator& integrator, + pcms::transfer::LinearFormIntegrator& integrator, const pcms::Field& source_field, const std::unordered_map& expected) { @@ -102,8 +104,8 @@ TEST_CASE("OmegaHIntersectionRHSIntegrator: integration points lie inside " auto source_space = pcms::test::MakeP1Space(source_mesh); auto target_space = pcms::test::MakeP1Space(target_mesh); - auto integrator = - pcms::BuildOmegaHConservativeRHSIntegrator(*source_space, *target_space); + auto integrator = pcms::transfer::BuildOmegaHConservativeRHSIntegrator( + *source_space, *target_space); const auto raw_coords = integrator->GetIntegrationPoints().GetValues(); auto raw_coords_host = pcms::test::CopyCoordinatesToHost(raw_coords); @@ -133,13 +135,15 @@ TEST_CASE("OmegaHIntersectionRHSIntegrator: space and layout constructors " auto source_space = pcms::test::MakeP1Space(source_mesh); auto target_space = pcms::test::MakeP1Space(target_mesh); - pcms::OmegaHIntersectionRHSIntegrator from_spaces(*source_space, - *target_space); - pcms::OmegaHIntersectionRHSIntegrator from_layouts( - std::dynamic_pointer_cast( + pcms::transfer::OmegaHIntersectionRHSIntegrator from_spaces(*source_space, + *target_space); + pcms::transfer::OmegaHIntersectionRHSIntegrator from_layouts( + std::dynamic_pointer_cast< + const pcms::backend::omega_h::OmegaHLagrangeLayout>( source_space->GetLayout()), source_space->GetCoordinateSystem(), - std::dynamic_pointer_cast( + std::dynamic_pointer_cast< + const pcms::backend::omega_h::OmegaHLagrangeLayout>( target_space->GetLayout()), target_space->GetCoordinateSystem()); @@ -171,8 +175,8 @@ TEST_CASE("OmegaHIntersectionRHSIntegrator: zero source field gives zero " auto source_field = source_space->CreateFunction(); // Default-constructed field has zero data. - auto integrator = - pcms::BuildOmegaHConservativeRHSIntegrator(*source_space, *target_space); + auto integrator = pcms::transfer::BuildOmegaHConservativeRHSIntegrator( + *source_space, *target_space); pcms::test::EvaluateAndAssemble(*integrator, source_space, source_field); Vec vec = integrator->GetVector(); @@ -201,14 +205,14 @@ TEST_CASE("OmegaHIntersectionRHSIntegrator: constant field matches " pcms::test::SetField( source_field, OMEGA_H_LAMBDA(pcms::Real, pcms::Real) { return c; }); - const auto target_layout = - std::dynamic_pointer_cast( - target_space->GetLayout()); + const auto target_layout = std::dynamic_pointer_cast< + const pcms::backend::omega_h::OmegaHLagrangeLayout>( + target_space->GetLayout()); const std::vector g(target_mesh.nverts(), c); const auto expected = ExpectedLoadByGid(target_mesh, *target_layout, g); - auto integrator = - pcms::BuildOmegaHConservativeRHSIntegrator(*source_space, *target_space); + auto integrator = pcms::transfer::BuildOmegaHConservativeRHSIntegrator( + *source_space, *target_space); CheckAssembledLoadMatches(source_space, *integrator, source_field, expected); } @@ -233,19 +237,19 @@ TEST_CASE( pcms::test::SetField( source_field, OMEGA_H_LAMBDA(pcms::Real x, pcms::Real y) { return x + y; }); - const auto target_layout = - std::dynamic_pointer_cast( - target_space->GetLayout()); + const auto target_layout = std::dynamic_pointer_cast< + const pcms::backend::omega_h::OmegaHLagrangeLayout>( + target_space->GetLayout()); const auto tgt_coords_h = pcms::test::CopyCoordinatesToHost( - pcms::MakeConstRank2View(target_mesh.coords(), 2)); + pcms::backend::omega_h::MakeConstRank2View(target_mesh.coords(), 2)); std::vector g(target_mesh.nverts()); for (int i = 0; i < target_mesh.nverts(); ++i) { g[i] = tgt_coords_h(i, 0) + tgt_coords_h(i, 1); } const auto expected = ExpectedLoadByGid(target_mesh, *target_layout, g); - auto integrator = - pcms::BuildOmegaHConservativeRHSIntegrator(*source_space, *target_space); + auto integrator = pcms::transfer::BuildOmegaHConservativeRHSIntegrator( + *source_space, *target_space); CheckAssembledLoadMatches(source_space, *integrator, source_field, expected); } @@ -258,42 +262,42 @@ TEST_CASE("OmegaHIntersectionRHSIntegrator: rejects invalid layouts", SECTION("multi-component source space throws") { - auto source_space = pcms::LagrangeFunctionSpace::FromMesh( + auto source_space = pcms::field::LagrangeFunctionSpace::FromMesh( source_mesh, 1, 2, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::OmegaH); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); auto target_space = pcms::test::MakeP1Space(target_mesh); - REQUIRE_THROWS( - pcms::BuildOmegaHConservativeRHSIntegrator(*source_space, *target_space)); + REQUIRE_THROWS(pcms::transfer::BuildOmegaHConservativeRHSIntegrator( + *source_space, *target_space)); } SECTION("multi-component target space throws") { auto source_space = pcms::test::MakeP1Space(source_mesh); - auto target_space = pcms::LagrangeFunctionSpace::FromMesh( + auto target_space = pcms::field::LagrangeFunctionSpace::FromMesh( target_mesh, 1, 2, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::OmegaH); - REQUIRE_THROWS( - pcms::BuildOmegaHConservativeRHSIntegrator(*source_space, *target_space)); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); + REQUIRE_THROWS(pcms::transfer::BuildOmegaHConservativeRHSIntegrator( + *source_space, *target_space)); } SECTION("non-Cartesian source coordinate system throws") { - auto source_space = pcms::LagrangeFunctionSpace::FromMesh( + auto source_space = pcms::field::LagrangeFunctionSpace::FromMesh( source_mesh, 1, 1, pcms::csys::CylindricalRZ::Create(), "global", - pcms::LagrangeFunctionSpace::Backend::OmegaH); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); auto target_space = pcms::test::MakeP1Space(target_mesh); - REQUIRE_THROWS( - pcms::BuildOmegaHConservativeRHSIntegrator(*source_space, *target_space)); + REQUIRE_THROWS(pcms::transfer::BuildOmegaHConservativeRHSIntegrator( + *source_space, *target_space)); } SECTION("non-Cartesian target coordinate system throws") { auto source_space = pcms::test::MakeP1Space(source_mesh); - auto target_space = pcms::LagrangeFunctionSpace::FromMesh( + auto target_space = pcms::field::LagrangeFunctionSpace::FromMesh( target_mesh, 1, 1, pcms::csys::CylindricalRZ::Create(), "global", - pcms::LagrangeFunctionSpace::Backend::OmegaH); - REQUIRE_THROWS( - pcms::BuildOmegaHConservativeRHSIntegrator(*source_space, *target_space)); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); + REQUIRE_THROWS(pcms::transfer::BuildOmegaHConservativeRHSIntegrator( + *source_space, *target_space)); } } @@ -337,8 +341,8 @@ TEST_CASE("OmegaHIntersectionRHSIntegrator (3D): constant load sums to c times " source_field, KOKKOS_LAMBDA(pcms::Real, pcms::Real, pcms::Real) { return c; }); - auto integrator = - pcms::BuildOmegaHConservativeRHSIntegrator(*source_space, *target_space); + auto integrator = pcms::transfer::BuildOmegaHConservativeRHSIntegrator( + *source_space, *target_space); const auto raw_coords = integrator->GetIntegrationPoints().GetValues(); REQUIRE(raw_coords.extent(0) > 0); @@ -400,8 +404,8 @@ TEST_CASE("OmegaHIntersectionRHSIntegrator (3D): dual tets overlap is an " auto source_space = pcms::test::MakeP1Space(source_mesh); auto target_space = pcms::test::MakeP1Space(target_mesh); - auto integrator = - pcms::BuildOmegaHConservativeRHSIntegrator(*source_space, *target_space); + auto integrator = pcms::transfer::BuildOmegaHConservativeRHSIntegrator( + *source_space, *target_space); const auto raw_coords = integrator->GetIntegrationPoints().GetValues(); REQUIRE(raw_coords.extent(0) > 0); diff --git a/test/test_omega_h_lagrange_field.cpp b/test/test_omega_h_lagrange_field.cpp index 65871ac54..0cd2c571c 100644 --- a/test/test_omega_h_lagrange_field.cpp +++ b/test/test_omega_h_lagrange_field.cpp @@ -4,17 +4,17 @@ #include #include -#include "pcms/field/layout/omega_h_lagrange.h" -#include "pcms/field/function_space/lagrange.h" +#include "pcms/backends/omega_h/lagrange_layout.hpp" +#include "pcms/field/function_space/lagrange.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/utility/arrays.h" -#include "pcms/utility/mesh_geometry.h" -#include "field_test_utils.h" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/mesh_geometry.hpp" +#include "field_test_utils.hpp" #include #include #include -#include "pcms/field/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" using pcms::LO; using pcms::Real; @@ -31,8 +31,8 @@ TEST_CASE("OmegaHLagrangeLayout order-1 properties") { auto lib = Omega_h::Library{}; auto mesh = MakeBox2D(lib.world()); - pcms::OmegaHLagrangeLayout layout(mesh, 1, 2, - pcms::csys::Cartesian::Deferred()); + pcms::backend::omega_h::OmegaHLagrangeLayout layout( + mesh, 1, 2, pcms::csys::Cartesian::Deferred()); REQUIRE(layout.GetOrder() == 1); REQUIRE(layout.GetNumComponents() == 2); @@ -65,8 +65,8 @@ TEST_CASE("OmegaHLagrangeLayout order-0 properties") { auto lib = Omega_h::Library{}; auto mesh = MakeBox2D(lib.world()); - pcms::OmegaHLagrangeLayout layout(mesh, 0, 1, - pcms::csys::Cartesian::Deferred()); + pcms::backend::omega_h::OmegaHLagrangeLayout layout( + mesh, 0, 1, pcms::csys::Cartesian::Deferred()); REQUIRE(layout.GetOrder() == 0); REQUIRE(layout.GetNumComponents() == 1); @@ -77,8 +77,8 @@ TEST_CASE("OmegaHLagrangeLayout order-0 properties") auto coords_device = layout.GetDOFHolderCoordinates().GetValues(); int nelems = mesh.nelems(); auto coords_view = pcms::test::CopyCoordinatesToHost(coords_device); - auto centroids = - Omega_h::HostRead(pcms::get_entity_centroids(mesh, mesh.dim())); + auto centroids = Omega_h::HostRead( + pcms::utility::get_entity_centroids(mesh, mesh.dim())); REQUIRE(static_cast(coords_view.extent(0)) == nelems); for (int e = 0; e < nelems; ++e) { for (int d = 0; d < mesh.dim(); ++d) { @@ -99,19 +99,19 @@ TEST_CASE("OmegaHLagrangeLayout invalid order throws") { auto lib = Omega_h::Library{}; auto mesh = MakeBox2D(lib.world()); - REQUIRE_THROWS_AS( - pcms::OmegaHLagrangeLayout(mesh, 2, 1, pcms::csys::Cartesian::Deferred()), - std::invalid_argument); - REQUIRE_THROWS_AS( - pcms::OmegaHLagrangeLayout(mesh, -1, 1, pcms::csys::Cartesian::Deferred()), - std::invalid_argument); + REQUIRE_THROWS_AS(pcms::backend::omega_h::OmegaHLagrangeLayout( + mesh, 2, 1, pcms::csys::Cartesian::Deferred()), + std::invalid_argument); + REQUIRE_THROWS_AS(pcms::backend::omega_h::OmegaHLagrangeLayout( + mesh, -1, 1, pcms::csys::Cartesian::Deferred()), + std::invalid_argument); } TEST_CASE("OmegaHLagrangeLayout layout sharing") { auto lib = Omega_h::Library{}; auto mesh = MakeBox2D(lib.world()); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred()); auto f1 = factory->CreateFunction(); @@ -126,7 +126,7 @@ TEST_CASE("OmegaHLagrangeField order-1: set/get DOF data round-trip") { auto lib = Omega_h::Library{}; auto mesh = MakeBox2D(lib.world()); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred()); auto field = factory->CreateFunction(); @@ -150,7 +150,7 @@ TEST_CASE("Field checked writes validate the view shape, not just total size") { auto lib = Omega_h::Library{}; auto mesh = MakeBox2D(lib.world()); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred()); auto field = factory->CreateFunction(); @@ -178,7 +178,7 @@ TEST_CASE("OmegaHLagrangeField order-1: linear function evaluation") { auto lib = Omega_h::Library{}; auto mesh = MakeBox2D(lib.world(), 20, 20); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred()); auto field = factory->CreateFunction(); @@ -196,7 +196,7 @@ TEST_CASE("MeshFieldsAdapter order-1: linear function evaluation (shared util)") { auto lib = Omega_h::Library{}; auto mesh = MakeBox2D(lib.world(), 20, 20); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred()); auto field = factory->CreateFunction(); @@ -212,7 +212,7 @@ TEST_CASE("OmegaHLagrangeField order-1: out-of-bounds FILL mode") { auto lib = Omega_h::Library{}; auto mesh = MakeBox2D(lib.world()); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred()); auto field = factory->CreateFunction(); @@ -231,7 +231,7 @@ TEST_CASE("OmegaHLagrangeField order-0: set/get DOF data round-trip") { auto lib = Omega_h::Library{}; auto mesh = MakeBox2D(lib.world()); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 0, 1, pcms::csys::Cartesian::Deferred()); auto field = factory->CreateFunction(); @@ -252,7 +252,7 @@ TEST_CASE("OmegaHLagrangeField order-0: constant field evaluation") { auto lib = Omega_h::Library{}; auto mesh = MakeBox2D(lib.world(), 10, 10); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 0, 1, pcms::csys::Cartesian::Deferred()); auto field = factory->CreateFunction(); @@ -274,7 +274,7 @@ TEST_CASE("OmegaHLagrangeField order-0: out-of-bounds FILL mode") { auto lib = Omega_h::Library{}; auto mesh = MakeBox2D(lib.world()); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 0, 1, pcms::csys::Cartesian::Deferred()); auto field = factory->CreateFunction(); @@ -314,7 +314,7 @@ TEST_CASE("OmegaHLagrangeField: field valid after layout destruction") std::optional> field; { - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred()); field.emplace(factory->CreateFunction()); } // factory goes out of scope; field keeps layout alive diff --git a/test/test_omega_h_mass_integrator.cpp b/test/test_omega_h_mass_integrator.cpp index ca3b1dc78..e2b255b91 100644 --- a/test/test_omega_h_mass_integrator.cpp +++ b/test/test_omega_h_mass_integrator.cpp @@ -5,11 +5,11 @@ #include #include #include -#include -#include +#include +#include #include #include -#include "field_test_utils.h" +#include "field_test_utils.hpp" #include #include #include @@ -18,8 +18,8 @@ #include #include #include -#include "pcms/field/coordinate_systems/cartesian.hpp" -#include "pcms/field/coordinate_systems/cylindrical.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_systems/cylindrical.hpp" // --------------------------------------------------------------------------- // Helpers @@ -68,12 +68,12 @@ std::map, pcms::Real> BuildReferenceMassMap( #else MeshField::FieldElement coordFe(mesh.nelems(), coordField.field, shp, map); #endif - auto elm_mass_dev = buildElementMassMatrix(mesh, coordFe); + auto elm_mass_dev = pcms::transfer::buildElementMassMatrix(mesh, coordFe); auto elm_mass_host = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, elm_mass_dev); - const auto layout = - std::dynamic_pointer_cast(space.GetLayout()); + const auto layout = std::dynamic_pointer_cast< + const pcms::backend::omega_h::OmegaHLagrangeLayout>(space.GetLayout()); REQUIRE(layout != nullptr); const auto faces2nodes_dev = mesh.ask_down(Omega_h::FACE, Omega_h::VERT).ab2b; const auto faces2nodes = Omega_h::HostRead(faces2nodes_dev); @@ -111,7 +111,7 @@ TEST_CASE( const auto ref = BuildReferenceMassMap(mesh, *space); - auto integrator = pcms::BuildOmegaHMassIntegrator(*space); + auto integrator = pcms::transfer::BuildOmegaHMassIntegrator(*space); Mat mat = integrator->GetMatrix(); for (const auto& [key, ref_val] : ref) { @@ -137,13 +137,12 @@ TEST_CASE("OmegaHMassIntegrator: row sums match lumped mass", auto space = pcms::test::MakeP1Space(mesh); - const auto layout = - std::dynamic_pointer_cast( - space->GetLayout()); + const auto layout = std::dynamic_pointer_cast< + const pcms::backend::omega_h::OmegaHLagrangeLayout>(space->GetLayout()); const auto& gids = layout->GetGidsHost(); const int nverts = mesh.nverts(); - auto integrator = pcms::BuildOmegaHMassIntegrator(*space); + auto integrator = pcms::transfer::BuildOmegaHMassIntegrator(*space); Mat mat = integrator->GetMatrix(); // Sum all row sums. @@ -177,19 +176,18 @@ TEST_CASE("OmegaHMassIntegrator: lumped diagonal equals consistent row sums", Omega_h::Library lib; auto mesh = pcms::test::BuildUnitSquare(lib, 0); - auto space = pcms::LagrangeFunctionSpace::FromMesh( + auto space = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::OmegaH); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); - const auto layout = - std::dynamic_pointer_cast( - space->GetLayout()); + const auto layout = std::dynamic_pointer_cast< + const pcms::backend::omega_h::OmegaHLagrangeLayout>(space->GetLayout()); const auto& gids = layout->GetGidsHost(); const int nverts = mesh.nverts(); - auto consistent = pcms::BuildOmegaHMassIntegrator(*space); - auto lumped = - pcms::BuildOmegaHMassIntegrator(*space, pcms::MassMatrixType::Lumped); + auto consistent = pcms::transfer::BuildOmegaHMassIntegrator(*space); + auto lumped = pcms::transfer::BuildOmegaHMassIntegrator( + *space, pcms::MassMatrixType::Lumped); CHECK_FALSE(consistent->IsDiagonal()); CHECK(lumped->IsDiagonal()); Mat consistent_mat = consistent->GetMatrix(); @@ -237,13 +235,13 @@ TEST_CASE("OmegaHMassIntegrator: P0 lumped equals consistent", Omega_h::Library lib; auto mesh = pcms::test::BuildUnitSquare(lib, 0); - auto space = pcms::LagrangeFunctionSpace::FromMesh( + auto space = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 0, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::OmegaH); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); - auto consistent = pcms::BuildOmegaHMassIntegrator(*space); - auto lumped = - pcms::BuildOmegaHMassIntegrator(*space, pcms::MassMatrixType::Lumped); + auto consistent = pcms::transfer::BuildOmegaHMassIntegrator(*space); + auto lumped = pcms::transfer::BuildOmegaHMassIntegrator( + *space, pcms::MassMatrixType::Lumped); CHECK(consistent->IsDiagonal()); CHECK(lumped->IsDiagonal()); Mat consistent_mat = consistent->GetMatrix(); @@ -251,9 +249,8 @@ TEST_CASE("OmegaHMassIntegrator: P0 lumped equals consistent", const auto elem_areas = Omega_h::measure_elements_real(&mesh); const auto elem_areas_h = Omega_h::HostRead(elem_areas); - const auto layout = - std::dynamic_pointer_cast( - space->GetLayout()); + const auto layout = std::dynamic_pointer_cast< + const pcms::backend::omega_h::OmegaHLagrangeLayout>(space->GetLayout()); const auto& gids = layout->GetGidsHost(); for (int e = 0; e < mesh.nelems(); ++e) { @@ -278,27 +275,27 @@ TEST_CASE("OmegaHMassIntegrator: rejects invalid layouts", "[mass_integrator]") SECTION("multi-component space throws") { - auto space = pcms::LagrangeFunctionSpace::FromMesh( + auto space = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 2, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::OmegaH); - REQUIRE_THROWS(pcms::BuildOmegaHMassIntegrator(*space)); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); + REQUIRE_THROWS(pcms::transfer::BuildOmegaHMassIntegrator(*space)); } SECTION("non-Cartesian coordinate system throws") { - auto space = pcms::LagrangeFunctionSpace::FromMesh( + auto space = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::CylindricalRZ::Create(), "global", - pcms::LagrangeFunctionSpace::Backend::OmegaH); - REQUIRE_THROWS(pcms::BuildOmegaHMassIntegrator(*space)); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); + REQUIRE_THROWS(pcms::transfer::BuildOmegaHMassIntegrator(*space)); } SECTION("distinct cartesian-kind system throws") { const std::shared_ptr other = std::make_shared(); - auto space = pcms::LagrangeFunctionSpace::FromMesh( + auto space = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, other, "global", - pcms::LagrangeFunctionSpace::Backend::OmegaH); - REQUIRE_THROWS(pcms::BuildOmegaHMassIntegrator(*space)); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); + REQUIRE_THROWS(pcms::transfer::BuildOmegaHMassIntegrator(*space)); } } diff --git a/test/test_omega_h_mc_rhs_integrator.cpp b/test/test_omega_h_mc_rhs_integrator.cpp index 1559a246d..a3e740a05 100644 --- a/test/test_omega_h_mc_rhs_integrator.cpp +++ b/test/test_omega_h_mc_rhs_integrator.cpp @@ -4,20 +4,21 @@ #include #include #include -#include -#include +#include +#include #include -#include -#include +#include +#include #include #include #include #include #include #include -#include "field_test_utils.h" +#include "field_test_utils.hpp" #include #include +#include "pcms/backends/omega_h/omega_h.hpp" // --------------------------------------------------------------------------- // Monte Carlo RHS integrator @@ -32,7 +33,7 @@ TEST_CASE("OmegaHMonteCarloRHSIntegrator: sample points lie inside the domain", const int samples_per_element = 16; for (const auto sampling : {pcms::MonteCarloSampling::UniformRandom}) { - pcms::OmegaHMonteCarloRHSIntegrator integrator( + pcms::transfer::OmegaHMonteCarloRHSIntegrator integrator( *target_space, samples_per_element, sampling); const auto raw_coords = integrator.GetIntegrationPoints().GetValues(); auto coords_h = pcms::test::CopyCoordinatesToHost(raw_coords); @@ -66,7 +67,8 @@ TEST_CASE("OmegaHMonteCarloRHSIntegrator: constant field integrates exactly", source_field, OMEGA_H_LAMBDA(pcms::Real, pcms::Real) { return 2.0; }); for (const auto sampling : {pcms::MonteCarloSampling::UniformRandom}) { - pcms::OmegaHMonteCarloRHSIntegrator integrator(*target_space, 8, sampling); + pcms::transfer::OmegaHMonteCarloRHSIntegrator integrator(*target_space, 8, + sampling); pcms::test::EvaluateAndAssemble(integrator, source_space, source_field); PetscScalar sum = 0.0; @@ -105,7 +107,7 @@ TEST_CASE("OmegaHControlVariateProjection: exact for fields in the target " GENERATE(pcms::MassMatrixType::Consistent, pcms::MassMatrixType::Lumped); CAPTURE(static_cast(mass_type)); - pcms::OmegaHControlVariateProjection projection( + pcms::transfer::OmegaHControlVariateProjection projection( *source_space, *target_space, /*samples_per_element=*/4, pcms::MonteCarloSampling::UniformRandom, /*seed=*/8675309, mass_type); projection.Apply(source_field, target_field); @@ -113,7 +115,7 @@ TEST_CASE("OmegaHControlVariateProjection: exact for fields in the target " const auto values = pcms::FlattenToRank1View(target_field.GetDOFHolderDataHost().GetValues()); const auto coords_h = pcms::test::CopyCoordinatesToHost( - pcms::MakeConstRank2View(target_mesh.coords(), 2)); + pcms::backend::omega_h::MakeConstRank2View(target_mesh.coords(), 2)); REQUIRE(static_cast(values.size()) == target_mesh.nverts()); for (Omega_h::LO i = 0; i < target_mesh.nverts(); ++i) { const double expected = 3.0 * coords_h(i, 0) - coords_h(i, 1) + 0.25; @@ -143,8 +145,8 @@ TEST_CASE("OmegaHControlVariateProjection: reduces error vs plain Monte Carlo", // Reference: exact mesh-intersection quadrature projection. auto reference_field = target_space->CreateFunction(); - pcms::OmegaHConservativeProjection reference_projection(*source_space, - *target_space); + pcms::transfer::OmegaHConservativeProjection reference_projection( + *source_space, *target_space); reference_projection.Apply(source_field, reference_field); const auto reference = pcms::FlattenToRank1View( reference_field.GetDOFHolderDataHost().GetValues()); @@ -153,20 +155,21 @@ TEST_CASE("OmegaHControlVariateProjection: reduces error vs plain Monte Carlo", const uint64_t seed = 20240611; // Plain Monte Carlo projection. - pcms::OmegaHMonteCarloRHSIntegrator mc_integrator( + pcms::transfer::OmegaHMonteCarloRHSIntegrator mc_integrator( *target_space, samples_per_element, pcms::MonteCarloSampling::UniformRandom, seed); auto evaluator = source_space->CreatePointEvaluator( pcms::EvaluationRequest::FromCoordinates( mc_integrator.GetIntegrationPoints())); - pcms::OmegaHMassIntegrator mass_integrator(*target_space); - pcms::GalerkinProjectionSolver solver(mass_integrator, mc_integrator); + pcms::transfer::OmegaHMassIntegrator mass_integrator(*target_space); + pcms::transfer::GalerkinProjectionSolver solver(mass_integrator, + mc_integrator); const auto mc_projected = solver.Solve(*evaluator, source_field); const auto mc_projected_h = Omega_h::HostRead(mc_projected); // Control-variate projection with the same sampling configuration. auto cv_field = target_space->CreateFunction(); - pcms::OmegaHControlVariateProjection cv_projection( + pcms::transfer::OmegaHControlVariateProjection cv_projection( *source_space, *target_space, samples_per_element, pcms::MonteCarloSampling::UniformRandom, seed); cv_projection.Apply(source_field, cv_field); @@ -197,7 +200,7 @@ TEST_CASE("OmegaHMonteCarloRHSIntegrator (3D): sample points lie inside the " auto target_space = pcms::test::MakeP1Space(target_mesh); const int samples_per_element = 16; - pcms::OmegaHMonteCarloRHSIntegrator integrator( + pcms::transfer::OmegaHMonteCarloRHSIntegrator integrator( *target_space, samples_per_element, pcms::MonteCarloSampling::UniformRandom); @@ -236,7 +239,7 @@ TEST_CASE("OmegaHMonteCarloRHSIntegrator (3D): constant field integrates " source_field, KOKKOS_LAMBDA(pcms::Real, pcms::Real, pcms::Real) { return 2.0; }); - pcms::OmegaHMonteCarloRHSIntegrator integrator( + pcms::transfer::OmegaHMonteCarloRHSIntegrator integrator( *target_space, /*samples_per_element=*/8, pcms::MonteCarloSampling::UniformRandom); @@ -264,7 +267,8 @@ TEST_CASE( }); auto reference = target_space->CreateFunction(); - pcms::OmegaHConservativeProjection ref_proj(*source_space, *target_space); + pcms::transfer::OmegaHConservativeProjection ref_proj(*source_space, + *target_space); ref_proj.Apply(source, reference); const auto ref_vals = pcms::FlattenToRank1View(reference.GetDOFHolderDataHost().GetValues()); @@ -272,17 +276,17 @@ TEST_CASE( const int nsample = 64; const uint64_t seed = 20240611; - pcms::OmegaHMonteCarloRHSIntegrator mc( + pcms::transfer::OmegaHMonteCarloRHSIntegrator mc( *target_space, nsample, pcms::MonteCarloSampling::UniformRandom, seed); auto ev = source_space->CreatePointEvaluator( pcms::EvaluationRequest::FromCoordinates(mc.GetIntegrationPoints())); - pcms::OmegaHMassIntegrator mass(*target_space); - pcms::GalerkinProjectionSolver solver(mass, mc); + pcms::transfer::OmegaHMassIntegrator mass(*target_space); + pcms::transfer::GalerkinProjectionSolver solver(mass, mc); const auto mc_x = solver.Solve(*ev, source); const auto mc_h = Omega_h::HostRead(mc_x); auto cv_field = target_space->CreateFunction(); - pcms::OmegaHControlVariateProjection cv( + pcms::transfer::OmegaHControlVariateProjection cv( *source_space, *target_space, nsample, pcms::MonteCarloSampling::UniformRandom, seed); cv.Apply(source, cv_field); @@ -357,7 +361,7 @@ TEST_CASE("OmegaHControlVariateProjection over a TransformedSource maps the " pcms::TransformedSource src_as_swapped(source_space, std::make_shared()); - pcms::OmegaHControlVariateProjection projection( + pcms::transfer::OmegaHControlVariateProjection projection( src_as_swapped, *target_space, /*samples_per_element=*/4, pcms::MonteCarloSampling::UniformRandom); projection.Apply(source_field, target_field); @@ -365,7 +369,7 @@ TEST_CASE("OmegaHControlVariateProjection over a TransformedSource maps the " const auto values = pcms::FlattenToRank1View(target_field.GetDOFHolderDataHost().GetValues()); const auto coords_h = pcms::test::CopyCoordinatesToHost( - pcms::MakeConstRank2View(target_mesh.coords(), 2)); + pcms::backend::omega_h::MakeConstRank2View(target_mesh.coords(), 2)); for (Omega_h::LO i = 0; i < target_mesh.nverts(); ++i) { const double expected = 3.0 * coords_h(i, 1) - coords_h(i, 0) + 0.25; CAPTURE(i, expected, values[i]); diff --git a/test/test_omega_h_same_mesh_p0_to_p1.cpp b/test/test_omega_h_same_mesh_p0_to_p1.cpp index 1e9116a03..290ccda49 100644 --- a/test/test_omega_h_same_mesh_p0_to_p1.cpp +++ b/test/test_omega_h_same_mesh_p0_to_p1.cpp @@ -9,8 +9,8 @@ #include #include #include -#include -#include "field_test_utils.h" +#include +#include "field_test_utils.hpp" #include #include @@ -195,14 +195,14 @@ Omega_h::HostRead SelfDecompositionMeasures(Omega_h::Mesh& mesh) Omega_h::Write indices(nelems); Omega_h::parallel_for(nelems + 1, OMEGA_H_LAMBDA(int i) { offsets[i] = i; }); Omega_h::parallel_for(nelems, OMEGA_H_LAMBDA(int i) { indices[i] = i; }); - const pcms::IntersectionResults self{Omega_h::LOs(offsets), - Omega_h::LOs(indices)}; + const pcms::transfer::IntersectionResults self{Omega_h::LOs(offsets), + Omega_h::LOs(indices)}; Omega_h::Write sums(nelems, 0.0); Omega_h::parallel_for( nelems, OMEGA_H_LAMBDA(int e) { Omega_h::Real acc = 0.0; - pcms::detail::ForEachIntersectionSubsimplex( + pcms::transfer::detail::ForEachIntersectionSubsimplex( e, self, coords, coords, e2n, e2n, [&](const Omega_h::Few, Dim + 1>&, int, Omega_h::Real measure) { acc += measure; }); @@ -359,8 +359,8 @@ std::vector ProjectSameMesh(Omega_h::Mesh& mesh, auto target = target_space->CreateFunction(); pcms::test::SetField(source, SourceFunction{}); - pcms::OmegaHConservativeProjection projection(*source_space, *target_space, - mass_type); + pcms::transfer::OmegaHConservativeProjection projection( + *source_space, *target_space, mass_type); projection.Apply(source, target); source_values = ToVector( @@ -459,7 +459,7 @@ double StarDecompositionMeasure(const r3d::Polytope& poly) const double eps = PCMS_INTERSECTION_ABS_TOL + PCMS_INTERSECTION_REL_TOL * std::fabs(r3d::measure(poly)); double sum = 0.0; - pcms::detail::ForEachPolytopeStarSimplex( + pcms::transfer::detail::ForEachPolytopeStarSimplex( poly, eps, [&](const Omega_h::Few, Dim + 1>&, Omega_h::Real measure) { sum += measure; }); @@ -483,7 +483,7 @@ void RequireCleanSimplexDecomposition(const double* coords) r3d::init(poly, verts); const double measure = std::fabs(r3d::measure(poly)); int pieces = 0; - pcms::detail::ForEachPolytopeStarSimplex( + pcms::transfer::detail::ForEachPolytopeStarSimplex( poly, 0.0, [&](const Omega_h::Few, Dim + 1>&, Omega_h::Real piece) { diff --git a/test/test_point_evaluator.cpp b/test/test_point_evaluator.cpp index 02f2e20b3..dea2431e4 100644 --- a/test/test_point_evaluator.cpp +++ b/test/test_point_evaluator.cpp @@ -3,17 +3,17 @@ #include #include -#include "pcms/field/function_space/lagrange.h" +#include "pcms/field/function_space/lagrange.hpp" #include "pcms/field/function_space/polynomial_reconstruction.hpp" -#include "pcms/field/function_space/spline.h" -#include "pcms/field/field_data.h" -#include "pcms/field/point_evaluator.h" -#include "pcms/field/out_of_bounds_policy.h" +#include "pcms/field/function_space/spline.hpp" +#include "pcms/field/field_data.hpp" +#include "pcms/field/point_evaluator.hpp" +#include "pcms/field/out_of_bounds_policy.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/field/coordinate_view.hpp" -#include "pcms/utility/arrays.h" -#include "field_test_utils.h" -#include "pcms/field/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_view.hpp" +#include "pcms/utility/arrays.hpp" +#include "field_test_utils.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" using pcms::CoordinateSystem; using pcms::Real; @@ -86,9 +86,9 @@ TEST_CASE("PointEvaluator::Evaluate checks the output for every evaluator") { auto mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1, 1, 0, 10, 10, 0, false); - auto space = pcms::LagrangeFunctionSpace::FromMesh( + auto space = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::OmegaH); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); CheckOutputValidation(*CreateFillEvaluator(*space), space->CreateFunction(), n); } @@ -97,23 +97,23 @@ TEST_CASE("PointEvaluator::Evaluate checks the output for every evaluator") { auto mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1, 1, 0, 10, 10, 0, false); - auto space = pcms::LagrangeFunctionSpace::FromMesh( + auto space = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::MeshFields); + pcms::field::LagrangeFunctionSpace::Backend::MeshFields); CheckOutputValidation(*CreateFillEvaluator(*space), space->CreateFunction(), n); } #endif SECTION("uniform grid Lagrange") { - auto space = pcms::LagrangeFunctionSpace::FromUniformGrid( + auto space = pcms::field::LagrangeFunctionSpace::FromUniformGrid( grid, 1, pcms::csys::Cartesian::Deferred(), 1); CheckOutputValidation(*CreateFillEvaluator(*space), space->CreateFunction(), n); } SECTION("uniform grid spline") { - auto space = pcms::SplineFunctionSpace::FromUniformGrid( + auto space = pcms::field::SplineFunctionSpace::FromUniformGrid( grid, pcms::csys::Cartesian::Deferred()); CheckOutputValidation(*CreateFillEvaluator(*space), space->CreateFunction(), n); @@ -127,7 +127,7 @@ TEST_CASE("PointEvaluator::Evaluate checks the output for every evaluator") sources.push_back(0.25 * j); } } - auto space = pcms::PolynomialReconstructionFunctionSpace::Create( + auto space = pcms::field::PolynomialReconstructionFunctionSpace::Create( pcms::CoordinateView( pcms::csys::Cartesian::Deferred(), pcms::Rank2View(sources.data(), 25, @@ -152,9 +152,9 @@ TEST_CASE("PointEvaluator: OmegaH order-1 linear evaluation") auto mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1, 1, 0, 100, 100, 0, false); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::OmegaH); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); auto field_data = factory->CreateFunction(); pcms::test::SetField( @@ -182,9 +182,9 @@ TEST_CASE("PointEvaluator: same evaluator reused for two FieldData objects") auto mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1, 1, 0, 50, 50, 0, false); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::OmegaH); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); auto field_a = factory->CreateFunction(); auto field_b = factory->CreateFunction(); @@ -221,9 +221,9 @@ TEST_CASE("PointEvaluator: OmegaH order-1 out-of-bounds fill") auto mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1, 1, 0, 20, 20, 0, false); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::OmegaH); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); auto field_data = factory->CreateFunction(); pcms::test::SetField( @@ -254,7 +254,7 @@ TEST_CASE("PointEvaluator: UniformGrid order-1 linear evaluation") grid.edge_length = {1.0, 1.0}; grid.divisions = {N, N}; - auto factory = pcms::LagrangeFunctionSpace::FromUniformGrid( + auto factory = pcms::field::LagrangeFunctionSpace::FromUniformGrid( grid, 1, pcms::csys::Cartesian::Deferred(), 1); auto field_data = factory->CreateFunction(); @@ -281,7 +281,7 @@ TEST_CASE("PointEvaluator: SplineFunctionSpace uniform-grid evaluation") grid.edge_length = {1.0, 1.0}; grid.divisions = {N, N}; - auto factory = pcms::SplineFunctionSpace::FromUniformGrid( + auto factory = pcms::field::SplineFunctionSpace::FromUniformGrid( grid, pcms::csys::Cartesian::Deferred()); auto field_data = factory->CreateFunction(); @@ -315,7 +315,7 @@ TEST_CASE("PointEvaluator: uniform grids report the points they fill") SECTION("Lagrange") { - auto factory = pcms::LagrangeFunctionSpace::FromUniformGrid( + auto factory = pcms::field::LagrangeFunctionSpace::FromUniformGrid( grid, 1, pcms::csys::Cartesian::Deferred(), 1); auto field = factory->CreateFunction(); pcms::test::SetField(field, linear); @@ -324,7 +324,7 @@ TEST_CASE("PointEvaluator: uniform grids report the points they fill") } SECTION("spline") { - auto factory = pcms::SplineFunctionSpace::FromUniformGrid( + auto factory = pcms::field::SplineFunctionSpace::FromUniformGrid( grid, pcms::csys::Cartesian::Deferred()); auto field = factory->CreateFunction(); pcms::test::SetField(field, linear); @@ -333,7 +333,7 @@ TEST_CASE("PointEvaluator: uniform grids report the points they fill") } SECTION("no fill without the FILL policy") { - auto factory = pcms::LagrangeFunctionSpace::FromUniformGrid( + auto factory = pcms::field::LagrangeFunctionSpace::FromUniformGrid( grid, 1, pcms::csys::Cartesian::Deferred(), 1); auto coords = pcms::test::CreateDeviceCoordinateView( pts, pcms::csys::Cartesian::Deferred()); @@ -355,9 +355,9 @@ TEST_CASE("FieldLayout: metadata queries") auto mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1, 1, 0, 10, 10, 0, false); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::OmegaH); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); auto layout = factory->GetLayout(); auto coords = layout->GetDOFHolderCoordinates(); @@ -377,9 +377,9 @@ TEST_CASE("FieldData: layout metadata queries") auto mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1, 1, 0, 10, 10, 0, false); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::OmegaH); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); auto field_data = factory->CreateFunction(); auto coords = factory->GetLayout()->GetDOFHolderCoordinates(); @@ -399,9 +399,9 @@ TEST_CASE("SimpleFieldData: set and get DOF holder data round-trip") auto mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1, 1, 0, 10, 10, 0, false); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::OmegaH); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); auto field_data = factory->CreateFunction(); auto& layout = *factory->GetLayout(); @@ -437,9 +437,9 @@ TEST_CASE("FieldLayout: MeshFields metadata queries") auto mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1, 1, 0, 10, 10, 0, false); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::MeshFields); + pcms::field::LagrangeFunctionSpace::Backend::MeshFields); auto layout = factory->GetLayout(); auto coords = layout->GetDOFHolderCoordinates(); @@ -455,9 +455,9 @@ TEST_CASE("PointEvaluator: MeshFields order-1 linear evaluation") auto mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1, 1, 0, 100, 100, 0, false); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::MeshFields); + pcms::field::LagrangeFunctionSpace::Backend::MeshFields); auto field_data = factory->CreateFunction(); pcms::test::SetField( @@ -481,9 +481,9 @@ TEST_CASE("PointEvaluator: MeshFields out-of-bounds fill") auto mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1, 1, 0, 20, 20, 0, false); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::MeshFields); + pcms::field::LagrangeFunctionSpace::Backend::MeshFields); auto field_data = factory->CreateFunction(); pcms::test::SetField( @@ -507,9 +507,9 @@ TEST_CASE( auto mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1, 1, 0, 50, 50, 0, false); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::MeshFields); + pcms::field::LagrangeFunctionSpace::Backend::MeshFields); auto field_a = factory->CreateFunction(); auto field_b = factory->CreateFunction(); @@ -540,9 +540,9 @@ TEST_CASE("PointEvaluator: MeshFields order-1 multi-component (2) evaluation") auto mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1, 1, 0, 50, 50, 0, false); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 2, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::MeshFields); + pcms::field::LagrangeFunctionSpace::Backend::MeshFields); auto field = factory->CreateFunction(); auto layout = factory->GetLayout(); @@ -595,9 +595,9 @@ TEST_CASE("PointEvaluator: MeshFields order-1 multi-component (3) evaluation") auto mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1, 1, 0, 50, 50, 0, false); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 3, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::Backend::MeshFields); + pcms::field::LagrangeFunctionSpace::Backend::MeshFields); auto field = factory->CreateFunction(); auto layout = factory->GetLayout(); diff --git a/test/test_point_search.cpp b/test/test_point_search.cpp index f19fa3141..4aac5984a 100644 --- a/test/test_point_search.cpp +++ b/test/test_point_search.cpp @@ -1,9 +1,9 @@ #include #include -#include -#include -#include -#include "field_test_utils.h" +#include +#include +#include +#include "field_test_utils.hpp" #include #include #include @@ -37,71 +37,71 @@ TEST_CASE("global to local") } TEST_CASE("Triangle AABB intersection") { - using pcms::triangle_intersects_bbox; + using pcms::localization::triangle_intersects_bbox; AABBox<2> unit_square{.center = {0, 0}, .half_width = {0.5, 0.5}}; SECTION("Triangle outside bbox") { - REQUIRE(triangle_intersects_bbox({{1, 1}, {2, 1}, {2, 2}}, unit_square) == - false); + REQUIRE(pcms::localization::triangle_intersects_bbox( + {{1, 1}, {2, 1}, {2, 2}}, unit_square) == false); } SECTION("BBOX inside Triangle") { - REQUIRE(triangle_intersects_bbox({{-10, -10}, {10, -10}, {10, 10}}, - unit_square) == true); + REQUIRE(pcms::localization::triangle_intersects_bbox( + {{-10, -10}, {10, -10}, {10, 10}}, unit_square) == true); } SECTION("All verts inside BBOX") { - REQUIRE(triangle_intersects_bbox({{-10, -10}, {10, -10}, {10, 10}}, - unit_square) == true); + REQUIRE(pcms::localization::triangle_intersects_bbox( + {{-10, -10}, {10, -10}, {10, 10}}, unit_square) == true); } SECTION("Single vert inside bbox") { - REQUIRE(triangle_intersects_bbox({{0, 0}, {1, 0}, {1, 1}}, unit_square) == - true); - REQUIRE(triangle_intersects_bbox({{1, 1}, {0, 0}, {1, 0}}, unit_square) == - true); - REQUIRE(triangle_intersects_bbox({{1, 0}, {1, 1}, {0, 0}}, unit_square) == - true); + REQUIRE(pcms::localization::triangle_intersects_bbox( + {{0, 0}, {1, 0}, {1, 1}}, unit_square) == true); + REQUIRE(pcms::localization::triangle_intersects_bbox( + {{1, 1}, {0, 0}, {1, 0}}, unit_square) == true); + REQUIRE(pcms::localization::triangle_intersects_bbox( + {{1, 0}, {1, 1}, {0, 0}}, unit_square) == true); } SECTION("edge crossed bbox") { // Triangle 1 with all vert permutations - REQUIRE(triangle_intersects_bbox({{-0.6, 0}, {0, 0.6}, {-1, 1}}, - unit_square) == true); - REQUIRE(triangle_intersects_bbox({{-1, 1}, {-0.6, 0}, {0, 0.6}}, - unit_square) == true); - REQUIRE(triangle_intersects_bbox({{0, 0.6}, {-1, 1}, {-0.6, 0}}, - unit_square) == true); + REQUIRE(pcms::localization::triangle_intersects_bbox( + {{-0.6, 0}, {0, 0.6}, {-1, 1}}, unit_square) == true); + REQUIRE(pcms::localization::triangle_intersects_bbox( + {{-1, 1}, {-0.6, 0}, {0, 0.6}}, unit_square) == true); + REQUIRE(pcms::localization::triangle_intersects_bbox( + {{0, 0.6}, {-1, 1}, {-0.6, 0}}, unit_square) == true); // triangle 2 with all vert permutations - REQUIRE(triangle_intersects_bbox({{-0.6, 0}, {0.6, 0}, {0, -1}}, - unit_square) == true); - REQUIRE(triangle_intersects_bbox({{0, -1}, {-0.6, 0}, {0.6, 0}}, - unit_square) == true); - REQUIRE(triangle_intersects_bbox({{0.6, 0}, {0, -1}, {-0.6, 0}}, - unit_square) == true); + REQUIRE(pcms::localization::triangle_intersects_bbox( + {{-0.6, 0}, {0.6, 0}, {0, -1}}, unit_square) == true); + REQUIRE(pcms::localization::triangle_intersects_bbox( + {{0, -1}, {-0.6, 0}, {0.6, 0}}, unit_square) == true); + REQUIRE(pcms::localization::triangle_intersects_bbox( + {{0.6, 0}, {0, -1}, {-0.6, 0}}, unit_square) == true); } } TEST_CASE("Triangle BBox Intersection Regression") { - using pcms::triangle_intersects_bbox; + using pcms::localization::triangle_intersects_bbox; AABBox<2> bbox{.center = {0.10833333, 0.10833333}, .half_width = {0.00833333, 0.00833333}}; - REQUIRE(triangle_intersects_bbox({{0, 0}, {0.1, 0}, {0.1, 0.1}}, bbox) == - true); - REQUIRE(triangle_intersects_bbox({{0.1, 0}, {0.2, 0}, {0.2, 0.1}}, bbox) == - false); - REQUIRE(triangle_intersects_bbox({{0.1, 0.1}, {0, 0.1}, {0, 0}}, bbox) == - true); - REQUIRE(triangle_intersects_bbox({{0.1, 0.1}, {0.2, 0.1}, {0.2, 0.2}}, - bbox) == true); - REQUIRE(triangle_intersects_bbox({{0, 0.1}, {0.1, 0.1}, {0.1, 0.2}}, bbox) == - true); - REQUIRE(triangle_intersects_bbox({{0.1, 0.2}, {0, 0.2}, {0, 0.1}}, bbox) == - false); - REQUIRE(triangle_intersects_bbox({{0.2, 0.2}, {0.1, 0.2}, {0.1, 0.1}}, - bbox) == true); - REQUIRE(triangle_intersects_bbox({{0.2, 0.1}, {0.1, 0.1}, {0.1, 0}}, bbox) == - true); + REQUIRE(pcms::localization::triangle_intersects_bbox( + {{0, 0}, {0.1, 0}, {0.1, 0.1}}, bbox) == true); + REQUIRE(pcms::localization::triangle_intersects_bbox( + {{0.1, 0}, {0.2, 0}, {0.2, 0.1}}, bbox) == false); + REQUIRE(pcms::localization::triangle_intersects_bbox( + {{0.1, 0.1}, {0, 0.1}, {0, 0}}, bbox) == true); + REQUIRE(pcms::localization::triangle_intersects_bbox( + {{0.1, 0.1}, {0.2, 0.1}, {0.2, 0.2}}, bbox) == true); + REQUIRE(pcms::localization::triangle_intersects_bbox( + {{0, 0.1}, {0.1, 0.1}, {0.1, 0.2}}, bbox) == true); + REQUIRE(pcms::localization::triangle_intersects_bbox( + {{0.1, 0.2}, {0, 0.2}, {0, 0.1}}, bbox) == false); + REQUIRE(pcms::localization::triangle_intersects_bbox( + {{0.2, 0.2}, {0.1, 0.2}, {0.1, 0.1}}, bbox) == true); + REQUIRE(pcms::localization::triangle_intersects_bbox( + {{0.2, 0.1}, {0.1, 0.1}, {0.1, 0}}, bbox) == true); } template @@ -145,8 +145,9 @@ TEST_CASE("construct intersection map") grid_h(0) = Uniform2DGrid{ .edge_length{1, 1}, .bot_left = {0, 0}, .divisions = {10, 10}}; Kokkos::deep_copy(grid_d, grid_h); - auto intersection_map = pcms::detail::construct_intersection_map_2d( - mesh, grid_d, grid_h(0).GetNumCells()); + auto intersection_map = + pcms::localization::detail::construct_intersection_map_2d( + mesh, grid_d, grid_h(0).GetNumCells()); // assert(cudaSuccess == cudaDeviceSynchronize()); REQUIRE(intersection_map.numRows() == 100); REQUIRE(num_candidates_within_range(intersection_map, 2, 16)); @@ -159,8 +160,9 @@ TEST_CASE("construct intersection map") .edge_length{1, 1}, .bot_left = {0, 0}, .divisions = {60, 60}}; Kokkos::deep_copy(grid_d, grid_h); // require number of candidates is >=1 and <=6 - auto intersection_map = pcms::detail::construct_intersection_map_2d( - mesh, grid_d, grid_h(0).GetNumCells()); + auto intersection_map = + pcms::localization::detail::construct_intersection_map_2d( + mesh, grid_d, grid_h(0).GetNumCells()); REQUIRE(intersection_map.numRows() == 3600); REQUIRE(num_candidates_within_range(intersection_map, 1, 6)); @@ -218,9 +220,10 @@ TEST_CASE("candidate map matches brute-force reference") Kokkos::deep_copy(grid_d, grid_h); const auto ncells = grid_h(0).GetNumCells(); require_maps_identical( - pcms::detail::construct_intersection_map_2d(mesh, grid_d, ncells), - pcms::detail::construct_intersection_map_reference_2d(mesh, grid_d, - ncells)); + pcms::localization::detail::construct_intersection_map_2d(mesh, grid_d, + ncells), + pcms::localization::detail::construct_intersection_map_reference_2d( + mesh, grid_d, ncells)); } } SECTION("3D") @@ -238,28 +241,30 @@ TEST_CASE("candidate map matches brute-force reference") Kokkos::deep_copy(grid_d, grid_h); const auto ncells = grid_h(0).GetNumCells(); require_maps_identical( - pcms::detail::construct_intersection_map_3d(mesh, grid_d, ncells), - pcms::detail::construct_intersection_map_reference_3d(mesh, grid_d, - ncells)); + pcms::localization::detail::construct_intersection_map_3d(mesh, grid_d, + ncells), + pcms::localization::detail::construct_intersection_map_reference_3d( + mesh, grid_d, ncells)); } } } TEST_CASE("uniform grid search") { - using pcms::GridPointSearch2D; + using pcms::localization::GridPointSearch2D; auto lib = Omega_h::Library{}; auto world = lib.world(); auto mesh = Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1, 1, 1, 10, 10, 0, false); auto tolerances = - GridPointSearch2D::PointSearchTolerances{"point search 2d tolerances"}; + pcms::localization::GridPointSearch2D::PointSearchTolerances{ + "point search 2d tolerances"}; auto tolerances_h = Kokkos::create_mirror_view(tolerances); tolerances_h(0) = 0.01; tolerances_h(1) = 0.01; Kokkos::deep_copy(tolerances, tolerances_h); - GridPointSearch2D search{mesh, 10, 10, tolerances}; + pcms::localization::GridPointSearch2D search{mesh, 10, 10, tolerances}; Kokkos::View points("test_points", 8); // Kokkos::View points("test_points", 1); @@ -292,7 +297,9 @@ TEST_CASE("uniform grid search") CAPTURE(idx); - REQUIRE(dim == GridPointSearch2D::Result::Dimensionality::VERTEX); + REQUIRE( + dim == + pcms::localization::GridPointSearch2D::Result::Dimensionality::VERTEX); REQUIRE(idx == 0); REQUIRE(face_idx >= 0); REQUIRE(coords[0] == Catch::Approx(1)); @@ -302,7 +309,9 @@ TEST_CASE("uniform grid search") { auto [dim, idx, coords] = results_h(1); const auto face_idx = search.GetOwningElementId(results_h(1)); - REQUIRE(dim == GridPointSearch2D::Result::Dimensionality::EDGE); + REQUIRE( + dim == + pcms::localization::GridPointSearch2D::Result::Dimensionality::EDGE); REQUIRE(idx == 156); REQUIRE(face_idx >= 0); REQUIRE(coords[0] == Catch::Approx(0.5)); @@ -312,7 +321,9 @@ TEST_CASE("uniform grid search") { auto [dim, idx, coords] = results_h(7); const auto face_idx = search.GetOwningElementId(results_h(7)); - REQUIRE(dim == GridPointSearch2D::Result::Dimensionality::FACE); + REQUIRE( + dim == + pcms::localization::GridPointSearch2D::Result::Dimensionality::FACE); REQUIRE(idx == 0); REQUIRE(face_idx >= 0); } @@ -321,23 +332,26 @@ TEST_CASE("uniform grid search") { auto out_of_bounds = results_h(2); auto top_right = results_h(3); - REQUIRE(out_of_bounds.dimensionality == - GridPointSearch2D::Result::Dimensionality::VERTEX); + REQUIRE( + out_of_bounds.dimensionality == + pcms::localization::GridPointSearch2D::Result::Dimensionality::VERTEX); REQUIRE(out_of_bounds.IsOutside()); REQUIRE(out_of_bounds.EntityId() == top_right.element_id); REQUIRE(search.GetOwningElementId(out_of_bounds) >= 0); out_of_bounds = results_h(4); auto bot_left = results_h(0); - REQUIRE(out_of_bounds.dimensionality == - GridPointSearch2D::Result::Dimensionality::VERTEX); + REQUIRE( + out_of_bounds.dimensionality == + pcms::localization::GridPointSearch2D::Result::Dimensionality::VERTEX); REQUIRE(out_of_bounds.IsOutside()); REQUIRE(out_of_bounds.EntityId() == bot_left.element_id); REQUIRE(search.GetOwningElementId(out_of_bounds) >= 0); out_of_bounds = results_h(5); - REQUIRE(out_of_bounds.dimensionality == - GridPointSearch2D::Result::Dimensionality::EDGE); + REQUIRE( + out_of_bounds.dimensionality == + pcms::localization::GridPointSearch2D::Result::Dimensionality::EDGE); REQUIRE(out_of_bounds.IsOutside()); REQUIRE(out_of_bounds.EntityId() == 219); REQUIRE(search.GetOwningElementId(out_of_bounds) >= 0); @@ -345,8 +359,9 @@ TEST_CASE("uniform grid search") // (0.05, -0.01) is within the edge tolerance of the bottom edge, so it is // located on that edge rather than reported outside. auto on_edge = results_h(6); - REQUIRE(on_edge.dimensionality == - GridPointSearch2D::Result::Dimensionality::EDGE); + REQUIRE( + on_edge.dimensionality == + pcms::localization::GridPointSearch2D::Result::Dimensionality::EDGE); REQUIRE_FALSE(on_edge.IsOutside()); REQUIRE(on_edge.element_id == 0); REQUIRE(search.GetOwningElementId(on_edge) >= 0); @@ -367,8 +382,9 @@ TEST_CASE("uniform grid search") REQUIRE(res.element_id < 0); // Dimensionality must be VERTEX — the nearest entity is the // rightmost bottom vertex (1.0, 0). - REQUIRE(res.dimensionality == - GridPointSearch2D::Result::Dimensionality::VERTEX); + REQUIRE( + res.dimensionality == + pcms::localization::GridPointSearch2D::Result::Dimensionality::VERTEX); // Owning element should still resolve to a valid face REQUIRE(search.GetOwningElementId(res) >= 0); } @@ -377,7 +393,7 @@ TEST_CASE("uniform grid search") TEST_CASE("point search locates points on shared faces", "[point_search][3d][regression]") { - using pcms::GridPointSearch3D; + using pcms::localization::GridPointSearch3D; auto lib = Omega_h::Library{}; auto world = lib.world(); @@ -392,10 +408,10 @@ TEST_CASE("point search locates points on shared faces", // Same grid resolution the intersection search uses for this mesh. const auto n = pcms::DivisionsPerAxisForMesh<3>(mesh.nelems()); - GridPointSearch3D search{mesh, n, n, n}; + pcms::localization::GridPointSearch3D search{mesh, n, n, n}; - const auto centroids_h = - Omega_h::HostRead(pcms::get_entity_centroids(query_mesh, 3)); + const auto centroids_h = Omega_h::HostRead( + pcms::utility::get_entity_centroids(query_mesh, 3)); const auto npoints = query_mesh.nelems(); Kokkos::View points("query points", npoints); @@ -428,11 +444,12 @@ TEST_CASE("point search encodes outside points unambiguously", SECTION("3D: nearest tetrahedron 0") { - using pcms::GridPointSearch3D; - using Dimensionality = GridPointSearch3D::Result::Dimensionality; + using pcms::localization::GridPointSearch3D; + using Dimensionality = + pcms::localization::GridPointSearch3D::Result::Dimensionality; auto mesh = pcms::test::BuildReferenceTet(lib); const auto n = pcms::DivisionsPerAxisForMesh<3>(mesh.nelems()); - GridPointSearch3D search{mesh, n, n, n}; + pcms::localization::GridPointSearch3D search{mesh, n, n, n}; Kokkos::View points("points", 2); auto points_h = Kokkos::create_mirror_view(points); @@ -466,10 +483,11 @@ TEST_CASE("point search encodes outside points unambiguously", // The grid over a single tet has no empty cell, so decode the // no-candidate result directly. - Kokkos::View none("none", 1); - Kokkos::deep_copy(none, - GridPointSearch3D::Result{Dimensionality::NO_INTERSECT, - -1, Omega_h::zero_vector<4>()}); + Kokkos::View none("none", + 1); + Kokkos::deep_copy( + none, pcms::localization::GridPointSearch3D::Result{ + Dimensionality::NO_INTERSECT, -1, Omega_h::zero_vector<4>()}); auto none_h = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, none); auto none_owners_h = Kokkos::create_mirror_view_and_copy( @@ -482,13 +500,14 @@ TEST_CASE("point search encodes outside points unambiguously", SECTION("2D: nearest vertex 0 and an empty query cell") { - using pcms::GridPointSearch2D; - using Dimensionality = GridPointSearch2D::Result::Dimensionality; + using pcms::localization::GridPointSearch2D; + using Dimensionality = + pcms::localization::GridPointSearch2D::Result::Dimensionality; // Only the triangle below the diagonal, so the cells above it hold no // candidates. auto mesh = pcms::test::BuildUnitSquare(lib, Omega_h::LOs({0, 1, 3})); const auto n = pcms::DivisionsPerAxisForMesh<2>(mesh.nelems()); - GridPointSearch2D search{mesh, n, n}; + pcms::localization::GridPointSearch2D search{mesh, n, n}; Kokkos::View points("points", 3); auto points_h = Kokkos::create_mirror_view(points); diff --git a/test/test_polynomial_reconstruction_function_space.cpp b/test/test_polynomial_reconstruction_function_space.cpp index c62865292..8896269a2 100644 --- a/test/test_polynomial_reconstruction_function_space.cpp +++ b/test/test_polynomial_reconstruction_function_space.cpp @@ -3,15 +3,15 @@ #include "pcms/field/function_space/polynomial_reconstruction.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/discretization/discretization.h" -#include "pcms/field/function_space/lagrange.h" -#include "pcms/field/layout/point_cloud.h" -#include "field_test_utils.h" +#include "pcms/discretization/discretization.hpp" +#include "pcms/field/function_space/lagrange.hpp" +#include "pcms/backends/point_cloud/layout.hpp" +#include "field_test_utils.hpp" #include #include #include -#include "pcms/field/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" using pcms::CoordinateSystem; using pcms::HostMemorySpace; @@ -36,7 +36,7 @@ TEST_CASE( auto coords = MakeCoords2D(); Rank2View coords_view(coords.data(), 4, 2); - auto factory = pcms::PolynomialReconstructionFunctionSpace::Create( + auto factory = pcms::field::PolynomialReconstructionFunctionSpace::Create( pcms::CoordinateView(pcms::csys::Cartesian::Deferred(), coords_view)); auto layout = factory->GetLayout(); @@ -64,7 +64,7 @@ TEST_CASE("PolynomialReconstructionFunctionSpace fields share layout") auto coords = MakeCoords2D(); Rank2View coords_view(coords.data(), 4, 2); - auto factory = pcms::PolynomialReconstructionFunctionSpace::Create( + auto factory = pcms::field::PolynomialReconstructionFunctionSpace::Create( pcms::CoordinateView(pcms::csys::Cartesian::Deferred(), coords_view)); auto source = factory->CreateFunction(); @@ -79,7 +79,7 @@ TEST_CASE("PolynomialReconstructionFunctionSpace point-cloud field set/get DOF " auto coords = MakeCoords2D(); Rank2View coords_view(coords.data(), 4, 2); - auto field = pcms::PolynomialReconstructionFunctionSpace::Create( + auto field = pcms::field::PolynomialReconstructionFunctionSpace::Create( pcms::CoordinateView( pcms::csys::Cartesian::Deferred(), coords_view)) ->CreateFunction(); @@ -105,14 +105,15 @@ TEST_CASE("PolynomialReconstructionFunctionSpace field keeps layout alive " Rank2View coords_view(coords.data(), 4, 2); auto field = [&]() { - auto factory = pcms::PolynomialReconstructionFunctionSpace::Create( + auto factory = pcms::field::PolynomialReconstructionFunctionSpace::Create( pcms::CoordinateView(pcms::csys::Cartesian::Deferred(), coords_view)); return factory->CreateFunction(); }(); auto point_cloud_layout = - dynamic_cast(&field.GetLayout()); + dynamic_cast( + &field.GetLayout()); REQUIRE(point_cloud_layout != nullptr); REQUIRE(point_cloud_layout->GetNumOwnedDofHolder() == 4); @@ -132,9 +133,9 @@ TEST_CASE("Different layouts on the same mesh report SameEntities") auto mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1.0, 1.0, 0.0, 2, 2, 0, false); - auto nodal = pcms::PolynomialReconstructionFunctionSpace::FromMesh( + auto nodal = pcms::field::PolynomialReconstructionFunctionSpace::FromMesh( mesh, pcms::Face, pcms::csys::Cartesian::Deferred()); - auto lagrange = pcms::LagrangeFunctionSpace::FromMesh( + auto lagrange = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred()); auto nodal_disc = nodal->GetLayout()->GetDiscretization(); @@ -159,9 +160,9 @@ TEST_CASE("Layouts on different meshes do not report SameEntities") auto mesh_b = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1.0, 1.0, 0.0, 3, 3, 0, false); - auto nodal_a = pcms::PolynomialReconstructionFunctionSpace::FromMesh( + auto nodal_a = pcms::field::PolynomialReconstructionFunctionSpace::FromMesh( mesh_a, pcms::Vertex, pcms::csys::Cartesian::Deferred()); - auto nodal_b = pcms::PolynomialReconstructionFunctionSpace::FromMesh( + auto nodal_b = pcms::field::PolynomialReconstructionFunctionSpace::FromMesh( mesh_b, pcms::Vertex, pcms::csys::Cartesian::Deferred()); auto disc_a = nodal_a->GetLayout()->GetDiscretization(); @@ -177,12 +178,12 @@ TEST_CASE( auto mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1.0, 1.0, 0.0, 2, 2, 0, false); - auto lagrange = pcms::LagrangeFunctionSpace::FromMesh( + auto lagrange = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred()); auto coords = MakeCoords2D(); Rank2View coords_view(coords.data(), 4, 2); - auto standalone = pcms::PolynomialReconstructionFunctionSpace::Create( + auto standalone = pcms::field::PolynomialReconstructionFunctionSpace::Create( pcms::CoordinateView(pcms::csys::Cartesian::Deferred(), coords_view)); diff --git a/test/test_polynomial_reconstruction_mls_evaluation.cpp b/test/test_polynomial_reconstruction_mls_evaluation.cpp index 9f8784d66..dfd256637 100644 --- a/test/test_polynomial_reconstruction_mls_evaluation.cpp +++ b/test/test_polynomial_reconstruction_mls_evaluation.cpp @@ -2,20 +2,20 @@ #include #include "pcms/field/function_space/polynomial_reconstruction.hpp" -#include "pcms/field/evaluator/mls_options.h" +#include "pcms/localization/mls_options.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/field/coordinate_view.hpp" -#include "pcms/field/out_of_bounds_policy.h" -#include "pcms/utility/arrays.h" -#include "pcms/utility/memory_spaces.h" -#include "field_test_utils.h" +#include "pcms/utility/coordinate_view.hpp" +#include "pcms/field/out_of_bounds_policy.hpp" +#include "pcms/utility/arrays.hpp" +#include "pcms/utility/memory_spaces.hpp" +#include "field_test_utils.hpp" #include #include #include #include -#include "pcms/field/coordinate_systems/cartesian.hpp" -#include "pcms/field/coordinate_systems/cylindrical.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_systems/cylindrical.hpp" using pcms::CoordinateSystem; using pcms::CoordinateView; @@ -113,7 +113,7 @@ void CheckPolynomialReproduction(unsigned degree, auto src = MakeGrid2D(9); Rank2View coords_view(src.data(), 81, 2); - auto fs = pcms::PolynomialReconstructionFunctionSpace::Create( + auto fs = pcms::field::PolynomialReconstructionFunctionSpace::Create( pcms::CoordinateView(pcms::csys::Cartesian::Deferred(), coords_view), SweepTestOptions(degree, basis)); @@ -168,7 +168,7 @@ TEST_CASE("PolynomialReconstructionFunctionSpace MLS: same PointEvaluator " auto src = MakeGrid2D(7); Rank2View coords_view(src.data(), 49, 2); - auto fs = pcms::PolynomialReconstructionFunctionSpace::Create( + auto fs = pcms::field::PolynomialReconstructionFunctionSpace::Create( pcms::CoordinateView(pcms::csys::Cartesian::Deferred(), coords_view), DefaultTestOptions()); @@ -207,7 +207,7 @@ TEST_CASE("PolynomialReconstructionFunctionSpace MLS: Evaluate throws for " auto src = MakeGrid2D(5); Rank2View coords_view(src.data(), 25, 2); - auto fs = pcms::PolynomialReconstructionFunctionSpace::Create( + auto fs = pcms::field::PolynomialReconstructionFunctionSpace::Create( pcms::CoordinateView(pcms::csys::Cartesian::Deferred(), coords_view)); auto field = fs->CreateFunction(); @@ -236,7 +236,7 @@ TEST_CASE("PolynomialReconstructionFunctionSpace MLS: default MLSOptions — " Rank2View coords_view(src.data(), 49, 2); // Use default options — no third argument - auto fs = pcms::PolynomialReconstructionFunctionSpace::Create( + auto fs = pcms::field::PolynomialReconstructionFunctionSpace::Create( pcms::CoordinateView(pcms::csys::Cartesian::Deferred(), coords_view)); auto field = fs->CreateFunction(); @@ -265,7 +265,7 @@ TEST_CASE("PolynomialReconstructionFunctionSpace MLS: CreatePointEvaluator " auto src = MakeGrid2D(5); Rank2View coords_view(src.data(), 25, 2); - auto fs = pcms::PolynomialReconstructionFunctionSpace::Create( + auto fs = pcms::field::PolynomialReconstructionFunctionSpace::Create( pcms::CoordinateView(pcms::csys::CylindricalRZ::Create(), coords_view), DefaultTestOptions()); @@ -288,7 +288,7 @@ TEST_CASE("PolynomialReconstructionFunctionSpace MLS: accepts the (R, Z) " Rank2View coords_view( src.data(), static_cast(src.size() / 2), 2); - auto fs = pcms::PolynomialReconstructionFunctionSpace::Create( + auto fs = pcms::field::PolynomialReconstructionFunctionSpace::Create( pcms::CoordinateView(pcms::csys::CylindricalRZ::Create(), coords_view), DefaultTestOptions()); @@ -329,7 +329,7 @@ TEST_CASE("PolynomialReconstructionFunctionSpace MLS: CreatePointEvaluator " Rank2View coords_view( src.data(), static_cast(src.size() / 3), 3); - auto fs = pcms::PolynomialReconstructionFunctionSpace::Create( + auto fs = pcms::field::PolynomialReconstructionFunctionSpace::Create( pcms::CoordinateView( pcms::csys::CylindricalRThetaZ::Create(), coords_view), DefaultTestOptions3D()); @@ -355,7 +355,7 @@ TEST_CASE("PolynomialReconstructionFunctionSpace MLS: radius option is " opts.adapt_radius = false; opts.basis = pcms::RadialBasisFunction::RBF_CONST; - auto fs = pcms::PolynomialReconstructionFunctionSpace::Create( + auto fs = pcms::field::PolynomialReconstructionFunctionSpace::Create( pcms::CoordinateView(pcms::csys::Cartesian::Deferred(), coords_view), opts); @@ -387,7 +387,7 @@ TEST_CASE("PolynomialReconstructionFunctionSpace MLS: 3D point clouds preserve " auto src = MakeGrid3D(3); Rank2View coords_view(src.data(), 27, 3); - auto fs = pcms::PolynomialReconstructionFunctionSpace::Create( + auto fs = pcms::field::PolynomialReconstructionFunctionSpace::Create( pcms::CoordinateView(pcms::csys::Cartesian::Deferred(), coords_view), DefaultTestOptions3D()); diff --git a/test/test_proxy_coupling.cpp b/test/test_proxy_coupling.cpp index 0e8c04d47..6fb6e6f3c 100644 --- a/test/test_proxy_coupling.cpp +++ b/test/test_proxy_coupling.cpp @@ -1,17 +1,17 @@ #include #include -#include -#include +#include +#include #include #include #include -#include "test_support.h" +#include "test_support.hpp" #include "pcms/coupler/coupler.hpp" -#include "pcms/field/function_space/lagrange.h" +#include "pcms/field/function_space/lagrange.hpp" #include "pcms/field/value_view.hpp" #include #include -#include "pcms/field/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" using pcms::GO; using pcms::make_array_view; @@ -95,9 +95,9 @@ void xgc_delta_f(MPI_Comm comm, Omega_h::Mesh& mesh) pcms::ApplicationComm* app = coupler.AddApplication("proxy_couple_xgc_delta_f"); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::DefaultBackend, "gids"); + pcms::field::LagrangeFunctionSpace::DefaultBackend, "gids"); auto gids_field = factory->CreateFunction("gids"); auto gids2_field = factory->CreateFunction("gids2"); @@ -134,9 +134,9 @@ void xgc_total_f(MPI_Comm comm, Omega_h::Mesh& mesh) pcms::ApplicationComm* app = coupler.AddApplication("proxy_couple_xgc_total_f"); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::DefaultBackend, "gids"); + pcms::field::LagrangeFunctionSpace::DefaultBackend, "gids"); auto gids_field = factory->CreateFunction("gids"); @@ -175,13 +175,13 @@ void xgc_coupler(MPI_Comm comm, Omega_h::Mesh& mesh, std::string_view cpn_file) const auto partition = std::get(cpl.GetPartition()); auto* total_f = cpl.AddApplication("proxy_couple_xgc_total_f"); auto* delta_f = cpl.AddApplication("proxy_couple_xgc_delta_f"); - auto factory_total = pcms::LagrangeFunctionSpace::FromMesh( + auto factory_total = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::DefaultBackend, "gids"); + pcms::field::LagrangeFunctionSpace::DefaultBackend, "gids"); - auto factory_delta = pcms::LagrangeFunctionSpace::FromMesh( + auto factory_delta = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred(), "global", - pcms::LagrangeFunctionSpace::DefaultBackend, "gids"); + pcms::field::LagrangeFunctionSpace::DefaultBackend, "gids"); // TODO, fields should have a transfer policy rather than parameters auto total_gids_field = factory_total->CreateFunction("gids"); auto delta_gids_field = factory_delta->CreateFunction("gids"); diff --git a/test/test_proxy_coupling_xgc_server.cpp b/test/test_proxy_coupling_xgc_server.cpp index b7d067547..c85976a2c 100644 --- a/test/test_proxy_coupling_xgc_server.cpp +++ b/test/test_proxy_coupling_xgc_server.cpp @@ -1,22 +1,22 @@ #include -#include -#include +#include +#include #include #include -#include +#include -#include "test_support.h" -#include "pcms/field/function_space/xgc.h" -#include "pcms/field/layout/xgc.h" +#include "test_support.hpp" +#include "pcms/backends/xgc/field_factory.hpp" +#include "pcms/backends/xgc/layout.hpp" #include "pcms/coupler/coupler.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/field/function_space/lagrange.h" -#include "pcms/field/coordinate_systems/cartesian.hpp" +#include "pcms/field/function_space/lagrange.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" -using pcms::ConstructRCFromOmegaHMesh; using pcms::GO; using pcms::make_array_view; -using pcms::ReverseClassificationVertex; +using pcms::backend::xgc::ConstructRCFromOmegaHMesh; +using pcms::backend::xgc::ReverseClassificationVertex; static constexpr bool done = true; namespace ts = test_support; @@ -30,11 +30,12 @@ void xgc_coupler(MPI_Comm comm, Omega_h::Mesh& mesh, std::string_view cpn_file) "proxy_couple_server", comm, true, redev::Partition{ts::setupServerPartition(mesh, cpn_file)}); const auto partition = std::get(cpl.GetPartition()); - ReverseClassificationVertex rc; + pcms::backend::xgc::ReverseClassificationVertex rc; if (mesh.has_tag(0, "simNumbering")) { - rc = ConstructRCFromOmegaHMesh(mesh, "simNumbering"); + rc = pcms::backend::xgc::ConstructRCFromOmegaHMesh(mesh, "simNumbering"); } else { - rc = ConstructRCFromOmegaHMesh(mesh, "global", pcms::IndexBase::Zero); + rc = pcms::backend::xgc::ConstructRCFromOmegaHMesh( + mesh, "global", pcms::backend::xgc::IndexBase::Zero); } auto is_overlap = @@ -54,10 +55,10 @@ void xgc_coupler(MPI_Comm comm, Omega_h::Mesh& mesh, std::string_view cpn_file) // FIXME: The current C/Fortran proxy API couples layout registration to // field registration, so each XGC plane is registered as a separate layout // communicator even though the layouts are geometrically identical. - auto function_space = - pcms::XGCFieldFactory(rc, static_cast(mesh.nverts()), ss.str()); + auto function_space = pcms::backend::xgc::XGCFieldFactory( + rc, static_cast(mesh.nverts()), ss.str()); auto field = function_space.CreateField( - ss.str(), std::make_unique>( + ss.str(), std::make_unique>( function_space.GetXGCLayout(), pcms::ValueBasis{}, make_array_view(data[i]), comm)); fields.push_back(application->AddField(std::move(field))); @@ -170,9 +171,9 @@ void omegah_coupler(MPI_Comm comm, Omega_h::Mesh& mesh, // FIXME: The current C/Fortran proxy API couples layout registration to // field registration, so each XGC plane is registered as a separate layout // communicator even though the layouts are geometrically identical. - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred(), numbering, - pcms::LagrangeFunctionSpace::Backend::OmegaH, ss.str()); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH, ss.str()); auto field = factory->CreateFunction( ss.str(), std::make_unique>( factory->GetLayout(), pcms::ValueBasis{})); diff --git a/test/test_proxy_coupling_xgc_server_overlap.cpp b/test/test_proxy_coupling_xgc_server_overlap.cpp index 4fd3eba1c..48dcd9cb4 100644 --- a/test/test_proxy_coupling_xgc_server_overlap.cpp +++ b/test/test_proxy_coupling_xgc_server_overlap.cpp @@ -1,23 +1,23 @@ #include -#include -#include +#include +#include #include #include -#include +#include -#include "test_support.h" -#include "pcms/field/function_space/xgc.h" -#include "pcms/field/layout/xgc.h" +#include "test_support.hpp" +#include "pcms/backends/xgc/field_factory.hpp" +#include "pcms/backends/xgc/layout.hpp" #include "pcms/coupler/coupler.hpp" -#include "pcms/coupler/overlap_mask.h" +#include "pcms/coupler/overlap_mask.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/field/function_space/lagrange.h" -#include "pcms/field/coordinate_systems/cartesian.hpp" +#include "pcms/field/function_space/lagrange.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" -using pcms::ConstructRCFromOmegaHMesh; using pcms::GO; using pcms::make_array_view; -using pcms::ReverseClassificationVertex; +using pcms::backend::xgc::ConstructRCFromOmegaHMesh; +using pcms::backend::xgc::ReverseClassificationVertex; static constexpr bool done = true; namespace ts = test_support; @@ -30,11 +30,12 @@ void xgc_coupler_with_overlap(MPI_Comm comm, Omega_h::Mesh& mesh, redev::Partition{ts::setupServerPartition(mesh, cpn_file)}); const auto partition = std::get(cpl.GetPartition()); - ReverseClassificationVertex rc; + pcms::backend::xgc::ReverseClassificationVertex rc; if (mesh.has_tag(0, "simNumbering")) { - rc = ConstructRCFromOmegaHMesh(mesh, "simNumbering"); + rc = pcms::backend::xgc::ConstructRCFromOmegaHMesh(mesh, "simNumbering"); } else { - rc = ConstructRCFromOmegaHMesh(mesh, "global", pcms::IndexBase::Zero); + rc = pcms::backend::xgc::ConstructRCFromOmegaHMesh( + mesh, "global", pcms::backend::xgc::IndexBase::Zero); } auto* application = cpl.AddApplication("proxy_couple"); @@ -55,11 +56,11 @@ void xgc_coupler_with_overlap(MPI_Comm comm, Omega_h::Mesh& mesh, application->SetLayoutOverlapMask(ss.str(), std::move(overlap_mask)); - auto function_space = - pcms::XGCFieldFactory(rc, static_cast(mesh.nverts()), ss.str()); + auto function_space = pcms::backend::xgc::XGCFieldFactory( + rc, static_cast(mesh.nverts()), ss.str()); auto field = function_space.CreateField( - ss.str(), std::make_unique>( + ss.str(), std::make_unique>( function_space.GetXGCLayout(), pcms::ValueBasis{}, make_array_view(data[i]), comm)); @@ -169,9 +170,9 @@ void omegah_coupler_with_overlap(MPI_Comm comm, Omega_h::Mesh& mesh, application->SetLayoutOverlapMask(ss.str(), std::move(overlap_mask)); - auto factory = pcms::LagrangeFunctionSpace::FromMesh( + auto factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred(), numbering, - pcms::LagrangeFunctionSpace::Backend::OmegaH, ss.str()); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH, ss.str()); auto field = factory->CreateFunction( ss.str(), std::make_unique>( diff --git a/test/test_rbf_interp.cpp b/test/test_rbf_interp.cpp index bc7a800d3..c1cd81a0c 100644 --- a/test/test_rbf_interp.cpp +++ b/test/test_rbf_interp.cpp @@ -1,8 +1,8 @@ #include #include -#include +#include #include -#include +#include #include #include #include @@ -46,13 +46,14 @@ void test(Omega_h::Mesh& mesh, Omega_h::Real cutoffDistance, int degree, }; - pcms::SupportResults support = - pcms::searchNeighbors(mesh, cutoffDistance, min_num_supports); + pcms::localization::SupportResults support = + pcms::backend::omega_h::searchNeighbors(mesh, cutoffDistance, + min_num_supports); for (const auto& rbf : rbf_types) { - auto approx_target_values = - mls_interpolation(source_values, source_coordinates, target_coordinates, - support, dim, degree, rbf); + auto approx_target_values = pcms::field::mls_interpolation( + source_values, source_coordinates, target_coordinates, support, dim, + degree, rbf); auto host_approx_target_values = Omega_h::HostRead(approx_target_values); @@ -95,7 +96,7 @@ TEST_CASE("test_mls_interpolation") const auto& ntargets = mesh.nverts(); const auto& faces2nodes = mesh.ask_down(Omega_h::FACE, Omega_h::VERT).ab2b; - const auto source_coordinates = pcms::get_entity_centroids(mesh, 2); + const auto source_coordinates = pcms::utility::get_entity_centroids(mesh, 2); pcms::Points source_points; source_points.coordinates = diff --git a/test/test_spline_interpolator.cpp b/test/test_spline_interpolator.cpp index 1bc682ef6..3565a904b 100644 --- a/test/test_spline_interpolator.cpp +++ b/test/test_spline_interpolator.cpp @@ -1,5 +1,5 @@ #include "mdspan/mdspan.hpp" -#include "pcms.h" +#include "pcms/pcms.hpp" #include #include #include @@ -12,8 +12,8 @@ #include #include #include -#include "pcms/field/evaluator/spline_interpolator.hpp" -#include "field_test_utils.h" +#include "pcms/backends/uniform_grid/spline_interpolator.hpp" +#include "field_test_utils.hpp" using namespace pcms; using pcms::test::CreateDeviceRank1View; @@ -185,27 +185,37 @@ void dotest1(int ns, Rank1View x, reset_2dspan(splinv); // interpolator.cspline(x, ns, fspl, 1, 1, 1, 1, wk); - ExplicitCubicSplineInterpolator - explicit_interpolator(x, f, BoundaryCondition::FIRST_DERIVATIVE_MATCH, 1, - BoundaryCondition::FIRST_DERIVATIVE_MATCH, 1); + pcms::backend::uniform_grid::ExplicitCubicSplineInterpolator + explicit_interpolator( + x, f, + pcms::backend::uniform_grid::BoundaryCondition::FIRST_DERIVATIVE_MATCH, 1, + pcms::backend::uniform_grid::BoundaryCondition::FIRST_DERIVATIVE_MATCH, + 1); explicit_interpolator.evaluate(xt, splinv); compare(splinv, ft, Kokkos::subview(res_1d, Kokkos::make_pair(0, 2)), "cspline"); reset_2dspan(splinv); - ExplicitCubicSplineInterpolator - explicit_interpolator_periodic(x, f, BoundaryCondition::PERIODIC, 0, - BoundaryCondition::PERIODIC, 0); + pcms::backend::uniform_grid::ExplicitCubicSplineInterpolator + explicit_interpolator_periodic( + x, f, pcms::backend::uniform_grid::BoundaryCondition::PERIODIC, 0, + pcms::backend::uniform_grid::BoundaryCondition::PERIODIC, 0); explicit_interpolator_periodic.evaluate(xt, splinv); compare(splinv, ft, Kokkos::subview(res_1d, Kokkos::make_pair(2, 4)), "cspline_periodic"); reset_2dspan(splinv); - CompactCubicSplineInterpolator compact_interpolator( - x, f, BoundaryCondition::FIRST_DERIVATIVE_MATCH, 1, - BoundaryCondition::FIRST_DERIVATIVE_MATCH, 1); + pcms::backend::uniform_grid::CompactCubicSplineInterpolator + compact_interpolator( + x, f, + pcms::backend::uniform_grid::BoundaryCondition::FIRST_DERIVATIVE_MATCH, 1, + pcms::backend::uniform_grid::BoundaryCondition::FIRST_DERIVATIVE_MATCH, + 1); compact_interpolator.evaluate(xt, splinv); compare(splinv, ft, Kokkos::subview(res_1d, Kokkos::make_pair(4, 6)), @@ -307,24 +317,36 @@ void dotest2(Rank1View x, auto splinv_gt = MakeRank1View(splinv_gt_view); generate_gt_2d(splinv_gt, fxtest, fthtest, ntest); - ExplicitBiCubicSplineInterpolator - explicit_interpolator(x, th, values, - BoundaryCondition::FIRST_DERIVATIVE_MATCH, bcx1, - BoundaryCondition::FIRST_DERIVATIVE_MATCH, bcx2, - BoundaryCondition::FIRST_DERIVATIVE_MATCH, bcth1, - BoundaryCondition::FIRST_DERIVATIVE_MATCH, bcth2); + pcms::backend::uniform_grid::ExplicitBiCubicSplineInterpolator< + double, TestMemorySpace> + explicit_interpolator( + x, th, values, + pcms::backend::uniform_grid::BoundaryCondition::FIRST_DERIVATIVE_MATCH, + bcx1, + pcms::backend::uniform_grid::BoundaryCondition::FIRST_DERIVATIVE_MATCH, + bcx2, + pcms::backend::uniform_grid::BoundaryCondition::FIRST_DERIVATIVE_MATCH, + bcth1, + pcms::backend::uniform_grid::BoundaryCondition::FIRST_DERIVATIVE_MATCH, + bcth2); explicit_interpolator.evaluate(xtest_grid, thtest_grid, splinv); compare_2d(splinv, splinv_gt, Kokkos::subview(res_2d, Kokkos::make_pair(0, 2)), "bcspline"); reset_2dspan(splinv); - CompactBiCubicSplineInterpolator - compact_interpolator(x, th, values, - BoundaryCondition::FIRST_DERIVATIVE_MATCH, bcx1, - BoundaryCondition::FIRST_DERIVATIVE_MATCH, bcx2, - BoundaryCondition::FIRST_DERIVATIVE_MATCH, bcth1, - BoundaryCondition::FIRST_DERIVATIVE_MATCH, bcth2); + pcms::backend::uniform_grid::CompactBiCubicSplineInterpolator + compact_interpolator( + x, th, values, + pcms::backend::uniform_grid::BoundaryCondition::FIRST_DERIVATIVE_MATCH, + bcx1, + pcms::backend::uniform_grid::BoundaryCondition::FIRST_DERIVATIVE_MATCH, + bcx2, + pcms::backend::uniform_grid::BoundaryCondition::FIRST_DERIVATIVE_MATCH, + bcth1, + pcms::backend::uniform_grid::BoundaryCondition::FIRST_DERIVATIVE_MATCH, + bcth2); compact_interpolator.evaluate(xtest_grid, thtest_grid, splinv); compare_2d(splinv, splinv_gt, @@ -485,17 +507,21 @@ std::vector sample_2d(const std::vector& x, } // namespace -TEMPLATE_TEST_CASE("two-point splines keep both endpoint derivatives", - "[spline]", - (ExplicitCubicSplineInterpolator), - (CompactCubicSplineInterpolator)) +TEMPLATE_TEST_CASE( + "two-point splines keep both endpoint derivatives", "[spline]", + (pcms::backend::uniform_grid::ExplicitCubicSplineInterpolator< + double, TestMemorySpace>), + (pcms::backend::uniform_grid::CompactCubicSplineInterpolator< + double, TestMemorySpace>)) { // f = x^3 on [1, 3]: any pair of first/second derivative end conditions // determines the cubic exactly auto x = CreateDeviceRank1View({1.0, 3.0}); auto f = CreateDeviceRank1View({1.0, 27.0}); - const auto d1 = BoundaryCondition::FIRST_DERIVATIVE_MATCH; - const auto d2 = BoundaryCondition::SECOND_DERIVATIVE_MATCH; + const auto d1 = + pcms::backend::uniform_grid::BoundaryCondition::FIRST_DERIVATIVE_MATCH; + const auto d2 = + pcms::backend::uniform_grid::BoundaryCondition::SECOND_DERIVATIVE_MATCH; auto [lo, lo_data, hi, hi_data] = GENERATE_COPY( std::make_tuple(d1, 3.0, d1, 27.0), std::make_tuple(d1, 3.0, d2, 18.0), std::make_tuple(d2, 6.0, d1, 27.0), std::make_tuple(d2, 6.0, d2, 18.0)); @@ -509,10 +535,12 @@ TEMPLATE_TEST_CASE("two-point splines keep both endpoint derivatives", } } -TEMPLATE_TEST_CASE("non-zero boundary data on the lower side only is applied", - "[spline]", - (ExplicitBiCubicSplineInterpolator), - (CompactBiCubicSplineInterpolator)) +TEMPLATE_TEST_CASE( + "non-zero boundary data on the lower side only is applied", "[spline]", + (pcms::backend::uniform_grid::ExplicitBiCubicSplineInterpolator< + double, TestMemorySpace>), + (pcms::backend::uniform_grid::CompactBiCubicSplineInterpolator< + double, TestMemorySpace>)) { // f = g(x) (y - y^2/2) has df/dy = g(x) at y = 0 and 0 at y = 1 auto g = [](double x) { return 1 + x + x * x + x * x * x; }; @@ -528,8 +556,9 @@ TEMPLATE_TEST_CASE("non-zero boundary data on the lower side only is applied", auto lo = CreateDeviceRank1View(lo_h); auto hi = CreateDeviceRank1View(std::vector(xh.size(), 0.0)); auto none = CreateDeviceRank1View({}); - const auto nak = BoundaryCondition::NOT_A_KNOT; - const auto d1 = BoundaryCondition::FIRST_DERIVATIVE_MATCH; + const auto nak = pcms::backend::uniform_grid::BoundaryCondition::NOT_A_KNOT; + const auto d1 = + pcms::backend::uniform_grid::BoundaryCondition::FIRST_DERIVATIVE_MATCH; TestType interp(MakeRank1View(x), MakeRank1View(y), MakeRank1View(v), nak, MakeRank1View(none), nak, MakeRank1View(none), d1, MakeRank1View(lo), d1, MakeRank1View(hi)); @@ -552,8 +581,9 @@ TEST_CASE("spline grids must be finite, ascending and non-degenerate", std::vector{0.0, 1.0, 2.0, inf}); auto x = CreateDeviceRank1View(grid); auto f = CreateDeviceRank1View(std::vector(grid.size(), 1.0)); - using Interp = CompactCubicSplineInterpolator; - const auto nak = BoundaryCondition::NOT_A_KNOT; + using Interp = pcms::backend::uniform_grid::CompactCubicSplineInterpolator< + double, TestMemorySpace>; + const auto nak = pcms::backend::uniform_grid::BoundaryCondition::NOT_A_KNOT; REQUIRE_THROWS_AS(Interp(MakeRank1View(x), MakeRank1View(f), nak, 0, nak, 0), pcms_error); } @@ -564,40 +594,46 @@ TEST_CASE("nearly uniform spline grids are rejected", "[spline]") // silently interpolated as if uniform auto x = CreateDeviceRank1View({0.0, 1.0, 2.0005, 3.0}); auto f = CreateDeviceRank1View({0.0, 1.0, 8.0, 27.0}); - using Interp = ExplicitCubicSplineInterpolator; - const auto nak = BoundaryCondition::NOT_A_KNOT; + using Interp = pcms::backend::uniform_grid::ExplicitCubicSplineInterpolator< + double, TestMemorySpace>; + const auto nak = pcms::backend::uniform_grid::BoundaryCondition::NOT_A_KNOT; REQUIRE_THROWS_AS(Interp(MakeRank1View(x), MakeRank1View(f), nak, 0, nak, 0), pcms_error); } -TEMPLATE_TEST_CASE("1D queries outside the grid leave the output untouched", - "[spline]", - (ExplicitCubicSplineInterpolator), - (CompactCubicSplineInterpolator)) +TEMPLATE_TEST_CASE( + "1D queries outside the grid leave the output untouched", "[spline]", + (pcms::backend::uniform_grid::ExplicitCubicSplineInterpolator< + double, TestMemorySpace>), + (pcms::backend::uniform_grid::CompactCubicSplineInterpolator< + double, TestMemorySpace>)) { auto xh = linspace(0, 1, 6); auto x = CreateDeviceRank1View(xh); auto f = CreateDeviceRank1View(xh); TestType interp(MakeRank1View(x), MakeRank1View(f), - BoundaryCondition::NOT_A_KNOT, 0, - BoundaryCondition::NOT_A_KNOT, 0); + pcms::backend::uniform_grid::BoundaryCondition::NOT_A_KNOT, 0, + pcms::backend::uniform_grid::BoundaryCondition::NOT_A_KNOT, + 0); const double nan = std::numeric_limits::quiet_NaN(); auto out = eval_1d(interp, {1, 1, 0}, {nan, -1.0e6, 1.0e6}, 2); for (double v : out) CHECK(v == 0.0); } -TEMPLATE_TEST_CASE("2D queries outside the grid leave the output untouched", - "[spline]", - (ExplicitBiCubicSplineInterpolator), - (CompactBiCubicSplineInterpolator)) +TEMPLATE_TEST_CASE( + "2D queries outside the grid leave the output untouched", "[spline]", + (pcms::backend::uniform_grid::ExplicitBiCubicSplineInterpolator< + double, TestMemorySpace>), + (pcms::backend::uniform_grid::CompactBiCubicSplineInterpolator< + double, TestMemorySpace>)) { auto xh = linspace(0, 1, 6); auto x = CreateDeviceRank1View(xh); auto v = CreateDeviceRank1View( sample_2d(xh, xh, [](double a, double b) { return a + b; })); auto none = CreateDeviceRank1View({}); - const auto nak = BoundaryCondition::NOT_A_KNOT; + const auto nak = pcms::backend::uniform_grid::BoundaryCondition::NOT_A_KNOT; TestType interp(MakeRank1View(x), MakeRank1View(x), MakeRank1View(v), nak, MakeRank1View(none), nak, MakeRank1View(none), nak, MakeRank1View(none), nak, MakeRank1View(none)); @@ -642,9 +678,12 @@ struct SelectorCase } // namespace -TEMPLATE_TEST_CASE("1D selectors pick derivatives in PSPLINE order", "[spline]", - (ExplicitCubicSplineInterpolator), - (CompactCubicSplineInterpolator)) +TEMPLATE_TEST_CASE( + "1D selectors pick derivatives in PSPLINE order", "[spline]", + (pcms::backend::uniform_grid::ExplicitCubicSplineInterpolator< + double, TestMemorySpace>), + (pcms::backend::uniform_grid::CompactCubicSplineInterpolator< + double, TestMemorySpace>)) { auto xh = linspace(-1, 2, 6); std::vector fh; @@ -653,8 +692,9 @@ TEMPLATE_TEST_CASE("1D selectors pick derivatives in PSPLINE order", "[spline]", auto x = CreateDeviceRank1View(xh); auto f = CreateDeviceRank1View(fh); TestType interp(MakeRank1View(x), MakeRank1View(f), - BoundaryCondition::NOT_A_KNOT, 0, - BoundaryCondition::NOT_A_KNOT, 0); + pcms::backend::uniform_grid::BoundaryCondition::NOT_A_KNOT, 0, + pcms::backend::uniform_grid::BoundaryCondition::NOT_A_KNOT, + 0); const std::vector cases = {{{1, 1, 1}, {{0}, {1}, {2}}}, {{0, 1, 0}, {{1}}}, {{0, 0, 1}, {{2}}}, @@ -677,13 +717,16 @@ TEMPLATE_TEST_CASE("1D selectors pick derivatives in PSPLINE order", "[spline]", } } -TEMPLATE_TEST_CASE("2D selectors pick derivatives in PSPLINE order", "[spline]", - (ExplicitBiCubicSplineInterpolator), - (CompactBiCubicSplineInterpolator)) +TEMPLATE_TEST_CASE( + "2D selectors pick derivatives in PSPLINE order", "[spline]", + (pcms::backend::uniform_grid::ExplicitBiCubicSplineInterpolator< + double, TestMemorySpace>), + (pcms::backend::uniform_grid::CompactBiCubicSplineInterpolator< + double, TestMemorySpace>)) { - constexpr bool is_explicit = - std::is_same_v>; + constexpr bool is_explicit = std::is_same_v< + TestType, pcms::backend::uniform_grid::ExplicitBiCubicSplineInterpolator< + double, TestMemorySpace>>; auto xh = linspace(0, 2, 6); auto yh = linspace(-1, 1, 5); auto x = CreateDeviceRank1View(xh); @@ -691,7 +734,7 @@ TEMPLATE_TEST_CASE("2D selectors pick derivatives in PSPLINE order", "[spline]", auto v = CreateDeviceRank1View( sample_2d(xh, yh, [](double a, double b) { return px(a, 0) * py(b, 0); })); auto none = CreateDeviceRank1View({}); - const auto nak = BoundaryCondition::NOT_A_KNOT; + const auto nak = pcms::backend::uniform_grid::BoundaryCondition::NOT_A_KNOT; TestType interp(MakeRank1View(x), MakeRank1View(y), MakeRank1View(v), nak, MakeRank1View(none), nak, MakeRank1View(none), nak, MakeRank1View(none), nak, MakeRank1View(none)); @@ -727,10 +770,12 @@ TEMPLATE_TEST_CASE("2D selectors pick derivatives in PSPLINE order", "[spline]", } } -TEMPLATE_TEST_CASE("1D evaluate without a selector writes every value", - "[spline]", - (ExplicitCubicSplineInterpolator), - (CompactCubicSplineInterpolator)) +TEMPLATE_TEST_CASE( + "1D evaluate without a selector writes every value", "[spline]", + (pcms::backend::uniform_grid::ExplicitCubicSplineInterpolator< + double, TestMemorySpace>), + (pcms::backend::uniform_grid::CompactCubicSplineInterpolator< + double, TestMemorySpace>)) { // the overload builds its own value-only selector on the device; NaN marks // outputs it never wrote @@ -741,8 +786,9 @@ TEMPLATE_TEST_CASE("1D evaluate without a selector writes every value", auto x = CreateDeviceRank1View(xh); auto f = CreateDeviceRank1View(fh); TestType interp(MakeRank1View(x), MakeRank1View(f), - BoundaryCondition::NOT_A_KNOT, 0, - BoundaryCondition::NOT_A_KNOT, 0); + pcms::backend::uniform_grid::BoundaryCondition::NOT_A_KNOT, 0, + pcms::backend::uniform_grid::BoundaryCondition::NOT_A_KNOT, + 0); const std::vector xq = {-1.0, 0.3, 1.7, 2.0}; auto xd = CreateDeviceRank1View(xq); Kokkos::View out("out", xq.size(), 1); @@ -755,10 +801,12 @@ TEMPLATE_TEST_CASE("1D evaluate without a selector writes every value", } } -TEMPLATE_TEST_CASE("2D evaluate without a selector writes every value", - "[spline]", - (ExplicitBiCubicSplineInterpolator), - (CompactBiCubicSplineInterpolator)) +TEMPLATE_TEST_CASE( + "2D evaluate without a selector writes every value", "[spline]", + (pcms::backend::uniform_grid::ExplicitBiCubicSplineInterpolator< + double, TestMemorySpace>), + (pcms::backend::uniform_grid::CompactBiCubicSplineInterpolator< + double, TestMemorySpace>)) { auto xh = linspace(0, 2, 6); auto yh = linspace(-1, 1, 5); @@ -767,7 +815,7 @@ TEMPLATE_TEST_CASE("2D evaluate without a selector writes every value", auto v = CreateDeviceRank1View( sample_2d(xh, yh, [](double a, double b) { return px(a, 0) * py(b, 0); })); auto none = CreateDeviceRank1View({}); - const auto nak = BoundaryCondition::NOT_A_KNOT; + const auto nak = pcms::backend::uniform_grid::BoundaryCondition::NOT_A_KNOT; TestType interp(MakeRank1View(x), MakeRank1View(y), MakeRank1View(v), nak, MakeRank1View(none), nak, MakeRank1View(none), nak, MakeRank1View(none), nak, MakeRank1View(none)); @@ -785,9 +833,12 @@ TEMPLATE_TEST_CASE("2D evaluate without a selector writes every value", } } -TEMPLATE_TEST_CASE("1D splines build and evaluate in host memory", "[spline]", - (ExplicitCubicSplineInterpolator), - (CompactCubicSplineInterpolator)) +TEMPLATE_TEST_CASE( + "1D splines build and evaluate in host memory", "[spline]", + (pcms::backend::uniform_grid::ExplicitCubicSplineInterpolator< + double, Kokkos::HostSpace>), + (pcms::backend::uniform_grid::CompactCubicSplineInterpolator< + double, Kokkos::HostSpace>)) { // every kernel must run in the interpolator's own space, even when the // default execution space is a device @@ -800,8 +851,9 @@ TEMPLATE_TEST_CASE("1D splines build and evaluate in host memory", "[spline]", Kokkos::View out("out", xq.size(), 1); Kokkos::deep_copy(out, std::numeric_limits::quiet_NaN()); TestType interp(make_array_view(xh), make_array_view(fh), - BoundaryCondition::NOT_A_KNOT, 0, - BoundaryCondition::NOT_A_KNOT, 0); + pcms::backend::uniform_grid::BoundaryCondition::NOT_A_KNOT, 0, + pcms::backend::uniform_grid::BoundaryCondition::NOT_A_KNOT, + 0); interp.evaluate(make_array_view(xq), MakeRank2View(out)); Kokkos::fence(); for (size_t i = 0; i < xq.size(); ++i) { @@ -812,8 +864,10 @@ TEMPLATE_TEST_CASE("1D splines build and evaluate in host memory", "[spline]", TEMPLATE_TEST_CASE( "2D splines build and evaluate in host memory", "[spline]", - (ExplicitBiCubicSplineInterpolator), - (CompactBiCubicSplineInterpolator)) + (pcms::backend::uniform_grid::ExplicitBiCubicSplineInterpolator< + double, Kokkos::HostSpace>), + (pcms::backend::uniform_grid::CompactBiCubicSplineInterpolator< + double, Kokkos::HostSpace>)) { auto xh = linspace(0, 2, 6); auto yh = linspace(-1, 1, 5); @@ -825,7 +879,7 @@ TEMPLATE_TEST_CASE( Kokkos::View out("out", xq.size(), 1); Kokkos::deep_copy(out, std::numeric_limits::quiet_NaN()); Rank1View none(nullptr, 0); - const auto nak = BoundaryCondition::NOT_A_KNOT; + const auto nak = pcms::backend::uniform_grid::BoundaryCondition::NOT_A_KNOT; TestType interp(make_array_view(xh), make_array_view(yh), make_array_view(v), nak, none, nak, none, nak, none, nak, none); interp.evaluate(make_array_view(xq), make_array_view(yq), MakeRank2View(out)); @@ -839,7 +893,7 @@ TEMPLATE_TEST_CASE( TEST_CASE("explicit and compact splines agree for every boundary condition", "[spline]") { - using BC = BoundaryCondition; + using BC = pcms::backend::uniform_grid::BoundaryCondition; const double pi2 = 2 * M_PI; auto [lo, hi] = GENERATE( std::make_pair(BC::NOT_A_KNOT, BC::NOT_A_KNOT), @@ -874,23 +928,27 @@ TEST_CASE("explicit and compact splines agree for every boundary condition", yq.push_back(pi2 * std::fmod(0.291 * i + 0.02, 1.0)); } - ExplicitCubicSplineInterpolator e1( - MakeRank1View(x), MakeRank1View(f1), lo, 0.7, hi, -0.4); - CompactCubicSplineInterpolator c1( - MakeRank1View(x), MakeRank1View(f1), lo, 0.7, hi, -0.4); + pcms::backend::uniform_grid::ExplicitCubicSplineInterpolator + e1(MakeRank1View(x), MakeRank1View(f1), lo, 0.7, hi, -0.4); + pcms::backend::uniform_grid::CompactCubicSplineInterpolator + c1(MakeRank1View(x), MakeRank1View(f1), lo, 0.7, hi, -0.4); auto oe1 = eval_1d(e1, {1, 1, 1}, xq, 3); auto oc1 = eval_1d(c1, {1, 1, 1}, xq, 3); for (size_t i = 0; i < oe1.size(); ++i) CHECK(oc1[i] == Catch::Approx(oe1[i]).margin(1e-10)); - ExplicitBiCubicSplineInterpolator e2( - MakeRank1View(x), MakeRank1View(y), MakeRank1View(f2), lo, - MakeRank1View(bx), hi, MakeRank1View(bx), lo, MakeRank1View(by), hi, - MakeRank1View(by)); - CompactBiCubicSplineInterpolator c2( - MakeRank1View(x), MakeRank1View(y), MakeRank1View(f2), lo, - MakeRank1View(bx), hi, MakeRank1View(bx), lo, MakeRank1View(by), hi, - MakeRank1View(by)); + pcms::backend::uniform_grid::ExplicitBiCubicSplineInterpolator< + double, TestMemorySpace> + e2(MakeRank1View(x), MakeRank1View(y), MakeRank1View(f2), lo, + MakeRank1View(bx), hi, MakeRank1View(bx), lo, MakeRank1View(by), hi, + MakeRank1View(by)); + pcms::backend::uniform_grid::CompactBiCubicSplineInterpolator + c2(MakeRank1View(x), MakeRank1View(y), MakeRank1View(f2), lo, + MakeRank1View(bx), hi, MakeRank1View(bx), lo, MakeRank1View(by), hi, + MakeRank1View(by)); auto oe2 = eval_2d(e2, {1, 1, 1, 1, 1, 1}, xq, yq, 6); auto oc2 = eval_2d(c2, {1, 1, 1, 1, 1, 1}, xq, yq, 6); for (size_t i = 0; i < oe2.size(); ++i) @@ -930,21 +988,27 @@ std::pair effective_conditions(int n, int lo, int hi) } /// End data that a product of the test cubics satisfies for condition bc -double end_data(BoundaryCondition bc, double (*p)(double, int), double x) +double end_data(pcms::backend::uniform_grid::BoundaryCondition bc, + double (*p)(double, int), double x) { switch (bc) { - case BoundaryCondition::FIRST_DERIVATIVE_MATCH: return p(x, 1); - case BoundaryCondition::SECOND_DERIVATIVE_MATCH: return p(x, 2); + case pcms::backend::uniform_grid::BoundaryCondition::FIRST_DERIVATIVE_MATCH: + return p(x, 1); + case pcms::backend::uniform_grid::BoundaryCondition:: + SECOND_DERIVATIVE_MATCH: + return p(x, 2); default: return 0; } } } // namespace -TEMPLATE_TEST_CASE("every end condition holds on grids of 2 to 8 points", - "[spline]", - (ExplicitCubicSplineInterpolator), - (CompactCubicSplineInterpolator)) +TEMPLATE_TEST_CASE( + "every end condition holds on grids of 2 to 8 points", "[spline]", + (pcms::backend::uniform_grid::ExplicitCubicSplineInterpolator< + double, TestMemorySpace>), + (pcms::backend::uniform_grid::CompactCubicSplineInterpolator< + double, TestMemorySpace>)) { const double lo_data = 0.7, hi_data = -0.4; for (int n = 2; n <= 8; ++n) { @@ -960,9 +1024,12 @@ TEMPLATE_TEST_CASE("every end condition holds on grids of 2 to 8 points", fh.back() = fh.front(); auto x = CreateDeviceRank1View(xh); auto f = CreateDeviceRank1View(fh); - TestType s(MakeRank1View(x), MakeRank1View(f), - static_cast(lo), lo_data, - static_cast(hi), hi_data); + TestType s( + MakeRank1View(x), MakeRank1View(f), + static_cast(lo), + lo_data, + static_cast(hi), + hi_data); // s', s'', s''' at both ends and in the two cells next to each end auto mid = [&](int cell) { return xh[cell] + h / 2; }; @@ -1015,12 +1082,14 @@ TEMPLATE_TEST_CASE("every end condition holds on grids of 2 to 8 points", } } -TEMPLATE_TEST_CASE("1D splines reproduce cubics for every exact end condition", - "[spline]", - (ExplicitCubicSplineInterpolator), - (CompactCubicSplineInterpolator)) +TEMPLATE_TEST_CASE( + "1D splines reproduce cubics for every exact end condition", "[spline]", + (pcms::backend::uniform_grid::ExplicitCubicSplineInterpolator< + double, TestMemorySpace>), + (pcms::backend::uniform_grid::CompactCubicSplineInterpolator< + double, TestMemorySpace>)) { - using BC = BoundaryCondition; + using BC = pcms::backend::uniform_grid::BoundaryCondition; const std::vector conditions = { BC::NOT_A_KNOT, BC::FIRST_DERIVATIVE_MATCH, BC::SECOND_DERIVATIVE_MATCH, BC::THIRD_DIV_DIFF_MATCH}; @@ -1053,10 +1122,12 @@ TEMPLATE_TEST_CASE("1D splines reproduce cubics for every exact end condition", TEMPLATE_TEST_CASE( "2D splines reproduce bicubics for every exact end condition", "[spline]", - (ExplicitBiCubicSplineInterpolator), - (CompactBiCubicSplineInterpolator)) + (pcms::backend::uniform_grid::ExplicitBiCubicSplineInterpolator< + double, TestMemorySpace>), + (pcms::backend::uniform_grid::CompactBiCubicSplineInterpolator< + double, TestMemorySpace>)) { - using BC = BoundaryCondition; + using BC = pcms::backend::uniform_grid::BoundaryCondition; const std::vector conditions = { BC::NOT_A_KNOT, BC::FIRST_DERIVATIVE_MATCH, BC::SECOND_DERIVATIVE_MATCH, BC::THIRD_DIV_DIFF_MATCH}; @@ -1103,10 +1174,12 @@ TEMPLATE_TEST_CASE( } } -TEMPLATE_TEST_CASE("periodic 1D splines wrap queries outside the period", - "[spline]", - (ExplicitCubicSplineInterpolator), - (CompactCubicSplineInterpolator)) +TEMPLATE_TEST_CASE( + "periodic 1D splines wrap queries outside the period", "[spline]", + (pcms::backend::uniform_grid::ExplicitCubicSplineInterpolator< + double, TestMemorySpace>), + (pcms::backend::uniform_grid::CompactCubicSplineInterpolator< + double, TestMemorySpace>)) { const double pi2 = 2 * M_PI; auto xh = linspace(0, pi2, 16); @@ -1116,7 +1189,7 @@ TEMPLATE_TEST_CASE("periodic 1D splines wrap queries outside the period", fh.back() = fh.front(); auto x = CreateDeviceRank1View(xh); auto f = CreateDeviceRank1View(fh); - const auto per = BoundaryCondition::PERIODIC; + const auto per = pcms::backend::uniform_grid::BoundaryCondition::PERIODIC; TestType s(MakeRank1View(x), MakeRank1View(f), per, 0, per, 0); const std::vector outside = {-0.1, pi2 + 0.1, -pi2 + 0.3, 2 * pi2 + 1.0}; @@ -1127,10 +1200,12 @@ TEMPLATE_TEST_CASE("periodic 1D splines wrap queries outside the period", CHECK(o[k] == Catch::Approx(i[k]).margin(1e-10)); } -TEMPLATE_TEST_CASE("periodic 2D splines wrap queries outside the period", - "[spline]", - (ExplicitBiCubicSplineInterpolator), - (CompactBiCubicSplineInterpolator)) +TEMPLATE_TEST_CASE( + "periodic 2D splines wrap queries outside the period", "[spline]", + (pcms::backend::uniform_grid::ExplicitBiCubicSplineInterpolator< + double, TestMemorySpace>), + (pcms::backend::uniform_grid::CompactBiCubicSplineInterpolator< + double, TestMemorySpace>)) { const double pi2 = 2 * M_PI; auto xh = linspace(0, pi2, 12); @@ -1142,7 +1217,7 @@ TEMPLATE_TEST_CASE("periodic 2D splines wrap queries outside the period", auto v = CreateDeviceRank1View(sample_2d( xh, yh, [](double a, double b) { return std::sin(a) * std::cos(b) + 1; })); auto none = CreateDeviceRank1View({}); - const auto per = BoundaryCondition::PERIODIC; + const auto per = pcms::backend::uniform_grid::BoundaryCondition::PERIODIC; TestType s(MakeRank1View(x), MakeRank1View(y), MakeRank1View(v), per, MakeRank1View(none), per, MakeRank1View(none), per, MakeRank1View(none), per, MakeRank1View(none)); @@ -1156,15 +1231,17 @@ TEMPLATE_TEST_CASE("periodic 2D splines wrap queries outside the period", CHECK(o[k] == Catch::Approx(i[k]).margin(1e-10)); } -TEMPLATE_TEST_CASE("short-grid splines agree with the two-point spline", - "[spline]", - (ExplicitCubicSplineInterpolator), - (CompactCubicSplineInterpolator)) +TEMPLATE_TEST_CASE( + "short-grid splines agree with the two-point spline", "[spline]", + (pcms::backend::uniform_grid::ExplicitCubicSplineInterpolator< + double, TestMemorySpace>), + (pcms::backend::uniform_grid::CompactCubicSplineInterpolator< + double, TestMemorySpace>)) { // a two-point spline with derivative ends is a cubic; splines on finer // grids sampled from it, with the same ends, must be that cubic (PSPLINE // smalltest) - using BC = BoundaryCondition; + using BC = pcms::backend::uniform_grid::BoundaryCondition; const auto d1 = BC::FIRST_DERIVATIVE_MATCH; const auto d2 = BC::SECOND_DERIVATIVE_MATCH; auto [lo, lo_data, hi, hi_data] = GENERATE_COPY( @@ -1205,13 +1282,16 @@ std::vector periodic_samples(const std::vector& y) } // namespace -TEMPLATE_TEST_CASE("2D splines take periodic ends on one axis only", "[spline]", - (ExplicitBiCubicSplineInterpolator), - (CompactBiCubicSplineInterpolator)) +TEMPLATE_TEST_CASE( + "2D splines take periodic ends on one axis only", "[spline]", + (pcms::backend::uniform_grid::ExplicitBiCubicSplineInterpolator< + double, TestMemorySpace>), + (pcms::backend::uniform_grid::CompactBiCubicSplineInterpolator< + double, TestMemorySpace>)) { // f = px(x) (2 + sin y): non-periodic in x, periodic in y (PSPLINE // bpspline and bpsplinb) - using BC = BoundaryCondition; + using BC = pcms::backend::uniform_grid::BoundaryCondition; const double pi2 = 2 * M_PI; auto xh = linspace(0, 2, 6); auto yh = linspace(0, pi2, 12); @@ -1280,13 +1360,16 @@ std::vector observed_orders(const std::vector& err) } // namespace -TEMPLATE_TEST_CASE("1D spline errors converge at fourth order", "[spline]", - (ExplicitCubicSplineInterpolator), - (CompactCubicSplineInterpolator)) +TEMPLATE_TEST_CASE( + "1D spline errors converge at fourth order", "[spline]", + (pcms::backend::uniform_grid::ExplicitCubicSplineInterpolator< + double, TestMemorySpace>), + (pcms::backend::uniform_grid::CompactCubicSplineInterpolator< + double, TestMemorySpace>)) { // f = exp(x) on [0, 1]; the value, f' and f'' errors fall as h^4, h^3 and // h^2 for exact first derivative and not-a-knot ends - using BC = BoundaryCondition; + using BC = pcms::backend::uniform_grid::BoundaryCondition; const BC bc = GENERATE(BC::FIRST_DERIVATIVE_MATCH, BC::NOT_A_KNOT); INFO("ends " << static_cast(bc)); const auto xq = linspace(0, 1, 101); @@ -1315,9 +1398,12 @@ TEMPLATE_TEST_CASE("1D spline errors converge at fourth order", "[spline]", } } -TEMPLATE_TEST_CASE("2D spline errors converge at fourth order", "[spline]", - (ExplicitBiCubicSplineInterpolator), - (CompactBiCubicSplineInterpolator)) +TEMPLATE_TEST_CASE( + "2D spline errors converge at fourth order", "[spline]", + (pcms::backend::uniform_grid::ExplicitBiCubicSplineInterpolator< + double, TestMemorySpace>), + (pcms::backend::uniform_grid::CompactBiCubicSplineInterpolator< + double, TestMemorySpace>)) { // f = exp(2x - 1) (2 + sin y) with exact x derivative faces and periodic // y, at 10, 20 and 40 points per axis (PSPLINE pspltest2) @@ -1350,8 +1436,9 @@ TEMPLATE_TEST_CASE("2D spline errors converge at fourth order", "[spline]", auto bxl = CreateDeviceRank1View(bx_lo); auto bxh = CreateDeviceRank1View(bx_hi); auto none = CreateDeviceRank1View({}); - const auto d1 = BoundaryCondition::FIRST_DERIVATIVE_MATCH; - const auto per = BoundaryCondition::PERIODIC; + const auto d1 = + pcms::backend::uniform_grid::BoundaryCondition::FIRST_DERIVATIVE_MATCH; + const auto per = pcms::backend::uniform_grid::BoundaryCondition::PERIODIC; TestType s(MakeRank1View(x), MakeRank1View(y), MakeRank1View(v), d1, MakeRank1View(bxl), d1, MakeRank1View(bxh), per, MakeRank1View(none), per, MakeRank1View(none)); @@ -1365,14 +1452,16 @@ TEMPLATE_TEST_CASE("2D spline errors converge at fourth order", "[spline]", CHECK(order > 3.5); } -TEMPLATE_TEST_CASE("1D splines of zero data follow the end conditions", - "[spline]", - (ExplicitCubicSplineInterpolator), - (CompactCubicSplineInterpolator)) +TEMPLATE_TEST_CASE( + "1D splines of zero data follow the end conditions", "[spline]", + (pcms::backend::uniform_grid::ExplicitCubicSplineInterpolator< + double, TestMemorySpace>), + (pcms::backend::uniform_grid::CompactCubicSplineInterpolator< + double, TestMemorySpace>)) { // zero samples with non-zero end data, and periodic splines of constant // data (PSPLINE smalltest) - using BC = BoundaryCondition; + using BC = pcms::backend::uniform_grid::BoundaryCondition; for (int n : {2, 3, 5}) { auto xh = linspace(0, 1, n); auto x = CreateDeviceRank1View(xh); @@ -1403,9 +1492,12 @@ TEMPLATE_TEST_CASE("1D splines of zero data follow the end conditions", } } -TEMPLATE_TEST_CASE("2D splines of zero data follow the face data", "[spline]", - (ExplicitBiCubicSplineInterpolator), - (CompactBiCubicSplineInterpolator)) +TEMPLATE_TEST_CASE( + "2D splines of zero data follow the face data", "[spline]", + (pcms::backend::uniform_grid::ExplicitBiCubicSplineInterpolator< + double, TestMemorySpace>), + (pcms::backend::uniform_grid::CompactBiCubicSplineInterpolator< + double, TestMemorySpace>)) { // all-zero values: only the x face derivative data drives the spline auto xh = linspace(0, 1, 5); @@ -1422,8 +1514,9 @@ TEMPLATE_TEST_CASE("2D splines of zero data follow the face data", "[spline]", auto lo = CreateDeviceRank1View(lo_h); auto hi = CreateDeviceRank1View(hi_h); auto none = CreateDeviceRank1View({}); - const auto nak = BoundaryCondition::NOT_A_KNOT; - const auto d1 = BoundaryCondition::FIRST_DERIVATIVE_MATCH; + const auto nak = pcms::backend::uniform_grid::BoundaryCondition::NOT_A_KNOT; + const auto d1 = + pcms::backend::uniform_grid::BoundaryCondition::FIRST_DERIVATIVE_MATCH; TestType s(MakeRank1View(x), MakeRank1View(y), MakeRank1View(v), d1, MakeRank1View(lo), d1, MakeRank1View(hi), nak, MakeRank1View(none), nak, MakeRank1View(none)); @@ -1446,9 +1539,12 @@ TEMPLATE_TEST_CASE("2D splines of zero data follow the face data", "[spline]", CHECK(faces[k] == Catch::Approx(expected[k]).margin(1e-10)); } -TEMPLATE_TEST_CASE("1D queries just outside the grid are clamped", "[spline]", - (ExplicitCubicSplineInterpolator), - (CompactCubicSplineInterpolator)) +TEMPLATE_TEST_CASE( + "1D queries just outside the grid are clamped", "[spline]", + (pcms::backend::uniform_grid::ExplicitCubicSplineInterpolator< + double, TestMemorySpace>), + (pcms::backend::uniform_grid::CompactCubicSplineInterpolator< + double, TestMemorySpace>)) { // the default lookup tolerance is 4e-7 relative to max(|x0|, |xn|) = 2 auto xh = linspace(0, 2, 6); @@ -1457,7 +1553,7 @@ TEMPLATE_TEST_CASE("1D queries just outside the grid are clamped", "[spline]", fh.push_back(px(a, 0)); auto x = CreateDeviceRank1View(xh); auto f = CreateDeviceRank1View(fh); - const auto nak = BoundaryCondition::NOT_A_KNOT; + const auto nak = pcms::backend::uniform_grid::BoundaryCondition::NOT_A_KNOT; TestType s(MakeRank1View(x), MakeRank1View(f), nak, 0, nak, 0); auto clamped = eval_1d(s, {1, 1, 1}, {-4e-7, 2 + 4e-7}, 3, -999.0); auto ends = eval_1d(s, {1, 1, 1}, {0.0, 2.0}, 3); @@ -1468,9 +1564,12 @@ TEMPLATE_TEST_CASE("1D queries just outside the grid are clamped", "[spline]", CHECK(val == -999.0); } -TEMPLATE_TEST_CASE("2D queries just outside the grid are clamped", "[spline]", - (ExplicitBiCubicSplineInterpolator), - (CompactBiCubicSplineInterpolator)) +TEMPLATE_TEST_CASE( + "2D queries just outside the grid are clamped", "[spline]", + (pcms::backend::uniform_grid::ExplicitBiCubicSplineInterpolator< + double, TestMemorySpace>), + (pcms::backend::uniform_grid::CompactBiCubicSplineInterpolator< + double, TestMemorySpace>)) { auto xh = linspace(0, 2, 6); auto yh = linspace(-1, 1, 5); @@ -1479,7 +1578,7 @@ TEMPLATE_TEST_CASE("2D queries just outside the grid are clamped", "[spline]", auto v = CreateDeviceRank1View( sample_2d(xh, yh, [](double a, double b) { return px(a, 0) * py(b, 0); })); auto none = CreateDeviceRank1View({}); - const auto nak = BoundaryCondition::NOT_A_KNOT; + const auto nak = pcms::backend::uniform_grid::BoundaryCondition::NOT_A_KNOT; TestType s(MakeRank1View(x), MakeRank1View(y), MakeRank1View(v), nak, MakeRank1View(none), nak, MakeRank1View(none), nak, MakeRank1View(none), nak, MakeRank1View(none)); diff --git a/test/test_spr_meshfields.cpp b/test/test_spr_meshfields.cpp index 7ad4470a9..c9b90b46e 100644 --- a/test/test_spr_meshfields.cpp +++ b/test/test_spr_meshfields.cpp @@ -1,9 +1,9 @@ #include #include -#include +#include #include -#include -#include +#include +#include #include #include #include @@ -66,9 +66,10 @@ void test(Mesh& mesh, Omega_h::Graph& patches, int degree, Omega_h::Real tolerance = 0.0005; Omega_h::Write ignored(patches.a2ab.size() - 1, 1); - SupportResults support{patches.a2ab, patches.ab2b, ignored}; + pcms::localization::SupportResults support{patches.a2ab, patches.ab2b, + ignored}; - auto approx_target_values = pcms::mls_interpolation( + auto approx_target_values = pcms::field::mls_interpolation( source_values, source_coordinates, target_coordinates, support, dim, degree, pcms::RadialBasisFunction::NO_OP, 1e-5); @@ -128,7 +129,8 @@ TEST_CASE("meshfields_spr_test") const auto& ntargets = mesh.nverts(); - const auto source_coordinates = pcms::get_entity_centroids(mesh, FACE); + const auto source_coordinates = + pcms::utility::get_entity_centroids(mesh, FACE); pcms::Points source_points; diff --git a/test/test_support.cpp b/test/test_support.cpp index e0941033d..9d256c6f8 100644 --- a/test/test_support.cpp +++ b/test/test_support.cpp @@ -1,4 +1,4 @@ -#include "test_support.h" +#include "test_support.hpp" #include //vtk::write_parallel #include //atomic_increment #include //parallel_for diff --git a/test/test_support.h b/test/test_support.hpp similarity index 98% rename from test/test_support.h rename to test/test_support.hpp index 697dca012..5624e5364 100644 --- a/test/test_support.h +++ b/test/test_support.hpp @@ -1,5 +1,5 @@ -#ifndef TEST_HELPERS_H -#define TEST_HELPERS_H +#ifndef PCMS_TEST_TEST_SUPPORT_HPP +#define PCMS_TEST_TEST_SUPPORT_HPP #include #include #include // steady_clock, duration @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include namespace test_support @@ -241,4 +241,4 @@ redev::ClassPtn setupServerPartition(Omega_h::Mesh& mesh, std::string_view cpnFileName); } // namespace test_support -#endif +#endif // PCMS_TEST_TEST_SUPPORT_HPP diff --git a/test/test_svd_serial.cpp b/test/test_svd_serial.cpp index 1774e29bb..7fc4d25eb 100644 --- a/test/test_svd_serial.cpp +++ b/test/test_svd_serial.cpp @@ -1,8 +1,8 @@ #include #include #include -#include -#include +#include +#include #include #include "KokkosBatched_SVD_Decl.hpp" #include "KokkosBatched_SVD_Serial_Impl.hpp" @@ -84,7 +84,7 @@ TEST_CASE("test_serial_svd") }); team.team_barrier(); - auto transposedU = detail::find_transpose(team, U); + auto transposedU = pcms::field::detail::find_transpose(team, U); team.team_barrier(); Kokkos::parallel_for(Kokkos::TeamThreadRange(team, row), [=](int i) { @@ -139,7 +139,7 @@ TEST_CASE("test_serial_svd") team.team_barrier(); - detail::eval_row_scaling(team, weight, A); + pcms::field::detail::eval_row_scaling(team, weight, A); Kokkos::parallel_for(Kokkos::TeamThreadRange(team, row), [=](int i) { for (int j = 0; j < column; ++j) { result(i, j) = A(i, j); @@ -229,7 +229,7 @@ TEST_CASE("test_serial_svd") tp.set_scratch_size(1, Kokkos::PerTeam(1000)), KOKKOS_LAMBDA(const member_type& team) { ScratchMatView A(team.team_scratch(1), rowA, colA); - detail::fill(0.0, team, A); + pcms::field::detail::fill(0.0, team, A); ScratchMatView result_matrix(team.team_scratch(1), rowB, colB); ScratchVecView weight(team.team_scratch(1), rowB); Kokkos::parallel_for(Kokkos::TeamThreadRange(team, rowA), [=](int i) { @@ -257,7 +257,7 @@ TEST_CASE("test_serial_svd") } } - detail::scale_and_adjust(team, weight, A, result_matrix); + pcms::field::detail::scale_and_adjust(team, weight, A, result_matrix); team.team_barrier(); Kokkos::parallel_for(Kokkos::TeamThreadRange(team, rowB), [=](int i) { for (int j = 0; j < colB; ++j) { @@ -288,10 +288,10 @@ TEST_CASE("test_serial_svd") ScratchMatView A(team.team_scratch(1), row, column); ScratchVecView rhs(team.team_scratch(1), row); ScratchVecView x(team.team_scratch(1), column); - detail::fill(0.0, team, x); + pcms::field::detail::fill(0.0, team, x); ScratchVecView weight(team.team_scratch(1), row); - detail::fill(1.0, team, weight); + pcms::field::detail::fill(1.0, team, weight); Kokkos::parallel_for(Kokkos::TeamThreadRange(team, row), [=](int i) { for (int j = 0; j < column; ++j) { A(i, j) = A_data(i, j); @@ -317,7 +317,8 @@ TEST_CASE("test_serial_svd") } team.team_barrier(); - detail::solve_matrix_svd(team, weight, rhs, A, x, 0, 1e-12); + pcms::field::detail::solve_matrix_svd(team, weight, rhs, A, x, 0, + 1e-12); team.team_barrier(); if (team.team_rank() == 0) { printf("[solution vector x after solve_matrix_svd]\n"); diff --git a/test/test_tagged_outputs.cpp b/test/test_tagged_outputs.cpp index 69dac2a7d..b07804980 100644 --- a/test/test_tagged_outputs.cpp +++ b/test/test_tagged_outputs.cpp @@ -4,20 +4,20 @@ #include #include #include -#include -#include -#include "field_test_utils.h" +#include +#include +#include "field_test_utils.hpp" #include #include -#include "pcms/field/coordinate_systems/cartesian.hpp" -#include "pcms/field/coordinate_systems/cylindrical.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_systems/cylindrical.hpp" using Catch::Matchers::ContainsSubstring; using pcms::DeviceMemorySpace; using pcms::Field; -using pcms::LagrangeFunctionSpace; using pcms::Real; using pcms::ValueView; +using pcms::field::LagrangeFunctionSpace; namespace values = pcms::values; using Catch::Matchers::WithinAbs; using pcms::ComponentScaling; @@ -36,15 +36,15 @@ Omega_h::Mesh BuildCylindricalMesh(Omega_h::Library& lib, int divisions) divisions, divisions, divisions, false); } -std::shared_ptr BuildCylindricalSpace( +std::shared_ptr BuildCylindricalSpace( Omega_h::Mesh& mesh, int num_components) { - return LagrangeFunctionSpace::FromMesh( + return pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, num_components, pcms::csys::CylindricalRThetaZ::Create(), "global", - LagrangeFunctionSpace::Backend::OmegaH); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); } -int NumDOFHolders(const LagrangeFunctionSpace& space) +int NumDOFHolders(const pcms::field::LagrangeFunctionSpace& space) { return static_cast( space.GetLayout()->GetDOFHolderCoordinates().GetValues().extent(0)); diff --git a/test/test_transformed_source.cpp b/test/test_transformed_source.cpp index 21433427d..9b027b460 100644 --- a/test/test_transformed_source.cpp +++ b/test/test_transformed_source.cpp @@ -5,12 +5,12 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include -#include -#include "field_test_utils.h" +#include +#include "field_test_utils.hpp" #include #include #include @@ -22,7 +22,6 @@ using pcms::DeviceMemorySpace; using pcms::EvaluationRequest; using pcms::GO; using pcms::HostMemorySpace; -using pcms::LagrangeFunctionSpace; using pcms::OutOfBoundsMode; using pcms::OutOfBoundsPolicy; using pcms::Real; @@ -30,6 +29,7 @@ using pcms::SameValueBasis; using pcms::TransformedSource; using pcms::ValueBasis; using pcms::ValueView; +using pcms::field::LagrangeFunctionSpace; namespace values = pcms::values; namespace @@ -37,25 +37,25 @@ namespace constexpr double kTol = 1e-10; -std::shared_ptr BuildCylindricalSource( +std::shared_ptr BuildCylindricalSource( Omega_h::Library& lib, Omega_h::Mesh& mesh, int num_components) { mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 2.0, 1.6, 1.1, 8, 8, 6, false); - return LagrangeFunctionSpace::FromMesh( + return pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, num_components, pcms::csys::CylindricalRThetaZ::Create(), "global", - LagrangeFunctionSpace::Backend::OmegaH); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); } -std::shared_ptr BuildCartesianTarget( +std::shared_ptr BuildCartesianTarget( Omega_h::Library& lib, Omega_h::Mesh& mesh, int num_components, double x_extent = 1.0) { mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, x_extent, 1.0, 1.0, 4, 4, 4, false); - return LagrangeFunctionSpace::FromMesh( + return pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, num_components, pcms::csys::Cartesian::Create(3), "global", - LagrangeFunctionSpace::Backend::OmegaH); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH); } ValueBasis CylindricalVector() diff --git a/test/test_twoClientOverlap.cpp b/test/test_twoClientOverlap.cpp index 61a03da69..8c99aafe8 100644 --- a/test/test_twoClientOverlap.cpp +++ b/test/test_twoClientOverlap.cpp @@ -6,8 +6,8 @@ #include #include #include // divide_no_remainder -#include "pcms.h" -#include "test_support.h" +#include "pcms/pcms.hpp" +#include "test_support.hpp" namespace ts = test_support; diff --git a/test/test_uniform_grid.cpp b/test/test_uniform_grid.cpp index d580c9f68..d1989956a 100644 --- a/test/test_uniform_grid.cpp +++ b/test/test_uniform_grid.cpp @@ -2,11 +2,12 @@ #include #include #include -#include +#include +#include "pcms/backends/omega_h/omega_h.hpp" -using pcms::CreateUniformGridFromMesh; using pcms::Uniform2DGrid; using pcms::UniformGrid; +using pcms::backend::omega_h::CreateUniformGridFromMesh; TEST_CASE("uniform grid") { @@ -68,7 +69,8 @@ TEST_CASE("Create uniform grid from omega_h mesh") SECTION("Create grid with specified divisions per dimension") { // Create a 10x12 uniform grid over the mesh - auto grid = CreateUniformGridFromMesh<2>(mesh, {10, 12}); + auto grid = + pcms::backend::omega_h::CreateUniformGridFromMesh<2>(mesh, {10, 12}); // Verify the grid properties REQUIRE(grid.GetNumCells() == 120); @@ -92,7 +94,7 @@ TEST_CASE("Create uniform grid from omega_h mesh") SECTION("Create grid with equal divisions") { // Create a 15x15 uniform grid - auto grid = CreateUniformGridFromMesh<2>(mesh, 15); + auto grid = pcms::backend::omega_h::CreateUniformGridFromMesh<2>(mesh, 15); REQUIRE(grid.GetNumCells() == 225); REQUIRE(grid.divisions[0] == 15); @@ -111,7 +113,8 @@ TEST_CASE("Create uniform grid from omega_h mesh") auto large_mesh = Omega_h::build_box(world, OMEGA_H_SIMPLEX, 5.0, 3.0, 0.0, 10, 6, 0, false); - auto grid = CreateUniformGridFromMesh<2>(large_mesh, {20, 30}); + auto grid = pcms::backend::omega_h::CreateUniformGridFromMesh<2>(large_mesh, + {20, 30}); REQUIRE(grid.GetNumCells() == 600); REQUIRE(grid.edge_length[0] == Catch::Approx(5.0)); @@ -127,7 +130,8 @@ TEST_CASE("Create uniform grid from omega_h mesh") SECTION("Test point location in grid cells") { - auto grid = CreateUniformGridFromMesh<2>(mesh, {10, 10}); + auto grid = + pcms::backend::omega_h::CreateUniformGridFromMesh<2>(mesh, {10, 10}); // Test corner points REQUIRE(grid.ClosestCellID(Omega_h::Vector<2>{0.0, 0.0}) == 0); @@ -149,7 +153,8 @@ TEST_CASE("Create uniform grid from 3D mesh") SECTION("Create 3D grid with specified divisions") { - auto grid = CreateUniformGridFromMesh<3>(mesh, {10, 15, 8}); + auto grid = + pcms::backend::omega_h::CreateUniformGridFromMesh<3>(mesh, {10, 15, 8}); REQUIRE(grid.GetNumCells() == 1200); // 10 * 15 * 8 REQUIRE(grid.edge_length[0] == Catch::Approx(2.0)); @@ -162,7 +167,7 @@ TEST_CASE("Create uniform grid from 3D mesh") SECTION("Create 3D grid with equal divisions") { - auto grid = CreateUniformGridFromMesh<3>(mesh, 12); + auto grid = pcms::backend::omega_h::CreateUniformGridFromMesh<3>(mesh, 12); REQUIRE(grid.GetNumCells() == 1728); // 12^3 REQUIRE(grid.divisions[0] == 12); diff --git a/test/test_uniform_grid_field.cpp b/test/test_uniform_grid_field.cpp index e4e44ec69..29b8ead5c 100644 --- a/test/test_uniform_grid_field.cpp +++ b/test/test_uniform_grid_field.cpp @@ -1,23 +1,24 @@ #include #include #include -#include "pcms/field/layout/uniform_grid.h" -#include "pcms/field/evaluator/uniform_grid.h" -#include "pcms/field/uniform_grid_binary_field.h" -#include "pcms/field/data/simple.h" +#include "pcms/backends/uniform_grid/layout.hpp" +#include "pcms/backends/uniform_grid/evaluator.hpp" +#include "pcms/backends/omega_h/uniform_grid_binary_field.hpp" +#include "pcms/field/simple_field_data.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/utility/uniform_grid.h" +#include "pcms/utility/uniform_grid.hpp" #include "Omega_h_library.hpp" #include "Omega_h_build.hpp" -#include "pcms/transfer/copy.h" -#include "pcms/transfer/interpolator.h" -#include "pcms/field/function_space/lagrange.h" -#include "pcms/utility/arrays.h" -#include "field_test_utils.h" +#include "pcms/transfer/copy.hpp" +#include "pcms/transfer/interpolator.hpp" +#include "pcms/field/function_space/lagrange.hpp" +#include "pcms/utility/arrays.hpp" +#include "field_test_utils.hpp" #include -#include "pcms/field/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" +#include "pcms/backends/omega_h/omega_h.hpp" -using pcms::CreateUniformGridFromMesh; +using pcms::backend::omega_h::CreateUniformGridFromMesh; TEST_CASE("UniformGridDiscretization SameEntities: identical grids") { @@ -26,10 +27,10 @@ TEST_CASE("UniformGridDiscretization SameEntities: identical grids") grid.edge_length = {1.0, 1.0}; grid.divisions = {4, 4}; - pcms::UniformGridFieldLayout<2> layout_a(grid, 1, - pcms::csys::Cartesian::Deferred()); - pcms::UniformGridFieldLayout<2> layout_b(grid, 1, - pcms::csys::Cartesian::Deferred()); + pcms::backend::uniform_grid::UniformGridFieldLayout<2> layout_a( + grid, 1, pcms::csys::Cartesian::Deferred()); + pcms::backend::uniform_grid::UniformGridFieldLayout<2> layout_b( + grid, 1, pcms::csys::Cartesian::Deferred()); auto disc_a = layout_a.GetDiscretization(); auto disc_b = layout_b.GetDiscretization(); @@ -51,10 +52,10 @@ TEST_CASE("UniformGridDiscretization SameEntities: different grids") grid_b.edge_length = {1.0, 1.0}; grid_b.divisions = {8, 8}; - pcms::UniformGridFieldLayout<2> layout_a(grid_a, 1, - pcms::csys::Cartesian::Deferred()); - pcms::UniformGridFieldLayout<2> layout_b(grid_b, 1, - pcms::csys::Cartesian::Deferred()); + pcms::backend::uniform_grid::UniformGridFieldLayout<2> layout_a( + grid_a, 1, pcms::csys::Cartesian::Deferred()); + pcms::backend::uniform_grid::UniformGridFieldLayout<2> layout_b( + grid_b, 1, pcms::csys::Cartesian::Deferred()); auto disc_a = layout_a.GetDiscretization(); auto disc_b = layout_b.GetDiscretization(); @@ -101,15 +102,16 @@ TEST_CASE("UniformGrid field creation") grid.edge_length = {10.0, 10.0}; grid.divisions = {5, 5}; - auto layout = std::make_shared>( - grid, 1, pcms::csys::Cartesian::Deferred()); + auto layout = + std::make_shared>( + grid, 1, pcms::csys::Cartesian::Deferred()); REQUIRE(layout->GetNumComponents() == 1); REQUIRE(layout->GetNumOwnedDofHolder() == 36); // (5+1)x(5+1) = 36 vertices REQUIRE(layout->GetNumGlobalDofHolder() == 36); REQUIRE_FALSE(layout->IsDistributed()); - auto field_space = pcms::LagrangeFunctionSpace::FromUniformGrid( + auto field_space = pcms::field::LagrangeFunctionSpace::FromUniformGrid( grid, 1, pcms::csys::Cartesian::Deferred()); auto field = field_space->CreateFunction(); REQUIRE(field.GetDOFHolderDataHost().size() == @@ -123,12 +125,14 @@ TEST_CASE("UniformGrid order-0 field creation and evaluation") grid.edge_length = {10.0, 10.0}; grid.divisions = {2, 2}; - auto layout = std::make_shared>( - grid, 1, pcms::csys::Cartesian::Deferred(), 0); - auto field_space = pcms::LagrangeFunctionSpace::FromUniformGrid( + auto layout = + std::make_shared>( + grid, 1, pcms::csys::Cartesian::Deferred(), 0); + auto field_space = pcms::field::LagrangeFunctionSpace::FromUniformGrid( grid, 1, pcms::csys::Cartesian::Deferred(), 0); auto field = field_space->CreateFunction(); - pcms::UniformGridEvaluatorFactory<2> eval_factory(layout); + pcms::backend::uniform_grid::UniformGridEvaluatorFactory<2> eval_factory( + layout); REQUIRE(layout->GetOrder() == 0); REQUIRE(layout->GetNumOwnedDofHolder() == 4); @@ -172,9 +176,10 @@ TEST_CASE("UniformGrid field data operations", "[uniform_grid_field]") grid.edge_length = {10.0, 10.0}; grid.divisions = {4, 4}; - auto layout = std::make_shared>( - grid, 1, pcms::csys::Cartesian::Deferred()); - auto field_space = pcms::LagrangeFunctionSpace::FromUniformGrid( + auto layout = + std::make_shared>( + grid, 1, pcms::csys::Cartesian::Deferred()); + auto field_space = pcms::field::LagrangeFunctionSpace::FromUniformGrid( grid, 1, pcms::csys::Cartesian::Deferred()); auto field = field_space->CreateFunction(); @@ -200,12 +205,14 @@ TEST_CASE("UniformGrid field evaluation - piecewise constant") grid.edge_length = {10.0, 10.0}; grid.divisions = {2, 2}; - auto layout = std::make_shared>( - grid, 1, pcms::csys::Cartesian::Deferred()); - auto field_space = pcms::LagrangeFunctionSpace::FromUniformGrid( + auto layout = + std::make_shared>( + grid, 1, pcms::csys::Cartesian::Deferred()); + auto field_space = pcms::field::LagrangeFunctionSpace::FromUniformGrid( grid, 1, pcms::csys::Cartesian::Deferred()); auto field = field_space->CreateFunction(); - pcms::UniformGridEvaluatorFactory<2> eval_factory(layout); + pcms::backend::uniform_grid::UniformGridEvaluatorFactory<2> eval_factory( + layout); // Set vertex values for a 2x2 cell grid (3x3 = 9 vertices) // Vertex layout: @@ -258,8 +265,9 @@ TEST_CASE("UniformGrid field copy") grid.edge_length = {10.0, 10.0}; grid.divisions = {2, 2}; - auto layout = std::make_shared>( - grid, 1, pcms::csys::Cartesian::Deferred()); + auto layout = + std::make_shared>( + grid, 1, pcms::csys::Cartesian::Deferred()); // Set vertex values with f(x,y) = x + y at 3x3 vertex positions // Vertices at: (0,0), (5,0), (10,0), (0,5), (5,5), (10,5), (0,10), (5,10), @@ -270,7 +278,7 @@ TEST_CASE("UniformGrid field copy") 10.0, 15.0, 20.0 // y=10: v6(0,10)=10, v7(5,10)=15, v8(10,10)=20 }; - auto factory = pcms::LagrangeFunctionSpace::FromUniformGrid( + auto factory = pcms::field::LagrangeFunctionSpace::FromUniformGrid( grid, 1, pcms::csys::Cartesian::Deferred()); auto field = factory->CreateFunction(); field.SetDOFHolderDataUncheckedHost( @@ -294,7 +302,7 @@ TEST_CASE("Transfer from OmegaH field to UniformGrid field") auto mesh = Omega_h::build_box(lib.world(), OMEGA_H_SIMPLEX, 1.0, 1.0, 0.0, 2, 2, 0, false); - auto omega_h_factory = pcms::LagrangeFunctionSpace::FromMesh( + auto omega_h_factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred()); auto omega_h_field = omega_h_factory->CreateFunction(); pcms::test::SetField( @@ -306,7 +314,7 @@ TEST_CASE("Transfer from OmegaH field to UniformGrid field") grid.edge_length = {1.0, 1.0}; grid.bot_left = {0.0, 0.0}; grid.divisions = {2, 2}; - auto ug_factory = pcms::LagrangeFunctionSpace::FromUniformGrid( + auto ug_factory = pcms::field::LagrangeFunctionSpace::FromUniformGrid( grid, 1, pcms::csys::Cartesian::Deferred()); auto ug_field = ug_factory->CreateFunction(); @@ -341,7 +349,8 @@ TEST_CASE("Create binary field from uniform grid") 10, 0, false); auto [layout, field] = - pcms::CreateUniformGridBinaryField<2>(mesh, std::array{5, 5}); + pcms::backend::omega_h::CreateUniformGridBinaryField<2>(mesh, + std::array{5, 5}); auto field_data = pcms::FlattenToRank1View(field.GetDOFHolderDataHost().GetValues()); @@ -361,7 +370,8 @@ TEST_CASE("Create binary field from uniform grid") Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1.0, 1.0, 0.0, 8, 8, 0, false); auto [layout, field] = - pcms::CreateUniformGridBinaryField<2>(mesh, std::array{10, 8}); + pcms::backend::omega_h::CreateUniformGridBinaryField<2>( + mesh, std::array{10, 8}); auto field_data = pcms::FlattenToRank1View(field.GetDOFHolderDataHost().GetValues()); @@ -380,7 +390,8 @@ TEST_CASE("Create binary field from uniform grid") Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1.0, 1.0, 0.0, 8, 8, 0, false); auto [layout, field] = - pcms::CreateUniformGridBinaryField<2>(mesh, std::array{10, 10}); + pcms::backend::omega_h::CreateUniformGridBinaryField<2>( + mesh, std::array{10, 10}); auto field_data = pcms::FlattenToRank1View(field.GetDOFHolderDataHost().GetValues()); @@ -399,7 +410,8 @@ TEST_CASE("Create binary field from uniform grid") grid.bot_left = {0.0, 0.0}; grid.divisions = {10, 10}; - auto [layout, field] = pcms::CreateUniformGridBinaryField<2>(mesh, grid); + auto [layout, field] = + pcms::backend::omega_h::CreateUniformGridBinaryField<2>(mesh, grid); auto field_data = pcms::FlattenToRank1View(field.GetDOFHolderDataHost().GetValues()); @@ -434,7 +446,8 @@ TEST_CASE("Create binary field from uniform grid") Omega_h::build_box(world, OMEGA_H_SIMPLEX, 2.0, 2.0, 0.0, 4, 4, 0, false); auto [layout, field] = - pcms::CreateUniformGridBinaryField<2>(mesh, std::array{20, 20}); + pcms::backend::omega_h::CreateUniformGridBinaryField<2>( + mesh, std::array{20, 20}); auto field_data = pcms::FlattenToRank1View(field.GetDOFHolderDataHost().GetValues()); @@ -456,7 +469,8 @@ TEST_CASE("Create binary field from uniform grid") 0, false); auto [layout, field] = - pcms::CreateUniformGridBinaryField<2>(mesh, std::array{30, 10}); + pcms::backend::omega_h::CreateUniformGridBinaryField<2>( + mesh, std::array{30, 10}); auto field_data = pcms::FlattenToRank1View(field.GetDOFHolderDataHost().GetValues()); @@ -482,9 +496,11 @@ TEST_CASE("Binary field integration with grid methods") SECTION("Query field value at specific grid vertex") { - auto grid = CreateUniformGridFromMesh<2>(mesh, std::array{8, 8}); + auto grid = pcms::backend::omega_h::CreateUniformGridFromMesh<2>( + mesh, std::array{8, 8}); auto [layout, field] = - pcms::CreateUniformGridBinaryField<2>(mesh, std::array{8, 8}); + pcms::backend::omega_h::CreateUniformGridBinaryField<2>(mesh, + std::array{8, 8}); auto field_data = pcms::FlattenToRank1View(field.GetDOFHolderDataHost().GetValues()); @@ -503,9 +519,11 @@ TEST_CASE("Binary field integration with grid methods") SECTION("Count vertices by region") { - auto grid = CreateUniformGridFromMesh<2>(mesh, std::array{10, 10}); + auto grid = pcms::backend::omega_h::CreateUniformGridFromMesh<2>( + mesh, std::array{10, 10}); auto [layout, field] = - pcms::CreateUniformGridBinaryField<2>(mesh, std::array{10, 10}); + pcms::backend::omega_h::CreateUniformGridBinaryField<2>( + mesh, std::array{10, 10}); auto field_data = pcms::FlattenToRank1View(field.GetDOFHolderDataHost().GetValues()); @@ -561,7 +579,8 @@ TEST_CASE("Performance and edge cases") Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1.0, 1.0, 0.0, 5, 5, 0, false); auto [layout, field] = - pcms::CreateUniformGridBinaryField<2>(mesh, std::array{50, 50}); + pcms::backend::omega_h::CreateUniformGridBinaryField<2>( + mesh, std::array{50, 50}); auto field_data = pcms::FlattenToRank1View(field.GetDOFHolderDataHost().GetValues()); @@ -579,7 +598,8 @@ TEST_CASE("Performance and edge cases") 10, 0, false); auto [layout, field] = - pcms::CreateUniformGridBinaryField<2>(mesh, std::array{2, 2}); + pcms::backend::omega_h::CreateUniformGridBinaryField<2>(mesh, + std::array{2, 2}); auto field_data = pcms::FlattenToRank1View(field.GetDOFHolderDataHost().GetValues()); @@ -597,7 +617,8 @@ TEST_CASE("Performance and edge cases") 0, false); auto [layout, field] = - pcms::CreateUniformGridBinaryField<2>(mesh, std::array{25, 10}); + pcms::backend::omega_h::CreateUniformGridBinaryField<2>( + mesh, std::array{25, 10}); auto field_data = pcms::FlattenToRank1View(field.GetDOFHolderDataHost().GetValues()); @@ -617,9 +638,10 @@ TEST_CASE("UniformGrid workflow") auto mesh = Omega_h::build_box(world, OMEGA_H_SIMPLEX, 1.0, 1.0, 0.0, 4, 4, 0, false); - auto grid = pcms::CreateUniformGridFromMesh<2>(mesh, {4, 4}); + auto grid = + pcms::backend::omega_h::CreateUniformGridFromMesh<2>(mesh, {4, 4}); - auto omega_h_factory = pcms::LagrangeFunctionSpace::FromMesh( + auto omega_h_factory = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred()); auto omega_h_field = omega_h_factory->CreateFunction(); pcms::test::SetField( @@ -627,12 +649,12 @@ TEST_CASE("UniformGrid workflow") return pcms::test::linear_f(x, y); }); - auto ug_factory = pcms::LagrangeFunctionSpace::FromUniformGrid( + auto ug_factory = pcms::field::LagrangeFunctionSpace::FromUniformGrid( grid, 1, pcms::csys::Cartesian::Deferred()); auto ug_field = ug_factory->CreateFunction(); auto [mask_layout, mask_field] = - pcms::CreateUniformGridBinaryField<2>(mesh, grid); + pcms::backend::omega_h::CreateUniformGridBinaryField<2>(mesh, grid); pcms::Interpolator interp(*omega_h_factory, *ug_factory); interp.Apply(omega_h_field, ug_field); @@ -664,12 +686,14 @@ TEST_CASE("UniformGrid Order-1 multi-component field evaluation") // symmetric cell-center samples would hide. const int num_components = 4; - auto layout = std::make_shared>( - grid, num_components, pcms::csys::Cartesian::Deferred()); - auto field_space = pcms::LagrangeFunctionSpace::FromUniformGrid( + auto layout = + std::make_shared>( + grid, num_components, pcms::csys::Cartesian::Deferred()); + auto field_space = pcms::field::LagrangeFunctionSpace::FromUniformGrid( grid, num_components, pcms::csys::Cartesian::Deferred()); auto field = field_space->CreateFunction(); - pcms::UniformGridEvaluatorFactory<2> eval_factory(layout); + pcms::backend::uniform_grid::UniformGridEvaluatorFactory<2> eval_factory( + layout); // Vertex layout: // v6---v7---v8 @@ -744,12 +768,14 @@ TEST_CASE("UniformGrid Order-0 multi-component field (regression)") const int num_components = 2; - auto layout = std::make_shared>( - grid, num_components, pcms::csys::Cartesian::Deferred(), 0); // Order 0 - auto field_space = pcms::LagrangeFunctionSpace::FromUniformGrid( + auto layout = + std::make_shared>( + grid, num_components, pcms::csys::Cartesian::Deferred(), 0); // Order 0 + auto field_space = pcms::field::LagrangeFunctionSpace::FromUniformGrid( grid, num_components, pcms::csys::Cartesian::Deferred(), 0); auto field = field_space->CreateFunction(); - pcms::UniformGridEvaluatorFactory<2> eval_factory(layout); + pcms::backend::uniform_grid::UniformGridEvaluatorFactory<2> eval_factory( + layout); // Set cell values (4 cells, 2 components each) std::vector data = { diff --git a/test/test_xgc_field_data.cpp b/test/test_xgc_field_data.cpp index 55a89d593..014c6437a 100644 --- a/test/test_xgc_field_data.cpp +++ b/test/test_xgc_field_data.cpp @@ -1,15 +1,15 @@ #include -#include "pcms/field/data/xgc.h" -#include "pcms/coupler/overlap_mask.h" -#include "pcms/field/function_space/xgc.h" +#include "pcms/backends/xgc/field_data.hpp" +#include "pcms/coupler/overlap_mask.hpp" +#include "pcms/backends/xgc/field_factory.hpp" #include namespace { -pcms::ReverseClassificationVertex create_dummy_rc(int size) +pcms::backend::xgc::ReverseClassificationVertex create_dummy_rc(int size) { - pcms::ReverseClassificationVertex rc; + pcms::backend::xgc::ReverseClassificationVertex rc; for (int i = 0; i < size; ++i) { if (i % 4 == 0) { rc.Insert({0, 0}, i); @@ -31,7 +31,7 @@ TEST_CASE("XGC FieldLayout owns and classifies every entry") { static constexpr int data_size = 16; auto rc = create_dummy_rc(data_size); - pcms::XGCFieldLayout layout(rc, data_size); + pcms::backend::xgc::XGCFieldLayout layout(rc, data_size); auto owned = layout.GetOwnedHost(); auto gids = layout.GetGidsHost(); @@ -53,12 +53,12 @@ TEST_CASE("XGCFieldFactory creates fields and rejects evaluator access") { static constexpr int data_size = 16; auto rc = create_dummy_rc(data_size); - pcms::XGCFieldFactory function_space(rc, data_size); + pcms::backend::xgc::XGCFieldFactory function_space(rc, data_size); std::vector data(data_size); std::iota(data.begin(), data.end(), 0.0); auto field = function_space.CreateField( - "", std::make_unique>( + "", std::make_unique>( function_space.GetXGCLayout(), pcms::ValueBasis{}, pcms::make_array_view(data))); diff --git a/test/test_xgc_reverse_classification.cpp b/test/test_xgc_reverse_classification.cpp index 5603b52b1..3ae24b482 100644 --- a/test/test_xgc_reverse_classification.cpp +++ b/test/test_xgc_reverse_classification.cpp @@ -1,4 +1,4 @@ -#include "pcms/discretization/discretization/xgc_reverse_classification.h" +#include "pcms/backends/xgc/reverse_classification.hpp" #include #include @@ -25,7 +25,7 @@ static constexpr auto test_data = R"( TEST_CASE("reverse classification") { std::stringstream ss{test_data}; - auto rc = pcms::ReadReverseClassificationVertex(ss); + auto rc = pcms::backend::xgc::ReadReverseClassificationVertex(ss); { const auto* q = rc.Query({2, 20}); REQUIRE(q == nullptr); @@ -38,7 +38,7 @@ TEST_CASE("reverse classification") REQUIRE(s == *q); } auto vec = rc.Serialize(); - pcms::ReverseClassificationVertex rc_deserialized; + pcms::backend::xgc::ReverseClassificationVertex rc_deserialized; auto av = pcms::make_array_view(vec); rc_deserialized.Deserialize(av); REQUIRE(rc_deserialized == rc); diff --git a/test/testing.cmake b/test/testing.cmake index d26a4a4eb..2fc39181c 100644 --- a/test/testing.cmake +++ b/test/testing.cmake @@ -1,6 +1,7 @@ -if(PCMS_ENABLE_OMEGA_H) +# test_support uses redev, so it needs the coupler +if(PCMS_ENABLE_OMEGA_H AND TARGET pcms::coupler) add_library(test_support test/test_support.cpp) - target_link_libraries(test_support pcms::core) # for omegah and redev + target_link_libraries(test_support pcms::pcms) # for omegah and redev endif() # TODO use submodule FetchContent/ExternalProject/ExternalData @@ -57,8 +58,8 @@ message(STATUS "VALGRIND_ARGS: ${VALGRIND_ARGS}") function(add_exe NAME) add_executable(${NAME} ${NAME}.cpp) - target_link_libraries(${NAME} pcms::core) - if(PCMS_ENABLE_OMEGA_H) + target_link_libraries(${NAME} pcms::pcms) + if(TARGET test_support) target_link_libraries(${NAME} test_support) endif() target_include_directories(${NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) diff --git a/test/unit_test_main.cpp b/test/unit_test_main.cpp index ade35e8b2..51a787472 100644 --- a/test/unit_test_main.cpp +++ b/test/unit_test_main.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #ifdef PCMS_ENABLE_PETSC #include diff --git a/test/xgc_n0_coupling_server.cpp b/test/xgc_n0_coupling_server.cpp index 417e965f5..12a39ef86 100644 --- a/test/xgc_n0_coupling_server.cpp +++ b/test/xgc_n0_coupling_server.cpp @@ -1,19 +1,19 @@ -#include -#include +#include +#include #include #include -#include "test_support.h" +#include "test_support.hpp" #include "pcms/coupler/coupler.hpp" -#include "pcms/coupler/field_serializer.h" -#include "pcms/field/function_space/lagrange.h" -#include "pcms/field/layout/omega_h_lagrange.h" -#include "pcms/field/field.h" +#include "pcms/coupler/detail/field_serializer.hpp" +#include "pcms/field/function_space/lagrange.hpp" +#include "pcms/backends/omega_h/lagrange_layout.hpp" +#include "pcms/field/field.hpp" #include "pcms/field/value_view.hpp" -#include "pcms/field/data/simple.h" -#include "pcms/transfer/copy.h" +#include "pcms/field/simple_field_data.hpp" +#include "pcms/transfer/copy.hpp" #include #include -#include "pcms/field/coordinate_systems/cartesian.hpp" +#include "pcms/utility/coordinate_systems/cartesian.hpp" using pcms::GO; using pcms::LO; @@ -43,7 +43,7 @@ struct RegisteredField [[nodiscard]] static RegisteredField AddField( pcms::ApplicationComm* application, - const std::shared_ptr& function_space, + const std::shared_ptr& function_space, const std::string& name, const std::string& path, int plane) { PCMS_ALWAYS_ASSERT(application != nullptr); @@ -216,9 +216,9 @@ void omegah_coupler(MPI_Comm comm, Omega_h::Mesh& mesh, // return 0; return 1; }); - auto function_space = pcms::LagrangeFunctionSpace::FromMesh( + auto function_space = pcms::field::LagrangeFunctionSpace::FromMesh( mesh, 1, 1, pcms::csys::Cartesian::Deferred(), is_overlap, numbering, - pcms::LagrangeFunctionSpace::Backend::OmegaH, "n0_layout"); + pcms::field::LagrangeFunctionSpace::Backend::OmegaH, "n0_layout"); auto time2 = std::chrono::steady_clock::now(); elapsed_seconds = time2 - time1; ts::timeMinMaxAvg(elapsed_seconds.count(), min, max, avg); diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index c5025a436..e31992713 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,6 +1,6 @@ if(PCMS_ENABLE_XGC AND PCMS_ENABLE_OMEGA_H) add_executable(osh2XgcRC XgcRCfromOsh.cpp) - target_link_libraries(osh2XgcRC pcms::core Omega_h::omega_h) + target_link_libraries(osh2XgcRC pcms::pcms Omega_h::omega_h) add_executable(cpn_gen CpnFromOsh.cpp) - target_link_libraries(cpn_gen pcms::core Omega_h::omega_h) + target_link_libraries(cpn_gen pcms::pcms Omega_h::omega_h) endif() diff --git a/tools/CpnFromOsh.cpp b/tools/CpnFromOsh.cpp index c51be067e..f29a8013d 100644 --- a/tools/CpnFromOsh.cpp +++ b/tools/CpnFromOsh.cpp @@ -4,7 +4,7 @@ #include #include #include -#include "pcms/utility/print.h" +#include "pcms/utility/print.hpp" int main(int argc, char** argv) { diff --git a/tools/XgcRCfromOsh.cpp b/tools/XgcRCfromOsh.cpp index 093e7baa5..aebac3500 100644 --- a/tools/XgcRCfromOsh.cpp +++ b/tools/XgcRCfromOsh.cpp @@ -1,6 +1,6 @@ #include -#include "pcms/discretization/discretization/xgc_reverse_classification.h" -#include "pcms/utility/print.h" +#include "pcms/backends/xgc/reverse_classification.hpp" +#include "pcms/utility/print.hpp" #include #include @@ -20,16 +20,16 @@ int main(int argc, char** argv) numbering = std::string(argv[2]); } const auto* tag = mesh.get_tagbase(0, numbering); - auto index_base = pcms::IndexBase::Zero; + auto index_base = pcms::backend::xgc::IndexBase::Zero; if (numbering == "simNumbering") { - index_base = pcms::IndexBase::One; + index_base = pcms::backend::xgc::IndexBase::One; } if (Omega_h::is(tag)) { - std::cout << pcms::ConstructRCFromOmegaHMesh(mesh, numbering, - index_base); + std::cout << pcms::backend::xgc::ConstructRCFromOmegaHMesh( + mesh, numbering, index_base); } else if (Omega_h::is(tag)) { - std::cout << pcms::ConstructRCFromOmegaHMesh(mesh, numbering, - index_base); + std::cout << pcms::backend::xgc::ConstructRCFromOmegaHMesh( + mesh, numbering, index_base); } else { std::cerr << "IDs should be either be LO or GO\n"; std::abort(); diff --git a/tools/check-public-includes.py b/tools/check-public-includes.py new file mode 100755 index 000000000..7a69ca09e --- /dev/null +++ b/tools/check-public-includes.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python3 +"""Reject backend-library includes in PCMS's public headers. + +Usage: tools/check-public-includes.py [] + +Every header below include/pcms/ may include the C++ standard library, +Kokkos, MPI and other PCMS public headers. Headers below +include/pcms/backends// may in addition include the libraries of that +backend. Headers below include/pcms/coupler/ may include redev (the coupler's +transport, see tools/reorg/decisions.md). Any other include of a backend +library (Omega_h, MFEM, MeshFields, PETSc, redev, ADIOS2) is reported, and the +script exits with status 1. +""" + +import os +import re +import sys + +BACKEND_LIBS = { + "Omega_h": re.compile(r"^(Omega_h|r3d)"), + "MFEM": re.compile(r"^mfem"), + "MeshFields": re.compile(r"^(MeshField|meshfields)"), + "PETSc": re.compile(r"^petsc"), + "redev": re.compile(r"^redev"), + "ADIOS2": re.compile(r"^adios2"), +} + +# which backend libraries a directory below include/pcms may use +ALLOWED = { + "backends/omega_h/": {"Omega_h"}, + "backends/mfem/": {"MFEM"}, + # the XGC reverse classification can be built from an Omega_h mesh + "backends/xgc/": {"Omega_h"}, + "coupler/": {"redev"}, +} + +INCLUDE = re.compile(r'^\s*#\s*include\s*[<"]([^>"]+)[>"]', re.M) + + +def check(root): + base = os.path.join(root, "include", "pcms") + bad = [] + for dirpath, _, files in os.walk(base): + for name in files: + if not name.endswith((".hpp", ".h")): + continue + path = os.path.join(dirpath, name) + rel = os.path.relpath(path, base).replace(os.sep, "/") + allowed = set() + for prefix, libs in ALLOWED.items(): + if rel.startswith(prefix): + allowed |= libs + with open(path, encoding="utf-8") as fh: + text = fh.read() + for inc in INCLUDE.findall(text): + if inc.startswith("pcms/"): + continue + for lib, pattern in BACKEND_LIBS.items(): + if pattern.match(inc) and lib not in allowed: + bad.append(f"include/pcms/{rel}: includes <{inc}> ({lib})") + return bad + + +def main(): + root = sys.argv[1] if len(sys.argv) > 1 else os.path.join( + os.path.dirname(__file__), "..") + bad = check(os.path.abspath(root)) + for line in bad: + print(line) + if bad: + print(f"{len(bad)} backend-library include(s) in public headers") + return 1 + print("public headers: no disallowed backend-library includes") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tools/migrate-pcms.sh b/tools/migrate-pcms.sh new file mode 100755 index 000000000..69c9a4dd4 --- /dev/null +++ b/tools/migrate-pcms.sh @@ -0,0 +1,195 @@ +#!/bin/bash +# Migrate a downstream source tree from PCMS 0.3 to PCMS 0.4. +# +# Usage: tools/migrate-pcms.sh [--dry-run] [--in-tree] ... +# +# Applies tools/reorg/header-map.txt and tools/reorg/symbol-map.txt: +# * rewrites #include directives of renamed public headers (C, C++, Fortran +# preprocessor files); +# * renames moved public C++ names, renamed macros, CMake options and the +# pcms::core target; +# * migrates Python code with tools/reorg/python_api_names.py; +# * reports, with file and line, every use of a header or name that is no +# longer public or whose API changed shape ("manual" entries), with the +# replacement to use. Those need a manual edit; see MIGRATION.md. +# Files are modified in place (back up or commit first). With --dry-run +# nothing is written; the planned changes are listed. --in-tree is for code +# inside PCMS (e.g. a pull request ported across the reorganization): includes +# of private headers and qualified uses of internal names are rewritten to +# their new locations instead of being reported. +set -euo pipefail + +here=$(cd "$(dirname "$0")" && pwd) +dry=0 +in_tree=0 +while [ $# -gt 0 ]; do + case "$1" in + --dry-run) dry=1; shift ;; + --in-tree) in_tree=1; shift ;; + *) break ;; + esac +done +if [ $# -lt 1 ]; then + sed -n '2,21p' "$0" + exit 2 +fi +for t in "$@"; do + if [ ! -e "$t" ]; then + echo "migrate-pcms.sh: $t does not exist" >&2 + exit 2 + fi +done + +PCMS_MIGRATE_DRY=$dry PCMS_MIGRATE_IN_TREE=$in_tree python3 - "$here/reorg/header-map.txt" \ + "$here/reorg/symbol-map.txt" "$@" <<'PY' +import os +import re +import sys + +header_map, symbol_map = sys.argv[1:3] +roots = sys.argv[3:] +dry = os.environ.get("PCMS_MIGRATE_DRY") == "1" +in_tree = os.environ.get("PCMS_MIGRATE_IN_TREE") == "1" + +headers, private_headers = {}, {} +for line in open(header_map): + line = line.split("#", 1)[0].split() + if len(line) >= 2: + if len(line) == 3 and line[2] == "private": + private_headers[line[0]] = line[1] + else: + headers[line[0]] = line[1] + +renames, cmake, private_syms, manual = [], [], [], [] +for line in open(symbol_map): + if line.startswith("#") or not line.strip(): + continue + if line.startswith("manual"): + old, new = line[len("manual"):].split("->", 1) + manual.append((old.strip(), new.strip())) + continue + kind, old, new, *flags = line.split() + if in_tree and "external" in flags: + continue + if kind in ("cpp", "macro"): + renames.append((old, new)) + elif kind in ("cmake-option", "cmake-target"): + cmake.append((old, new)) + elif kind == "cpp-private": + private_syms.append((old, new)) + +if in_tree: + # inside PCMS, private headers and internal names are still usable + headers.update({k: v for k, v in private_headers.items() if v != "-"}) + private_headers = {k: v for k, v in private_headers.items() if v == "-"} + renames += private_syms + private_syms = [] + +CODE = re.compile(r"\.(h|hh|hpp|hxx|c|cc|cpp|cxx|cu|F90|f90|F|inc)$") +CMAKE = re.compile(r"(CMakeLists\.txt|\.cmake)$") +INCLUDE = re.compile(r'^(\s*#\s*include\s*)([<"])([^>"]+)([>"])', re.M) + + +def word(old): + # old may contain ::, so build the boundaries by hand + return re.compile(r"(? {rep}") + if new != text: + changed += 1 + print(("would update " if dry else "updated ") + path) + if not dry: + open(path, "w", encoding="utf-8").write(new) + +print(f"{'would update' if dry else 'updated'} {changed} C/C++/CMake files") +if reports: + print(f"\n{len(reports)} place(s) need a manual change:") + for r in reports: + print(" " + r) +PY + +# Python code +mapfile -t pyfiles < <(find "$@" -name '*.py' -not -path '*/.git/*' \ + -exec grep -lE 'LagrangeFunctionSpace|PolynomialReconstructionFunctionSpace|OmegaHConservativeProjection|OmegaHControlVariateProjection|create_uniform_grid_binary_field|create_uniform_grid_from_mesh|compute_entity_centroids|map_entity_field_to_vertices_|\.mesh\(\)' {} +) +if [ ${#pyfiles[@]} -gt 0 ]; then + if [ $dry = 1 ]; then + printf 'would update (Python) %s\n' "${pyfiles[@]}" + else + python3 "$here/reorg/python_api_names.py" "${pyfiles[@]}" + fi +fi diff --git a/tools/reorg/absolute_includes.py b/tools/reorg/absolute_includes.py new file mode 100755 index 000000000..df2257382 --- /dev/null +++ b/tools/reorg/absolute_includes.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +"""Rewrite relative includes of PCMS headers as pcms/-rooted includes. + +Usage (from the repository root): + tools/reorg/absolute_includes.py [ ...] + +For every C/C++ source or header below each , each *quoted* include +whose path, resolved relative to the including file's directory, names a +tracked file under src/pcms (or a generated header there) is rewritten to +"pcms/", keeping the quote style. Includes that are already +pcms/-rooted, angle-bracket includes, and SWIG %include directives are left +unchanged (the SWIG interface files are processed by `swig -fortran` from +their own directory). Running it twice is a no-op. +""" + +import os +import re +import subprocess +import sys + +ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) +SRC_PCMS = os.path.join(ROOT, "src", "pcms") +CODE = re.compile(r"\.(h|hpp|c|cpp|cc)(\.in)?$") +INCLUDE = re.compile(r'^(\s*#\s*include\s*)"([^"]+)"', re.M) + + +def tracked(): + out = subprocess.run(["git", "ls-files"], cwd=ROOT, check=True, + capture_output=True, text=True).stdout.split() + return out + + +def main(dirs): + files = tracked() + exist = {os.path.join(ROOT, f) for f in files} + # generated headers live as *.in in the source tree + exist |= {p[:-3] for p in exist if p.endswith(".hpp.in")} + changed = rewrites = 0 + for f in files: + absf = os.path.join(ROOT, f) + if not CODE.search(f): + continue + if not any(absf.startswith(os.path.abspath(d) + os.sep) for d in dirs): + continue + + def repl(m): + nonlocal rewrites + inc = m.group(2) + if inc.startswith("pcms/"): + return m.group(0) + target = os.path.normpath(os.path.join(os.path.dirname(absf), inc)) + if target in exist and target.startswith(SRC_PCMS + os.sep): + rewrites += 1 + rel = os.path.relpath(target, os.path.dirname(SRC_PCMS)) + return f'{m.group(1)}"{rel}"' + return m.group(0) + + with open(absf, encoding="utf-8") as fh: + text = fh.read() + new = INCLUDE.sub(repl, text) + if new != text: + with open(absf, "w", encoding="utf-8") as fh: + fh.write(new) + changed += 1 + print(f"rewrote {rewrites} includes in {changed} files") + + +if __name__ == "__main__": + if len(sys.argv) < 2: + sys.exit(__doc__) + main([os.path.join(ROOT, d) for d in sys.argv[1:]]) diff --git a/tools/reorg/backend_namespace.py b/tools/reorg/backend_namespace.py new file mode 100755 index 000000000..8173ee14b --- /dev/null +++ b/tools/reorg/backend_namespace.py @@ -0,0 +1,246 @@ +#!/usr/bin/env python3 +"""Move a backend's code into namespace pcms::backend::. + +Usage (from the repository root): + tools/reorg/backend_namespace.py + + lists, one per line, the namespace-scope names declared by the +backend's files in namespace pcms ('#' starts a comment). The backend's files +are every tracked C++ file below src/pcms/backends//. + +In the backend's own files: +* ``namespace pcms`` (opening line and closing comment) becomes + ``namespace pcms::backend::``; nested ``pcms::detail`` etc. are left; +* ``pcms::`` becomes ``pcms::backend::::`` (e.g. in + std::hash specializations); +* a compact ``namespace pcms::detail`` block becomes + ``namespace pcms::backend::::detail`` (nested under the new + namespace); uses in other files of the names declared in the moved detail + namespaces (``pcms::detail::X`` or ``detail::X``) are qualified with the + new namespace, unless another file also declares X in a detail namespace; +* if the backend declares its own nested ``detail`` namespace, references + to ``detail::X`` for names it does not declare there are written + ``pcms::detail::X`` (inside pcms::backend::, ``detail::`` would + otherwise find only the backend's own detail namespace); +* uses of a library namespace that a backend namespace shadows are written + with a leading ``::`` (``mfem``, which pcms::backend::mfem hides from + code inside pcms::backend); other library namespaces (Kokkos, Omega_h, + ...) are left as written. + +In every other tracked C++ file, each use of a listed symbol that is not in +a comment or string literal and is not a member access is rewritten to +``pcms::backend::::``; an existing ``pcms::`` qualifier is +replaced. Running the script twice is a no-op. +""" + +import os +import re +import subprocess +import sys + +ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) +CODE = re.compile(r"\.(h|hpp|cpp|cc|c)(\.in)?$") +# library namespaces shadowed by a pcms::backend:: namespace +EXTERNAL = ("mfem",) + + +def tracked(): + return subprocess.run(["git", "ls-files"], cwd=ROOT, check=True, + capture_output=True, text=True).stdout.split() + + +def code_spans(text): + """Yield (start, end) of text that is code (not comment/string/char).""" + i, n, start = 0, len(text), 0 + while i < n: + c = text[i] + two = text[i:i + 2] + if two == "//" or two == "/*" or c in "\"'": + if start < i: + yield start, i + if two == "//": + j = text.find("\n", i) + i = n if j < 0 else j + elif two == "/*": + j = text.find("*/", i + 2) + i = n if j < 0 else j + 2 + elif c == '"' and text[max(0, i - 1)] == "R": # raw string R"(...)" + m = re.match(r'"([^(]*)\(', text[i:]) + end = text.find(")" + m.group(1) + '"', i) if m else -1 + i = n if end < 0 else end + len(m.group(1)) + 2 + else: + j = i + 1 + while j < n and text[j] != c: + j += 2 if text[j] == "\\" else 1 + i = j + 1 + start = i + elif c == "#" and (i == 0 or text[i - 1] == "\n"): + # preprocessor line: keep #include paths untouched, but code in + # #if/#define lines is still code + j = text.find("\n", i) + j = n if j < 0 else j + if re.match(r"#\s*include", text[i:j]): + if start < i: + yield start, i + start = j + i = j + else: + i += 1 + if start < n: + yield start, n + + +def transform_code(text, fn): + out, last = [], 0 + for s, e in code_spans(text): + out.append(text[last:s]) + out.append(fn(text[s:e])) + last = e + out.append(text[last:]) + return "".join(out) + + +DECL = re.compile(r"^\s*(?:template\s*<.*>\s*)?(?:struct|class|using|enum class|enum)\s+(\w+)" + r"|^\s*(?:(?:inline|static|constexpr|[A-Z][A-Z0-9_]+|\[\[\w+\]\])\s+)*" + r"[\w:<>,]+[\s&*]+(\w+)\s*\(") + + +def collect_detail_names(paths): + """Names declared directly in `namespace detail` blocks (nested in + namespace pcms...) or compact `namespace pcms::detail` blocks of paths. + Returns (all names, names of compact blocks).""" + names, compact_names = set(), set() + for f in paths: + try: + fh = open(os.path.join(ROOT, f), encoding="utf-8") + except OSError: + continue + with fh: + depth = None # brace depth inside a detail namespace + compact = False + for line in fh: + code = line.split("//", 1)[0] + if depth is None: + if re.match(r"\s*namespace detail\b", code): + depth, compact = 0, False + elif re.match(r"namespace pcms::detail\b", code): + depth, compact = 0, True + else: + continue + elif depth == 1: + m = DECL.match(code) + name = (m.group(1) or m.group(2)) if m else None + if name is None and re.match(r"\S", code) and "(" in code: + # unindented declaration with a complex return type: + # the name is the identifier before the first '(' + f2 = re.search(r"(\w+)\s*\(", code) + if f2 and f2.group(1) not in ("if", "for", "while", + "switch", "return"): + name = f2.group(1) + if name: + names.add(name) + if compact: + compact_names.add(name) + depth += code.count("{") - code.count("}") + if depth <= 0 and "}" in code: + depth = None + return names, compact_names + + +def read_list(path): + out = [] + with open(path) as fh: + for line in fh: + line = line.split("#", 1)[0].strip() + if line: + out.append(line) + return out + + +def main(name, symfile): + syms = read_list(symfile) + dirs = (f"src/pcms/backends/{name}/", f"include/pcms/backends/{name}/") + own = [f for f in tracked() if CODE.search(f) and f.startswith(dirs)] + if not own: + sys.exit(f"no files below {dirs[0]}") + move_namespace(f"pcms::backend::{name}", own, syms, external_prefix=True) + + +def move_namespace(ns, own, syms, external_prefix): + """Move the code of the files `own` from namespace pcms into ns and + qualify uses of `syms` elsewhere (see the module docstring).""" + files = [f for f in tracked() if CODE.search(f)] + # names declared directly at the scope of a backend's own `namespace + # detail` (not names merely used inside it) + own_detail, compact_detail = collect_detail_names(own) + # names a file outside `own` declares in a detail namespace: uses of + # those names cannot be attributed to the moved code + others = [f for f in files if f not in own] + elsewhere, _ = collect_detail_names(others) + moved_detail = own_detail - elsewhere + if os.environ.get("REORG_DEBUG"): + print("own detail names:", sorted(own_detail)) + detail_ref = re.compile(r"(? ns::detail + new = re.sub(r"^namespace pcms::detail([ \t]*\{|[ \t]*$)", + lambda m: f"namespace {ns}::detail{m.group(1)}", new, + flags=re.M) + new = re.sub(r"(\}[ \t]*//[ \t]*namespace) pcms::detail[ \t]*$", + lambda m: f"{m.group(1)} {ns}::detail", new, flags=re.M) + + def own_fn(code): + code = qualified.sub(lambda m: f"{ns}::{m.group(1)}", code) + if moved_detail: + code = compact_ref.sub( + lambda m: f"{ns}::detail::{m.group(1)}" + if m.group(0).lstrip(":").startswith("pcms::") + else m.group(0), code) + if own_detail: + code = detail_ref.sub( + lambda m: m.group(0) if m.group(1) in own_detail + else f"pcms::detail::{m.group(1)}", code) + if external_prefix: + code = ext.sub(lambda m: f"::{m.group(1)}::", code) + return code + new = transform_code(new, own_fn) + else: + def other_fn(code): + code = qualified.sub(lambda m: f"{ns}::{m.group(1)}", code) + if moved_detail: + code = compact_ref.sub( + lambda m: f"{ns}::detail::{m.group(1)}", code) + # bare uses (not already qualified, not member access) + code = re.sub(r"(?)(" + sym_alt + r")\b", + lambda m: f"{ns}::{m.group(1)}", code) + return code + new = transform_code(text, other_fn) + # undo double qualification produced on already-rewritten text + new = new.replace(f"{ns}::{ns}::", f"{ns}::") + if new != text: + with open(path, "w", encoding="utf-8") as fh: + fh.write(new) + changed += 1 + print(f"updated {changed} files ({len(own)} files moved to {ns})") + + +if __name__ == "__main__": + if len(sys.argv) != 3: + sys.exit(__doc__) + main(sys.argv[1], sys.argv[2]) diff --git a/tools/reorg/decisions.md b/tools/reorg/decisions.md new file mode 100644 index 000000000..d1dade1bb --- /dev/null +++ b/tools/reorg/decisions.md @@ -0,0 +1,266 @@ +# PCMS breaking reorganization: decisions and amendments + +This file records the decisions made with the maintainer before and during the +reorganization, including where they deliberately differ from the original task +description (`refactor.md`). Reviewers should read this first. + +## Process + +| Item | Decision | +|---|---| +| Base | `reorg/breaking-block` from `upstream/develop` (c33f816c) | +| PR #379, #401 | Still open; judged not to conflict materially; not blocking | +| PR #410 (CMake 3.23) | Will not be merged; the first commit of this branch bumps `cmake_minimum_required` to 3.23 (required by `FILE_SET`, already in use) | +| Version | Minor bump: 0.3.0 → 0.4.0 | +| Push / PR | Commits are local; the maintainer pushes and opens the draft PR | +| Verification per commit | Minimal-static and Full-shared build + `ctest` | +| Verification per phase boundary and at tip | Additionally Full-static, `cmake --install`, and `examples/external-usage-example` built against the install tree | +| Open branches (#400 dof-access, external-eval-infra, fusion-io, nimrod) | Reorg lands first; those branches migrate afterwards with `tools/migrate-pcms.sh` | +| Old CMake target names (`pcms::core`, ...) | Kept for one release as deprecated `INTERFACE` targets linking `pcms::pcms` | +| Old header paths | No forwarding stubs; `tools/reorg/header-map.txt` + `tools/migrate-pcms.sh` cover them | +| Fortran SWIG wrappers | Not regenerated: they include `"pcms/capi/*.h"`, which keeps its path, and the C API does not change | +| Commit granularity | Deviation from the plan's one-commit-per-sub-library rule, decided at review: the `.h`→`.hpp` renames, the `pcms/`-rooted includes, the moves to `include/` and the install rules are one commit each (each mechanical commit lists its commands in order; every one reproduces its diff). Fixes to the reorg scripts are folded into the commits that add the scripts, and the decision/inventory updates into the two docs commits. Backend moves and sub-library namespaces stay one commit per backend / library. | +| Verification | Per commit (Minimal-static for CMake changes, Full-shared for all) through Phase 5; after that, the end of each phase, the commits with temporary Python aliases and the tip, bisecting only on failure (decided at review) | + +### Baseline limitation + +On develop the coupler is built unconditionally (`find_package(redev REQUIRED)`, +`find_package(ADIOS2 REQUIRED)` at top level, `smoke_test` links `pcms::core`). +The "Minimal: no coupler" configuration therefore cannot be built until Phase 2. +Until then "Minimal" means: Omega_h only; meshfields, PETSc, MFEM, XGC, Python, +C, Fortran and transient off; static. + +## Public API (amendment: the task originally excluded API redesign) + +The change is limited to *how objects are constructed*; semantics of the +existing interfaces do not change. + +### Principles + +- Public headers contain **interfaces** and **free-function factories** only. + All concrete implementation classes are private (stay in `src/`, not + installed). In-tree targets and tests may still include private headers. +- Function spaces are created **by space type, from a `Discretization`**. Mesh + sources produce discretizations. +- Codes with their own representation (XGC, MFEM in place, later NIMROD, + Fusion-IO, BOUT++) get **per-code factories** returning the same interfaces. +- Only backend headers (`include/pcms/backends//`) may include or name + backend-library types. +- Factories return `std::shared_ptr`; transfer factories return + `std::unique_ptr>`. + +Rationale for interface-only (vs. keeping concrete classes public with factories +moved out): an audit of every non-override public method on concrete classes +found no external user that needs one. The only uses outside the owning +sub-library are the C API, the Python bindings and tests (XGC +`GetXGCLayout`/`SetLayoutName`, MFEM `OverlapMaskFromAttribute`, +`OmegaHDiscretization::GetMesh`); these become factory arguments or free +functions. Making a class public later is non-breaking; hiding it later is not. + +### Public interfaces and types (`namespace pcms`) + +Interfaces: `Discretization`, `FieldLayout`, `FunctionSpace`, `Field` / +`Function`, `FieldData` / `DOFAccess`, `PointEvaluator` / +`PointEvaluatorFactory`, `TransferOperator`, `CoordinateSystem` / +`CoordinateMap`, coupler types, `Timestepper`. + +Backend-free types users construct directly: `Interpolator`, `Copy`, +`TransformedSource`, coordinate systems and maps, `FixedTimestepper`. + +### Factories + +```cpp +// Discretizations (core) +std::shared_ptr CreateUniformGridDiscretization(const UniformGrid&); +std::shared_ptr CreatePointCloudDiscretization(...); +std::shared_ptr CreateEmptyDiscretization(...); +std::shared_ptr CreateEmptyLayout(csys, ncomp); // for out-of-tree evaluation-only spaces + +// Discretizations (backend) +namespace pcms::backend::omega_h { +std::shared_ptr +CreateDiscretization(::Omega_h::Mesh& mesh, std::string global_id_name = "global", /* owned mask */ ...); // borrows mesh, as today +::Omega_h::Mesh& GetMesh(const Discretization&); +} + +// Function spaces, by type (core) +std::shared_ptr CreateLagrangeSpace(disc, order, ncomp, csys, LagrangeOptions = {}); + // LagrangeOptions: today's MeshFields/OmegaH evaluator choice, layout_name +std::shared_ptr CreateSplineSpace(disc, ..., SplineOptions = {}); +std::shared_ptr CreatePolynomialReconstructionSpace(disc, ..., PolynomialReconstructionOptions = {}); + +// Adopted application spaces (backend headers) +namespace pcms::backend::xgc { CreateFunctionSpace(..., layout_name); CreateField(space, name, data, plane_comm); } +namespace pcms::backend::mfem { CreateFunctionSpace(::mfem::ParFiniteElementSpace&, ..., layout_name); + OverlapMaskFromAttribute(::mfem::ParMesh&, int); } + +// Transfers (core header include/pcms/transfer/, always declared; +// throw "not available in this build" if the implementing backend is disabled) +std::unique_ptr> CreateConservativeProjection(src_space, tgt_space, opts = {}); +std::unique_ptr> CreateControlVariateProjection(src_space, tgt_space, opts = {}); +``` + +Space and transfer factories dispatch on the concrete discretization type and +call internal implementation functions directly (e.g. `detail::FromOmegaH`, +`detail::FromUniformGrid`). `Discretization` does not know about function +spaces (virtual hooks on `Discretization` were rejected as coupling the two). + +Unsupported combinations (e.g. a Lagrange space on an XGC discretization) throw +with a message naming both types. + +### Coupler + +`pcms::Mode` (today `using Mode = redev::Mode`) becomes a real enum +`{Deferred, Synchronous}`, converted to `redev::Mode` inside the coupler. Public +signatures use `pcms::Mode`; redev no longer appears in public headers. + +### Python + +The Python API is changed to match the C++ shape in this release +(`pcms.backend.omega_h.create_discretization(mesh)`, +`pcms.create_lagrange_space(disc, ...)`); the old names are removed. + +## Backends and build layout (amendment to Phase 3) + +- Namespace `pcms::backend::` (instead of `pcms::_backend`); bridges + `pcms::backend::omega_h_meshfields`. Inside `pcms::backend`, `mfem::` would + find `pcms::backend::mfem`, so backend code writes `::mfem::`. Other library + namespaces (Kokkos, Omega_h, ...) are not shadowed and are written without + a leading `::` (amended at review: qualifying them too changed about 1000 + lines and caused most conflicts with open PRs). Nothing enforces this; an + unqualified `mfem::` that resolves to `pcms::backend::mfem` fails to + compile, so the mistake cannot go unnoticed. +- Backends are **directories, namespaces and headers**, not libraries: + sources in `src/pcms/backends//`, public headers in + `include/pcms/backends//`, compiled into the core target that uses them + (`pcms::field`, `pcms::transfer`, `pcms::coupler`) behind + `PCMS_ENABLE_` / `PCMS_HAS_`. A bridge is compiled when both backends + are enabled. +- No `pcms::` targets and no `pcms_backend_part()` helper. Reason: separate + backend libraries only pay off for static-link dependency hygiene and + `COMPONENTS` support, neither of which is in scope; they would force a + dispatch layer above `pcms::field`. +- Downstream links **`pcms::pcms`**, the documented, stable entry point. Splitting + backends into libraries later (e.g. when Omega_h becomes optional) is then an + internal change. + +## Deferred (follow-ups, non-breaking) + +- `ReadDiscretization(comm, path, opts)` with file-type dispatch (needs a + partitioning option; owns the mesh it reads). Further mesh sources (MFEM + mesh → shared infrastructure, gmsh, BOUT++). +- **Multi-field sources** (EQDSK, NIMROD, Fusion-IO, VMEC): a `FieldSource` + layer on top of spaces (`Quantities()`, `CreateFunction(quantity)`, + `QuantityInfo`, `OpenEQDSK`, `OpenFieldSource(path)`), designed separately. + In this reorg `MakeEQDSKField` only changes its struct member to + `std::shared_ptr`. +- Batch evaluation of several quantities in one call; EQDSK flux functions + (needs a composition evaluator). +- Making Omega_h optional for core internals. + +## Include guards (amendment to Phase 1.4) + +`#pragma once` is not standard C++ and is **not used**. Every header keeps an +`#ifndef`/`#define`/`#endif` guard. Instead of switching to `#pragma once`, +guard names are normalized to a path-derived scheme +(`pcms/field/field.hpp` → `PCMS_FIELD_FIELD_HPP`) in one mechanical pass +**after Phase 5**, when header paths are final. Before that, only headers that +had no guard (or `#pragma once`) are fixed. + +## Phase 3 notes (backends) + +- Layout: `src/pcms/backends//` with a `CMakeLists.txt` that adds the + backend's sources and headers to the core target that uses them (see + "Backends and build layout"); namespaces `pcms::backend::`. Done for + `xgc`, `mfem`, `point_cloud`, `uniform_grid`, `omega_h` and the bridge + `omega_h_meshfields`. +- **MeshFields is a bridge.** Every MeshFields file needs the Omega_h adapter + (`MeshFieldsAdapterLayout` is built from an `OmegaHDiscretization`), so the + whole MeshFields adapter is in `backends/omega_h_meshfields/`, built only + when both Omega_h and MeshFields are enabled. There is no `backends/meshfields`. +- **`function_space/lagrange` stays in `field`.** The plan listed it under the + Omega_h adapter, but it is the generic Lagrange space (it also serves uniform + grids) behind `CreateLagrangeSpace`. +- **Omega_h-based transfer algorithms stay in `transfer`** (conservative and + control-variate projection, the integrators, `mesh_intersection`); the plan + only listed field/localization parts for the adapter. They are private. +- `point_cloud` and `uniform_grid` have no external dependency and are used by + other backends (the MFEM layout builds a `PointCloudDiscretization`); this is + not treated as a bridge. +- `SupportResults`, the result type of the `LocalizationFactory` interface, + moved out of `adj_search.hpp` into `localization/support_results.hpp` before + the adjacency search moved into the Omega_h adapter. +- `transfer/linear_interpolant.hpp` and `transfer/multidimarray.hpp` moved to + `backends/uniform_grid/` (only the uniform-grid evaluator uses them; field + must not include transfer headers). +- In a backend with its own nested `detail` namespace, references to + `pcms::detail` names are written `pcms::detail::X`. + +## Phase 0 checkpoint (approved) + +The classification in `inventory.md` is approved with these decisions: + +1. Coupler communicator templates (`field_communicator`, `field_layout_communicator`, + `field_exchange_planner`, `global_communicator`, `field_serializer`) become + installed-detail (`include/pcms/coupler/detail/`); redev remains a public + dependency of `pcms::coupler` only. +2. XGC and MFEM factories are `pcms::backend::xgc::CreateFieldFactory` and + `pcms::backend::mfem::CreateFieldFactory`, returning + `std::shared_ptr` (they are not evaluable function spaces). +3. `SimpleFieldData` stays a public class. +4. `spline_interpolator.hpp` becomes private. +5. `CreateUniformGridBinaryField` is a public free function in the Omega_h + backend header. +6. `utility/print.hpp` is public (`setStdout`/`setStderr` let applications + redirect PCMS output); `bounding_box`, `array_mask`, `mpi_type` are private. +7. Localization stays private (its public API is deferred). + +Further decisions: the external usage example is rewritten in Phase 9 to use +only the public API; Python tests/examples are updated to the new Python names; +`UniformGrid::ClosestCellID` takes any indexable point type (template) instead of +`Omega_h::Vector` (`std::array` is not usable in device code without +relaxed constexpr); `FindPETSc.cmake` stays installed because the package +config's `find_dependency(PETSc)` needs it. + +## Phases 5-9 notes + +- **Factories (Phase 5).** Space factories take a `Discretization` and call the + existing builders with the same arguments (the space still builds its own + layout and internal discretization from the mesh or grid). The Omega_h + discretization carries the global-id tag name and the optional owned mask, + which were `LagrangeFunctionSpace::FromMesh` arguments. Polynomial + reconstruction over points takes the points directly; there is no public + point-cloud discretization factory (nothing public would consume it). + `CreateUniformGridBinaryField` returns only the `Field` (its layout type is + private). +- **Reclassified while splitting:** `utility/bounding_box.hpp` is public + (`UniformGrid::GetCellBBOX` returns `AABBox`); `transfer/monte_carlo_sampling.hpp` + is public (enum used in the projection options). +- **Install rules:** every library's installed FILE_SET contains only its + headers under `include/pcms`; private headers are private sources. + `pcms::localization` switched from `PUBLIC_HEADER` (installed flat) to a + FILE_SET. The C API install include directory is `include`. +- **PUBLIC dependencies that remain:** Kokkos; redev (coupler and its + installed-detail templates); perfstubs (`utility/detail/profile.hpp`); MFEM + (MFEM backend header); Omega_h (Omega_h and XGC backend headers, and core + internals). MeshFields is PRIVATE. +- **Omega_h out of core public signatures (Phase 6):** no new vector type; + `UniformGrid` point queries are templates on the point type. + The Python bindings follow: `create_uniform_grid_from_mesh`, + `compute_entity_centroids` and `map_entity_field_to_vertices_{average,mls}` + take an Omega_h mesh and moved to `pcms.backend.omega_h`; the + `compute_entity_centroids_few` alias is removed; `patch_size_for_degree` + (no mesh) stays top-level (maintainer decision during review). +- **Sub-library namespaces (Phase 7):** private code of utility, + discretization, localization, field, transfer and the coupler's internal + classes (including its installed-detail templates) moved to `pcms::`. + Transient has no internal code. `field/evaluator/interpolator_aliases.hpp` + keeps its generic aliases (`member_type`, `ScratchMatView`, ...) in `pcms::` + because other files define unrelated local aliases with those names. +- **Packaging (Phase 8):** package files in `lib/cmake/pcms` + (`PCMS_INSTALL_CMAKEDIR`); `SameMinorVersion`; version 0.4.0, SOVERSION 0.4; + SWIG `.i` files no longer installed; `FindPETSc.cmake` kept (needed by the + config's `find_dependency(PETSc)`); baked `HINTS` removed; baked + `PETSC_DIR`/`PETSC_ARCH` defaults kept (used by the installed FindPETSc). +- **Guards and migration (Phase 9):** see `tools/check-public-includes.py`, + `test/public_headers/`, `tools/migrate-pcms.sh`, `MIGRATION.md`. diff --git a/tools/reorg/deps-after-phase2.dot b/tools/reorg/deps-after-phase2.dot new file mode 100644 index 000000000..118cf0727 --- /dev/null +++ b/tools/reorg/deps-after-phase2.dot @@ -0,0 +1,190 @@ +digraph "pcms" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "pcms_field\n(pcms::field)", shape = octagon ]; + "node1" [ label = "Kokkos::kokkoskernels\n(KokkosKernels::all_libs)\n(KokkosKernels::kokkoskernels)", shape = doubleoctagon ]; + "node2" [ label = "Kokkos::kokkos\n(Kokkos::all_libs)", shape = pentagon ]; + "node3" [ label = "Kokkos::kokkosalgorithms", shape = doubleoctagon ]; + "node4" [ label = "Kokkos::kokkoscore", shape = doubleoctagon ]; + "node5" [ label = "OpenMP::OpenMP_CXX", shape = pentagon ]; + "node6" [ label = "/usr/lib64/gcc/x86_64-suse-linux/13/libgomp.so", shape = septagon ]; + "node5" -> "node6" [ style = dashed ] // OpenMP::OpenMP_CXX -> /usr/lib64/gcc/x86_64-suse-linux/13/libgomp.so + "node7" [ label = "/usr/lib64/libpthread.a", shape = septagon ]; + "node5" -> "node7" [ style = dashed ] // OpenMP::OpenMP_CXX -> /usr/lib64/libpthread.a + "node4" -> "node5" [ style = dashed ] // Kokkos::kokkoscore -> OpenMP::OpenMP_CXX + "node8" [ label = "dl", shape = septagon ]; + "node4" -> "node8" [ style = dashed ] // Kokkos::kokkoscore -> dl + "node3" -> "node4" [ style = dashed ] // Kokkos::kokkosalgorithms -> Kokkos::kokkoscore + "node2" -> "node3" [ style = dashed ] // Kokkos::kokkos -> Kokkos::kokkosalgorithms + "node9" [ label = "Kokkos::kokkoscontainers", shape = doubleoctagon ]; + "node9" -> "node4" [ style = dashed ] // Kokkos::kokkoscontainers -> Kokkos::kokkoscore + "node2" -> "node9" [ style = dashed ] // Kokkos::kokkos -> Kokkos::kokkoscontainers + "node2" -> "node4" [ style = dashed ] // Kokkos::kokkos -> Kokkos::kokkoscore + "node10" [ label = "Kokkos::kokkossimd", shape = doubleoctagon ]; + "node2" -> "node10" [ style = dashed ] // Kokkos::kokkos -> Kokkos::kokkossimd + "node1" -> "node2" [ style = dashed ] // Kokkos::kokkoskernels -> Kokkos::kokkos + "node0" -> "node1" [ style = dotted ] // pcms_field -> Kokkos::kokkoskernels + "node11" [ label = "Omega_h::omega_h", shape = doubleoctagon ]; + "node12" [ label = "MPI::MPI_CXX", shape = pentagon ]; + "node13" [ label = "/opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpi.so", shape = septagon ]; + "node12" -> "node13" [ style = dashed ] // MPI::MPI_CXX -> /opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpi.so + "node14" [ label = "/opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpicxx.so", shape = septagon ]; + "node12" -> "node14" [ style = dashed ] // MPI::MPI_CXX -> /opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpicxx.so + "node11" -> "node12" [ style = dashed ] // Omega_h::omega_h -> MPI::MPI_CXX + "node15" [ label = "Omega_h-Kokkos", shape = pentagon ]; + "node15" -> "node2" [ style = dashed ] // Omega_h-Kokkos -> Kokkos::kokkos + "node11" -> "node15" [ style = dashed ] // Omega_h::omega_h -> Omega_h-Kokkos + "node16" [ label = "Omega_h-ZLIB", shape = pentagon ]; + "node17" [ label = "ZLIB::ZLIB", shape = septagon ]; + "node16" -> "node17" [ style = dashed ] // Omega_h-ZLIB -> ZLIB::ZLIB + "node11" -> "node16" [ style = dashed ] // Omega_h::omega_h -> Omega_h-ZLIB + "node0" -> "node11" // pcms_field -> Omega_h::omega_h + "node18" [ label = "meshfields::meshfields", shape = doubleoctagon ]; + "node19" [ label = "Cabana::Core", shape = pentagon ]; + "node19" -> "node2" [ style = dashed ] // Cabana::Core -> Kokkos::kokkos + "node19" -> "node12" [ style = dashed ] // Cabana::Core -> MPI::MPI_CXX + "node18" -> "node19" [ style = dashed ] // meshfields::meshfields -> Cabana::Core + "node18" -> "node2" [ style = dashed ] // meshfields::meshfields -> Kokkos::kokkos + "node18" -> "node11" [ style = dashed ] // meshfields::meshfields -> Omega_h::omega_h + "node0" -> "node18" // pcms_field -> meshfields::meshfields + "node20" [ label = "mfem", shape = doubleoctagon ]; + "node21" [ label = "-Wl,-rpath -Wl,/opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib", shape = septagon ]; + "node20" -> "node21" [ style = dashed ] // mfem -> -Wl,-rpath -Wl,/opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib + "node22" [ label = "/opt/software/linux-x86_64_v3/hypre-3.2.0-bqpag5omddy4brurswolc4ulqg66mikx/lib64/libHYPRE.so", shape = septagon ]; + "node20" -> "node22" [ style = dashed ] // mfem -> /opt/software/linux-x86_64_v3/hypre-3.2.0-bqpag5omddy4brurswolc4ulqg66mikx/lib64/libHYPRE.so + "node23" [ label = "/opt/software/linux-x86_64_v3/metis-5.1.0-cvgy73kn3vhq4m4wgetebgwjsblfxz77/lib/libmetis.so", shape = septagon ]; + "node20" -> "node23" [ style = dashed ] // mfem -> /opt/software/linux-x86_64_v3/metis-5.1.0-cvgy73kn3vhq4m4wgetebgwjsblfxz77/lib/libmetis.so + "node20" -> "node13" [ style = dashed ] // mfem -> /opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpi.so + "node20" -> "node14" [ style = dashed ] // mfem -> /opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpicxx.so + "node24" [ label = "/opt/software/linux-x86_64_v3/zlib-ng-2.3.3-ihl2h74e3fqqrg5j3f7jvxiezcnkhiq4/lib/libz.so", shape = septagon ]; + "node20" -> "node24" [ style = dashed ] // mfem -> /opt/software/linux-x86_64_v3/zlib-ng-2.3.3-ihl2h74e3fqqrg5j3f7jvxiezcnkhiq4/lib/libz.so + "node0" -> "node20" // pcms_field -> mfem + "node25" [ label = "pcms_discretization\n(pcms::discretization)", shape = octagon ]; + "node25" -> "node2" // pcms_discretization -> Kokkos::kokkos + "node25" -> "node11" [ style = dotted ] // pcms_discretization -> Omega_h::omega_h + "node26" [ label = "pcms_utility\n(pcms::utility)", shape = octagon ]; + "node26" -> "node2" // pcms_utility -> Kokkos::kokkos + "node26" -> "node11" // pcms_utility -> Omega_h::omega_h + "node27" [ label = "perfstubs", shape = doubleoctagon ]; + "node27" -> "node8" [ style = dashed ] // perfstubs -> dl + "node28" [ label = "m", shape = septagon ]; + "node27" -> "node28" [ style = dashed ] // perfstubs -> m + "node26" -> "node27" // pcms_utility -> perfstubs + "node25" -> "node26" // pcms_discretization -> pcms_utility + "node0" -> "node25" // pcms_field -> pcms_discretization + "node29" [ label = "pcms_localization\n(pcms::localization)", shape = octagon ]; + "node29" -> "node2" // pcms_localization -> Kokkos::kokkos + "node29" -> "node11" // pcms_localization -> Omega_h::omega_h + "node29" -> "node25" // pcms_localization -> pcms_discretization + "node29" -> "node26" // pcms_localization -> pcms_utility + "node0" -> "node29" // pcms_field -> pcms_localization + "node0" -> "node26" // pcms_field -> pcms_utility + "node30" [ label = "pcms_transfer\n(pcms::transfer)", shape = octagon ]; + "node30" -> "node11" // pcms_transfer -> Omega_h::omega_h + "node31" [ label = "PETSc::PETSc", shape = pentagon ]; + "node32" [ label = "petsc", shape = septagon ]; + "node31" -> "node32" [ style = dashed ] // PETSc::PETSc -> petsc + "node30" -> "node31" [ style = dotted ] // pcms_transfer -> PETSc::PETSc + "node30" -> "node18" [ style = dotted ] // pcms_transfer -> meshfields::meshfields + "node30" -> "node0" // pcms_transfer -> pcms_field + "node30" -> "node29" // pcms_transfer -> pcms_localization + "node33" [ label = "pcms_pcms\n(pcms::pcms)", shape = pentagon ]; + "node34" [ label = "pcms_capi\n(pcms::capi)", shape = pentagon ]; + "node35" [ label = "pcms_capi_core\n(pcms::capi::core)", shape = octagon ]; + "node36" [ label = "MPI::MPI_C", shape = pentagon ]; + "node36" -> "node13" [ style = dashed ] // MPI::MPI_C -> /opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpi.so + "node35" -> "node36" // pcms_capi_core -> MPI::MPI_C + "node37" [ label = "pcms_coupler\n(pcms::coupler)", shape = octagon ]; + "node37" -> "node2" // pcms_coupler -> Kokkos::kokkos + "node37" -> "node12" // pcms_coupler -> MPI::MPI_CXX + "node37" -> "node11" // pcms_coupler -> Omega_h::omega_h + "node37" -> "node18" // pcms_coupler -> meshfields::meshfields + "node37" -> "node0" // pcms_coupler -> pcms_field + "node37" -> "node26" // pcms_coupler -> pcms_utility + "node37" -> "node27" // pcms_coupler -> perfstubs + "node38" [ label = "redev::redev", shape = doubleoctagon ]; + "node38" -> "node36" [ style = dashed ] // redev::redev -> MPI::MPI_C + "node39" [ label = "adios2::cxx11_mpi", shape = pentagon ]; + "node40" [ label = "adios2::cxx_mpi", shape = doubleoctagon ]; + "node40" -> "node12" [ style = dashed ] // adios2::cxx_mpi -> MPI::MPI_CXX + "node41" [ label = "adios2::cxx", shape = doubleoctagon ]; + "node40" -> "node41" [ style = dashed ] // adios2::cxx_mpi -> adios2::cxx + "node39" -> "node40" [ style = dashed ] // adios2::cxx11_mpi -> adios2::cxx_mpi + "node38" -> "node39" [ style = dashed ] // redev::redev -> adios2::cxx11_mpi + "node38" -> "node27" [ style = dashed ] // redev::redev -> perfstubs + "node37" -> "node38" // pcms_coupler -> redev::redev + "node35" -> "node37" [ style = dotted ] // pcms_capi_core -> pcms_coupler + "node34" -> "node35" [ style = dashed ] // pcms_capi -> pcms_capi_core + "node42" [ label = "pcms_capi_transfer\n(pcms::capi::transfer)", shape = octagon ]; + "node42" -> "node36" // pcms_capi_transfer -> MPI::MPI_C + "node42" -> "node30" [ style = dotted ] // pcms_capi_transfer -> pcms_transfer + "node34" -> "node42" [ style = dashed ] // pcms_capi -> pcms_capi_transfer + "node33" -> "node34" [ style = dashed ] // pcms_pcms -> pcms_capi + "node33" -> "node37" [ style = dashed ] // pcms_pcms -> pcms_coupler + "node33" -> "node25" [ style = dashed ] // pcms_pcms -> pcms_discretization + "node33" -> "node0" [ style = dashed ] // pcms_pcms -> pcms_field + "node43" [ label = "pcms_fortranapi\n(pcms::fortranapi)", shape = pentagon ]; + "node44" [ label = "pcms_fortranapi_core\n(pcms::fortranapi::core)", shape = octagon ]; + "node44" -> "node2" // pcms_fortranapi_core -> Kokkos::kokkos + "node44" -> "node35" [ style = dotted ] // pcms_fortranapi_core -> pcms_capi_core + "node43" -> "node44" [ style = dashed ] // pcms_fortranapi -> pcms_fortranapi_core + "node45" [ label = "pcms_fortranapi_transfer\n(pcms::fortranapi::transfer)", shape = octagon ]; + "node45" -> "node2" // pcms_fortranapi_transfer -> Kokkos::kokkos + "node45" -> "node42" [ style = dotted ] // pcms_fortranapi_transfer -> pcms_capi_transfer + "node43" -> "node45" [ style = dashed ] // pcms_fortranapi -> pcms_fortranapi_transfer + "node33" -> "node43" [ style = dashed ] // pcms_pcms -> pcms_fortranapi + "node33" -> "node29" [ style = dashed ] // pcms_pcms -> pcms_localization + "node33" -> "node30" [ style = dashed ] // pcms_pcms -> pcms_transfer + "node46" [ label = "pcms_transient\n(pcms::transient)", shape = octagon ]; + "node46" -> "node26" // pcms_transient -> pcms_utility + "node33" -> "node46" [ style = dashed ] // pcms_pcms -> pcms_transient + "node33" -> "node26" [ style = dashed ] // pcms_pcms -> pcms_utility + "node47" [ label = "pcms", shape = tripleoctagon ]; + "node47" -> "node2" [ style = dotted ] // pcms -> Kokkos::kokkos + "node47" -> "node36" [ style = dotted ] // pcms -> MPI::MPI_C + "node47" -> "node31" [ style = dotted ] // pcms -> PETSc::PETSc + "node48" [ label = "Python::Module", shape = pentagon ]; + "node47" -> "node48" [ style = dotted ] // pcms -> Python::Module + "node47" -> "node18" [ style = dotted ] // pcms -> meshfields::meshfields + "node47" -> "node37" [ style = dotted ] // pcms -> pcms_coupler + "node47" -> "node30" [ style = dotted ] // pcms -> pcms_transfer + "node49" [ label = "pybind11::headers", shape = pentagon ]; + "node50" [ label = "pybind11::pybind11_headers", shape = pentagon ]; + "node49" -> "node50" [ style = dashed ] // pybind11::headers -> pybind11::pybind11_headers + "node47" -> "node49" [ style = dotted ] // pcms -> pybind11::headers + "node51" [ label = "pybind11::module", shape = pentagon ]; + "node51" -> "node48" [ style = dashed ] // pybind11::module -> Python::Module + "node52" [ label = "pybind11::pybind11", shape = pentagon ]; + "node52" -> "node49" [ style = dashed ] // pybind11::pybind11 -> pybind11::headers + "node53" [ label = "pybind11::python_headers", shape = pentagon ]; + "node52" -> "node53" [ style = dashed ] // pybind11::pybind11 -> pybind11::python_headers + "node51" -> "node52" [ style = dashed ] // pybind11::module -> pybind11::pybind11 + "node47" -> "node51" [ style = dotted ] // pcms -> pybind11::module + "node54" [ label = "pcms_core\n(pcms::core)", shape = pentagon ]; + "node54" -> "node33" [ style = dashed ] // pcms_core -> pcms_pcms + "node55" [ label = "MPI::MPI_Fortran", shape = pentagon ]; + "node55" -> "node13" [ style = dashed ] // MPI::MPI_Fortran -> /opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpi.so + "node56" [ label = "/opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpifort.so", shape = septagon ]; + "node55" -> "node56" [ style = dashed ] // MPI::MPI_Fortran -> /opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpifort.so +} diff --git a/tools/reorg/deps-after.dot b/tools/reorg/deps-after.dot new file mode 100644 index 000000000..083b73bcc --- /dev/null +++ b/tools/reorg/deps-after.dot @@ -0,0 +1,193 @@ +digraph "pcms" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "pcms_field\n(pcms::field)", shape = octagon ]; + "node1" [ label = "Kokkos::kokkoskernels\n(KokkosKernels::all_libs)\n(KokkosKernels::kokkoskernels)", shape = doubleoctagon ]; + "node2" [ label = "Kokkos::kokkos\n(Kokkos::all_libs)", shape = pentagon ]; + "node3" [ label = "Kokkos::kokkosalgorithms", shape = doubleoctagon ]; + "node4" [ label = "Kokkos::kokkoscore", shape = doubleoctagon ]; + "node5" [ label = "OpenMP::OpenMP_CXX", shape = pentagon ]; + "node6" [ label = "/usr/lib64/gcc/x86_64-suse-linux/13/libgomp.so", shape = septagon ]; + "node5" -> "node6" [ style = dashed ] // OpenMP::OpenMP_CXX -> /usr/lib64/gcc/x86_64-suse-linux/13/libgomp.so + "node7" [ label = "/usr/lib64/libpthread.a", shape = septagon ]; + "node5" -> "node7" [ style = dashed ] // OpenMP::OpenMP_CXX -> /usr/lib64/libpthread.a + "node4" -> "node5" [ style = dashed ] // Kokkos::kokkoscore -> OpenMP::OpenMP_CXX + "node8" [ label = "dl", shape = septagon ]; + "node4" -> "node8" [ style = dashed ] // Kokkos::kokkoscore -> dl + "node3" -> "node4" [ style = dashed ] // Kokkos::kokkosalgorithms -> Kokkos::kokkoscore + "node2" -> "node3" [ style = dashed ] // Kokkos::kokkos -> Kokkos::kokkosalgorithms + "node9" [ label = "Kokkos::kokkoscontainers", shape = doubleoctagon ]; + "node9" -> "node4" [ style = dashed ] // Kokkos::kokkoscontainers -> Kokkos::kokkoscore + "node2" -> "node9" [ style = dashed ] // Kokkos::kokkos -> Kokkos::kokkoscontainers + "node2" -> "node4" [ style = dashed ] // Kokkos::kokkos -> Kokkos::kokkoscore + "node10" [ label = "Kokkos::kokkossimd", shape = doubleoctagon ]; + "node2" -> "node10" [ style = dashed ] // Kokkos::kokkos -> Kokkos::kokkossimd + "node1" -> "node2" [ style = dashed ] // Kokkos::kokkoskernels -> Kokkos::kokkos + "node0" -> "node1" [ style = dotted ] // pcms_field -> Kokkos::kokkoskernels + "node11" [ label = "Omega_h::omega_h", shape = doubleoctagon ]; + "node12" [ label = "MPI::MPI_CXX", shape = pentagon ]; + "node13" [ label = "/opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpi.so", shape = septagon ]; + "node12" -> "node13" [ style = dashed ] // MPI::MPI_CXX -> /opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpi.so + "node14" [ label = "/opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpicxx.so", shape = septagon ]; + "node12" -> "node14" [ style = dashed ] // MPI::MPI_CXX -> /opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpicxx.so + "node11" -> "node12" [ style = dashed ] // Omega_h::omega_h -> MPI::MPI_CXX + "node15" [ label = "Omega_h-Kokkos", shape = pentagon ]; + "node15" -> "node2" [ style = dashed ] // Omega_h-Kokkos -> Kokkos::kokkos + "node11" -> "node15" [ style = dashed ] // Omega_h::omega_h -> Omega_h-Kokkos + "node16" [ label = "Omega_h-ZLIB", shape = pentagon ]; + "node17" [ label = "ZLIB::ZLIB", shape = septagon ]; + "node16" -> "node17" [ style = dashed ] // Omega_h-ZLIB -> ZLIB::ZLIB + "node11" -> "node16" [ style = dashed ] // Omega_h::omega_h -> Omega_h-ZLIB + "node0" -> "node11" // pcms_field -> Omega_h::omega_h + "node18" [ label = "meshfields::meshfields", shape = doubleoctagon ]; + "node19" [ label = "Cabana::Core", shape = pentagon ]; + "node19" -> "node2" [ style = dashed ] // Cabana::Core -> Kokkos::kokkos + "node19" -> "node12" [ style = dashed ] // Cabana::Core -> MPI::MPI_CXX + "node18" -> "node19" [ style = dashed ] // meshfields::meshfields -> Cabana::Core + "node18" -> "node2" [ style = dashed ] // meshfields::meshfields -> Kokkos::kokkos + "node18" -> "node11" [ style = dashed ] // meshfields::meshfields -> Omega_h::omega_h + "node0" -> "node18" [ style = dotted ] // pcms_field -> meshfields::meshfields + "node20" [ label = "mfem", shape = doubleoctagon ]; + "node21" [ label = "-Wl,-rpath -Wl,/opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib", shape = septagon ]; + "node20" -> "node21" [ style = dashed ] // mfem -> -Wl,-rpath -Wl,/opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib + "node22" [ label = "/opt/software/linux-x86_64_v3/hypre-3.2.0-bqpag5omddy4brurswolc4ulqg66mikx/lib64/libHYPRE.so", shape = septagon ]; + "node20" -> "node22" [ style = dashed ] // mfem -> /opt/software/linux-x86_64_v3/hypre-3.2.0-bqpag5omddy4brurswolc4ulqg66mikx/lib64/libHYPRE.so + "node23" [ label = "/opt/software/linux-x86_64_v3/metis-5.1.0-cvgy73kn3vhq4m4wgetebgwjsblfxz77/lib/libmetis.so", shape = septagon ]; + "node20" -> "node23" [ style = dashed ] // mfem -> /opt/software/linux-x86_64_v3/metis-5.1.0-cvgy73kn3vhq4m4wgetebgwjsblfxz77/lib/libmetis.so + "node20" -> "node13" [ style = dashed ] // mfem -> /opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpi.so + "node20" -> "node14" [ style = dashed ] // mfem -> /opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpicxx.so + "node24" [ label = "/opt/software/linux-x86_64_v3/zlib-ng-2.3.3-ihl2h74e3fqqrg5j3f7jvxiezcnkhiq4/lib/libz.so", shape = septagon ]; + "node20" -> "node24" [ style = dashed ] // mfem -> /opt/software/linux-x86_64_v3/zlib-ng-2.3.3-ihl2h74e3fqqrg5j3f7jvxiezcnkhiq4/lib/libz.so + "node0" -> "node20" // pcms_field -> mfem + "node25" [ label = "pcms_discretization\n(pcms::discretization)", shape = octagon ]; + "node25" -> "node2" // pcms_discretization -> Kokkos::kokkos + "node25" -> "node11" [ style = dotted ] // pcms_discretization -> Omega_h::omega_h + "node26" [ label = "pcms_utility\n(pcms::utility)", shape = octagon ]; + "node26" -> "node2" // pcms_utility -> Kokkos::kokkos + "node26" -> "node11" // pcms_utility -> Omega_h::omega_h + "node27" [ label = "perfstubs", shape = doubleoctagon ]; + "node27" -> "node8" [ style = dashed ] // perfstubs -> dl + "node28" [ label = "m", shape = septagon ]; + "node27" -> "node28" [ style = dashed ] // perfstubs -> m + "node26" -> "node27" // pcms_utility -> perfstubs + "node25" -> "node26" // pcms_discretization -> pcms_utility + "node0" -> "node25" // pcms_field -> pcms_discretization + "node29" [ label = "pcms_localization\n(pcms::localization)", shape = octagon ]; + "node29" -> "node2" // pcms_localization -> Kokkos::kokkos + "node29" -> "node11" // pcms_localization -> Omega_h::omega_h + "node29" -> "node25" // pcms_localization -> pcms_discretization + "node29" -> "node26" // pcms_localization -> pcms_utility + "node0" -> "node29" // pcms_field -> pcms_localization + "node0" -> "node26" // pcms_field -> pcms_utility + "node30" [ label = "pcms_transfer\n(pcms::transfer)", shape = octagon ]; + "node30" -> "node11" // pcms_transfer -> Omega_h::omega_h + "node31" [ label = "PETSc::PETSc", shape = pentagon ]; + "node32" [ label = "petsc", shape = septagon ]; + "node31" -> "node32" [ style = dashed ] // PETSc::PETSc -> petsc + "node30" -> "node31" [ style = dotted ] // pcms_transfer -> PETSc::PETSc + "node30" -> "node18" [ style = dotted ] // pcms_transfer -> meshfields::meshfields + "node30" -> "node0" // pcms_transfer -> pcms_field + "node30" -> "node29" // pcms_transfer -> pcms_localization + "node33" [ label = "pcms_pcms\n(pcms::pcms)", shape = pentagon ]; + "node34" [ label = "pcms_capi\n(pcms::capi)", shape = pentagon ]; + "node35" [ label = "pcms_capi_core\n(pcms::capi::core)", shape = octagon ]; + "node36" [ label = "MPI::MPI_C", shape = pentagon ]; + "node36" -> "node13" [ style = dashed ] // MPI::MPI_C -> /opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpi.so + "node35" -> "node36" // pcms_capi_core -> MPI::MPI_C + "node37" [ label = "pcms_coupler\n(pcms::coupler)", shape = octagon ]; + "node37" -> "node2" // pcms_coupler -> Kokkos::kokkos + "node37" -> "node12" // pcms_coupler -> MPI::MPI_CXX + "node37" -> "node11" // pcms_coupler -> Omega_h::omega_h + "node37" -> "node18" [ style = dotted ] // pcms_coupler -> meshfields::meshfields + "node37" -> "node0" // pcms_coupler -> pcms_field + "node37" -> "node26" // pcms_coupler -> pcms_utility + "node37" -> "node27" // pcms_coupler -> perfstubs + "node38" [ label = "redev::redev", shape = doubleoctagon ]; + "node38" -> "node36" [ style = dashed ] // redev::redev -> MPI::MPI_C + "node39" [ label = "adios2::cxx11_mpi", shape = pentagon ]; + "node40" [ label = "adios2::cxx_mpi", shape = doubleoctagon ]; + "node40" -> "node12" [ style = dashed ] // adios2::cxx_mpi -> MPI::MPI_CXX + "node41" [ label = "adios2::cxx", shape = doubleoctagon ]; + "node40" -> "node41" [ style = dashed ] // adios2::cxx_mpi -> adios2::cxx + "node39" -> "node40" [ style = dashed ] // adios2::cxx11_mpi -> adios2::cxx_mpi + "node38" -> "node39" [ style = dashed ] // redev::redev -> adios2::cxx11_mpi + "node38" -> "node27" [ style = dashed ] // redev::redev -> perfstubs + "node37" -> "node38" // pcms_coupler -> redev::redev + "node35" -> "node37" [ style = dotted ] // pcms_capi_core -> pcms_coupler + "node34" -> "node35" [ style = dashed ] // pcms_capi -> pcms_capi_core + "node42" [ label = "pcms_capi_transfer\n(pcms::capi::transfer)", shape = octagon ]; + "node42" -> "node36" // pcms_capi_transfer -> MPI::MPI_C + "node42" -> "node30" [ style = dotted ] // pcms_capi_transfer -> pcms_transfer + "node34" -> "node42" [ style = dashed ] // pcms_capi -> pcms_capi_transfer + "node33" -> "node34" [ style = dashed ] // pcms_pcms -> pcms_capi + "node33" -> "node37" [ style = dashed ] // pcms_pcms -> pcms_coupler + "node33" -> "node25" [ style = dashed ] // pcms_pcms -> pcms_discretization + "node33" -> "node0" [ style = dashed ] // pcms_pcms -> pcms_field + "node43" [ label = "pcms_fortranapi\n(pcms::fortranapi)", shape = pentagon ]; + "node44" [ label = "pcms_fortranapi_core\n(pcms::fortranapi::core)", shape = octagon ]; + "node44" -> "node2" // pcms_fortranapi_core -> Kokkos::kokkos + "node44" -> "node35" [ style = dotted ] // pcms_fortranapi_core -> pcms_capi_core + "node43" -> "node44" [ style = dashed ] // pcms_fortranapi -> pcms_fortranapi_core + "node45" [ label = "pcms_fortranapi_transfer\n(pcms::fortranapi::transfer)", shape = octagon ]; + "node45" -> "node2" // pcms_fortranapi_transfer -> Kokkos::kokkos + "node45" -> "node42" [ style = dotted ] // pcms_fortranapi_transfer -> pcms_capi_transfer + "node43" -> "node45" [ style = dashed ] // pcms_fortranapi -> pcms_fortranapi_transfer + "node33" -> "node43" [ style = dashed ] // pcms_pcms -> pcms_fortranapi + "node33" -> "node29" [ style = dashed ] // pcms_pcms -> pcms_localization + "node33" -> "node30" [ style = dashed ] // pcms_pcms -> pcms_transfer + "node46" [ label = "pcms_transient\n(pcms::transient)", shape = octagon ]; + "node46" -> "node26" // pcms_transient -> pcms_utility + "node33" -> "node46" [ style = dashed ] // pcms_pcms -> pcms_transient + "node33" -> "node26" [ style = dashed ] // pcms_pcms -> pcms_utility + "node47" [ label = "pcms", shape = tripleoctagon ]; + "node47" -> "node2" [ style = dotted ] // pcms -> Kokkos::kokkos + "node47" -> "node36" [ style = dotted ] // pcms -> MPI::MPI_C + "node47" -> "node31" [ style = dotted ] // pcms -> PETSc::PETSc + "node48" [ label = "Python::Module", shape = pentagon ]; + "node47" -> "node48" [ style = dotted ] // pcms -> Python::Module + "node47" -> "node18" [ style = dotted ] // pcms -> meshfields::meshfields + "node47" -> "node37" [ style = dotted ] // pcms -> pcms_coupler + "node47" -> "node30" [ style = dotted ] // pcms -> pcms_transfer + "node49" [ label = "pybind11::headers", shape = pentagon ]; + "node50" [ label = "pybind11::pybind11_headers", shape = pentagon ]; + "node49" -> "node50" [ style = dashed ] // pybind11::headers -> pybind11::pybind11_headers + "node47" -> "node49" [ style = dotted ] // pcms -> pybind11::headers + "node51" [ label = "pybind11::module", shape = pentagon ]; + "node51" -> "node48" [ style = dashed ] // pybind11::module -> Python::Module + "node52" [ label = "pybind11::pybind11", shape = pentagon ]; + "node52" -> "node49" [ style = dashed ] // pybind11::pybind11 -> pybind11::headers + "node53" [ label = "pybind11::python_headers", shape = pentagon ]; + "node52" -> "node53" [ style = dashed ] // pybind11::pybind11 -> pybind11::python_headers + "node51" -> "node52" [ style = dashed ] // pybind11::module -> pybind11::pybind11 + "node47" -> "node51" [ style = dotted ] // pcms -> pybind11::module + "node54" [ label = "pcms_core\n(pcms::core)", shape = pentagon ]; + "node54" -> "node33" [ style = dashed ] // pcms_core -> pcms_pcms + "node55" [ label = "pcms_public_header_check", shape = hexagon ]; + "node55" -> "node20" [ style = dotted ] // pcms_public_header_check -> mfem + "node55" -> "node33" [ style = dotted ] // pcms_public_header_check -> pcms_pcms + "node56" [ label = "MPI::MPI_Fortran", shape = pentagon ]; + "node56" -> "node13" [ style = dashed ] // MPI::MPI_Fortran -> /opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpi.so + "node57" [ label = "/opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpifort.so", shape = septagon ]; + "node56" -> "node57" [ style = dashed ] // MPI::MPI_Fortran -> /opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpifort.so +} diff --git a/tools/reorg/deps-before.dot b/tools/reorg/deps-before.dot new file mode 100644 index 000000000..3e0566751 --- /dev/null +++ b/tools/reorg/deps-before.dot @@ -0,0 +1,194 @@ +digraph "pcms" { +node [ + fontsize = "12" +]; +subgraph clusterLegend { + label = "Legend"; + color = black; + edge [ style = invis ]; + legendNode0 [ label = "Executable", shape = egg ]; + legendNode1 [ label = "Static Library", shape = octagon ]; + legendNode2 [ label = "Shared Library", shape = doubleoctagon ]; + legendNode3 [ label = "Module Library", shape = tripleoctagon ]; + legendNode4 [ label = "Interface Library", shape = pentagon ]; + legendNode5 [ label = "Object Library", shape = hexagon ]; + legendNode6 [ label = "Unknown Library", shape = septagon ]; + legendNode7 [ label = "Custom Target", shape = box ]; + legendNode0 -> legendNode1 [ style = solid ]; + legendNode0 -> legendNode2 [ style = solid ]; + legendNode0 -> legendNode3; + legendNode1 -> legendNode4 [ label = "Interface", style = dashed ]; + legendNode2 -> legendNode5 [ label = "Private", style = dotted ]; + legendNode3 -> legendNode6 [ style = solid ]; + legendNode0 -> legendNode7; +} + "node0" [ label = "pcms_field\n(pcms::field)", shape = doubleoctagon ]; + "node1" [ label = "Kokkos::kokkoskernels\n(KokkosKernels::all_libs)\n(KokkosKernels::kokkoskernels)", shape = doubleoctagon ]; + "node2" [ label = "Kokkos::kokkos\n(Kokkos::all_libs)", shape = pentagon ]; + "node3" [ label = "Kokkos::kokkosalgorithms", shape = doubleoctagon ]; + "node4" [ label = "Kokkos::kokkoscore", shape = doubleoctagon ]; + "node5" [ label = "OpenMP::OpenMP_CXX", shape = pentagon ]; + "node6" [ label = "/usr/lib64/gcc/x86_64-suse-linux/13/libgomp.so", shape = septagon ]; + "node5" -> "node6" [ style = dashed ] // OpenMP::OpenMP_CXX -> /usr/lib64/gcc/x86_64-suse-linux/13/libgomp.so + "node7" [ label = "/usr/lib64/libpthread.a", shape = septagon ]; + "node5" -> "node7" [ style = dashed ] // OpenMP::OpenMP_CXX -> /usr/lib64/libpthread.a + "node4" -> "node5" [ style = dashed ] // Kokkos::kokkoscore -> OpenMP::OpenMP_CXX + "node8" [ label = "dl", shape = septagon ]; + "node4" -> "node8" [ style = dashed ] // Kokkos::kokkoscore -> dl + "node3" -> "node4" [ style = dashed ] // Kokkos::kokkosalgorithms -> Kokkos::kokkoscore + "node2" -> "node3" [ style = dashed ] // Kokkos::kokkos -> Kokkos::kokkosalgorithms + "node9" [ label = "Kokkos::kokkoscontainers", shape = doubleoctagon ]; + "node9" -> "node4" [ style = dashed ] // Kokkos::kokkoscontainers -> Kokkos::kokkoscore + "node2" -> "node9" [ style = dashed ] // Kokkos::kokkos -> Kokkos::kokkoscontainers + "node2" -> "node4" [ style = dashed ] // Kokkos::kokkos -> Kokkos::kokkoscore + "node10" [ label = "Kokkos::kokkossimd", shape = doubleoctagon ]; + "node2" -> "node10" [ style = dashed ] // Kokkos::kokkos -> Kokkos::kokkossimd + "node1" -> "node2" [ style = dashed ] // Kokkos::kokkoskernels -> Kokkos::kokkos + "node0" -> "node1" [ style = dotted ] // pcms_field -> Kokkos::kokkoskernels + "node11" [ label = "Omega_h::omega_h", shape = doubleoctagon ]; + "node12" [ label = "MPI::MPI_CXX", shape = pentagon ]; + "node13" [ label = "/opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpi.so", shape = septagon ]; + "node12" -> "node13" [ style = dashed ] // MPI::MPI_CXX -> /opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpi.so + "node14" [ label = "/opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpicxx.so", shape = septagon ]; + "node12" -> "node14" [ style = dashed ] // MPI::MPI_CXX -> /opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpicxx.so + "node11" -> "node12" [ style = dashed ] // Omega_h::omega_h -> MPI::MPI_CXX + "node15" [ label = "Omega_h-Kokkos", shape = pentagon ]; + "node15" -> "node2" [ style = dashed ] // Omega_h-Kokkos -> Kokkos::kokkos + "node11" -> "node15" [ style = dashed ] // Omega_h::omega_h -> Omega_h-Kokkos + "node16" [ label = "Omega_h-ZLIB", shape = pentagon ]; + "node17" [ label = "ZLIB::ZLIB", shape = septagon ]; + "node16" -> "node17" [ style = dashed ] // Omega_h-ZLIB -> ZLIB::ZLIB + "node11" -> "node16" [ style = dashed ] // Omega_h::omega_h -> Omega_h-ZLIB + "node0" -> "node11" // pcms_field -> Omega_h::omega_h + "node18" [ label = "meshfields::meshfields", shape = doubleoctagon ]; + "node19" [ label = "Cabana::Core", shape = pentagon ]; + "node19" -> "node2" [ style = dashed ] // Cabana::Core -> Kokkos::kokkos + "node19" -> "node12" [ style = dashed ] // Cabana::Core -> MPI::MPI_CXX + "node18" -> "node19" [ style = dashed ] // meshfields::meshfields -> Cabana::Core + "node18" -> "node2" [ style = dashed ] // meshfields::meshfields -> Kokkos::kokkos + "node18" -> "node11" [ style = dashed ] // meshfields::meshfields -> Omega_h::omega_h + "node0" -> "node18" // pcms_field -> meshfields::meshfields + "node20" [ label = "mfem", shape = doubleoctagon ]; + "node21" [ label = "-Wl,-rpath -Wl,/opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib", shape = septagon ]; + "node20" -> "node21" [ style = dashed ] // mfem -> -Wl,-rpath -Wl,/opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib + "node22" [ label = "/opt/software/linux-x86_64_v3/hypre-3.2.0-bqpag5omddy4brurswolc4ulqg66mikx/lib64/libHYPRE.so", shape = septagon ]; + "node20" -> "node22" [ style = dashed ] // mfem -> /opt/software/linux-x86_64_v3/hypre-3.2.0-bqpag5omddy4brurswolc4ulqg66mikx/lib64/libHYPRE.so + "node23" [ label = "/opt/software/linux-x86_64_v3/metis-5.1.0-cvgy73kn3vhq4m4wgetebgwjsblfxz77/lib/libmetis.so", shape = septagon ]; + "node20" -> "node23" [ style = dashed ] // mfem -> /opt/software/linux-x86_64_v3/metis-5.1.0-cvgy73kn3vhq4m4wgetebgwjsblfxz77/lib/libmetis.so + "node20" -> "node13" [ style = dashed ] // mfem -> /opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpi.so + "node20" -> "node14" [ style = dashed ] // mfem -> /opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpicxx.so + "node24" [ label = "/opt/software/linux-x86_64_v3/zlib-ng-2.3.3-ihl2h74e3fqqrg5j3f7jvxiezcnkhiq4/lib/libz.so", shape = septagon ]; + "node20" -> "node24" [ style = dashed ] // mfem -> /opt/software/linux-x86_64_v3/zlib-ng-2.3.3-ihl2h74e3fqqrg5j3f7jvxiezcnkhiq4/lib/libz.so + "node0" -> "node20" // pcms_field -> mfem + "node25" [ label = "pcms_discretization\n(pcms::discretization)", shape = doubleoctagon ]; + "node25" -> "node2" // pcms_discretization -> Kokkos::kokkos + "node25" -> "node11" [ style = dotted ] // pcms_discretization -> Omega_h::omega_h + "node26" [ label = "pcms_utility\n(pcms::utility)", shape = doubleoctagon ]; + "node26" -> "node2" // pcms_utility -> Kokkos::kokkos + "node26" -> "node11" // pcms_utility -> Omega_h::omega_h + "node27" [ label = "perfstubs", shape = doubleoctagon ]; + "node27" -> "node8" [ style = dashed ] // perfstubs -> dl + "node28" [ label = "m", shape = septagon ]; + "node27" -> "node28" [ style = dashed ] // perfstubs -> m + "node26" -> "node27" // pcms_utility -> perfstubs + "node25" -> "node26" // pcms_discretization -> pcms_utility + "node0" -> "node25" // pcms_field -> pcms_discretization + "node29" [ label = "pcms_localization\n(pcms::localization)", shape = doubleoctagon ]; + "node29" -> "node2" // pcms_localization -> Kokkos::kokkos + "node29" -> "node11" // pcms_localization -> Omega_h::omega_h + "node29" -> "node25" // pcms_localization -> pcms_discretization + "node29" -> "node26" // pcms_localization -> pcms_utility + "node0" -> "node29" // pcms_field -> pcms_localization + "node0" -> "node26" // pcms_field -> pcms_utility + "node30" [ label = "pcms_transfer\n(pcms::transfer)", shape = doubleoctagon ]; + "node30" -> "node11" // pcms_transfer -> Omega_h::omega_h + "node31" [ label = "PETSc::PETSc", shape = pentagon ]; + "node32" [ label = "petsc", shape = septagon ]; + "node31" -> "node32" [ style = dashed ] // PETSc::PETSc -> petsc + "node30" -> "node31" [ style = dotted ] // pcms_transfer -> PETSc::PETSc + "node30" -> "node18" [ style = dotted ] // pcms_transfer -> meshfields::meshfields + "node33" [ label = "pcms_core\n(pcms::core)", shape = doubleoctagon ]; + "node33" -> "node2" // pcms_core -> Kokkos::kokkos + "node33" -> "node12" // pcms_core -> MPI::MPI_CXX + "node34" [ label = "pcms_coupler\n(pcms::coupler)", shape = doubleoctagon ]; + "node34" -> "node2" // pcms_coupler -> Kokkos::kokkos + "node34" -> "node12" // pcms_coupler -> MPI::MPI_CXX + "node34" -> "node11" // pcms_coupler -> Omega_h::omega_h + "node34" -> "node18" // pcms_coupler -> meshfields::meshfields + "node34" -> "node0" // pcms_coupler -> pcms_field + "node34" -> "node26" // pcms_coupler -> pcms_utility + "node34" -> "node27" // pcms_coupler -> perfstubs + "node35" [ label = "redev::redev", shape = doubleoctagon ]; + "node36" [ label = "MPI::MPI_C", shape = pentagon ]; + "node36" -> "node13" [ style = dashed ] // MPI::MPI_C -> /opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpi.so + "node35" -> "node36" [ style = dashed ] // redev::redev -> MPI::MPI_C + "node37" [ label = "adios2::cxx11_mpi", shape = pentagon ]; + "node38" [ label = "adios2::cxx_mpi", shape = doubleoctagon ]; + "node38" -> "node12" [ style = dashed ] // adios2::cxx_mpi -> MPI::MPI_CXX + "node39" [ label = "adios2::cxx", shape = doubleoctagon ]; + "node38" -> "node39" [ style = dashed ] // adios2::cxx_mpi -> adios2::cxx + "node37" -> "node38" [ style = dashed ] // adios2::cxx11_mpi -> adios2::cxx_mpi + "node35" -> "node37" [ style = dashed ] // redev::redev -> adios2::cxx11_mpi + "node35" -> "node27" [ style = dashed ] // redev::redev -> perfstubs + "node34" -> "node35" // pcms_coupler -> redev::redev + "node33" -> "node34" // pcms_core -> pcms_coupler + "node33" -> "node0" // pcms_core -> pcms_field + "node33" -> "node29" // pcms_core -> pcms_localization + "node33" -> "node26" // pcms_core -> pcms_utility + "node33" -> "node27" // pcms_core -> perfstubs + "node33" -> "node35" // pcms_core -> redev::redev + "node30" -> "node33" // pcms_transfer -> pcms_core + "node30" -> "node0" // pcms_transfer -> pcms_field + "node30" -> "node29" // pcms_transfer -> pcms_localization + "node40" [ label = "pcms", shape = tripleoctagon ]; + "node40" -> "node2" [ style = dotted ] // pcms -> Kokkos::kokkos + "node40" -> "node36" [ style = dotted ] // pcms -> MPI::MPI_C + "node40" -> "node31" [ style = dotted ] // pcms -> PETSc::PETSc + "node41" [ label = "Python::Module", shape = pentagon ]; + "node40" -> "node41" [ style = dotted ] // pcms -> Python::Module + "node40" -> "node18" [ style = dotted ] // pcms -> meshfields::meshfields + "node40" -> "node33" [ style = dotted ] // pcms -> pcms_core + "node40" -> "node30" [ style = dotted ] // pcms -> pcms_transfer + "node42" [ label = "pybind11::headers", shape = pentagon ]; + "node43" [ label = "pybind11::pybind11_headers", shape = pentagon ]; + "node42" -> "node43" [ style = dashed ] // pybind11::headers -> pybind11::pybind11_headers + "node40" -> "node42" [ style = dotted ] // pcms -> pybind11::headers + "node44" [ label = "pybind11::module", shape = pentagon ]; + "node44" -> "node41" [ style = dashed ] // pybind11::module -> Python::Module + "node45" [ label = "pybind11::pybind11", shape = pentagon ]; + "node45" -> "node42" [ style = dashed ] // pybind11::pybind11 -> pybind11::headers + "node46" [ label = "pybind11::python_headers", shape = pentagon ]; + "node45" -> "node46" [ style = dashed ] // pybind11::pybind11 -> pybind11::python_headers + "node44" -> "node45" [ style = dashed ] // pybind11::module -> pybind11::pybind11 + "node40" -> "node44" [ style = dotted ] // pcms -> pybind11::module + "node47" [ label = "pcms_capi\n(pcms::capi)", shape = pentagon ]; + "node48" [ label = "pcms_capi_core\n(pcms::capi::core)", shape = doubleoctagon ]; + "node48" -> "node36" // pcms_capi_core -> MPI::MPI_C + "node48" -> "node33" [ style = dotted ] // pcms_capi_core -> pcms_core + "node47" -> "node48" [ style = dashed ] // pcms_capi -> pcms_capi_core + "node49" [ label = "pcms_capi_transfer\n(pcms::capi::transfer)", shape = doubleoctagon ]; + "node49" -> "node36" // pcms_capi_transfer -> MPI::MPI_C + "node49" -> "node30" [ style = dotted ] // pcms_capi_transfer -> pcms_transfer + "node47" -> "node49" [ style = dashed ] // pcms_capi -> pcms_capi_transfer + "node50" [ label = "pcms_fortranapi\n(pcms::fortranapi)", shape = pentagon ]; + "node51" [ label = "pcms_fortranapi_core\n(pcms::fortranapi::core)", shape = doubleoctagon ]; + "node51" -> "node2" // pcms_fortranapi_core -> Kokkos::kokkos + "node51" -> "node48" [ style = dotted ] // pcms_fortranapi_core -> pcms_capi_core + "node50" -> "node51" [ style = dashed ] // pcms_fortranapi -> pcms_fortranapi_core + "node52" [ label = "pcms_fortranapi_transfer\n(pcms::fortranapi::transfer)", shape = doubleoctagon ]; + "node52" -> "node2" // pcms_fortranapi_transfer -> Kokkos::kokkos + "node52" -> "node49" [ style = dotted ] // pcms_fortranapi_transfer -> pcms_capi_transfer + "node50" -> "node52" [ style = dashed ] // pcms_fortranapi -> pcms_fortranapi_transfer + "node53" [ label = "pcms_pcms", shape = pentagon ]; + "node53" -> "node47" [ style = dashed ] // pcms_pcms -> pcms_capi + "node53" -> "node33" [ style = dashed ] // pcms_pcms -> pcms_core + "node53" -> "node50" [ style = dashed ] // pcms_pcms -> pcms_fortranapi + "node53" -> "node30" [ style = dashed ] // pcms_pcms -> pcms_transfer + "node54" [ label = "pcms_transient\n(pcms::transient)", shape = doubleoctagon ]; + "node54" -> "node26" // pcms_transient -> pcms_utility + "node53" -> "node54" [ style = dashed ] // pcms_pcms -> pcms_transient + "node55" [ label = "MPI::MPI_Fortran", shape = pentagon ]; + "node55" -> "node13" [ style = dashed ] // MPI::MPI_Fortran -> /opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpi.so + "node56" [ label = "/opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpifort.so", shape = septagon ]; + "node55" -> "node56" [ style = dashed ] // MPI::MPI_Fortran -> /opt/software/linux-x86_64_v3/mpich-5.0.2-d2527v4agb4p5odc43zhqsyuwprgiczd/lib/libmpifort.so +} diff --git a/tools/reorg/header-map.txt b/tools/reorg/header-map.txt new file mode 100644 index 000000000..9c3549578 --- /dev/null +++ b/tools/reorg/header-map.txt @@ -0,0 +1,103 @@ +# PCMS 0.3 -> 0.4 header map, used by tools/migrate-pcms.sh. +# Format: [private] +# "private" means the header is no longer installed: code outside PCMS must +# use the public API instead (usually the factories in pcms/field/function_spaces.hpp, +# pcms/discretization/discretization.hpp, pcms/transfer/projection.hpp or a +# backend header pcms/backends//.hpp); see MIGRATION.md. +# A "-" as new path means the header was removed. +pcms.h pcms/pcms.hpp +pcms/configuration.h pcms/configuration.hpp +pcms/coupler/coupler_types.h pcms/coupler/coupler_types.hpp +pcms/coupler/field_communicator.hpp pcms/coupler/detail/field_communicator.hpp +pcms/coupler/field_exchange_planner.h pcms/coupler/detail/field_exchange_planner.hpp +pcms/coupler/field_layout_communicator.h pcms/coupler/detail/field_layout_communicator.hpp +pcms/coupler/field_serializer.h pcms/coupler/detail/field_serializer.hpp +pcms/coupler/global_communicator.h pcms/coupler/detail/global_communicator.hpp +pcms/coupler/overlap_mask.h pcms/coupler/overlap_mask.hpp +pcms/coupler/partition.h pcms/coupler/partition.hpp private +pcms/discretization/discretization.h pcms/discretization/discretization.hpp +pcms/discretization/discretization/empty.hpp pcms/discretization/empty.hpp private +pcms/discretization/discretization/omega_h.hpp pcms/backends/omega_h/discretization.hpp private +pcms/discretization/discretization/point_cloud.hpp pcms/backends/point_cloud/discretization.hpp private +pcms/discretization/discretization/uniform_grid.hpp pcms/backends/uniform_grid/discretization.hpp private +pcms/discretization/discretization/xgc.hpp pcms/backends/xgc/discretization.hpp private +pcms/discretization/discretization/xgc_reverse_classification.h pcms/backends/xgc/reverse_classification.hpp +pcms/field/coordinate_system.hpp pcms/utility/coordinate_system.hpp +pcms/field/coordinate_systems/cartesian.hpp pcms/utility/coordinate_systems/cartesian.hpp +pcms/field/coordinate_systems/cylindrical.hpp pcms/utility/coordinate_systems/cylindrical.hpp +pcms/field/coordinate_view.hpp pcms/utility/coordinate_view.hpp +pcms/field/data/mesh_fields.h pcms/backends/omega_h_meshfields/field_data.hpp private +pcms/field/data/mfem.hpp pcms/backends/mfem/field_data.hpp private +pcms/field/data/point_cloud.h pcms/backends/point_cloud/field_data.hpp private +pcms/field/data/simple.h pcms/field/simple_field_data.hpp +pcms/field/data/xgc.h pcms/backends/xgc/field_data.hpp private +pcms/field/element_dispatch.h pcms/field/element_dispatch.hpp private +pcms/field/eqdsk_field.h pcms/field/eqdsk_field.hpp +pcms/field/evaluation_request.h pcms/field/evaluation_request.hpp +pcms/field/evaluator/mesh_fields.h pcms/backends/omega_h_meshfields/evaluator.hpp private +pcms/field/evaluator/mesh_fields_backend.h pcms/backends/omega_h_meshfields/evaluator_backend.hpp private +pcms/field/evaluator/mls_options.h pcms/localization/mls_options.hpp +pcms/field/evaluator/mls_point_cloud.h pcms/backends/point_cloud/mls_evaluator.hpp private +pcms/field/evaluator/omega_h_lagrange.h pcms/backends/omega_h/lagrange_evaluator.hpp private +pcms/field/evaluator/pcms_interpolator_aliases.hpp pcms/field/evaluator/interpolator_aliases.hpp private +pcms/field/evaluator/pcms_interpolator_logger.hpp pcms/field/evaluator/interpolator_logger.hpp private +pcms/field/evaluator/pcms_interpolator_view_utils.hpp pcms/field/evaluator/interpolator_view_utils.hpp private +pcms/field/evaluator/point_cloud.h pcms/backends/point_cloud/evaluator.hpp private +pcms/field/evaluator/spline_interpolator.hpp pcms/backends/uniform_grid/spline_interpolator.hpp private +pcms/field/evaluator/uniform_grid.h pcms/backends/uniform_grid/evaluator.hpp private +pcms/field/evaluator/uniform_grid_spline.h pcms/backends/uniform_grid/spline_evaluator.hpp private +pcms/field/field.h pcms/field/field.hpp +pcms/field/field_data.h pcms/field/field_data.hpp +pcms/field/field_evaluator_factory.h pcms/field/field_evaluator_factory.hpp private +pcms/field/field_factory.h pcms/field/field_factory.hpp +pcms/field/field_layout.h pcms/field/field_layout.hpp +pcms/field/function_space.h pcms/field/function_space.hpp +pcms/field/function_space/lagrange.h pcms/field/function_space/lagrange.hpp private +pcms/field/function_space/mfem.hpp pcms/backends/mfem/field_factory.hpp private +pcms/field/function_space/spline.h pcms/field/function_space/spline.hpp private +pcms/field/function_space/xgc.h pcms/backends/xgc/field_factory.hpp private +pcms/field/layout/empty.h pcms/field/layout/empty.hpp private +pcms/field/layout/mesh_fields.h pcms/backends/omega_h_meshfields/layout.hpp private +pcms/field/layout/mfem.hpp pcms/backends/mfem/layout.hpp private +pcms/field/layout/omega_h_entity.h pcms/backends/omega_h/entity_layout.hpp private +pcms/field/layout/omega_h_lagrange.h pcms/backends/omega_h/lagrange_layout.hpp private +pcms/field/layout/point_cloud.h pcms/backends/point_cloud/layout.hpp private +pcms/field/layout/uniform_grid.h pcms/backends/uniform_grid/layout.hpp private +pcms/field/layout/xgc.h pcms/backends/xgc/layout.hpp private +pcms/field/out_of_bounds_policy.h pcms/field/out_of_bounds_policy.hpp +pcms/field/point_evaluator.h pcms/field/point_evaluator.hpp +pcms/field/uniform_grid_binary_field.h pcms/backends/omega_h/uniform_grid_binary_field.hpp private +pcms/localization/adj_search.hpp pcms/backends/omega_h/adj_search.hpp private +pcms/localization/localization_factory.h pcms/localization/localization_factory.hpp private +pcms/localization/localization_path_selection.h pcms/field/localization_path_selection.hpp private +pcms/localization/mesh_localization.h pcms/localization/mesh_localization.hpp private +pcms/localization/mls_support_helpers.h pcms/localization/mls_support_helpers.hpp private +pcms/localization/point_cloud_localization.h pcms/backends/point_cloud/localization.hpp private +pcms/localization/point_search.h pcms/localization/point_search.hpp private +pcms/localization/queue_visited.hpp pcms/backends/omega_h/queue_visited.hpp private +pcms/pythonapi/numpy_array_transform.h pcms/pythonapi/numpy_array_transform.hpp private +pcms/pythonapi/numpy_view.h pcms/pythonapi/numpy_view.hpp private +pcms/pythonapi/py_value_types.h pcms/pythonapi/py_value_types.hpp private +pcms/transfer/copy.h pcms/transfer/copy.hpp +pcms/transfer/interpolation_base.h pcms/transfer/interpolation_base.hpp private +pcms/transfer/interpolation_helpers.h pcms/transfer/interpolation_helpers.hpp private +pcms/transfer/interpolator.h pcms/transfer/interpolator.hpp +pcms/transfer/linear_interpolant.hpp pcms/backends/uniform_grid/linear_interpolant.hpp private +pcms/transfer/multidimarray.hpp pcms/backends/uniform_grid/multidimarray.hpp private +pcms/utility/array_mask.h pcms/utility/array_mask.hpp private +pcms/utility/arrays.h pcms/utility/arrays.hpp +pcms/utility/assert.h pcms/utility/assert.hpp +pcms/utility/bounding_box.h pcms/utility/bounding_box.hpp +pcms/utility/common.h pcms/utility/detail/common.hpp +pcms/utility/entity_types.h pcms/utility/entity_types.hpp +pcms/utility/eqdsk.h pcms/utility/eqdsk.hpp +pcms/utility/inclusive_scan.h pcms/utility/detail/inclusive_scan.hpp +pcms/utility/memory_spaces.h pcms/utility/memory_spaces.hpp +pcms/utility/mesh_geometry.h pcms/utility/mesh_geometry.hpp private +pcms/utility/mpi_type.h pcms/utility/mpi_type.hpp private +pcms/utility/omega_h_array_utils.h pcms/utility/omega_h_array_utils.hpp private +pcms/utility/print.h pcms/utility/print.hpp +pcms/utility/profile.h pcms/utility/detail/profile.hpp +pcms/utility/types.h pcms/utility/types.hpp +pcms/utility/uniform_grid.h pcms/utility/uniform_grid.hpp +pcms/version.h pcms/version.hpp diff --git a/tools/reorg/inventory.md b/tools/reorg/inventory.md new file mode 100644 index 000000000..1fa18c3a6 --- /dev/null +++ b/tools/reorg/inventory.md @@ -0,0 +1,373 @@ +# PCMS reorganization inventory (Phase 0) + +Baseline: `upstream/develop` c33f816c. Decisions referenced below are in +[`decisions.md`](decisions.md). + +## 1. Baseline build and test results + +Environment: container image derived from the PCMS dev image (Spack: GCC 13.3.1, +MPICH 5.0.2, Kokkos 4.7.04 (Serial+OpenMP), Omega_h 11.4.0-scorec, meshfields +main, PETSc 3.26.0, redev main, ADIOS2 2.12.1, MFEM 4.10.0, Python 3.14, +pybind11 3.0.4). `RelWithDebInfo`, `ctest -j1`. + +| Configuration | Options | Result | +|---|---|---| +| Minimal-static | `BUILD_SHARED_LIBS=OFF`, Omega_h on; meshfields, PETSc, MFEM, XGC, Python, C, Fortran, transient off | build OK, **187/187** tests pass | +| Full-shared | `BUILD_SHARED_LIBS=ON`, everything on (Omega_h, meshfields, PETSc, XGC, MFEM, C, Fortran, Python, transient, server, client) | build OK, **257/257** tests pass | +| Install | `cmake --install` of Full-shared; `examples/external-usage-example` built against the install tree | OK | +| Full-static | as Full-shared, `BUILD_SHARED_LIBS=OFF`, Python off | build OK, **257/257** tests pass | + +Limitation: the coupler cannot be disabled on develop (`redev` and `ADIOS2` are +`REQUIRED` at top level, `smoke_test` links `pcms::core`), so the "Minimal: no +coupler" configuration does not exist yet. It becomes buildable in Phase 2. + +## 2. Target dependency graph (before) + +Generated with `cmake --graphviz` on the Full-shared build (executables and +tests excluded); the raw file is [`deps-before.dot`](deps-before.dot). +Solid = PUBLIC, dotted = PRIVATE, dashed = INTERFACE. + +``` +pcms -> Kokkos::kokkos (private), MPI::MPI_C (private), PETSc::PETSc (private), Python::Module (private), meshfields::meshfields (private), pcms_core (private), pcms_transfer (private), pybind11::headers (private), pybind11::module (private) +pcms_capi -> pcms_capi_core (interface), pcms_capi_transfer (interface) +pcms_capi_core -> MPI::MPI_C, pcms_core (private) +pcms_capi_transfer -> MPI::MPI_C, pcms_transfer (private) +pcms_core -> Kokkos::kokkos, MPI::MPI_CXX, pcms_coupler, pcms_field, pcms_localization, pcms_utility, perfstubs, redev::redev +pcms_coupler -> Kokkos::kokkos, MPI::MPI_CXX, Omega_h::omega_h, meshfields::meshfields, pcms_field, pcms_utility, perfstubs, redev::redev +pcms_discretization -> Kokkos::kokkos, Omega_h::omega_h (private), pcms_utility +pcms_field -> Kokkos::kokkoskernels (private), Omega_h::omega_h, meshfields::meshfields, mfem, pcms_discretization, pcms_localization, pcms_utility +pcms_fortranapi -> pcms_fortranapi_core (interface), pcms_fortranapi_transfer (interface) +pcms_fortranapi_core -> Kokkos::kokkos, pcms_capi_core (private) +pcms_fortranapi_transfer -> Kokkos::kokkos, pcms_capi_transfer (private) +pcms_localization -> Kokkos::kokkos, Omega_h::omega_h, pcms_discretization, pcms_utility +pcms_pcms -> pcms_capi (interface), pcms_core (interface), pcms_fortranapi (interface), pcms_transfer (interface), pcms_transient (interface) +pcms_transfer -> Omega_h::omega_h, PETSc::PETSc (private), meshfields::meshfields (private), pcms_core, pcms_field, pcms_localization +pcms_transient -> pcms_utility +pcms_utility -> Kokkos::kokkos, Omega_h::omega_h, perfstubs +``` + +Layering problems visible in the graph: + +- `pcms_transfer` links `pcms_core` (= coupler + redev + ADIOS2). +- `pcms_coupler` links Omega_h and meshfields; `pcms_utility` links Omega_h. +- `pcms::core` is "coupler plus everything"; the C API's `capi_core` links it. + +## 2b. Target dependency graph after Phase 2 + +Raw file: [`deps-after-phase2.dot`](deps-after-phase2.dot) (Full configuration). + +``` +pcms -> Kokkos::kokkos (private), MPI::MPI_C (private), PETSc::PETSc (private), Python::Module (private), meshfields::meshfields (private), pcms_coupler (private), pcms_transfer (private), pybind11::headers (private), pybind11::module (private) +pcms_capi -> pcms_capi_core (interface), pcms_capi_transfer (interface) +pcms_capi_core -> MPI::MPI_C, pcms_coupler (private) +pcms_capi_transfer -> MPI::MPI_C, pcms_transfer (private) +pcms_core -> pcms_pcms (interface) +pcms_coupler -> Kokkos::kokkos, MPI::MPI_CXX, Omega_h::omega_h, meshfields::meshfields, pcms_field, pcms_utility, perfstubs, redev::redev +pcms_discretization -> Kokkos::kokkos, Omega_h::omega_h (private), pcms_utility +pcms_field -> Kokkos::kokkoskernels (private), Omega_h::omega_h, meshfields::meshfields, mfem, pcms_discretization, pcms_localization, pcms_utility +pcms_fortranapi -> pcms_fortranapi_core (interface), pcms_fortranapi_transfer (interface) +pcms_fortranapi_core -> Kokkos::kokkos, pcms_capi_core (private) +pcms_fortranapi_transfer -> Kokkos::kokkos, pcms_capi_transfer (private) +pcms_localization -> Kokkos::kokkos, Omega_h::omega_h, pcms_discretization, pcms_utility +pcms_pcms -> pcms_capi (interface), pcms_coupler (interface), pcms_discretization (interface), pcms_field (interface), pcms_fortranapi (interface), pcms_localization (interface), pcms_transfer (interface), pcms_transient (interface), pcms_utility (interface) +pcms_transfer -> Omega_h::omega_h, PETSc::PETSc (private), meshfields::meshfields (private), pcms_field, pcms_localization +pcms_transient -> pcms_utility +pcms_utility -> Kokkos::kokkos, Omega_h::omega_h, perfstubs +``` + +Changes: + +- `pcms_transfer` no longer links `pcms_core`; transfer and everything below + it is free of redev and ADIOS2. +- `pcms::core` is a deprecated interface alias of `pcms::pcms`; `pcms::pcms` + links every library that was built. +- `pcms::localization` does not use any field header: the coordinate types moved + to utility, the field-layout adapters moved to field. +- `PCMS_ENABLE_COUPLER=OFF` builds without redev and ADIOS2 (no + `pcms_coupler`, `pcms_capi_core`, `pcms_fortranapi_core`). Minimal + configuration (static, coupler off): 172/172 tests pass. + +Remaining in the graph, handled in later phases: `pcms_utility` and +`pcms_localization` link Omega_h publicly (Phases 3, 5, 6); +`pcms_coupler` links Omega_h and meshfields publicly (Phase 5). + +## 2c. Target dependency graph at the end of the reorganization + +Raw file: [`deps-after.dot`](deps-after.dot) (Full configuration, shared). + +``` +pcms -> Kokkos::kokkos (private), MPI::MPI_C (private), PETSc::PETSc (private), Python::Module (private), meshfields::meshfields (private), pcms_coupler (private), pcms_transfer (private), pybind11::headers (private), pybind11::module (private) +pcms_capi -> pcms_capi_core (interface), pcms_capi_transfer (interface) +pcms_capi_core -> MPI::MPI_C, pcms_coupler (private) +pcms_capi_transfer -> MPI::MPI_C, pcms_transfer (private) +pcms_core -> pcms_pcms (interface) +pcms_coupler -> Kokkos::kokkos, MPI::MPI_CXX, Omega_h::omega_h, meshfields::meshfields (private), pcms_field, pcms_utility, perfstubs, redev::redev +pcms_discretization -> Kokkos::kokkos, Omega_h::omega_h (private), pcms_utility +pcms_field -> Kokkos::kokkoskernels (private), Omega_h::omega_h, meshfields::meshfields (private), mfem, pcms_discretization, pcms_localization, pcms_utility +pcms_fortranapi -> pcms_fortranapi_core (interface), pcms_fortranapi_transfer (interface) +pcms_fortranapi_core -> Kokkos::kokkos, pcms_capi_core (private) +pcms_fortranapi_transfer -> Kokkos::kokkos, pcms_capi_transfer (private) +pcms_localization -> Kokkos::kokkos, Omega_h::omega_h, pcms_discretization, pcms_utility +pcms_pcms -> pcms_capi (interface), pcms_coupler (interface), pcms_discretization (interface), pcms_field (interface), pcms_fortranapi (interface), pcms_localization (interface), pcms_transfer (interface), pcms_transient (interface), pcms_utility (interface) +pcms_public_header_check -> mfem (private), pcms_pcms (private) +pcms_transfer -> Omega_h::omega_h, PETSc::PETSc (private), meshfields::meshfields (private), pcms_field, pcms_localization +pcms_transient -> pcms_utility +pcms_utility -> Kokkos::kokkos, Omega_h::omega_h, perfstubs +``` + +Changes since 2b: `pcms_coupler` and `pcms_field` link MeshFields +privately (Phase 5). Omega_h stays a public dependency of `pcms_utility`, +`pcms_localization`, `pcms_field`, `pcms_transfer` and `pcms_coupler`: +the Omega_h and XGC backend headers are public and compiled into those +targets, and Omega_h is still a required dependency. No core public header +includes Omega_h (checked by `tools/check-public-includes.py`). +`pcms_public_header_check` is the test target of +`test/public_headers/`. + +### Final public headers (57 files under `include/pcms/`, plus the generated `pcms/version.hpp` and `pcms/configuration.hpp`) + +- `(top level)`: `pcms.hpp` +- `backends/mfem`: `mfem.hpp` +- `backends/omega_h`: `omega_h.hpp` +- `backends/xgc`: `reverse_classification.hpp`, `xgc.hpp` +- `capi`: `client.h`, `interpolator.h`, `kokkos.h`, `mesh.h` +- `coupler`: `coupler.hpp`, `coupler_types.hpp`, `overlap_mask.hpp` +- `coupler/detail`: `field_communicator.hpp`, `field_exchange_planner.hpp`, `field_layout_communicator.hpp`, `field_serializer.hpp`, `global_communicator.hpp` +- `discretization`: `discretization.hpp` +- `field`: `coordinate_map.hpp`, `eqdsk_field.hpp`, `evaluation_request.hpp`, `field.hpp`, `field_data.hpp`, `field_factory.hpp`, `field_layout.hpp`, `function_space.hpp`, `function_spaces.hpp`, `out_of_bounds_policy.hpp`, `point_evaluator.hpp`, `point_evaluator_factory.hpp`, `simple_field_data.hpp`, `transformed_source.hpp`, `value_view.hpp` +- `localization`: `mls_options.hpp` +- `transfer`: `copy.hpp`, `interpolator.hpp`, `mass_matrix_type.hpp`, `monte_carlo_sampling.hpp`, `projection.hpp`, `transfer_operator.hpp` +- `transient`: `timestepper.hpp` +- `utility`: `arrays.hpp`, `assert.hpp`, `bounding_box.hpp`, `coordinate_system.hpp`, `coordinate_view.hpp`, `entity_types.hpp`, `eqdsk.hpp`, `memory_spaces.hpp`, `print.hpp`, `types.hpp`, `uniform_grid.hpp` +- `utility/coordinate_systems`: `cartesian.hpp`, `cylindrical.hpp` +- `utility/detail`: `common.hpp`, `inclusive_scan.hpp`, `profile.hpp` + +## 3. Installed files + +127 files under `include/pcms` (122 headers, 5 files of +`external/flibhpc`: `LICENSE`, `README.md`, `mpi.i`, `openacc.i`, `thrust.i`), +plus `lib64/cmake/pcms/FindPETSc.cmake`. Every C++ header in `src/pcms` +(outside the Python and Fortran bindings) is installed except +`localization/localization_path_selection.h`. The per-header list with +backend includes and the proposed classification is in section 5. + +Headers that include a backend library directly: **44**. Headers that reach +one only through other PCMS headers: **50**, almost all through +`utility/arrays.h` → ``. Removing that one include +(`MakeConstRank2View(Omega_h::Read, int)` moves to the Omega_h backend) +removes Omega_h from the transitive closure of most headers. + +## 4. Omega_h types in public signatures + +All installed headers using `Omega_h::` are listed in section 5 (column +"Backend includes"). Under the proposed classification, only these +declarations remain in headers that stay installed: + +| Header | Line | Declaration | +|---|---|---| +| `pcms/coupler/overlap_mask.h` | 42 | `OverlapMask(size_t size, Omega_h::HostRead is_overlap_host)` | +| `pcms/coupler/overlap_mask.h` | 51 | `OverlapMask(size_t size, Omega_h::Read is_overlap_device)` | +| `pcms/discretization/discretization/xgc_reverse_classification.h` | 111 | `template ` | +| `pcms/discretization/discretization/xgc_reverse_classification.h` | 113 | `Omega_h::Mesh& mesh, std::string numbering = "simNumbering",` | +| `pcms/discretization/discretization/xgc_reverse_classification.h` | 116 | `auto class_ids_h = Omega_h::HostRead(` | +| `pcms/discretization/discretization/xgc_reverse_classification.h` | 120 | `auto vert_id = Omega_h::HostRead(mesh.get_array(0, numbering));` | +| `pcms/utility/arrays.h` | 248 | `auto MakeConstRank2View(Omega_h::Read array, int dim)` | +| `pcms/utility/uniform_grid.h` | 36 | `ClosestCellID(const Omega_h::Vector& point) const` | +| `pcms/utility/uniform_grid.h` | 178 | `UniformGrid CreateUniformGridFromMesh(Omega_h::Mesh& mesh,` | +| `pcms/utility/uniform_grid.h` | 182 | `auto bbox = Omega_h::get_bounding_box(&mesh);` | +| `pcms/utility/uniform_grid.h` | 212 | `UniformGrid CreateUniformGridFromMesh(Omega_h::Mesh& mesh,` | + +Handling: + +- `OverlapMask`: add a constructor from a pcms `Rank1View`; the Omega_h + constructors become free functions in the Omega_h backend header. +- `xgc_reverse_classification.h`: `ConstructRCFromOmegaHMesh` moves to an + Omega_h+XGC bridge header; the rest has no Omega_h. +- `MakeConstRank2View(Omega_h::Read, int)`: moves to the Omega_h backend. +- `UniformGrid::ClosestCellID(Omega_h::Vector)`: takes the new pcms + fixed-size vector type (Phase 6). `CreateUniformGridFromMesh(Omega_h::Mesh&)` + moves to the Omega_h backend. + +The other uses of `Omega_h::` (188 declaration lines in 30 headers) are in +headers proposed as private. + +## 5. Proposed header classification + +- **public**: `include/pcms//`, no backend library includes. +- **backend public**: `include/pcms/backends//`, may include its library. +- **installed-detail**: `include/pcms//detail/`, required by public + templates. +- **private**: stays under `src/` (or moves to `src/pcms/backends//`), + not installed. In-tree targets and tests may still include it. + +New public headers created for the factories (see `decisions.md`): +`include/pcms/backends/omega_h/omega_h.hpp`, `include/pcms/backends/mfem/mfem.hpp`, +`include/pcms/backends/xgc/xgc.hpp`, plus the space and projection factory +declarations in `include/pcms/field/` and `include/pcms/transfer/`. + +| Class | Count | +|---|---| +| public | 43 | +| backend public | 1 | +| installed-detail | 8 | +| private | 70 | + +| Current installed header | Class | Proposed location | Backend includes (direct / via) | Notes | +|---|---|---|---|---| +| `pcms/capi/client.h` | public | `include/pcms/capi/client.h` | – / – | C API, stays .h | +| `pcms/capi/interpolator.h` | public | `include/pcms/capi/interpolator.h` | – / – | C API, stays .h | +| `pcms/capi/kokkos.h` | public | `include/pcms/capi/kokkos.h` | – / – | C API, stays .h | +| `pcms/capi/mesh.h` | public | `include/pcms/capi/mesh.h` | – / – | C API, stays .h | +| `pcms/configuration.h` | public | `include/pcms/configuration.hpp` | – / – | generated | +| `pcms/coupler/coupler.hpp` | public | `include/pcms/coupler/coupler.hpp` | – / Omega_h/redev | ApplicationComm, handles; includes the communicator templates below (redev) | +| `pcms/coupler/coupler_types.h` | public | `include/pcms/coupler/coupler_types.hpp` | redev / – | Mode becomes a pcms enum | +| `pcms/coupler/field_communicator.hpp` | installed-detail | `include/pcms/coupler/detail/field_communicator.hpp` | redev / Omega_h | template used by coupler.hpp; uses redev (see open question) | +| `pcms/coupler/field_exchange_planner.h` | installed-detail | `include/pcms/coupler/detail/field_exchange_planner.hpp` | redev / Omega_h | used by coupler.hpp; redev | +| `pcms/coupler/field_layout_communicator.h` | installed-detail | `include/pcms/coupler/detail/field_layout_communicator.hpp` | redev / Omega_h | used by coupler.hpp; redev | +| `pcms/coupler/field_serializer.h` | installed-detail | `include/pcms/coupler/detail/field_serializer.hpp` | – / Omega_h | used by coupler.hpp | +| `pcms/coupler/global_communicator.h` | installed-detail | `include/pcms/coupler/detail/global_communicator.hpp` | redev / – | used by coupler.hpp; redev | +| `pcms/coupler/overlap_mask.h` | public | `include/pcms/coupler/overlap_mask.hpp` | Omega_h / – | argument of ApplicationComm::SetLayoutOverlapMask; Omega_h ctors move to backend | +| `pcms/coupler/partition.h` | private | `src/pcms/coupler/partition.hpp` | redev / – | internal | +| `pcms/discretization/discretization.h` | public | `include/pcms/discretization/discretization.hpp` | – / Omega_h | interface + new Create*Discretization factories | +| `pcms/discretization/discretization/empty.hpp` | private | `src/pcms/discretization/empty.hpp` | – / Omega_h | impl; factory CreateEmptyDiscretization | +| `pcms/discretization/discretization/omega_h.hpp` | private | `src/pcms/backends/omega_h/discretization.hpp` | Omega_h / – | impl; factory backend::omega_h::CreateDiscretization | +| `pcms/discretization/discretization/point_cloud.hpp` | private | `src/pcms/backends/point_cloud/discretization.hpp` | – / Omega_h | impl; factory CreatePointCloudDiscretization | +| `pcms/discretization/discretization/uniform_grid.hpp` | private | `src/pcms/backends/uniform_grid/discretization.hpp` | – / Omega_h | impl; factory CreateUniformGridDiscretization | +| `pcms/discretization/discretization/xgc.hpp` | private | `src/pcms/backends/xgc/discretization.hpp` | – / Omega_h | impl | +| `pcms/discretization/discretization/xgc_reverse_classification.h` | backend public | `include/pcms/backends/xgc/reverse_classification.hpp` | Omega_h / – | ReverseClassificationVertex is an XGC input (C API); ConstructRCFromOmegaHMesh moves to an omega_h+xgc bridge | +| `pcms/field/coordinate_map.hpp` | public | `include/pcms/field/coordinate_map.hpp` | – / Omega_h | | +| `pcms/field/coordinate_system.hpp` | public | `include/pcms/field/coordinate_system.hpp` | – / – | | +| `pcms/field/coordinate_systems/cartesian.hpp` | public | `include/pcms/field/coordinate_systems/cartesian.hpp` | – / – | | +| `pcms/field/coordinate_systems/cylindrical.hpp` | public | `include/pcms/field/coordinate_systems/cylindrical.hpp` | – / – | | +| `pcms/field/coordinate_view.hpp` | public | `include/pcms/field/coordinate_view.hpp` | – / Omega_h | | +| `pcms/field/data/mesh_fields.h` | private | `src/pcms/backends/meshfields/field_data.hpp` | – / Omega_h/meshfields | | +| `pcms/field/data/mfem.hpp` | private | `src/pcms/backends/mfem/field_data.hpp` | MFEM / Omega_h | | +| `pcms/field/data/point_cloud.h` | private | `src/pcms/backends/point_cloud/field_data.hpp` | – / Omega_h | | +| `pcms/field/data/simple.h` | public | `include/pcms/field/simple_field_data.hpp` | – / Omega_h | generic FieldData over user views; used by C API and tests to wrap user arrays (question: public or replace with a factory) | +| `pcms/field/data/xgc.h` | private | `src/pcms/backends/xgc/field_data.hpp` | – / Omega_h | replaced by backend::xgc::CreateField | +| `pcms/field/element_dispatch.h` | private | `src/pcms/field/element_dispatch.hpp` | – / – | | +| `pcms/field/eqdsk_field.h` | public | `include/pcms/field/eqdsk_field.hpp` | – / Omega_h | MakeEQDSKField; struct member becomes shared_ptr | +| `pcms/field/evaluation_request.h` | public | `include/pcms/field/evaluation_request.hpp` | – / Omega_h | | +| `pcms/field/evaluator/mesh_fields.h` | private | `src/pcms/backends/meshfields/evaluator.hpp` | – / Omega_h/meshfields | | +| `pcms/field/evaluator/mesh_fields_backend.h` | private | `src/pcms/backends/omega_h_meshfields/evaluator_backend.hpp` | meshfields / Omega_h | needs Omega_h + meshfields: bridge | +| `pcms/field/evaluator/mls_interpolation.hpp` | private | `src/pcms/field/evaluator/mls_interpolation.hpp` | Omega_h / – | RadialBasisFunction enum moves to mls_options | +| `pcms/field/evaluator/mls_interpolation_impl.hpp` | private | `src/pcms/field/evaluator/mls_interpolation_impl.hpp` | Omega_h / – | | +| `pcms/field/evaluator/mls_options.h` | public | `include/pcms/field/mls_options.hpp` | – / Omega_h | options for polynomial reconstruction (Python binds it); stop including mls_interpolation.hpp | +| `pcms/field/evaluator/mls_point_cloud.h` | private | `src/pcms/backends/point_cloud/mls_evaluator.hpp` | Omega_h / – | | +| `pcms/field/evaluator/omega_h_lagrange.h` | private | `src/pcms/backends/omega_h/lagrange_evaluator.hpp` | Omega_h / – | | +| `pcms/field/evaluator/pcms_interpolator_aliases.hpp` | private | `src/pcms/field/evaluator/interpolator_aliases.hpp` | – / Omega_h | stutter dropped (Phase 4) | +| `pcms/field/evaluator/pcms_interpolator_logger.hpp` | private | `src/pcms/field/evaluator/interpolator_logger.hpp` | – / Omega_h | stutter dropped (Phase 4) | +| `pcms/field/evaluator/pcms_interpolator_view_utils.hpp` | private | `src/pcms/field/evaluator/interpolator_view_utils.hpp` | Omega_h / – | stutter dropped (Phase 4) | +| `pcms/field/evaluator/point_cloud.h` | private | `src/pcms/backends/point_cloud/evaluator.hpp` | Omega_h / – | | +| `pcms/field/evaluator/spline_interpolator.hpp` | private | `src/pcms/backends/uniform_grid/spline_interpolator.hpp` | – / Omega_h | installed on purpose in an earlier PR ("install spline_interpolator.hpp"); question: any external user? | +| `pcms/field/evaluator/uniform_grid.h` | private | `src/pcms/backends/uniform_grid/evaluator.hpp` | – / Omega_h | | +| `pcms/field/evaluator/uniform_grid_spline.h` | private | `src/pcms/backends/uniform_grid/spline_evaluator.hpp` | – / Omega_h | | +| `pcms/field/field.h` | public | `include/pcms/field/field.hpp` | – / Omega_h | | +| `pcms/field/field_data.h` | public | `include/pcms/field/field_data.hpp` | – / Omega_h | FieldData / DOFAccess interfaces | +| `pcms/field/field_evaluator_factory.h` | private | `src/pcms/field/field_evaluator_factory.hpp` | – / Omega_h | internal evaluator-factory interface (expert access kept internal) | +| `pcms/field/field_factory.h` | public | `include/pcms/field/field_factory.hpp` | – / Omega_h | interface; XGC/MFEM adapters are FieldFactory, not FunctionSpace | +| `pcms/field/field_layout.h` | public | `include/pcms/field/field_layout.hpp` | – / Omega_h | | +| `pcms/field/function_space.h` | public | `include/pcms/field/function_space.hpp` | – / Omega_h | interface + new space factories (or a sibling function_spaces.hpp) | +| `pcms/field/function_space/lagrange.h` | private | `src/pcms/field/function_space/lagrange.hpp` | Omega_h / – | impl; factory CreateLagrangeSpace | +| `pcms/field/function_space/mfem.hpp` | private | `src/pcms/backends/mfem/field_factory.hpp` | MFEM / Omega_h | impl; factory backend::mfem::CreateFieldFactory | +| `pcms/field/function_space/polynomial_reconstruction.hpp` | private | `src/pcms/field/function_space/polynomial_reconstruction.hpp` | Omega_h / – | impl; factory CreatePolynomialReconstructionSpace | +| `pcms/field/function_space/spline.h` | private | `src/pcms/field/function_space/spline.hpp` | – / Omega_h | impl; factory CreateSplineSpace | +| `pcms/field/function_space/xgc.h` | private | `src/pcms/backends/xgc/field_factory.hpp` | – / Omega_h | impl; factory backend::xgc::CreateFieldFactory | +| `pcms/field/gid_permutation.hpp` | private | `src/pcms/field/gid_permutation.hpp` | – / Omega_h | | +| `pcms/field/layout/empty.h` | private | `src/pcms/field/layout/empty.hpp` | – / Omega_h | impl; factory CreateEmptyLayout | +| `pcms/field/layout/mesh_fields.h` | private | `src/pcms/backends/omega_h_meshfields/layout.hpp` | Omega_h / – | Omega_h + meshfields | +| `pcms/field/layout/mfem.hpp` | private | `src/pcms/backends/mfem/layout.hpp` | MFEM / Omega_h | OverlapMaskFromAttribute becomes a backend free function | +| `pcms/field/layout/omega_h_entity.h` | private | `src/pcms/backends/omega_h/entity_layout.hpp` | Omega_h / – | | +| `pcms/field/layout/omega_h_lagrange.h` | private | `src/pcms/backends/omega_h/lagrange_layout.hpp` | Omega_h / – | | +| `pcms/field/layout/point_cloud.h` | private | `src/pcms/backends/point_cloud/layout.hpp` | – / Omega_h | | +| `pcms/field/layout/uniform_grid.h` | private | `src/pcms/backends/uniform_grid/layout.hpp` | – / Omega_h | | +| `pcms/field/layout/xgc.h` | private | `src/pcms/backends/xgc/layout.hpp` | – / Omega_h | | +| `pcms/field/out_of_bounds_policy.h` | public | `include/pcms/field/out_of_bounds_policy.hpp` | – / – | | +| `pcms/field/point_evaluator.h` | public | `include/pcms/field/point_evaluator.hpp` | – / Omega_h | | +| `pcms/field/point_evaluator_factory.hpp` | public | `include/pcms/field/point_evaluator_factory.hpp` | – / Omega_h | | +| `pcms/field/transformed_source.hpp` | public | `include/pcms/field/transformed_source.hpp` | – / Omega_h | | +| `pcms/field/uniform_grid_binary_field.h` | private | `src/pcms/backends/omega_h/uniform_grid_binary_field.hpp` | Omega_h / – | builds a uniform-grid field from an Omega_h mesh; Python binds it (question: public backend function?) | +| `pcms/field/value_view.hpp` | public | `include/pcms/field/value_view.hpp` | – / Omega_h | | +| `pcms/localization/adj_search.hpp` | private | `src/pcms/backends/omega_h/adj_search.hpp` | – / Omega_h | Omega_h adapter (Phase 3.6) | +| `pcms/localization/localization_factory.h` | private | `src/pcms/localization/localization_factory.hpp` | – / Omega_h | | +| `pcms/localization/mesh_localization.h` | private | `src/pcms/localization/mesh_localization.hpp` | Omega_h / – | | +| `pcms/localization/mls_support_helpers.h` | private | `src/pcms/localization/mls_support_helpers.hpp` | Omega_h / – | | +| `pcms/localization/point_cloud_localization.h` | private | `src/pcms/localization/point_cloud_localization.hpp` | Omega_h / – | | +| `pcms/localization/point_search.h` | private | `src/pcms/localization/point_search.hpp` | Omega_h / – | | +| `pcms/localization/queue_visited.hpp` | private | `src/pcms/backends/omega_h/queue_visited.hpp` | Omega_h / – | Omega_h adapter (Phase 3.6) | +| `pcms/pcms.h` | public | `include/pcms/pcms.hpp` | – / – | becomes umbrella header (Phase 4) | +| `pcms/transfer/bilinear_form_integrator.hpp` | private | `src/pcms/transfer/bilinear_form_integrator.hpp` | PETSc / – | | +| `pcms/transfer/conservative_projection_solver.hpp` | private | `src/pcms/transfer/conservative_projection_solver.hpp` | Omega_h/PETSc / – | | +| `pcms/transfer/coo_assembly_utils.hpp` | private | `src/pcms/transfer/coo_assembly_utils.hpp` | Omega_h/PETSc / – | | +| `pcms/transfer/copy.h` | public | `include/pcms/transfer/copy.hpp` | – / Omega_h | | +| `pcms/transfer/interpolation_base.h` | private | `src/pcms/transfer/interpolation_base.hpp` | Omega_h / – | legacy MLS interpolation used by the C API | +| `pcms/transfer/interpolation_helpers.h` | private | `src/pcms/transfer/interpolation_helpers.hpp` | Omega_h / – | | +| `pcms/transfer/interpolator.h` | public | `include/pcms/transfer/interpolator.hpp` | – / Omega_h | | +| `pcms/transfer/linear_form_integrator.hpp` | private | `src/pcms/transfer/linear_form_integrator.hpp` | PETSc / Omega_h | | +| `pcms/transfer/linear_interpolant.hpp` | private | `src/pcms/transfer/linear_interpolant.hpp` | – / – | used by uniform-grid evaluator + a test | +| `pcms/transfer/mass_matrix_integrator.hpp` | private | `src/pcms/transfer/mass_matrix_integrator.hpp` | Omega_h/meshfields / – | | +| `pcms/transfer/mass_matrix_type.hpp` | public | `include/pcms/transfer/mass_matrix_type.hpp` | – / – | enum in projection options (Python binds it) | +| `pcms/transfer/mesh_intersection.hpp` | private | `src/pcms/backends/omega_h/mesh_intersection.hpp` | Omega_h / – | | +| `pcms/transfer/monte_carlo_sampling.hpp` | private | `src/pcms/transfer/monte_carlo_sampling.hpp` | – / – | | +| `pcms/transfer/multidimarray.hpp` | private | `src/pcms/transfer/multidimarray.hpp` | – / – | | +| `pcms/transfer/omega_h_conservative_projection.hpp` | private | `src/pcms/backends/omega_h/conservative_projection.hpp` | – / Omega_h | factory CreateConservativeProjection | +| `pcms/transfer/omega_h_control_variate_projection.hpp` | private | `src/pcms/backends/omega_h/control_variate_projection.hpp` | – / Omega_h | factory CreateControlVariateProjection | +| `pcms/transfer/omega_h_form_integrator_utils.hpp` | private | `src/pcms/backends/omega_h_meshfields/form_integrator_utils.hpp` | Omega_h/meshfields / – | Omega_h + meshfields | +| `pcms/transfer/omega_h_intersection_rhs_integrator.hpp` | private | `src/pcms/backends/omega_h/intersection_rhs_integrator.hpp` | – / Omega_h/PETSc | | +| `pcms/transfer/omega_h_mass_integrator.hpp` | private | `src/pcms/backends/omega_h/mass_integrator.hpp` | – / Omega_h/PETSc | | +| `pcms/transfer/omega_h_mc_rhs_integrator.hpp` | private | `src/pcms/backends/omega_h/mc_rhs_integrator.hpp` | – / Omega_h/PETSc | | +| `pcms/transfer/petsc_utils.hpp` | private | `src/pcms/transfer/petsc_utils.hpp` | PETSc / – | | +| `pcms/transfer/transfer_operator.hpp` | public | `include/pcms/transfer/transfer_operator.hpp` | – / – | | +| `pcms/transient/timestepper.hpp` | public | `include/pcms/transient/timestepper.hpp` | – / – | | +| `pcms/utility/array_mask.h` | private | `src/pcms/utility/array_mask.hpp` | – / Omega_h | no external user | +| `pcms/utility/arrays.h` | public | `include/pcms/utility/arrays.hpp` | Omega_h / – | View aliases; Omega_h overload MakeConstRank2View moves to the Omega_h backend | +| `pcms/utility/assert.h` | public | `include/pcms/utility/assert.hpp` | – / – | pcms_error, PCMS_ALWAYS_ASSERT | +| `pcms/utility/bounding_box.h` | private | `src/pcms/utility/bounding_box.hpp` | – / – | only a test uses it | +| `pcms/utility/common.h` | installed-detail | `include/pcms/utility/detail/common.hpp` | – / – | find_or_error helpers used by coupler.hpp templates | +| `pcms/utility/entity_types.h` | public | `include/pcms/utility/entity_types.hpp` | – / – | entity-dimension constants used by public interfaces | +| `pcms/utility/eqdsk.h` | public | `include/pcms/utility/eqdsk.hpp` | – / Omega_h | EQDSKData (MakeEQDSKField input) | +| `pcms/utility/inclusive_scan.h` | installed-detail | `include/pcms/utility/detail/inclusive_scan.hpp` | – / – | used by coupler.hpp templates | +| `pcms/utility/memory_spaces.h` | public | `include/pcms/utility/memory_spaces.hpp` | – / – | | +| `pcms/utility/mesh_geometry.h` | private | `src/pcms/backends/omega_h/mesh_geometry.hpp` | Omega_h / – | Omega_h geometry kernels | +| `pcms/utility/mpi_type.h` | private | `src/pcms/utility/mpi_type.hpp` | – / – | | +| `pcms/utility/omega_h_array_utils.h` | private | `src/pcms/backends/omega_h/array_utils.hpp` | Omega_h / – | | +| `pcms/utility/print.h` | public | `include/pcms/utility/print.hpp` | – / – | used by examples/external-usage-example | +| `pcms/utility/profile.h` | installed-detail | `include/pcms/utility/detail/profile.hpp` | – / – | PCMS_FUNCTION_TIMER used inside public templates; perfstubs | +| `pcms/utility/types.h` | public | `include/pcms/utility/types.hpp` | – / – | LO, GO, Real, Type | +| `pcms/utility/uniform_grid.h` | public | `include/pcms/utility/uniform_grid.hpp` | Omega_h / – | UniformGrid; ClosestCellID takes a pcms vector (Phase 6); CreateUniformGridFromMesh moves to the Omega_h backend | +| `pcms/version.h` | public | `include/pcms/version.hpp` | – / – | generated | + +Not installed today and stays private: `localization/localization_path_selection.h`. + +Installed non-header files: `pcms/external/flibhpc/*` (SWIG `.i` files) and +`FindPETSc.cmake` are removal candidates in Phase 8. + +## 6. Questions for the checkpoint + +1. **Coupler templates and redev.** `coupler.hpp` (public) includes + `field_communicator.hpp`, `field_exchange_planner.h`, + `field_layout_communicator.h`, `global_communicator.h` and + `field_serializer.h`, which are templates over the field value type and + use redev in their bodies. Moving them to `detail/` keeps redev as a public + dependency of the coupler. Removing it needs a hand-written change: a + non-template (pimpl) boundary plus explicit instantiation for the closed set + of value types in `FieldVariant`. That is behavior-preserving but is more + than a move. Do it in this release, or list redev as a remaining public + dependency of `pcms::coupler`? +2. **XGC and MFEM factory names.** `XGCFieldFactory` and `MFEMFieldFactory` + derive from `FieldFactory`, not `FunctionSpace` (their fields are not + evaluable). `decisions.md` says `CreateFunctionSpace`; the correct name is + `backend::xgc::CreateFieldFactory` / `backend::mfem::CreateFieldFactory` + returning `std::shared_ptr`. OK? +3. **`SimpleFieldData`** (`field/data/simple.h`): the generic `FieldData` over + user-provided views, used by the C API and tests. Proposed public. Keep the + class public, or hide it behind a `CreateFieldData(...)` factory? +4. **`spline_interpolator.hpp`** was installed on purpose by an earlier PR. The + only user outside its sub-library is a test. Proposed private. Is there an + external user (e.g. a PSPLINE replacement)? +5. **`uniform_grid_binary_field.h`** (builds a uniform-grid field from an + Omega_h mesh) is bound in Python. Proposed: private implementation plus a + free function in the Omega_h backend header. OK? +6. **`utility/print.h`, `bounding_box.h`, `array_mask.h`, `mpi_type.h`.** + `print.h` stays public because the external usage example uses it; the + others have no external user and become private. diff --git a/tools/reorg/move_files.py b/tools/reorg/move_files.py new file mode 100755 index 000000000..a7d49d940 --- /dev/null +++ b/tools/reorg/move_files.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python3 +"""Move files with git mv and update every reference to them. + +Usage (from the repository root): + tools/reorg/move_files.py + tools/reorg/move_files.py [ ...] + +A mapping file has one " " pair per line (paths relative +to the repository root, '#' starts a comment). A directory can be given as a +pair; every tracked file below it is moved. + +After moving, references are updated so the tree keeps building: + +* #include directives written pcms/-rooted, or (quoted only) relative to + the including file, are rewritten to the new pcms/-rooted path when the + moved file lives under include/ or src/ (relative includes are kept + relative when the moved file is outside both); +* paths in CMakeLists.txt / *.cmake files that name a moved file (relative to + that CMake file's directory, the repository root, or src/) are rewritten + relative to the same base. + +Only paths change; file contents are otherwise untouched. CMake entries keep +belonging to the same target; moving them between targets is a separate, +hand-written step. Running the script again with the same mapping is a +no-op. +""" + +import os +import re +import subprocess +import sys + +ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) +SRC = os.path.join(ROOT, "src") +INCLUDE_DIR = os.path.join(ROOT, "include") +INCLUDE_ROOTS = (INCLUDE_DIR, SRC) # pcms/... resolves against these +CODE = re.compile(r"\.(h|hpp|c|cpp|cc|i)(\.in)?$") +INCLUDE = re.compile(r'^(\s*#\s*include\s*)([<"])([^>"]+)([>"])', re.M) +CMAKE_TOKEN = re.compile(r'(? names a library header (e.g. ) + cands.insert(0, os.path.normpath( + os.path.join(os.path.dirname(where), inc))) + t = target_of(cands) + if not t: + return m.group(0) + out = include_rel(t) + if out is None: + out = os.path.relpath(t, os.path.dirname(absf)) + return f"{m.group(1)}{m.group(2)}{out}{m.group(4)}" + new = INCLUDE.sub(repl, text) + if new != text: + with open(absf, "w", encoding="utf-8") as fh: + fh.write(new) + changed += 1 + print(f"moved {len(moves)} files, updated {changed} files") + + +if __name__ == "__main__": + if len(sys.argv) < 2: + sys.exit(__doc__) + main(sys.argv[1:]) diff --git a/tools/reorg/moves/02-localization-layering.txt b/tools/reorg/moves/02-localization-layering.txt new file mode 100644 index 000000000..53713951d --- /dev/null +++ b/tools/reorg/moves/02-localization-layering.txt @@ -0,0 +1,11 @@ +# Phase 2: make localization independent of field. +# Coordinate vocabulary moves below localization (into utility). +src/pcms/field/coordinate_view.hpp src/pcms/utility/coordinate_view.hpp +src/pcms/field/coordinate_system.hpp src/pcms/utility/coordinate_system.hpp +src/pcms/field/coordinate_system.cpp src/pcms/utility/coordinate_system.cpp +src/pcms/field/coordinate_systems src/pcms/utility/coordinate_systems +# Support-search options are used by localization. +src/pcms/field/evaluator/mls_options.hpp src/pcms/localization/mls_options.hpp +# Adapters from field layouts to localization move up into field. +src/pcms/localization/localization_path_selection.hpp src/pcms/field/localization_path_selection.hpp +src/pcms/localization/point_cloud_localization.hpp src/pcms/field/point_cloud_localization.hpp diff --git a/tools/reorg/moves/03-mfem.txt b/tools/reorg/moves/03-mfem.txt new file mode 100644 index 000000000..3b5731ae4 --- /dev/null +++ b/tools/reorg/moves/03-mfem.txt @@ -0,0 +1,6 @@ +# Phase 3.2: MFEM backend +src/pcms/field/layout/mfem.hpp src/pcms/backends/mfem/layout.hpp +src/pcms/field/layout/mfem.cpp src/pcms/backends/mfem/layout.cpp +src/pcms/field/data/mfem.hpp src/pcms/backends/mfem/field_data.hpp +src/pcms/field/data/mfem.cpp src/pcms/backends/mfem/field_data.cpp +src/pcms/field/function_space/mfem.hpp src/pcms/backends/mfem/field_factory.hpp diff --git a/tools/reorg/moves/03-omega_h.txt b/tools/reorg/moves/03-omega_h.txt new file mode 100644 index 000000000..c0004dadc --- /dev/null +++ b/tools/reorg/moves/03-omega_h.txt @@ -0,0 +1,14 @@ +# Phase 3.6: Omega_h adapter. function_space/lagrange stays in field: it is +# the generic Lagrange space (it also serves uniform grids) behind +# CreateLagrangeSpace. The Omega_h-based transfer algorithms stay in transfer. +src/pcms/discretization/discretization/omega_h.hpp src/pcms/backends/omega_h/discretization.hpp +src/pcms/discretization/discretization/omega_h.cpp src/pcms/backends/omega_h/discretization.cpp +src/pcms/field/layout/omega_h_entity.hpp src/pcms/backends/omega_h/entity_layout.hpp +src/pcms/field/layout/omega_h_entity.cpp src/pcms/backends/omega_h/entity_layout.cpp +src/pcms/field/layout/omega_h_lagrange.hpp src/pcms/backends/omega_h/lagrange_layout.hpp +src/pcms/field/layout/omega_h_lagrange.cpp src/pcms/backends/omega_h/lagrange_layout.cpp +src/pcms/field/evaluator/omega_h_lagrange.hpp src/pcms/backends/omega_h/lagrange_evaluator.hpp +src/pcms/localization/adj_search.hpp src/pcms/backends/omega_h/adj_search.hpp +src/pcms/localization/adj_search.cpp src/pcms/backends/omega_h/adj_search.cpp +src/pcms/localization/queue_visited.hpp src/pcms/backends/omega_h/queue_visited.hpp +src/pcms/field/uniform_grid_binary_field.hpp src/pcms/backends/omega_h/uniform_grid_binary_field.hpp diff --git a/tools/reorg/moves/03-omega_h_meshfields.txt b/tools/reorg/moves/03-omega_h_meshfields.txt new file mode 100644 index 000000000..7a7ded7d8 --- /dev/null +++ b/tools/reorg/moves/03-omega_h_meshfields.txt @@ -0,0 +1,8 @@ +# Phase 3.3: MeshFields adapter. Every file depends on both MeshFields and the +# Omega_h adapter (MeshFieldsAdapterLayout is built from an +# OmegaHDiscretization), so it goes to the omega_h_meshfields bridge. +src/pcms/field/layout/mesh_fields.hpp src/pcms/backends/omega_h_meshfields/layout.hpp +src/pcms/field/layout/mesh_fields.cpp src/pcms/backends/omega_h_meshfields/layout.cpp +src/pcms/field/data/mesh_fields.hpp src/pcms/backends/omega_h_meshfields/field_data.hpp +src/pcms/field/evaluator/mesh_fields.hpp src/pcms/backends/omega_h_meshfields/evaluator.hpp +src/pcms/field/evaluator/mesh_fields_backend.hpp src/pcms/backends/omega_h_meshfields/evaluator_backend.hpp diff --git a/tools/reorg/moves/03-point_cloud.txt b/tools/reorg/moves/03-point_cloud.txt new file mode 100644 index 000000000..bb4f8dcb7 --- /dev/null +++ b/tools/reorg/moves/03-point_cloud.txt @@ -0,0 +1,10 @@ +# Phase 3.4: point-cloud backend +src/pcms/discretization/discretization/point_cloud.hpp src/pcms/backends/point_cloud/discretization.hpp +src/pcms/discretization/discretization/point_cloud.cpp src/pcms/backends/point_cloud/discretization.cpp +src/pcms/field/layout/point_cloud.hpp src/pcms/backends/point_cloud/layout.hpp +src/pcms/field/layout/point_cloud.cpp src/pcms/backends/point_cloud/layout.cpp +src/pcms/field/data/point_cloud.hpp src/pcms/backends/point_cloud/field_data.hpp +src/pcms/field/data/point_cloud.cpp src/pcms/backends/point_cloud/field_data.cpp +src/pcms/field/evaluator/point_cloud.hpp src/pcms/backends/point_cloud/evaluator.hpp +src/pcms/field/evaluator/mls_point_cloud.hpp src/pcms/backends/point_cloud/mls_evaluator.hpp +src/pcms/field/point_cloud_localization.hpp src/pcms/backends/point_cloud/localization.hpp diff --git a/tools/reorg/moves/03-uniform_grid.txt b/tools/reorg/moves/03-uniform_grid.txt new file mode 100644 index 000000000..23fdc9d35 --- /dev/null +++ b/tools/reorg/moves/03-uniform_grid.txt @@ -0,0 +1,11 @@ +# Phase 3.5: uniform-grid backend. linear_interpolant.hpp and +# multidimarray.hpp were in transfer/ but are used only by the uniform-grid +# evaluator; moving them here removes field's include of a transfer header. +src/pcms/discretization/discretization/uniform_grid.hpp src/pcms/backends/uniform_grid/discretization.hpp +src/pcms/field/layout/uniform_grid.hpp src/pcms/backends/uniform_grid/layout.hpp +src/pcms/field/layout/uniform_grid.cpp src/pcms/backends/uniform_grid/layout.cpp +src/pcms/field/evaluator/uniform_grid.hpp src/pcms/backends/uniform_grid/evaluator.hpp +src/pcms/field/evaluator/uniform_grid_spline.hpp src/pcms/backends/uniform_grid/spline_evaluator.hpp +src/pcms/field/evaluator/spline_interpolator.hpp src/pcms/backends/uniform_grid/spline_interpolator.hpp +src/pcms/transfer/linear_interpolant.hpp src/pcms/backends/uniform_grid/linear_interpolant.hpp +src/pcms/transfer/multidimarray.hpp src/pcms/backends/uniform_grid/multidimarray.hpp diff --git a/tools/reorg/moves/03-xgc.txt b/tools/reorg/moves/03-xgc.txt new file mode 100644 index 000000000..f4274b44b --- /dev/null +++ b/tools/reorg/moves/03-xgc.txt @@ -0,0 +1,9 @@ +# Phase 3.1: XGC backend +src/pcms/discretization/discretization/xgc.hpp src/pcms/backends/xgc/discretization.hpp +src/pcms/discretization/discretization/xgc.cpp src/pcms/backends/xgc/discretization.cpp +src/pcms/discretization/discretization/xgc_reverse_classification.hpp src/pcms/backends/xgc/reverse_classification.hpp +src/pcms/discretization/discretization/xgc_reverse_classification.cpp src/pcms/backends/xgc/reverse_classification.cpp +src/pcms/field/layout/xgc.hpp src/pcms/backends/xgc/layout.hpp +src/pcms/field/layout/xgc.cpp src/pcms/backends/xgc/layout.cpp +src/pcms/field/data/xgc.hpp src/pcms/backends/xgc/field_data.hpp +src/pcms/field/function_space/xgc.hpp src/pcms/backends/xgc/field_factory.hpp diff --git a/tools/reorg/moves/04-flatten-discretization.txt b/tools/reorg/moves/04-flatten-discretization.txt new file mode 100644 index 000000000..d6967c3b0 --- /dev/null +++ b/tools/reorg/moves/04-flatten-discretization.txt @@ -0,0 +1,4 @@ +# Phase 4.1: flatten discretization/discretization/ (only the empty +# discretization is left after the backends moved out) +src/pcms/discretization/discretization/empty.hpp src/pcms/discretization/empty.hpp +src/pcms/discretization/discretization/empty.cpp src/pcms/discretization/empty.cpp diff --git a/tools/reorg/moves/04-interpolator-stutter.txt b/tools/reorg/moves/04-interpolator-stutter.txt new file mode 100644 index 000000000..e09e8b9eb --- /dev/null +++ b/tools/reorg/moves/04-interpolator-stutter.txt @@ -0,0 +1,4 @@ +# Phase 4.2: drop the pcms_ stutter from the interpolator helper headers +src/pcms/field/evaluator/pcms_interpolator_aliases.hpp src/pcms/field/evaluator/interpolator_aliases.hpp +src/pcms/field/evaluator/pcms_interpolator_logger.hpp src/pcms/field/evaluator/interpolator_logger.hpp +src/pcms/field/evaluator/pcms_interpolator_view_utils.hpp src/pcms/field/evaluator/interpolator_view_utils.hpp diff --git a/tools/reorg/moves/05-backends-mfem.txt b/tools/reorg/moves/05-backends-mfem.txt new file mode 100644 index 000000000..1d1b3b706 --- /dev/null +++ b/tools/reorg/moves/05-backends-mfem.txt @@ -0,0 +1,2 @@ +# Phase 5: public / installed-detail headers of backends-mfem move to include/ +src/pcms/backends/mfem/mfem.hpp include/pcms/backends/mfem/mfem.hpp diff --git a/tools/reorg/moves/05-backends-omega_h.txt b/tools/reorg/moves/05-backends-omega_h.txt new file mode 100644 index 000000000..c5fed2836 --- /dev/null +++ b/tools/reorg/moves/05-backends-omega_h.txt @@ -0,0 +1,2 @@ +# Phase 5: public / installed-detail headers of backends-omega_h move to include/ +src/pcms/backends/omega_h/omega_h.hpp include/pcms/backends/omega_h/omega_h.hpp diff --git a/tools/reorg/moves/05-backends-xgc.txt b/tools/reorg/moves/05-backends-xgc.txt new file mode 100644 index 000000000..3d780b65b --- /dev/null +++ b/tools/reorg/moves/05-backends-xgc.txt @@ -0,0 +1,3 @@ +# Phase 5: public / installed-detail headers of backends-xgc move to include/ +src/pcms/backends/xgc/xgc.hpp include/pcms/backends/xgc/xgc.hpp +src/pcms/backends/xgc/reverse_classification.hpp include/pcms/backends/xgc/reverse_classification.hpp diff --git a/tools/reorg/moves/05-capi.txt b/tools/reorg/moves/05-capi.txt new file mode 100644 index 000000000..3334e8af8 --- /dev/null +++ b/tools/reorg/moves/05-capi.txt @@ -0,0 +1,5 @@ +# Phase 5: public / installed-detail headers of capi move to include/ +src/pcms/capi/client.h include/pcms/capi/client.h +src/pcms/capi/interpolator.h include/pcms/capi/interpolator.h +src/pcms/capi/kokkos.h include/pcms/capi/kokkos.h +src/pcms/capi/mesh.h include/pcms/capi/mesh.h diff --git a/tools/reorg/moves/05-coupler.txt b/tools/reorg/moves/05-coupler.txt new file mode 100644 index 000000000..788b6aa9f --- /dev/null +++ b/tools/reorg/moves/05-coupler.txt @@ -0,0 +1,9 @@ +# Phase 5: public / installed-detail headers of coupler move to include/ +src/pcms/coupler/coupler.hpp include/pcms/coupler/coupler.hpp +src/pcms/coupler/coupler_types.hpp include/pcms/coupler/coupler_types.hpp +src/pcms/coupler/overlap_mask.hpp include/pcms/coupler/overlap_mask.hpp +src/pcms/coupler/field_communicator.hpp include/pcms/coupler/detail/field_communicator.hpp +src/pcms/coupler/field_exchange_planner.hpp include/pcms/coupler/detail/field_exchange_planner.hpp +src/pcms/coupler/field_layout_communicator.hpp include/pcms/coupler/detail/field_layout_communicator.hpp +src/pcms/coupler/field_serializer.hpp include/pcms/coupler/detail/field_serializer.hpp +src/pcms/coupler/global_communicator.hpp include/pcms/coupler/detail/global_communicator.hpp diff --git a/tools/reorg/moves/05-discretization.txt b/tools/reorg/moves/05-discretization.txt new file mode 100644 index 000000000..f4e2f74a5 --- /dev/null +++ b/tools/reorg/moves/05-discretization.txt @@ -0,0 +1,2 @@ +# Phase 5: public / installed-detail headers of discretization move to include/ +src/pcms/discretization/discretization.hpp include/pcms/discretization/discretization.hpp diff --git a/tools/reorg/moves/05-field.txt b/tools/reorg/moves/05-field.txt new file mode 100644 index 000000000..28df7913d --- /dev/null +++ b/tools/reorg/moves/05-field.txt @@ -0,0 +1,16 @@ +# Phase 5: public / installed-detail headers of field move to include/ +src/pcms/field/coordinate_map.hpp include/pcms/field/coordinate_map.hpp +src/pcms/field/evaluation_request.hpp include/pcms/field/evaluation_request.hpp +src/pcms/field/field.hpp include/pcms/field/field.hpp +src/pcms/field/field_data.hpp include/pcms/field/field_data.hpp +src/pcms/field/field_factory.hpp include/pcms/field/field_factory.hpp +src/pcms/field/field_layout.hpp include/pcms/field/field_layout.hpp +src/pcms/field/function_space.hpp include/pcms/field/function_space.hpp +src/pcms/field/function_spaces.hpp include/pcms/field/function_spaces.hpp +src/pcms/field/out_of_bounds_policy.hpp include/pcms/field/out_of_bounds_policy.hpp +src/pcms/field/point_evaluator.hpp include/pcms/field/point_evaluator.hpp +src/pcms/field/point_evaluator_factory.hpp include/pcms/field/point_evaluator_factory.hpp +src/pcms/field/transformed_source.hpp include/pcms/field/transformed_source.hpp +src/pcms/field/value_view.hpp include/pcms/field/value_view.hpp +src/pcms/field/eqdsk_field.hpp include/pcms/field/eqdsk_field.hpp +src/pcms/field/data/simple.hpp include/pcms/field/simple_field_data.hpp diff --git a/tools/reorg/moves/05-localization.txt b/tools/reorg/moves/05-localization.txt new file mode 100644 index 000000000..56e715a52 --- /dev/null +++ b/tools/reorg/moves/05-localization.txt @@ -0,0 +1,2 @@ +# Phase 5: public / installed-detail headers of localization move to include/ +src/pcms/localization/mls_options.hpp include/pcms/localization/mls_options.hpp diff --git a/tools/reorg/moves/05-transfer.txt b/tools/reorg/moves/05-transfer.txt new file mode 100644 index 000000000..737364257 --- /dev/null +++ b/tools/reorg/moves/05-transfer.txt @@ -0,0 +1,7 @@ +# Phase 5: public / installed-detail headers of transfer move to include/ +src/pcms/transfer/copy.hpp include/pcms/transfer/copy.hpp +src/pcms/transfer/interpolator.hpp include/pcms/transfer/interpolator.hpp +src/pcms/transfer/mass_matrix_type.hpp include/pcms/transfer/mass_matrix_type.hpp +src/pcms/transfer/monte_carlo_sampling.hpp include/pcms/transfer/monte_carlo_sampling.hpp +src/pcms/transfer/projection.hpp include/pcms/transfer/projection.hpp +src/pcms/transfer/transfer_operator.hpp include/pcms/transfer/transfer_operator.hpp diff --git a/tools/reorg/moves/05-transient.txt b/tools/reorg/moves/05-transient.txt new file mode 100644 index 000000000..fa9a57a1b --- /dev/null +++ b/tools/reorg/moves/05-transient.txt @@ -0,0 +1,2 @@ +# Phase 5: public / installed-detail headers of transient move to include/ +src/pcms/transient/timestepper.hpp include/pcms/transient/timestepper.hpp diff --git a/tools/reorg/moves/05-umbrella.txt b/tools/reorg/moves/05-umbrella.txt new file mode 100644 index 000000000..21aaae434 --- /dev/null +++ b/tools/reorg/moves/05-umbrella.txt @@ -0,0 +1,2 @@ +# Phase 5: public / installed-detail headers of umbrella move to include/ +src/pcms/pcms.hpp include/pcms/pcms.hpp diff --git a/tools/reorg/moves/05-utility.txt b/tools/reorg/moves/05-utility.txt new file mode 100644 index 000000000..04ce49e88 --- /dev/null +++ b/tools/reorg/moves/05-utility.txt @@ -0,0 +1,17 @@ +# Phase 5: public / installed-detail headers of utility move to include/ +src/pcms/utility/arrays.hpp include/pcms/utility/arrays.hpp +src/pcms/utility/assert.hpp include/pcms/utility/assert.hpp +src/pcms/utility/coordinate_system.hpp include/pcms/utility/coordinate_system.hpp +src/pcms/utility/coordinate_systems/cartesian.hpp include/pcms/utility/coordinate_systems/cartesian.hpp +src/pcms/utility/coordinate_systems/cylindrical.hpp include/pcms/utility/coordinate_systems/cylindrical.hpp +src/pcms/utility/coordinate_view.hpp include/pcms/utility/coordinate_view.hpp +src/pcms/utility/entity_types.hpp include/pcms/utility/entity_types.hpp +src/pcms/utility/eqdsk.hpp include/pcms/utility/eqdsk.hpp +src/pcms/utility/memory_spaces.hpp include/pcms/utility/memory_spaces.hpp +src/pcms/utility/print.hpp include/pcms/utility/print.hpp +src/pcms/utility/types.hpp include/pcms/utility/types.hpp +src/pcms/utility/uniform_grid.hpp include/pcms/utility/uniform_grid.hpp +src/pcms/utility/common.hpp include/pcms/utility/detail/common.hpp +src/pcms/utility/inclusive_scan.hpp include/pcms/utility/detail/inclusive_scan.hpp +src/pcms/utility/profile.hpp include/pcms/utility/detail/profile.hpp +src/pcms/utility/bounding_box.hpp include/pcms/utility/bounding_box.hpp diff --git a/tools/reorg/namespaces/mfem.txt b/tools/reorg/namespaces/mfem.txt new file mode 100644 index 000000000..d27f314e7 --- /dev/null +++ b/tools/reorg/namespaces/mfem.txt @@ -0,0 +1,4 @@ +# namespace-scope names declared in src/pcms/backends/mfem +MFEMLayout +MFEMVertexFieldData +MFEMFieldFactory diff --git a/tools/reorg/namespaces/omega_h.txt b/tools/reorg/namespaces/omega_h.txt new file mode 100644 index 000000000..b6ca44fb8 --- /dev/null +++ b/tools/reorg/namespaces/omega_h.txt @@ -0,0 +1,13 @@ +# namespace-scope names declared in src/pcms/backends/omega_h that are used +# elsewhere (file-local helpers move with the namespace) +OmegaHDiscretization +OmegaHEntityLayout +OmegaHLagrangeLayout +OmegaHLagrangeEvaluatorFactory +OmegaHLagrangePointEvaluator +OmegaHLagrangeLocHint +FindSupports +searchNeighbors +Queue +Track +CreateUniformGridBinaryField diff --git a/tools/reorg/namespaces/omega_h_meshfields.txt b/tools/reorg/namespaces/omega_h_meshfields.txt new file mode 100644 index 000000000..c30752a82 --- /dev/null +++ b/tools/reorg/namespaces/omega_h_meshfields.txt @@ -0,0 +1,11 @@ +# namespace-scope names declared in src/pcms/backends/omega_h_meshfields that +# are used elsewhere (file-local helpers move with the namespace) +MeshFieldBackend +MeshFieldBackendImpl +MakeBackendForComponents +MakeMeshFieldBackend +MeshFieldsAdapter2LocalizationHint +MeshFieldsAdapterLayout +MeshFieldsFieldData +MeshFieldsEvaluatorFactory +MeshFieldsPointEvaluator diff --git a/tools/reorg/namespaces/point_cloud.txt b/tools/reorg/namespaces/point_cloud.txt new file mode 100644 index 000000000..22d867088 --- /dev/null +++ b/tools/reorg/namespaces/point_cloud.txt @@ -0,0 +1,8 @@ +# namespace-scope names declared in src/pcms/backends/point_cloud that are +# used elsewhere +PointCloudDiscretization +PointCloud +PointCloudLayout +PointCloudEvaluatorFactory +MLSPointEvaluator +PointCloudLocalizationFactory diff --git a/tools/reorg/namespaces/sublib-coupler-files.txt b/tools/reorg/namespaces/sublib-coupler-files.txt new file mode 100644 index 000000000..1c72e3106 --- /dev/null +++ b/tools/reorg/namespaces/sublib-coupler-files.txt @@ -0,0 +1,9 @@ +# files whose code moves to pcms::coupler +include/pcms/coupler/detail/field_communicator.hpp +include/pcms/coupler/detail/field_exchange_planner.hpp +include/pcms/coupler/detail/field_layout_communicator.hpp +include/pcms/coupler/detail/field_serializer.hpp +include/pcms/coupler/detail/global_communicator.hpp +src/pcms/coupler/partition.hpp +src/pcms/coupler/field_exchange_planner.cpp +src/pcms/coupler/field_layout_communicator.cpp diff --git a/tools/reorg/namespaces/sublib-coupler.txt b/tools/reorg/namespaces/sublib-coupler.txt new file mode 100644 index 000000000..c804d929d --- /dev/null +++ b/tools/reorg/namespaces/sublib-coupler.txt @@ -0,0 +1,12 @@ +# namespace-scope names declared by the files that move to pcms::coupler +ExchangePlan +FieldCommunicator +FieldCommunicator2Ptr +FieldCommunicator2PtrT +FieldExchangePlanner +FieldLayoutCommunicator +FieldSerializer +GenericFieldExchangePlanner +GetRank +GlobalCommunicator +Partition diff --git a/tools/reorg/namespaces/sublib-discretization-files.txt b/tools/reorg/namespaces/sublib-discretization-files.txt new file mode 100644 index 000000000..cd5986779 --- /dev/null +++ b/tools/reorg/namespaces/sublib-discretization-files.txt @@ -0,0 +1,3 @@ +# files whose code moves to pcms::discretization +src/pcms/discretization/empty.hpp +src/pcms/discretization/empty.cpp diff --git a/tools/reorg/namespaces/sublib-discretization.txt b/tools/reorg/namespaces/sublib-discretization.txt new file mode 100644 index 000000000..6e68a3be5 --- /dev/null +++ b/tools/reorg/namespaces/sublib-discretization.txt @@ -0,0 +1,2 @@ +# namespace-scope names declared by the files that move to pcms::discretization +EmptyDiscretization diff --git a/tools/reorg/namespaces/sublib-field-files.txt b/tools/reorg/namespaces/sublib-field-files.txt new file mode 100644 index 000000000..c18455734 --- /dev/null +++ b/tools/reorg/namespaces/sublib-field-files.txt @@ -0,0 +1,22 @@ +# files whose code moves to pcms::field +# interpolator_aliases.hpp keeps its generic type aliases (member_type, +# ScratchMatView, ...) in pcms:: (still private), since other files define +# unrelated aliases with the same names. +src/pcms/field/element_dispatch.hpp +src/pcms/field/evaluator/interpolator_logger.hpp +src/pcms/field/evaluator/interpolator_view_utils.hpp +src/pcms/field/evaluator/mls_interpolation.hpp +src/pcms/field/evaluator/mls_interpolation_impl.hpp +src/pcms/field/field_evaluator_factory.hpp +src/pcms/field/function_space/lagrange.hpp +src/pcms/field/function_space/polynomial_reconstruction.hpp +src/pcms/field/function_space/spline.hpp +src/pcms/field/gid_permutation.hpp +src/pcms/field/layout/empty.hpp +src/pcms/field/localization_path_selection.hpp +src/pcms/field/evaluator/mls_interpolation.cpp +src/pcms/field/function_space/lagrange.cpp +src/pcms/field/function_space/polynomial_reconstruction.cpp +src/pcms/field/function_space/spline.cpp +src/pcms/field/gid_permutation.cpp +src/pcms/field/layout/empty.cpp diff --git a/tools/reorg/namespaces/sublib-field.txt b/tools/reorg/namespaces/sublib-field.txt new file mode 100644 index 000000000..ab8ef7c3b --- /dev/null +++ b/tools/reorg/namespaces/sublib-field.txt @@ -0,0 +1,11 @@ +# namespace-scope names declared by the files that move to pcms::field +AppendGidPermutation +BuildSortedGidPermutation +EmptyFieldLayout +FieldEvaluatorFactory +GidToIndexMaps +LagrangeFunctionSpace +MakeUnmappedPermutation +PolynomialReconstructionFunctionSpace +SplineFunctionSpace +mls_interpolation diff --git a/tools/reorg/namespaces/sublib-localization-files.txt b/tools/reorg/namespaces/sublib-localization-files.txt new file mode 100644 index 000000000..681a2bbf4 --- /dev/null +++ b/tools/reorg/namespaces/sublib-localization-files.txt @@ -0,0 +1,9 @@ +# files whose code moves to pcms::localization +src/pcms/localization/localization_factory.hpp +src/pcms/localization/mesh_localization.hpp +src/pcms/localization/mls_support_helpers.hpp +src/pcms/localization/point_search.hpp +src/pcms/localization/support_results.hpp +src/pcms/localization/mesh_localization.cpp +src/pcms/localization/mls_support_helpers.cpp +src/pcms/localization/point_search.cpp diff --git a/tools/reorg/namespaces/sublib-localization.txt b/tools/reorg/namespaces/sublib-localization.txt new file mode 100644 index 000000000..d0a3a9ac0 --- /dev/null +++ b/tools/reorg/namespaces/sublib-localization.txt @@ -0,0 +1,16 @@ +# namespace-scope names declared by the files that move to pcms::localization +AdjacencyLocalizationFactory +BuildPointCloudSupports +GetOwningElementId +GridPointSearch2D +GridPointSearch3D +GridPointSearchVariant +LocalizationFactory +PointLocalizationSearch +PointLocalizationSearch2D +PointLocalizationSearch3D +SupportResults +adapt_radii +minmax +triangle_intersects_bbox +within_number_of_support_range diff --git a/tools/reorg/namespaces/sublib-transfer-files.txt b/tools/reorg/namespaces/sublib-transfer-files.txt new file mode 100644 index 000000000..becaa6a02 --- /dev/null +++ b/tools/reorg/namespaces/sublib-transfer-files.txt @@ -0,0 +1,26 @@ +# files whose code moves to pcms::transfer +src/pcms/transfer/bilinear_form_integrator.hpp +src/pcms/transfer/conservative_projection_solver.hpp +src/pcms/transfer/coo_assembly_utils.hpp +src/pcms/transfer/interpolation_base.hpp +src/pcms/transfer/interpolation_helpers.hpp +src/pcms/transfer/linear_form_integrator.hpp +src/pcms/transfer/mass_matrix_integrator.hpp +src/pcms/transfer/mesh_intersection.hpp +src/pcms/transfer/omega_h_conservative_projection.hpp +src/pcms/transfer/omega_h_control_variate_projection.hpp +src/pcms/transfer/omega_h_form_integrator_utils.hpp +src/pcms/transfer/omega_h_intersection_rhs_integrator.hpp +src/pcms/transfer/omega_h_mass_integrator.hpp +src/pcms/transfer/omega_h_mc_rhs_integrator.hpp +src/pcms/transfer/petsc_utils.hpp +src/pcms/transfer/conservative_projection_solver.cpp +src/pcms/transfer/coo_assembly_utils.cpp +src/pcms/transfer/interpolation_base.cpp +src/pcms/transfer/mesh_intersection.cpp +src/pcms/transfer/omega_h_conservative_projection.cpp +src/pcms/transfer/omega_h_control_variate_projection.cpp +src/pcms/transfer/omega_h_intersection_rhs_integrator.cpp +src/pcms/transfer/omega_h_mass_integrator.cpp +src/pcms/transfer/omega_h_mc_rhs_integrator.cpp +src/pcms/transfer/petsc_utils.cpp diff --git a/tools/reorg/namespaces/sublib-transfer.txt b/tools/reorg/namespaces/sublib-transfer.txt new file mode 100644 index 000000000..1e167447c --- /dev/null +++ b/tools/reorg/namespaces/sublib-transfer.txt @@ -0,0 +1,26 @@ +# namespace-scope names declared by the files that move to pcms::transfer +BilinearFormIntegrator +BuildOmegaHConservativeRHSIntegrator +BuildOmegaHMassIntegrator +FindIntersections +GalerkinProjectionSolver +InterpolationBase +IntersectionResults +LinearFormIntegrator +MLSMeshInterpolation +MLSPointCloudInterpolation +MassMatrixIntegrator +OmegaHConservativeProjection +OmegaHControlVariateProjection +OmegaHIntersectionRHSIntegrator +OmegaHMassIntegrator +OmegaHMonteCarloRHSIntegrator +buildElementMassMatrix +build_linear_triangle_coo_rows +build_linear_triangle_coo_rows_cols +copyHostScalarArrayView2HostWrite +copyHostWrite2ScalarArrayView +createSeqAIJMat +createSeqVec +intersectTargets +simplices_have_degenerate_overlap diff --git a/tools/reorg/namespaces/sublib-utility-files.txt b/tools/reorg/namespaces/sublib-utility-files.txt new file mode 100644 index 000000000..5c04aa716 --- /dev/null +++ b/tools/reorg/namespaces/sublib-utility-files.txt @@ -0,0 +1,5 @@ +# files whose code moves to pcms::utility +src/pcms/utility/array_mask.hpp +src/pcms/utility/mesh_geometry.hpp +src/pcms/utility/mpi_type.hpp +src/pcms/utility/omega_h_array_utils.hpp diff --git a/tools/reorg/namespaces/sublib-utility.txt b/tools/reorg/namespaces/sublib-utility.txt new file mode 100644 index 000000000..95033657b --- /dev/null +++ b/tools/reorg/namespaces/sublib-utility.txt @@ -0,0 +1,9 @@ +# namespace-scope names declared by the files that move to pcms::utility +ArrayMask +ConvertCoordsTo2D +EnsureClassification +GetMPIType +distance_squared +flatten_to_omega_h_reals +flatten_to_omega_h_reals_host +get_entity_centroids diff --git a/tools/reorg/namespaces/uniform_grid.txt b/tools/reorg/namespaces/uniform_grid.txt new file mode 100644 index 000000000..95cee9118 --- /dev/null +++ b/tools/reorg/namespaces/uniform_grid.txt @@ -0,0 +1,24 @@ +# namespace-scope names declared in src/pcms/backends/uniform_grid that are +# used elsewhere (UniformGrid / UniformGrid2D / UniformGrid3D stay in utility) +UniformGridDiscretization +UniformGridFieldLayout +UniformGridFieldLayout2D +UniformGridEvaluatorFactory +UniformGridEvaluatorFactory2D +UniformGridFieldLocalizationHint +UniformGridPointEvaluator +UniformGridSplineEvaluatorFactory2D +UniformGridSplinePointEvaluator2D +BoundaryCondition +CubicSplineInterpolator +ExplicitCubicSplineInterpolator +CompactCubicSplineInterpolator +BiCubicSplineInterpolator +ExplicitBiCubicSplineInterpolator +CompactBiCubicSplineInterpolator +RegularGridInterpolator +RealMatView +RealVecView +IntMatView +IntVecView +HostIntVecView diff --git a/tools/reorg/namespaces/xgc.txt b/tools/reorg/namespaces/xgc.txt new file mode 100644 index 000000000..34a321588 --- /dev/null +++ b/tools/reorg/namespaces/xgc.txt @@ -0,0 +1,10 @@ +# namespace-scope names declared in src/pcms/backends/xgc +XGCDiscretization +DimID +ReverseClassificationVertex +ReadReverseClassificationVertex +IndexBase +ConstructRCFromOmegaHMesh +XGCFieldLayout +XGCFieldData +XGCFieldFactory diff --git a/tools/reorg/normalize_guards.py b/tools/reorg/normalize_guards.py new file mode 100755 index 000000000..b0ba6ce1d --- /dev/null +++ b/tools/reorg/normalize_guards.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +"""Give every header a path-derived include guard. + +Usage (from the repository root): + tools/reorg/normalize_guards.py + +For each tracked header (*.h, *.hpp, *.h.in, *.hpp.in) whose first directives +are an `#ifndef X` / `#define X` guard closed by the file's last `#endif`, the +guard macro is replaced by a name derived from the header's include path: + + include/pcms/field/field.hpp -> PCMS_FIELD_FIELD_HPP + src/pcms/backends/omega_h/adj_search.hpp -> PCMS_BACKENDS_OMEGA_H_ADJ_SEARCH_HPP + include/pcms/capi/client.h -> PCMS_CAPI_CLIENT_H + src/pcms/configuration.hpp.in -> PCMS_CONFIGURATION_HPP + test/field_test_utils.hpp -> PCMS_TEST_FIELD_TEST_UTILS_HPP + +The trailing comment of the closing #endif is updated as well (and added if +missing). Guards are never replaced by #pragma once. Running the script +twice is a no-op. +""" + +import re +import subprocess +import sys + + +def guard_name(path): + p = re.sub(r"\.in$", "", path) + if p.startswith(("include/pcms/", "src/pcms/")): + rel = p.split("/pcms/", 1)[1] + prefix = "PCMS_" + elif p.startswith("test/"): + rel = p[len("test/"):] + prefix = "PCMS_TEST_" + else: + rel = p + prefix = "PCMS_" + return prefix + re.sub(r"[^A-Za-z0-9]", "_", rel).upper() + + +def main(): + files = subprocess.run(["git", "ls-files"], check=True, capture_output=True, + text=True).stdout.split() + headers = [f for f in files if re.search(r"\.(h|hpp)(\.in)?$", f) + and not f.startswith(("tools/", "src/pcms/external/"))] + names, changed, skipped = {}, 0, [] + for f in headers: + new_guard = guard_name(f) + if new_guard in names: + sys.exit(f"guard clash: {f} and {names[new_guard]}") + names[new_guard] = f + text = open(f, encoding="utf-8").read() + m = re.search(r"^([ \t]*#[ \t]*ifndef[ \t]+)(\w+)([ \t]*\n[ \t]*#[ \t]*define[ \t]+)\2\b", + text, re.M) + if not m: + skipped.append(f) + continue + old = m.group(2) + endifs = list(re.finditer(r"^[ \t]*#[ \t]*endif\b[^\n]*", text, re.M)) + if not endifs or text[endifs[-1].end():].strip(): + skipped.append(f) + continue + new = (text[:m.start()] + m.group(1) + new_guard + m.group(3) + new_guard + + text[m.end():]) + # recompute the last #endif in the edited text + last = list(re.finditer(r"^[ \t]*#[ \t]*endif\b[^\n]*", new, re.M))[-1] + new = new[:last.start()] + f"#endif // {new_guard}" + new[last.end():] + if new != text: + open(f, "w", encoding="utf-8").write(new) + changed += 1 + del old + print(f"updated {changed} of {len(headers)} headers") + for f in skipped: + print(f"SKIPPED (no standard guard): {f}", file=sys.stderr) + return 1 if skipped else 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tools/reorg/omega_h_boundary_calls.py b/tools/reorg/omega_h_boundary_calls.py new file mode 100755 index 000000000..2af4e4e50 --- /dev/null +++ b/tools/reorg/omega_h_boundary_calls.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python3 +"""Point callers of the Omega_h-typed helpers at the Omega_h backend. + +Usage (from the repository root): + tools/reorg/omega_h_boundary_calls.py + +* pcms::MakeConstRank2View(, ) (the two-argument overload) + -> pcms::backend::omega_h::MakeConstRank2View(...) +* pcms::CreateUniformGridFromMesh / unqualified uses in namespace pcms + -> pcms::backend::omega_h::CreateUniformGridFromMesh +and adds #include "pcms/backends/omega_h/omega_h.hpp" to each changed file +that does not include it yet. Running it twice is a no-op. +""" +import re +import subprocess + +files = subprocess.run(["git", "ls-files", "src", "test", "examples", "tools"], + check=True, capture_output=True, text=True).stdout.split() +OH = "pcms::backend::omega_h::" +two_arg = re.compile(r"(? [ ...] + +Rewrites, preserving the arguments: + + pcms.LagrangeFunctionSpace.from_mesh(mesh, order, n[, csys][, global_id_name=g][, backend=B]) + -> pcms.create_lagrange_space(pcms.backend.omega_h.create_discretization(mesh[, global_id_name=g]), + order, n[, csys][, implementation=B]) + pcms.LagrangeFunctionSpace.from_uniform_grid(grid, n[, csys][, order]) + -> pcms.create_lagrange_space(pcms.create_uniform_grid_discretization(grid), order(=1), n[, csys]) + pcms.LagrangeFunctionSpace.Backend.X -> pcms.LagrangeImplementation.X + pcms.PolynomialReconstructionFunctionSpace.create(...) + -> pcms.create_polynomial_reconstruction_space(...) + pcms.PolynomialReconstructionFunctionSpace.from_mesh(mesh, ...) + -> pcms.create_polynomial_reconstruction_space(pcms.backend.omega_h.create_discretization(mesh), ...) + pcms.OmegaHConservativeProjection(...) -> pcms.create_conservative_projection(...) + pcms.OmegaHControlVariateProjection(...) -> pcms.create_control_variate_projection(...) + pcms.create_uniform_grid_binary_field(...) -> pcms.backend.omega_h.create_uniform_grid_binary_field(...) + pcms.create_uniform_grid_from_mesh(...) -> pcms.backend.omega_h.create_uniform_grid_from_mesh(...) + pcms.map_entity_field_to_vertices_X(...) -> pcms.backend.omega_h.map_entity_field_to_vertices_X(...) + pcms.compute_entity_centroids[_few](...) -> pcms.backend.omega_h.compute_entity_centroids(...) + .mesh() -> pcms.backend.omega_h.get_mesh(.get_discretization()) + +The keyword mesh_coordinate_system= becomes coordinate_system=. Running the +script twice is a no-op. +""" + +import re +import sys + +KW_RENAME = {"mesh_coordinate_system": "coordinate_system", + "backend": "implementation"} + + +def split_args(text): + """Split a call's argument text at top-level commas.""" + args, depth, cur, quote = [], 0, "", None + for ch in text: + if quote: + cur += ch + if ch == quote: + quote = None + continue + if ch in "\"'": + quote = ch + elif ch in "([{": + depth += 1 + elif ch in ")]}": + depth -= 1 + elif ch == "," and depth == 0: + args.append(cur.strip()) + cur = "" + continue + cur += ch + if cur.strip(): + args.append(cur.strip()) + return args + + +def find_call(text, start): + """Given the index of an opening '(', return the index of its ')'.""" + depth = 0 + for i in range(start, len(text)): + if text[i] == "(": + depth += 1 + elif text[i] == ")": + depth -= 1 + if depth == 0: + return i + raise ValueError("unbalanced call") + + +def kw(arg): + m = re.match(r"(\w+)\s*=(?!=)\s*(.*)", arg, re.S) + return (m.group(1), m.group(2)) if m else (None, arg) + + +def rewrite_calls(text, prefix, fn): + out, pos = [], 0 + while True: + i = text.find(prefix, pos) + if i < 0: + out.append(text[pos:]) + return "".join(out) + open_paren = i + len(prefix) - 1 + close = find_call(text, open_paren) + args = split_args(text[open_paren + 1:close]) + out.append(text[pos:i]) + try: + name, new_args = fn(args) + except (IndexError, ValueError): + # not a call this script understands (e.g. text in a docstring) + out.append(text[i:close + 1]) + pos = close + 1 + continue + if "\n" in text[i:close]: + # keep a multi-line call multi-line: one argument per line, + # indented 4 more than the line the call starts on + line_start = text.rfind("\n", 0, i) + 1 + indent = re.match(r"[ \t]*", text[line_start:]).group(0) + " " + sep = ",\n" + indent + out.append(f"{name}(\n{indent}{sep.join(new_args)})") + else: + out.append(f"{name}({', '.join(new_args)})") + pos = close + 1 + + +def lagrange_from_mesh(args): + pos = [a for a in args if kw(a)[0] is None] + kws = [kw(a) for a in args if kw(a)[0] is not None] + disc_args = [pos[0]] + [f"{k}={v}" for k, v in kws if k == "global_id_name"] + rest = pos[1:] + [f"{KW_RENAME.get(k, k)}={v}" for k, v in kws + if k != "global_id_name"] + disc = f"pcms.backend.omega_h.create_discretization({', '.join(disc_args)})" + return "pcms.create_lagrange_space", [disc] + rest + + +def lagrange_from_uniform_grid(args): + pos = [a for a in args if kw(a)[0] is None] + kws = dict(kw(a) for a in args if kw(a)[0] is not None) + grid, ncomp = pos[0], pos[1] + csys = pos[2] if len(pos) > 2 else kws.pop("mesh_coordinate_system", None) + order = pos[3] if len(pos) > 3 else kws.pop("order", "1") + out = [f"pcms.create_uniform_grid_discretization({grid})", order, ncomp] + if csys is not None: + out.append(csys) + out += [f"{KW_RENAME.get(k, k)}={v}" for k, v in kws.items()] + return "pcms.create_lagrange_space", out + + +def pr_from_mesh(args): + disc = f"pcms.backend.omega_h.create_discretization({args[0]})" + rest = [f"{KW_RENAME.get(kw(a)[0], kw(a)[0])}={kw(a)[1]}" + if kw(a)[0] else a for a in args[1:]] + return "pcms.create_polynomial_reconstruction_space", [disc] + rest + + +def simple(name): + return lambda args: (name, args) + + +def convert(text): + text = rewrite_calls(text, "pcms.LagrangeFunctionSpace.from_mesh(", + lagrange_from_mesh) + text = rewrite_calls(text, "pcms.LagrangeFunctionSpace.from_uniform_grid(", + lagrange_from_uniform_grid) + text = text.replace("pcms.LagrangeFunctionSpace.Backend.", + "pcms.LagrangeImplementation.") + text = rewrite_calls(text, + "pcms.PolynomialReconstructionFunctionSpace.from_mesh(", + pr_from_mesh) + text = rewrite_calls(text, "pcms.PolynomialReconstructionFunctionSpace.create(", + simple("pcms.create_polynomial_reconstruction_space")) + text = rewrite_calls(text, "pcms.OmegaHConservativeProjection(", + simple("pcms.create_conservative_projection")) + text = rewrite_calls(text, "pcms.OmegaHControlVariateProjection(", + simple("pcms.create_control_variate_projection")) + text = re.sub(r"\bpcms\.compute_entity_centroids_few\b", + "pcms.compute_entity_centroids", text) + for name in ("create_uniform_grid_binary_field", + "create_uniform_grid_from_mesh", + "map_entity_field_to_vertices_average", + "map_entity_field_to_vertices_mls", + "compute_entity_centroids"): + text = re.sub(rf"(? [ ...] + +Each is a path relative to the repository root, e.g. src/pcms/field. +Every ``*.h`` and ``*.h.in`` file below it is renamed with ``git mv`` to +``*.hpp`` / ``*.hpp.in``. Then every reference to a renamed header is +rewritten: + +* ``#include`` / ``%include`` directives in C/C++/SWIG sources, whether the + include is written relative to the including file or relative to ``src/`` + (``pcms/...``); +* file names listed in ``CMakeLists.txt`` / ``*.cmake`` files, relative to the + directory of that CMake file, its binary-dir equivalent, or ``src/``. + +The C API headers in ``src/pcms/capi`` are never renamed. The script is +deterministic: running it twice is a no-op. +""" + +import os +import re +import subprocess +import sys + +ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) +SRC = os.path.join(ROOT, "src") +EXCLUDE_DIRS = [os.path.join(SRC, "pcms", "capi")] +CODE_EXT = (".h", ".hpp", ".c", ".cpp", ".cc", ".i", ".h.in", ".hpp.in") +CMAKE_NAMES = ("CMakeLists.txt",) +CMAKE_EXT = (".cmake", ".cmake.in") +SKIP_TREES = (".git", "build") + +INCLUDE_RE = re.compile(r'^(\s*[#%]\s*include\s*)([<"])([^>"]+)([>"])', re.M) +CMAKE_TOKEN_RE = re.compile(r'(?. + +Usage (from the repository root): + tools/reorg/sublib_namespace.py + + lists the files whose code moves (the private headers of the +sub-library and the sources that implement them; '#' starts a comment); + lists the namespace-scope names they declare that are used +elsewhere. Same rules as backend_namespace.py: `namespace pcms` becomes +`namespace pcms::` in the listed files, references to pcms::detail +names from a file set that declares its own nested detail namespace are +written pcms::detail::X, and uses of the listed symbols in every other file +become pcms::::X. Public API types are not listed and stay in pcms. +External library namespaces are left as they are (no sub-library namespace +shadows one). Running the script twice is a no-op. +""" +import os +import sys + +sys.path.insert(0, os.path.dirname(__file__)) +import backend_namespace as bn # noqa: E402 + +if __name__ == "__main__": + if len(sys.argv) != 4: + sys.exit(__doc__) + lib, symfile, filesfile = sys.argv[1:] + bn.move_namespace(f"pcms::{lib}", bn.read_list(filesfile), + bn.read_list(symfile), external_prefix=False) diff --git a/tools/reorg/symbol-map.txt b/tools/reorg/symbol-map.txt new file mode 100644 index 000000000..439a42208 --- /dev/null +++ b/tools/reorg/symbol-map.txt @@ -0,0 +1,168 @@ +# PCMS 0.3 -> 0.4 symbol map, used by tools/migrate-pcms.sh. +# Format: +# cmake-option / cmake-target: renamed CMake option or imported target +# (the old option names still work in 0.4 with a deprecation warning; +# pcms::core is a deprecated alias of pcms::pcms) +# macro: renamed preprocessor macro +# cpp: C++ name that moved to another namespace and is still public; +# migrate-pcms.sh rewrites it +# cpp-private: C++ name that moved and is no longer installed; code outside +# PCMS must use the public replacement (see the manual entries and +# MIGRATION.md); migrate-pcms.sh only reports it +# manual: API that changed shape; migrate-pcms.sh reports uses +# A trailing "external" flag skips the entry under --in-tree: PCMS itself +# still defines the old name (the deprecated pcms::core alias; MAX_DIM, the +# MLS kernels' constant, which is unrelated to the renamed macro). +# Python code is migrated by tools/reorg/python_api_names.py. +cmake-option PCMS_ENABLE_Python PCMS_ENABLE_PYTHON +cmake-option PCMS_ENABLE_Fortran PCMS_ENABLE_FORTRAN +cmake-option PETSC_LINK_STATIC PCMS_PETSC_LINK_STATIC +cmake-target pcms::core pcms::pcms external +macro MAX_DIM PCMS_MAX_DIM external +macro ACTIVE_GPU_EXECUTION PCMS_ACTIVE_GPU_EXECUTION +macro PCMS_ENABLE_Fortran PCMS_ENABLE_FORTRAN +cpp-private pcms::MFEMLayout pcms::backend::mfem::MFEMLayout +cpp-private pcms::MFEMVertexFieldData pcms::backend::mfem::MFEMVertexFieldData +cpp-private pcms::MFEMFieldFactory pcms::backend::mfem::MFEMFieldFactory +cpp-private pcms::OmegaHDiscretization pcms::backend::omega_h::OmegaHDiscretization +cpp-private pcms::OmegaHEntityLayout pcms::backend::omega_h::OmegaHEntityLayout +cpp-private pcms::OmegaHLagrangeLayout pcms::backend::omega_h::OmegaHLagrangeLayout +cpp-private pcms::OmegaHLagrangeEvaluatorFactory pcms::backend::omega_h::OmegaHLagrangeEvaluatorFactory +cpp-private pcms::OmegaHLagrangePointEvaluator pcms::backend::omega_h::OmegaHLagrangePointEvaluator +cpp-private pcms::OmegaHLagrangeLocHint pcms::backend::omega_h::OmegaHLagrangeLocHint +cpp-private pcms::FindSupports pcms::backend::omega_h::FindSupports +cpp-private pcms::searchNeighbors pcms::backend::omega_h::searchNeighbors +cpp-private pcms::Queue pcms::backend::omega_h::Queue +cpp-private pcms::Track pcms::backend::omega_h::Track +cpp pcms::CreateUniformGridBinaryField pcms::backend::omega_h::CreateUniformGridBinaryField +cpp-private pcms::MeshFieldBackend pcms::backend::omega_h_meshfields::MeshFieldBackend +cpp-private pcms::MeshFieldBackendImpl pcms::backend::omega_h_meshfields::MeshFieldBackendImpl +cpp-private pcms::MakeBackendForComponents pcms::backend::omega_h_meshfields::MakeBackendForComponents +cpp-private pcms::MakeMeshFieldBackend pcms::backend::omega_h_meshfields::MakeMeshFieldBackend +cpp-private pcms::MeshFieldsAdapter2LocalizationHint pcms::backend::omega_h_meshfields::MeshFieldsAdapter2LocalizationHint +cpp-private pcms::MeshFieldsAdapterLayout pcms::backend::omega_h_meshfields::MeshFieldsAdapterLayout +cpp-private pcms::MeshFieldsFieldData pcms::backend::omega_h_meshfields::MeshFieldsFieldData +cpp-private pcms::MeshFieldsEvaluatorFactory pcms::backend::omega_h_meshfields::MeshFieldsEvaluatorFactory +cpp-private pcms::MeshFieldsPointEvaluator pcms::backend::omega_h_meshfields::MeshFieldsPointEvaluator +cpp-private pcms::PointCloudDiscretization pcms::backend::point_cloud::PointCloudDiscretization +cpp-private pcms::PointCloud pcms::backend::point_cloud::PointCloud +cpp-private pcms::PointCloudLayout pcms::backend::point_cloud::PointCloudLayout +cpp-private pcms::PointCloudEvaluatorFactory pcms::backend::point_cloud::PointCloudEvaluatorFactory +cpp-private pcms::MLSPointEvaluator pcms::backend::point_cloud::MLSPointEvaluator +cpp-private pcms::PointCloudLocalizationFactory pcms::backend::point_cloud::PointCloudLocalizationFactory +cpp pcms::ExchangePlan pcms::coupler::ExchangePlan +cpp pcms::FieldCommunicator pcms::coupler::FieldCommunicator +cpp pcms::FieldCommunicator2Ptr pcms::coupler::FieldCommunicator2Ptr +cpp pcms::FieldCommunicator2PtrT pcms::coupler::FieldCommunicator2PtrT +cpp pcms::FieldExchangePlanner pcms::coupler::FieldExchangePlanner +cpp pcms::FieldLayoutCommunicator pcms::coupler::FieldLayoutCommunicator +cpp pcms::FieldSerializer pcms::coupler::FieldSerializer +cpp pcms::GenericFieldExchangePlanner pcms::coupler::GenericFieldExchangePlanner +cpp-private pcms::GetRank pcms::coupler::GetRank +cpp pcms::GlobalCommunicator pcms::coupler::GlobalCommunicator +cpp-private pcms::Partition pcms::coupler::Partition +cpp-private pcms::EmptyDiscretization pcms::discretization::EmptyDiscretization +cpp-private pcms::AppendGidPermutation pcms::field::AppendGidPermutation +cpp-private pcms::BuildSortedGidPermutation pcms::field::BuildSortedGidPermutation +cpp-private pcms::EmptyFieldLayout pcms::field::EmptyFieldLayout +cpp-private pcms::FieldEvaluatorFactory pcms::field::FieldEvaluatorFactory +cpp-private pcms::GidToIndexMaps pcms::field::GidToIndexMaps +cpp-private pcms::LagrangeFunctionSpace pcms::field::LagrangeFunctionSpace +cpp-private pcms::MakeUnmappedPermutation pcms::field::MakeUnmappedPermutation +cpp-private pcms::PolynomialReconstructionFunctionSpace pcms::field::PolynomialReconstructionFunctionSpace +cpp-private pcms::SplineFunctionSpace pcms::field::SplineFunctionSpace +cpp-private pcms::mls_interpolation pcms::field::mls_interpolation +cpp-private pcms::AdjacencyLocalizationFactory pcms::localization::AdjacencyLocalizationFactory +cpp-private pcms::BuildPointCloudSupports pcms::localization::BuildPointCloudSupports +cpp-private pcms::GetOwningElementId pcms::localization::GetOwningElementId +cpp-private pcms::GridPointSearch2D pcms::localization::GridPointSearch2D +cpp-private pcms::GridPointSearch3D pcms::localization::GridPointSearch3D +cpp-private pcms::GridPointSearchVariant pcms::localization::GridPointSearchVariant +cpp-private pcms::LocalizationFactory pcms::localization::LocalizationFactory +cpp-private pcms::PointLocalizationSearch pcms::localization::PointLocalizationSearch +cpp-private pcms::PointLocalizationSearch2D pcms::localization::PointLocalizationSearch2D +cpp-private pcms::PointLocalizationSearch3D pcms::localization::PointLocalizationSearch3D +cpp-private pcms::SupportResults pcms::localization::SupportResults +cpp-private pcms::adapt_radii pcms::localization::adapt_radii +cpp-private pcms::minmax pcms::localization::minmax +cpp-private pcms::triangle_intersects_bbox pcms::localization::triangle_intersects_bbox +cpp-private pcms::within_number_of_support_range pcms::localization::within_number_of_support_range +cpp-private pcms::BilinearFormIntegrator pcms::transfer::BilinearFormIntegrator +cpp-private pcms::BuildOmegaHConservativeRHSIntegrator pcms::transfer::BuildOmegaHConservativeRHSIntegrator +cpp-private pcms::BuildOmegaHMassIntegrator pcms::transfer::BuildOmegaHMassIntegrator +cpp-private pcms::FindIntersections pcms::transfer::FindIntersections +cpp-private pcms::GalerkinProjectionSolver pcms::transfer::GalerkinProjectionSolver +cpp-private pcms::InterpolationBase pcms::transfer::InterpolationBase +cpp-private pcms::IntersectionResults pcms::transfer::IntersectionResults +cpp-private pcms::LinearFormIntegrator pcms::transfer::LinearFormIntegrator +cpp-private pcms::MLSMeshInterpolation pcms::transfer::MLSMeshInterpolation +cpp-private pcms::MLSPointCloudInterpolation pcms::transfer::MLSPointCloudInterpolation +cpp-private pcms::MassMatrixIntegrator pcms::transfer::MassMatrixIntegrator +cpp-private pcms::OmegaHConservativeProjection pcms::transfer::OmegaHConservativeProjection +cpp-private pcms::OmegaHControlVariateProjection pcms::transfer::OmegaHControlVariateProjection +cpp-private pcms::OmegaHIntersectionRHSIntegrator pcms::transfer::OmegaHIntersectionRHSIntegrator +cpp-private pcms::OmegaHMassIntegrator pcms::transfer::OmegaHMassIntegrator +cpp-private pcms::OmegaHMonteCarloRHSIntegrator pcms::transfer::OmegaHMonteCarloRHSIntegrator +cpp-private pcms::build_linear_triangle_coo_rows pcms::transfer::build_linear_triangle_coo_rows +cpp-private pcms::build_linear_triangle_coo_rows_cols pcms::transfer::build_linear_triangle_coo_rows_cols +cpp-private pcms::copyHostScalarArrayView2HostWrite pcms::transfer::copyHostScalarArrayView2HostWrite +cpp-private pcms::copyHostWrite2ScalarArrayView pcms::transfer::copyHostWrite2ScalarArrayView +cpp-private pcms::createSeqAIJMat pcms::transfer::createSeqAIJMat +cpp-private pcms::createSeqVec pcms::transfer::createSeqVec +cpp-private pcms::intersectTargets pcms::transfer::intersectTargets +cpp-private pcms::ArrayMask pcms::utility::ArrayMask +cpp-private pcms::EnsureClassification pcms::utility::EnsureClassification +cpp-private pcms::GetMPIType pcms::utility::GetMPIType +cpp-private pcms::distance_squared pcms::utility::distance_squared +cpp-private pcms::flatten_to_omega_h_reals pcms::utility::flatten_to_omega_h_reals +cpp-private pcms::flatten_to_omega_h_reals_host pcms::utility::flatten_to_omega_h_reals_host +cpp-private pcms::get_entity_centroids pcms::utility::get_entity_centroids +cpp-private pcms::UniformGridDiscretization pcms::backend::uniform_grid::UniformGridDiscretization +cpp-private pcms::UniformGridFieldLayout pcms::backend::uniform_grid::UniformGridFieldLayout +cpp-private pcms::UniformGridFieldLayout2D pcms::backend::uniform_grid::UniformGridFieldLayout2D +cpp-private pcms::UniformGridEvaluatorFactory pcms::backend::uniform_grid::UniformGridEvaluatorFactory +cpp-private pcms::UniformGridEvaluatorFactory2D pcms::backend::uniform_grid::UniformGridEvaluatorFactory2D +cpp-private pcms::UniformGridFieldLocalizationHint pcms::backend::uniform_grid::UniformGridFieldLocalizationHint +cpp-private pcms::UniformGridPointEvaluator pcms::backend::uniform_grid::UniformGridPointEvaluator +cpp-private pcms::UniformGridSplineEvaluatorFactory2D pcms::backend::uniform_grid::UniformGridSplineEvaluatorFactory2D +cpp-private pcms::UniformGridSplinePointEvaluator2D pcms::backend::uniform_grid::UniformGridSplinePointEvaluator2D +cpp-private pcms::BoundaryCondition pcms::backend::uniform_grid::BoundaryCondition +cpp-private pcms::CubicSplineInterpolator pcms::backend::uniform_grid::CubicSplineInterpolator +cpp-private pcms::ExplicitCubicSplineInterpolator pcms::backend::uniform_grid::ExplicitCubicSplineInterpolator +cpp-private pcms::CompactCubicSplineInterpolator pcms::backend::uniform_grid::CompactCubicSplineInterpolator +cpp-private pcms::BiCubicSplineInterpolator pcms::backend::uniform_grid::BiCubicSplineInterpolator +cpp-private pcms::ExplicitBiCubicSplineInterpolator pcms::backend::uniform_grid::ExplicitBiCubicSplineInterpolator +cpp-private pcms::CompactBiCubicSplineInterpolator pcms::backend::uniform_grid::CompactBiCubicSplineInterpolator +cpp-private pcms::RegularGridInterpolator pcms::backend::uniform_grid::RegularGridInterpolator +cpp-private pcms::RealMatView pcms::backend::uniform_grid::RealMatView +cpp-private pcms::RealVecView pcms::backend::uniform_grid::RealVecView +cpp-private pcms::IntMatView pcms::backend::uniform_grid::IntMatView +cpp-private pcms::IntVecView pcms::backend::uniform_grid::IntVecView +cpp-private pcms::HostIntVecView pcms::backend::uniform_grid::HostIntVecView +cpp-private pcms::XGCDiscretization pcms::backend::xgc::XGCDiscretization +cpp pcms::DimID pcms::backend::xgc::DimID +cpp pcms::ReverseClassificationVertex pcms::backend::xgc::ReverseClassificationVertex +cpp pcms::ReadReverseClassificationVertex pcms::backend::xgc::ReadReverseClassificationVertex +cpp pcms::IndexBase pcms::backend::xgc::IndexBase +cpp pcms::ConstructRCFromOmegaHMesh pcms::backend::xgc::ConstructRCFromOmegaHMesh +cpp-private pcms::XGCFieldLayout pcms::backend::xgc::XGCFieldLayout +cpp-private pcms::XGCFieldData pcms::backend::xgc::XGCFieldData +cpp-private pcms::XGCFieldFactory pcms::backend::xgc::XGCFieldFactory +cpp pcms::CreateUniformGridFromMesh pcms::backend::omega_h::CreateUniformGridFromMesh +manual pcms::LagrangeFunctionSpace::FromMesh -> pcms::CreateLagrangeSpace(pcms::backend::omega_h::CreateDiscretization(mesh[, global_id_name]), order, ncomp, csys, {implementation}) +manual pcms::LagrangeFunctionSpace::FromUniformGrid -> pcms::CreateLagrangeSpace(pcms::CreateUniformGridDiscretization(grid), order, ncomp, csys) +manual pcms::LagrangeFunctionSpace::Backend -> pcms::LagrangeImplementation (in pcms::LagrangeOptions) +manual pcms::SplineFunctionSpace::FromUniformGrid -> pcms::CreateSplineSpace(pcms::CreateUniformGridDiscretization(grid), csys) +manual pcms::PolynomialReconstructionFunctionSpace::Create -> pcms::CreatePolynomialReconstructionSpace(points, options) +manual pcms::PolynomialReconstructionFunctionSpace::FromMesh -> pcms::CreatePolynomialReconstructionSpace(pcms::backend::omega_h::CreateDiscretization(mesh), entity_dim, csys, options) +manual pcms::OmegaHConservativeProjection -> pcms::CreateConservativeProjection(source_space, target_space, {mass_matrix_type}) +manual pcms::OmegaHControlVariateProjection -> pcms::CreateControlVariateProjection(source, target_space, {samples_per_element, sampling, seed, mass_matrix_type}) +manual pcms::XGCFieldFactory -> pcms::backend::xgc::CreateFieldFactory(rc, num_plane_nodes, layout_name) +manual pcms::XGCFieldData -> pcms::backend::xgc::CreateField(factory, name, data, plane_comm) +manual pcms::MFEMFieldFactory -> pcms::backend::mfem::CreateFieldFactory(pmesh, pfes, gf, csys, layout_name) +manual pcms::MFEMLayout::OverlapMaskFromAttribute -> pcms::backend::mfem::OverlapMaskFromAttribute(pmesh, attribute) +manual pcms::EmptyFieldLayout -> pcms::CreateEmptyLayout(csys, num_components) +manual pcms::OverlapMask(size, Omega_h::Read) -> pcms::OverlapMask(size, pcms::backend::omega_h::OverlapMaskFromArray(mask)) +manual pcms::MakeConstRank2View(Omega_h::Read, dim) -> pcms::backend::omega_h::MakeConstRank2View(array, dim) +manual redev::Mode (in ApplicationComm/FieldHandle/DataHandle Send/Receive) -> pcms::Mode +manual FunctionSpace::mesh() (Python) -> pcms.backend.omega_h.get_mesh(space.get_discretization())