diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 88ae664449..d671f2cd8f 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -12,8 +12,8 @@ concurrency: cancel-in-progress: ${{ github.ref != 'refs/heads/develop' }} env: - CLANG_DOCKER_IMAGE: axom/tpls:clang-19_01-29-26_21h-32m - GCC_DOCKER_IMAGE: axom/tpls:gcc-13_01-29-26_21h-28m + CLANG_DOCKER_IMAGE: axom/tpls:clang-19_02-17-26_21h-05m + GCC_DOCKER_IMAGE: axom/tpls:gcc-13_02-17-26_21h-05m jobs: # Hacky solution to reference env variables outside of `run` steps https://stackoverflow.com/a/74217028 @@ -43,7 +43,7 @@ jobs: - job_name: gcc@13.3.1, shared, 32bit host_config: gcc@13.3.1.cmake compiler_image: ${{ needs.set_image_vars.outputs.gcc_docker_image }} - cmake_opts: '-DBUILD_SHARED_LIBS=ON -DAXOM_USE_64BIT_INDEXTYPE:BOOL=OFF' + cmake_opts: '-DBUILD_SHARED_LIBS=ON -DAXOM_USE_64BIT_INDEXTYPE:BOOL=OFF -DAXOM_NO_INT64_T=1' do_build: 'yes' do_benchmarks: 'no' - job_name: llvm@19.0.0, shared, benchmarks, quest regression diff --git a/.gitlab/build_tuolumne.yml b/.gitlab/build_tuolumne.yml index b1ca276a65..fbededfef3 100644 --- a/.gitlab/build_tuolumne.yml +++ b/.gitlab/build_tuolumne.yml @@ -36,17 +36,17 @@ #### # PR Build jobs -tuolumne-llvm-amdgpu_6_4_2_hip-src: +tuolumne-llvm-amdgpu_6_4_3_hip-src: variables: - COMPILER: "llvm-amdgpu@6.4.2_hip" + COMPILER: "llvm-amdgpu@6.4.3_hip" HOST_CONFIG: "tuolumne-toss_4_x86_64_ib_cray-${COMPILER}.cmake" extends: .src_build_on_tuolumne #### # Full Build jobs -tuolumne-llvm-amdgpu_6_4_2_hip-full: +tuolumne-llvm-amdgpu_6_4_3_hip-full: variables: - COMPILER: "llvm-amdgpu@6.4.2_hip" + COMPILER: "llvm-amdgpu@6.4.3_hip" SPEC: "%${COMPILER}~openmp+rocm+mfem+c2c" - EXTRASPEC: "amdgpu_target=gfx90a ^hip@6.4.2 ^hsa-rocr-dev@6.4.2 ^raja~openmp+rocm ^umpire~openmp+rocm ^hdf5 cflags=-Wno-int-conversion" + EXTRASPEC: "amdgpu_target=gfx90a ^hip@6.4.3 ^hsa-rocr-dev@6.4.3 ^raja~openmp+rocm ^umpire~openmp+rocm ^hdf5 cflags=-Wno-int-conversion" extends: .full_build_on_tuolumne diff --git a/.gitmodules b/.gitmodules index 1f509ed31e..3967cf78b9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,6 +7,3 @@ [submodule "scripts/uberenv"] path = scripts/uberenv url = https://github.com/LLNL/uberenv.git -[submodule "scripts/spack/radiuss-spack-configs"] - path = scripts/spack/radiuss-spack-configs - url = https://github.com/LLNL/radiuss-spack-configs.git diff --git a/.uberenv_config.json b/.uberenv_config.json index cfdb246a9e..810d574338 100644 --- a/.uberenv_config.json +++ b/.uberenv_config.json @@ -4,10 +4,10 @@ "package_final_phase": "initconfig", "package_source_dir": "../..", "spack_url": "https://github.com/spack/spack.git", -"spack_commit": "0c2be44e4ece21eb091ad5de4c97716b7c6d4c87", +"spack_commit": "2e2169d5282d166f63e3ee4db8d4446c43cefa8a", "spack_configs_path": "scripts/spack/configs", -"spack_packages_commit": "ba7ec6e6121679029b2f4ccff8c3806f0450e563", -"spack_packages_path": ["scripts/spack/radiuss-spack-configs/spack_repo/llnl_radiuss/packages", "scripts/spack/packages"], +"spack_packages_commit": "17ea6a6d483fc0bde1b2cca96ddaad0a10f2ef69", +"spack_packages_path": "scripts/spack/packages", "spack_concretizer": "clingo", "vcpkg_url": "https://github.com/microsoft/vcpkg", "vcpkg_commit": "ce613c41372b23b1f51333815feb3edd87ef8a8b", diff --git a/COPYRIGHT b/COPYRIGHT index 48a76480c0..d30c983997 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -1,6 +1,20 @@ Intellectual Property Notice ------------------------------ +Axom is produced at the Lawrence Livermore National Laboratory + +Unlimited Open Source - BSD Distribution +LLNL-CODE-825966 +CP02462 + +Previous open source releases: +Unlimited Open Source - BSD Distribution +LLNL-CODE-741217 +OCEC-17-187 + +This file is part of Axom +For details, see https://github.com/llnl/axom + Axom is licensed under the BSD 3-Clause license (BSD-3-Clause or https://opensource.org/licenses/BSD-3-Clause). diff --git a/LICENSE b/LICENSE index fa5acdbbe0..61b9091bab 100644 --- a/LICENSE +++ b/LICENSE @@ -1,24 +1,8 @@ -Copyright (c) 2017-2026, Lawrence Livermore National Security, LLC. - -Produced at the Lawrence Livermore National Laboratory - -Unlimited Open Source - BSD Distribution -LLNL-CODE-825966 -CP02462 - -Previous open source releases: -Unlimited Open Source - BSD Distribution -LLNL-CODE-741217 -OCEC-17-187 +BSD 3-Clause License +Copyright (c) 2017-2026, Lawrence Livermore National Security, LLC. All rights reserved. -This file is part of Axom - -For details, see https://github.com/llnl/axom - -Please also read axom/COPYRIGHT - Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: diff --git a/RELEASE-NOTES.md b/RELEASE-NOTES.md index 6998290f14..e11540da9b 100644 --- a/RELEASE-NOTES.md +++ b/RELEASE-NOTES.md @@ -18,6 +18,42 @@ The Axom project release numbers follow [Semantic Versioning](http://semver.org/ ## [Unreleased] - Release date yyyy-mm-dd +### Added + +### Removed + +### Deprecated + +### Changed + +### Fixed + +## [Version 0.14.0] - Release date 2026-03-31 + +### Added +- Lumberjack: Adds optional virtual function `isMessageCandidateForCombiner()` to the `Combiner` + class that checks if a single given Message is a candidate for the Combiner (returns true by default). +- Sidre: Added Conduit `Node` to the Python interface. +- Adds yapf as a Python formatter. +- Quest: Adds fast GWN methods for STL/Triangulated STEP input and linearized NURBS Curve input which + leverage error-controlled approximation and a spatial index (BVH). + +### Changed +- Primal: Axom's polygon clipping was modified to handle some corner cases. +- Mir: The `EquiZAlgorithm` class was improved so it performs better with OpenMP. +- Bump: Several Bump algorithms were improved so they perform better with OpenMP. +- Many algorithms in Bump and Mir have been enhanced with `setAllocatorID()` methods to permit use of custom allocators. +- Uberenv's spack updated to v1.1.1 +- `radiuss-spack-configs` submodule removed. + +### Fixed +- Primal: Fixed `NURBSPatch::evaluateDerivatives` returning a matrix with empty values. The old behavior + can be recovered with an optional flag, which is more efficient if the previously missing values are unneeded +- Core: the `ArrayView` class was modified so it defers initializing an internal + allocator id via Umpire, if present. This prevents excessive calls to Umpire, + which are not needed in all use cases. +- Quest: A compilation problem with `-DAXOM_NO_INT64_T=1` was fixed. + ## [Version 0.13.0] - Release date 2026-02-05 ### Added @@ -1384,7 +1420,8 @@ fractions for the associated materials must be supplied before shaping. - Use this section in case of vulnerabilities -[Unreleased]: https://github.com/LLNL/axom/compare/v0.13.0...develop +[Unreleased]: https://github.com/LLNL/axom/compare/v0.14.0...develop +[Version 0.14.0]: https://github.com/LLNL/axom/compare/v0.13.0...v0.14.0 [Version 0.13.0]: https://github.com/LLNL/axom/compare/v0.12.0...v0.13.0 [Version 0.12.0]: https://github.com/LLNL/axom/compare/v0.11.0...v0.12.0 [Version 0.11.0]: https://github.com/LLNL/axom/compare/v0.10.1...v0.11.0 diff --git a/data b/data index 34b0dae40b..1619ab1f98 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit 34b0dae40b204879101c5d94e8920ac1f0f55409 +Subproject commit 1619ab1f98f3cc3b06f356c531c0b385ea42b0b7 diff --git a/host-configs/dane-toss_4_x86_64_ib-gcc@13.3.1.cmake b/host-configs/dane-toss_4_x86_64_ib-gcc@13.3.1.cmake index e32d6dbc63..0e8f266def 100644 --- a/host-configs/dane-toss_4_x86_64_ib-gcc@13.3.1.cmake +++ b/host-configs/dane-toss_4_x86_64_ib-gcc@13.3.1.cmake @@ -4,28 +4,28 @@ # CMake executable path: /usr/tce/packages/cmake/cmake-3.26.3/bin/cmake #------------------------------------------------------------------------------ -set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/blt-develop-vkyjvzyg7n4ig7x4llo53lndvnwsrbjq;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/c2c-1.8.0-3bch3wbxcl3eji2wsbbbzmagowxe4lpc;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-yhzgzz2ex4ic63ogwwtds2izsvkkadh3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/conduit-0.9.5-icskqkcmikkfw2itxiq6xdt6nilzlsvr;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/mfem-4.9.0-bipzszywmjx53fi7latomyhw5665mi4h;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-xqo4atvwmb3az7u6odq3zmsdlk2j3xhe;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/scr-3.0.1-lwjvdlbifmo7m3d552nskugm6lssccnm;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-btsargdd7jlgzc76ciko62u6tg5twsaz;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/adiak-0.4.0-45h4d32dvvatilujstudj3ucvmdeyi6a;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/libunwind-1.8.3-74hjhhtejjsdgxjpp262xlm5ow6psq4r;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/hdf5-1.8.23-gokrordtweyfprtzgrzsycyilhy32uc7;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/parmetis-4.0.3-euggsyckxbtpzv6kzq74k3ndngpw2yqh;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/hypre-2.27.0-ddqcjjo7acriziqye5rracqx6pnkncj5;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/axl-0.7.1-q2rxtt4nowyjknvxudfg5vszvdgwhr57;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/dtcmp-1.1.5-4bnm6uirjgbss5vgcmahsappp7cjjquh;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/er-0.3.0-4tzpoetvdc2tohxujfxu5ctlu6ndjytt;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/libyogrt-1.35-hp6xkhmzi5wbhvc4jzqli66m4uhrqz4i;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/spath-0.2.0-yip5q3eadzz56niotmpoqf4p3hkmlrmb;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-t6jbvd33b45eq6ssp5guraifij3y7huw;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/fmt-11.0.2-faqgdwrlrl4nwv35msienhldhqrq2vce;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/metis-5.1.0-ovo3o7do7zr5fxw6mi2flzy6ftfsavk2;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/lwgrp-1.0.6-5aend7qfofhskqpuwduxvzaqcyrs6w4e;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/redset-0.2.0-ml4pwcex7h2rsooauoaoajsli7yg2po6;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/shuffile-0.2.0-6qqtnapl6yb5gq7ii6l7e4543wqumv75;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/rankstr-0.2.0-4mvhlooa4a5gqoyvwel73p4aimodhbqn;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/kvtree-1.3.0-ldkjgqadvd44hgy7djvq4xgmwmxjs4gx;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/none-none/gcc-runtime-13.3.1-k43mnfzd4ehqvovn4d5qq7b5f6sfetsx;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/usr/tce/packages/cmake/cmake-3.26.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/gcc-13.3.1/cppcheck-2.18.0-d2tmb7ls2d5vgh6vhcyohecwcu6msopb;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/doxygen-1.13.2;/usr/tce/packages/gcc/gcc-13.3.1;/usr/tce/packages/clang/clang-19.1.3;/usr/tce/packages/mvapich2/mvapich2-2.3.7-gcc-13.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5" CACHE STRING "") +set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/blt-0.7.1-yiu2olkumeazbrto7x4v2dv6qbefhf5a;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/c2c-1.8.0-jkclfdpl7igj3ur3ufnpt6dupjfvotpc;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-f4kbq52oexscd7dhlwdbffygha5losj5;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/conduit-0.9.5-xyt2d2ot4eozuhrjv7mccoe7tw6ef7ui;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/mfem-4.9.0-heih2kd5qpkalflltitlry3g4qpyx5xw;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/py-nanobind-2.7.0-szozdpwzge7ah4bsilit6fijezxqbfop;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/py-pytest-9.0.0-vozuj6nkk42nhxeo5mawnux3w7bj3awe;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-ktky5uf7luvuf4cnczifj5av5ndbajco;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/scr-3.0.1-tnom76yaaoeyob7dncuafxebkzf2fbv7;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/umpire-2025.12.0-m6o7ya6pnrpixhpygzywlzoue3zuuir3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/adiak-0.4.0-i5bahteezqmswdv2ulpfvfogmuue463q;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/libunwind-1.8.3-pwdmczcnf7vugfly5zk7eztefnn7kv75;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/hdf5-1.8.23-2pnsuxpt6r2wmdc6sqyku6ki6na4gcfl;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/parmetis-4.0.3-tt2yxrbsrccyglhjqcs2y2nspmt4qoqx;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/py-numpy-2.4.2-z4yapdkn22w6adfrl7ibucqiokgrwb7f;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/hypre-2.27.0-vwir3t6mlgbmo3mgfbiayrpbbdxsrsha;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/axl-0.7.1-yoi3m7zjahalmglnbo33aitshq6cj43q;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/dtcmp-1.1.5-ipjglgrmgotna4yza37ecwiur3rkx6wf;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/er-0.3.0-bdvz66gxhiflazj3irsv5vleaphtypqz;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/libyogrt-1.35-qwz3xpqmkwgh5byk2kiy3txbazfwwf3c;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/spath-0.2.0-pmsauxzx75wu4kyfwjf3ite5dzzaymhv;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-cc5noebugovl4o6ir2d65bx7qizwznef;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/fmt-11.0.2-ggfpxocredbjrldu7ar33cjedhmkm3da;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/metis-5.1.0-3jtvhjwnhqqaf5v2na7f675qgvlusyx3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/lwgrp-1.0.6-lkotiz6t6q3r5nmgqcfhfvdyukzdnnuu;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/redset-0.2.0-2kb4kg3ypf7l66vxdt6x2z4oqvimt3bs;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/shuffile-0.2.0-v2buhpkgx2py4m4bny4lsflaoeqbmqof;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/rankstr-0.2.0-xkzr7o47vbxkwtxppil7a7i57dhlk5gf;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/kvtree-1.3.0-py6ds6lmww6eqlhjgb4vilk6ftkxsuud;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/gcc-runtime-13.3.1-zsobnkwck2glzcbukupgvgbiwwhdonys;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/usr/tce/packages/cmake/cmake-3.26.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/gcc-13.3.1/cppcheck-2.18.0-i3p56kpf66xzj4wm5kfqxyc4vgox7gb3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/doxygen-1.15.0;/usr/tce/packages/gcc/gcc-13.3.1;/usr/tce/packages/clang/clang-19.1.3;/usr/tce/packages/mvapich2/mvapich2-2.3.7-gcc-13.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11" CACHE STRING "") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") -set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/axom-develop-ygincdbfj2qpcjz3hznn64bsr5v76e6v/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/axom-develop-ygincdbfj2qpcjz3hznn64bsr5v76e6v/lib64;;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/axom-develop-s37sdvbj7bw3warwbjp4izofxn5mok4c/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/axom-develop-s37sdvbj7bw3warwbjp4izofxn5mok4c/lib64;;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") -set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/axom-develop-ygincdbfj2qpcjz3hznn64bsr5v76e6v/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1/axom-develop-ygincdbfj2qpcjz3hznn64bsr5v76e6v/lib64;;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/axom-develop-s37sdvbj7bw3warwbjp4izofxn5mok4c/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1/axom-develop-s37sdvbj7bw3warwbjp4izofxn5mok4c/lib64;;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") #------------------------------------------------------------------------------ # Compilers #------------------------------------------------------------------------------ -# Compiler Spec: gcc@13.3.1/75lfrhqb3monlgkmkokrboaqienagc6u +# Compiler Spec: gcc@13.3.1/xrm3n2pex2en2wvm6p4ap62nieoz7kne #------------------------------------------------------------------------------ if(DEFINED ENV{SPACK_CC}) - set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/gcc/gcc" CACHE PATH "") + set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/gcc/gcc" CACHE PATH "") - set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/gcc/g++" CACHE PATH "") + set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/gcc/g++" CACHE PATH "") - set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/gcc/gfortran" CACHE PATH "") + set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/gcc/gfortran" CACHE PATH "") else() @@ -73,72 +73,84 @@ set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") # TPLs #------------------------------------------------------------------------------ -set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/gcc-13.3.1" CACHE PATH "") +set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/gcc-13.3.1" CACHE PATH "") -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-icskqkcmikkfw2itxiq6xdt6nilzlsvr" CACHE PATH "") +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-xyt2d2ot4eozuhrjv7mccoe7tw6ef7ui" CACHE PATH "") -set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-3bch3wbxcl3eji2wsbbbzmagowxe4lpc" CACHE PATH "") +set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-jkclfdpl7igj3ur3ufnpt6dupjfvotpc" CACHE PATH "") -set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-bipzszywmjx53fi7latomyhw5665mi4h" CACHE PATH "") +set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-heih2kd5qpkalflltitlry3g4qpyx5xw" CACHE PATH "") -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-gokrordtweyfprtzgrzsycyilhy32uc7" CACHE PATH "") +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-2pnsuxpt6r2wmdc6sqyku6ki6na4gcfl" CACHE PATH "") set(LUA_DIR "/usr" CACHE PATH "") -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-xqo4atvwmb3az7u6odq3zmsdlk2j3xhe" CACHE PATH "") +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-ktky5uf7luvuf4cnczifj5av5ndbajco" CACHE PATH "") -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-btsargdd7jlgzc76ciko62u6tg5twsaz" CACHE PATH "") +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-m6o7ya6pnrpixhpygzywlzoue3zuuir3" CACHE PATH "") # OPENCASCADE not built -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-45h4d32dvvatilujstudj3ucvmdeyi6a" CACHE PATH "") +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-i5bahteezqmswdv2ulpfvfogmuue463q" CACHE PATH "") -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-yhzgzz2ex4ic63ogwwtds2izsvkkadh3" CACHE PATH "") +set(CALIPER_DIR "${TPL_ROOT}/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-f4kbq52oexscd7dhlwdbffygha5losj5" CACHE PATH "") -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-t6jbvd33b45eq6ssp5guraifij3y7huw" CACHE PATH "") +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-cc5noebugovl4o6ir2d65bx7qizwznef" CACHE PATH "") -set(SCR_DIR "${TPL_ROOT}/scr-3.0.1-lwjvdlbifmo7m3d552nskugm6lssccnm" CACHE PATH "") +set(SCR_DIR "${TPL_ROOT}/scr-3.0.1-tnom76yaaoeyob7dncuafxebkzf2fbv7" CACHE PATH "") -set(KVTREE_DIR "${TPL_ROOT}/kvtree-1.3.0-ldkjgqadvd44hgy7djvq4xgmwmxjs4gx" CACHE PATH "") +set(KVTREE_DIR "${TPL_ROOT}/kvtree-1.3.0-py6ds6lmww6eqlhjgb4vilk6ftkxsuud" CACHE PATH "") -set(DTCMP_DIR "${TPL_ROOT}/dtcmp-1.1.5-4bnm6uirjgbss5vgcmahsappp7cjjquh" CACHE PATH "") +set(DTCMP_DIR "${TPL_ROOT}/dtcmp-1.1.5-ipjglgrmgotna4yza37ecwiur3rkx6wf" CACHE PATH "") -set(SPATH_DIR "${TPL_ROOT}/spath-0.2.0-yip5q3eadzz56niotmpoqf4p3hkmlrmb" CACHE PATH "") +set(SPATH_DIR "${TPL_ROOT}/spath-0.2.0-pmsauxzx75wu4kyfwjf3ite5dzzaymhv" CACHE PATH "") -set(AXL_DIR "${TPL_ROOT}/axl-0.7.1-q2rxtt4nowyjknvxudfg5vszvdgwhr57" CACHE PATH "") +set(AXL_DIR "${TPL_ROOT}/axl-0.7.1-yoi3m7zjahalmglnbo33aitshq6cj43q" CACHE PATH "") -set(LWGRP_DIR "${TPL_ROOT}/lwgrp-1.0.6-5aend7qfofhskqpuwduxvzaqcyrs6w4e" CACHE PATH "") +set(LWGRP_DIR "${TPL_ROOT}/lwgrp-1.0.6-lkotiz6t6q3r5nmgqcfhfvdyukzdnnuu" CACHE PATH "") -set(ER_DIR "${TPL_ROOT}/er-0.3.0-4tzpoetvdc2tohxujfxu5ctlu6ndjytt" CACHE PATH "") +set(ER_DIR "${TPL_ROOT}/er-0.3.0-bdvz66gxhiflazj3irsv5vleaphtypqz" CACHE PATH "") -set(RANKSTR_DIR "${TPL_ROOT}/rankstr-0.2.0-4mvhlooa4a5gqoyvwel73p4aimodhbqn" CACHE PATH "") +set(RANKSTR_DIR "${TPL_ROOT}/rankstr-0.2.0-xkzr7o47vbxkwtxppil7a7i57dhlk5gf" CACHE PATH "") -set(REDSET_DIR "${TPL_ROOT}/redset-0.2.0-ml4pwcex7h2rsooauoaoajsli7yg2po6" CACHE PATH "") +set(REDSET_DIR "${TPL_ROOT}/redset-0.2.0-2kb4kg3ypf7l66vxdt6x2z4oqvimt3bs" CACHE PATH "") -set(SHUFFILE_DIR "${TPL_ROOT}/shuffile-0.2.0-6qqtnapl6yb5gq7ii6l7e4543wqumv75" CACHE PATH "") +set(SHUFFILE_DIR "${TPL_ROOT}/shuffile-0.2.0-v2buhpkgx2py4m4bny4lsflaoeqbmqof" CACHE PATH "") -set(LIBYOGRT_DIR "${TPL_ROOT}/libyogrt-1.35-hp6xkhmzi5wbhvc4jzqli66m4uhrqz4i" CACHE PATH "") +set(LIBYOGRT_DIR "${TPL_ROOT}/libyogrt-1.35-qwz3xpqmkwgh5byk2kiy3txbazfwwf3c" CACHE PATH "") #------------------------------------------------------------------------------ -# Devtools +# Devtools & Python #------------------------------------------------------------------------------ -set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37" CACHE PATH "") +set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14" CACHE PATH "") set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/clang/clang-19.1.3/bin/clang-format" CACHE PATH "") -set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/python3" CACHE PATH "") +set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/python3" CACHE PATH "") -set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/jsonschema" CACHE PATH "") +set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/jsonschema" CACHE PATH "") set(ENABLE_DOCS ON CACHE BOOL "") -set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/sphinx-build" CACHE PATH "") +set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/sphinx-build" CACHE PATH "") + +set(YAPF_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/yapf" CACHE PATH "") set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0/bin/shroud" CACHE PATH "") -set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-d2tmb7ls2d5vgh6vhcyohecwcu6msopb/bin/cppcheck" CACHE PATH "") +set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-i3p56kpf66xzj4wm5kfqxyc4vgox7gb3/bin/cppcheck" CACHE PATH "") + +set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/doxygen-1.15.0/bin/doxygen" CACHE PATH "") + +set(PY_NANOBIND_DIR "${TPL_ROOT}/py-nanobind-2.7.0-szozdpwzge7ah4bsilit6fijezxqbfop/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PYTEST_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/py-pytest-9.0.0-vozuj6nkk42nhxeo5mawnux3w7bj3awe/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_NUMPY_DIR "${TPL_ROOT}/py-numpy-2.4.2-z4yapdkn22w6adfrl7ibucqiokgrwb7f/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PLUGGY_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/py-pluggy-1.6.0-6zab4pck6v7johubbhalr2waowbwpjei/lib/python3.13/site-packages" CACHE PATH "") -set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/doxygen-1.13.2/bin/doxygen" CACHE PATH "") +set(PY_INICONFIG_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/py-iniconfig-2.1.0-xwmbxuhk2oo3dcuizdp3z4hqbpqykkom/lib/python3.13/site-packages" CACHE PATH "") diff --git a/host-configs/dane-toss_4_x86_64_ib-intel-oneapi-compilers@2025.2.0.cmake b/host-configs/dane-toss_4_x86_64_ib-intel-oneapi-compilers@2025.2.0.cmake index c75e7a7b32..2c46309ced 100644 --- a/host-configs/dane-toss_4_x86_64_ib-intel-oneapi-compilers@2025.2.0.cmake +++ b/host-configs/dane-toss_4_x86_64_ib-intel-oneapi-compilers@2025.2.0.cmake @@ -4,28 +4,28 @@ # CMake executable path: /usr/tce/packages/cmake/cmake-3.26.3/bin/cmake #------------------------------------------------------------------------------ -set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/intel-oneapi-compilers-2025.2.0/blt-develop-scbtv5nm655fcgkpm7775x4u6wopde2o;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/intel-oneapi-compilers-2025.2.0/c2c-1.8.0-ogkaflkbghohdikxnvj4mmksdcjn2qud;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/intel-oneapi-compilers-2025.2.0/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-zjssskiaerbodbkih5epbj5fmpjq5m6p;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/intel-oneapi-compilers-2025.2.0/conduit-0.9.5-3tyhzfysh4umcgsnrp7d7p3abdbmkshp;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/intel-oneapi-compilers-2025.2.0/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-aqzabesamv77gi5i6cpgrbnka4zc4eni;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/intel-oneapi-compilers-2025.2.0/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-wps2nos3umjdrwudniuuo6xoosyp6qco;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/intel-oneapi-compilers-2025.2.0/adiak-0.4.0-svzknmon3cgc5yjd54hrxrzdc4e4htga;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/intel-oneapi-compilers-2025.2.0/libunwind-1.8.3-m7b5iissbuvvgj3ciugmytzudq5u3e3i;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/intel-oneapi-compilers-2025.2.0/hdf5-1.8.23-7sqi7ybehcspqaajunz7v6loau63ma2j;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/intel-oneapi-compilers-2025.2.0/parmetis-4.0.3-5rej7ae573vmqplcqozlpu5i6s4yipq3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/intel-oneapi-compilers-2025.2.0/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-kaem7te2437otmrrjhzhfclcq6j77pke;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/intel-oneapi-compilers-2025.2.0/fmt-11.0.2-blytd32zjrnjzszsgsvqknm24i6sdbn2;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/intel-oneapi-compilers-2025.2.0/metis-5.1.0-kkbw2eu3rzrxrtihlskhc6kwfle4ixfj;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/none-none/intel-oneapi-runtime-2025.2.0-24wotiwlsqmeinqvfb3b2qlvcjh4pcju;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/none-none/gcc-runtime-13.3.1-k43mnfzd4ehqvovn4d5qq7b5f6sfetsx;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/usr/tce/packages/cmake/cmake-3.26.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/gcc-13.3.1/cppcheck-2.18.0-d2tmb7ls2d5vgh6vhcyohecwcu6msopb;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/doxygen-1.13.2;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/intel-oneapi-compilers-2025.2.0-ngszoacyp2i5d5nawitlyuh37jswjtie/compiler/2025.2;/usr/tce/packages/intel/intel-2025.2.0;/usr/tce/packages/clang/clang-19.1.3;/usr/tce/packages/mvapich2/mvapich2-2.3.7-intel-2025.2.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5" CACHE STRING "") +set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/intel-oneapi-compilers-2025.2.0/blt-0.7.1-2n76efajatydczwltuk6plxpgoyvu6jj;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/intel-oneapi-compilers-2025.2.0/c2c-1.8.0-rl42nhoa33aux3tluna3bftevqokiiqc;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/intel-oneapi-compilers-2025.2.0/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-ti2c3tm4pc6rma2cedok5hy5vnpxmsj7;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/intel-oneapi-compilers-2025.2.0/conduit-0.9.5-z4aapemtohmue4rikzbgjhmfyexwuym4;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/intel-oneapi-compilers-2025.2.0/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-jz235wsh3nhxjuzqxse57hcojia7x4mj;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/intel-oneapi-compilers-2025.2.0/umpire-2025.12.0-2eti2r3wjt4qs772djlcgf6axs44qmko;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/intel-oneapi-compilers-2025.2.0/adiak-0.4.0-rgjvxwzjod55ialozetvkjyi3hjczviy;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/intel-oneapi-compilers-2025.2.0/libunwind-1.8.3-h42c2h7kzkiaeq63dzvt32wlhcqbcrra;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/intel-oneapi-compilers-2025.2.0/hdf5-1.8.23-74fr7atqhw4jlzxt22xi5szeqpoxcwkh;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/intel-oneapi-compilers-2025.2.0/parmetis-4.0.3-g7bp5ds3u3laspneww3scyujjwebgdzh;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/intel-oneapi-compilers-2025.2.0/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-2gq3ddrhfxqlgzr6zxbvmwpzvtqxqj25;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/intel-oneapi-compilers-2025.2.0/fmt-11.0.2-orofhwltz3p5ckiw2t7gzhkgiifetwjt;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/intel-oneapi-compilers-2025.2.0/metis-5.1.0-zschch2gorb5k7t4rmrtc3aubm663i6u;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/intel-oneapi-runtime-2025.2.0-mfk4ezunnyprzpfps5pncx2nhttsa4z3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/gcc-runtime-13.3.1-zsobnkwck2glzcbukupgvgbiwwhdonys;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/usr/tce/packages/cmake/cmake-3.26.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/gcc-13.3.1/cppcheck-2.18.0-i3p56kpf66xzj4wm5kfqxyc4vgox7gb3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/doxygen-1.15.0;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/intel-oneapi-compilers-2025.2.0-ngszoacyp2i5d5nawitlyuh37jswjtie/compiler/2025.2;/usr/tce/packages/intel/intel-2025.2.0;/usr/tce/packages/clang/clang-19.1.3;/usr/tce/packages/mvapich2/mvapich2-2.3.7-intel-2025.2.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11" CACHE STRING "") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") -set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/intel-oneapi-compilers-2025.2.0/axom-develop-mbee5akrmx5h3qn444hq24evfukehk4x/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/intel-oneapi-compilers-2025.2.0/axom-develop-mbee5akrmx5h3qn444hq24evfukehk4x/lib64;;/usr/tce/packages/intel/intel-2025.2.0/compiler/2025.2/lib;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/intel-oneapi-compilers-2025.2.0-ngszoacyp2i5d5nawitlyuh37jswjtie/compiler/2025.2/lib;/usr/tce/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/intel-oneapi-compilers-2025.2.0/axom-develop-5onyrt7zct4lirem7z34t2uqdtngl45l/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/intel-oneapi-compilers-2025.2.0/axom-develop-5onyrt7zct4lirem7z34t2uqdtngl45l/lib64;;/usr/tce/packages/intel/intel-2025.2.0/compiler/2025.2/lib;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/intel-oneapi-compilers-2025.2.0-ngszoacyp2i5d5nawitlyuh37jswjtie/compiler/2025.2/lib;/usr/tce/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") -set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/intel-oneapi-compilers-2025.2.0/axom-develop-mbee5akrmx5h3qn444hq24evfukehk4x/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/intel-oneapi-compilers-2025.2.0/axom-develop-mbee5akrmx5h3qn444hq24evfukehk4x/lib64;;/usr/tce/packages/intel/intel-2025.2.0/compiler/2025.2/lib;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/intel-oneapi-compilers-2025.2.0-ngszoacyp2i5d5nawitlyuh37jswjtie/compiler/2025.2/lib;/usr/tce/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/intel-oneapi-compilers-2025.2.0/axom-develop-5onyrt7zct4lirem7z34t2uqdtngl45l/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/intel-oneapi-compilers-2025.2.0/axom-develop-5onyrt7zct4lirem7z34t2uqdtngl45l/lib64;;/usr/tce/packages/intel/intel-2025.2.0/compiler/2025.2/lib;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/intel-oneapi-compilers-2025.2.0-ngszoacyp2i5d5nawitlyuh37jswjtie/compiler/2025.2/lib;/usr/tce/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") #------------------------------------------------------------------------------ # Compilers #------------------------------------------------------------------------------ -# Compiler Spec: intel-oneapi-compilers@2025.2.0/eve4yjde2izalfck3273wfyvpu2pilqw +# Compiler Spec: intel-oneapi-compilers@2025.2.0/pfgmabeqlm6quu3niafr24bgm7vzeeug #------------------------------------------------------------------------------ if(DEFINED ENV{SPACK_CC}) - set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/oneapi/icx" CACHE PATH "") + set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/oneapi/icx" CACHE PATH "") - set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/oneapi/icpx" CACHE PATH "") + set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/oneapi/icpx" CACHE PATH "") - set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/oneapi/ifx" CACHE PATH "") + set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/oneapi/ifx" CACHE PATH "") else() @@ -75,52 +75,54 @@ set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") # TPLs #------------------------------------------------------------------------------ -set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/intel-oneapi-compilers-2025.2.0" CACHE PATH "") +set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/intel-oneapi-compilers-2025.2.0" CACHE PATH "") -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-3tyhzfysh4umcgsnrp7d7p3abdbmkshp" CACHE PATH "") +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-z4aapemtohmue4rikzbgjhmfyexwuym4" CACHE PATH "") -set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-ogkaflkbghohdikxnvj4mmksdcjn2qud" CACHE PATH "") +set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-rl42nhoa33aux3tluna3bftevqokiiqc" CACHE PATH "") # MFEM not built -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-7sqi7ybehcspqaajunz7v6loau63ma2j" CACHE PATH "") +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-74fr7atqhw4jlzxt22xi5szeqpoxcwkh" CACHE PATH "") set(LUA_DIR "/usr" CACHE PATH "") -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-aqzabesamv77gi5i6cpgrbnka4zc4eni" CACHE PATH "") +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-jz235wsh3nhxjuzqxse57hcojia7x4mj" CACHE PATH "") -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-wps2nos3umjdrwudniuuo6xoosyp6qco" CACHE PATH "") +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-2eti2r3wjt4qs772djlcgf6axs44qmko" CACHE PATH "") # OPENCASCADE not built -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-svzknmon3cgc5yjd54hrxrzdc4e4htga" CACHE PATH "") +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-rgjvxwzjod55ialozetvkjyi3hjczviy" CACHE PATH "") -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-zjssskiaerbodbkih5epbj5fmpjq5m6p" CACHE PATH "") +set(CALIPER_DIR "${TPL_ROOT}/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-ti2c3tm4pc6rma2cedok5hy5vnpxmsj7" CACHE PATH "") -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-kaem7te2437otmrrjhzhfclcq6j77pke" CACHE PATH "") +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-2gq3ddrhfxqlgzr6zxbvmwpzvtqxqj25" CACHE PATH "") # scr not built #------------------------------------------------------------------------------ -# Devtools +# Devtools & Python #------------------------------------------------------------------------------ -set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37" CACHE PATH "") +set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14" CACHE PATH "") set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/clang/clang-19.1.3/bin/clang-format" CACHE PATH "") -set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/python3" CACHE PATH "") +set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/python3" CACHE PATH "") -set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/jsonschema" CACHE PATH "") +set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/jsonschema" CACHE PATH "") set(ENABLE_DOCS ON CACHE BOOL "") -set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/sphinx-build" CACHE PATH "") +set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/sphinx-build" CACHE PATH "") + +set(YAPF_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/yapf" CACHE PATH "") set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0/bin/shroud" CACHE PATH "") -set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-d2tmb7ls2d5vgh6vhcyohecwcu6msopb/bin/cppcheck" CACHE PATH "") +set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-i3p56kpf66xzj4wm5kfqxyc4vgox7gb3/bin/cppcheck" CACHE PATH "") -set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/doxygen-1.13.2/bin/doxygen" CACHE PATH "") +set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/doxygen-1.15.0/bin/doxygen" CACHE PATH "") diff --git a/host-configs/dane-toss_4_x86_64_ib-llvm@19.1.3.cmake b/host-configs/dane-toss_4_x86_64_ib-llvm@19.1.3.cmake index f82bc50196..2daa90b595 100644 --- a/host-configs/dane-toss_4_x86_64_ib-llvm@19.1.3.cmake +++ b/host-configs/dane-toss_4_x86_64_ib-llvm@19.1.3.cmake @@ -4,28 +4,28 @@ # CMake executable path: /usr/tce/packages/cmake/cmake-3.26.3/bin/cmake #------------------------------------------------------------------------------ -set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/blt-develop-lv6kxkbht6tnhkesyvxpn4co7wh7yqkx;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/c2c-1.8.0-jcvyunoextaorp7eqlrec6s53cnlm7cn;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-u5dbyica2utd23dhlivu3xlu5jm4kz5f;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/conduit-0.9.5-dmle6tliomp27z2usvm22ukviomsvezy;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/mfem-4.9.0-qho2znbjhj2le6bbtw7vu6u3xsum2pc3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/opencascade-7.8.1-fwujcloxwvdjk22xrygpdpswx4tkp3u4;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-tk6vqmvsga2oebnzgilq4lz57xuafkqz;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/scr-3.0.1-cgbl5sb7kix2siwcwv57xzkry6kgssgl;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-szryy27okevlutgru2jtvaflqbw6rgax;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/adiak-0.4.0-t7ws2osd4v4fd3bffvzozbcq6gqdlf2i;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/libunwind-1.8.3-222s6ifq5wyaudy7h43urrshydfjig3q;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/hdf5-1.8.23-lw4obzkj7og4qegzmwizuxvotpz4lkot;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/parmetis-4.0.3-muygwq5u7gusmbn24red6rvpwbxck6l5;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/hypre-2.27.0-gk6f6jl4mtsegkjobf3lf4n74fmfcdbf;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/none-none/glx-1.4-a2eq27mib3shdyabgdpesg3jadr34yho;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/tcl-8.6.17-ouu2hfwmzya4w3xjd6ngexnntldlztob;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/axl-0.7.1-bnrhlub5ov4zupowegt5eguglxs5plz6;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/dtcmp-1.1.5-t25ihiw2whyfjbuyc5kbxapiscvs5wh3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/er-0.3.0-nkyqbtlnwzhuzww6lvyqdqkyew6xzub4;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/libyogrt-1.35-yhzbg7kgssgtbrp7hkzes5la3jmqyaxi;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/spath-0.2.0-4arh7twlqiyc6cvxa6i627bhvj32va76;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-z32b7c752x5r4p2fgji5rfhxbqyltuws;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/fmt-11.0.2-g4qwjp4qo7vxtvq3zijosapcbpnf6zja;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/metis-5.1.0-xzd22iguknjmsctpcvgd5blzwx6aq6wd;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/lwgrp-1.0.6-vts7nmjhqaqzp2uqcwqs5tl32ml6rpae;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/redset-0.2.0-6ynap7s37t2x46ykj75s7yssdadxa7g5;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/shuffile-0.2.0-q3lg5hzi5gfpwxipsq7uceo7oqkjgy5v;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/none-none/gcc-runtime-13.3.1-k43mnfzd4ehqvovn4d5qq7b5f6sfetsx;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/rankstr-0.2.0-nf3ih7rxaa4dfgqe5wujoxdtipfmqdld;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/kvtree-1.3.0-e2usbkamf4ies6sntmnlwtu2nzkltqgh;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/usr/tce/packages/cmake/cmake-3.26.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/gcc-13.3.1/cppcheck-2.18.0-d2tmb7ls2d5vgh6vhcyohecwcu6msopb;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/doxygen-1.13.2;/usr/tce/packages/gcc/gcc-13.3.1;/usr/tce/packages/clang/clang-19.1.3;/usr/tce/packages/mvapich2/mvapich2-2.3.7-clang-19.1.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5" CACHE STRING "") +set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/blt-0.7.1-577uis2w7b3ipf4v4v6y6vogmy52d6ay;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/c2c-1.8.0-pk3z5zabg2gtkur2c4mqzc5zz7z5f2tv;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-b7lmqorkofkrib5foi4fzbvd3eh2tbkj;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/conduit-0.9.5-gracxngtjim7b6zjsb5z4kf7qk347eo2;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/mfem-4.9.0-yseuuwvugp6qd45xmxp3ok67ibvfzkff;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/opencascade-7.8.1-6fd4qesv7tghklsteqoqe2mbvayuwgsa;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/py-nanobind-2.7.0-6akjhhlga6h3jx75swovfvo76k6rw6fp;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/py-pytest-9.0.0-vozuj6nkk42nhxeo5mawnux3w7bj3awe;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-7e5u3r4qt7erhbp67xbqnywbgobidj54;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/scr-3.0.1-t3vscu7yv2wkvgff46iwigx6fof72kws;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/umpire-2025.12.0-zbrxcsg5vgv63mpro6ar2rhm7ejx24h5;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/adiak-0.4.0-27bezbcpd5jxnvs65h3m6u2aheplxbmv;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/libunwind-1.8.3-ddv7ypujzw2wvlzabw3d42qygcbtofuq;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/hdf5-1.8.23-b37o2ze3w5sozwz6jmalg4pgg66jcogm;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/parmetis-4.0.3-slhcesf5fhsucwxtlxxana67jcrligfy;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/py-numpy-2.4.2-7qsjxyuuh7rh5hccdziewhwqymkmepb3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/hypre-2.27.0-qkqgpzdh6t7s2pakhss6qnikhwfltykn;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/glx-1.4-4kahrsr5vciz372vpdvlmvxahspecwif;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/tcl-8.6.17-yk7vfdrbz2n7cr2mc3j33ehvukl3kkbz;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/axl-0.7.1-pbcj3g7dqmuiogpb2mawnyuqiyng2vh7;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/dtcmp-1.1.5-cto5znftnfq2kdwpunaegg6trpraj4ke;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/er-0.3.0-4xpuy3lnjbc5ii2peposyxlve7exzijq;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/libyogrt-1.35-n3wzi44wyx5i63jyrn7mozyiec6nake3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/spath-0.2.0-owqpu5cpinfj56adgrwimokhecl37hdp;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-ck62ywjq7i3hn5utmvio42ifdegjxgma;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/fmt-11.0.2-uougkyc3rcyd7punvwjtcme2zlhehpgz;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/metis-5.1.0-3jeshrn7tydsgn5zdkf3iirdhw3u3oeq;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/lwgrp-1.0.6-fvf5w43ygbspsrft2gbc4tbrgamobo6n;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/redset-0.2.0-ou4lf63bu5chfljcdkaot6feubhmedoh;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/shuffile-0.2.0-mbm3htxivpgso6ogxf5jzdsjhzwqltnm;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/gcc-runtime-13.3.1-zsobnkwck2glzcbukupgvgbiwwhdonys;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/rankstr-0.2.0-5a5trmqremlbnqljjn6u7cqndylpzuhw;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/kvtree-1.3.0-hoxrqia25kplgu63o6275e3phsxgldfr;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/usr/tce/packages/cmake/cmake-3.26.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/gcc-13.3.1/cppcheck-2.18.0-i3p56kpf66xzj4wm5kfqxyc4vgox7gb3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/doxygen-1.15.0;/usr/tce/packages/gcc/gcc-13.3.1;/usr/tce/packages/clang/clang-19.1.3;/usr/tce/packages/mvapich2/mvapich2-2.3.7-clang-19.1.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11" CACHE STRING "") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") -set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/axom-develop-cwpovyigrpt4mshzw4qudrdthxkva3af/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/axom-develop-cwpovyigrpt4mshzw4qudrdthxkva3af/lib64;;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/llvm-19.1.3-gy2lu5xbi4csr2k47emlajzfs5mlsd4g/lib/x86_64-unknown-linux-gnu;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13;/usr/tce/packages/clang/clang-19.1.3/lib;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/axom-develop-nb67hwsw6xydhvmny7vtyu5nzqzrs2o2/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/axom-develop-nb67hwsw6xydhvmny7vtyu5nzqzrs2o2/lib64;;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/llvm-19.1.3-gy2lu5xbi4csr2k47emlajzfs5mlsd4g/lib/x86_64-unknown-linux-gnu;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13;/usr/tce/packages/clang/clang-19.1.3/lib;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") -set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/axom-develop-cwpovyigrpt4mshzw4qudrdthxkva3af/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3/axom-develop-cwpovyigrpt4mshzw4qudrdthxkva3af/lib64;;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/llvm-19.1.3-gy2lu5xbi4csr2k47emlajzfs5mlsd4g/lib/x86_64-unknown-linux-gnu;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13;/usr/tce/packages/clang/clang-19.1.3/lib;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/axom-develop-nb67hwsw6xydhvmny7vtyu5nzqzrs2o2/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3/axom-develop-nb67hwsw6xydhvmny7vtyu5nzqzrs2o2/lib64;;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/llvm-19.1.3-gy2lu5xbi4csr2k47emlajzfs5mlsd4g/lib/x86_64-unknown-linux-gnu;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13;/usr/tce/packages/clang/clang-19.1.3/lib;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") #------------------------------------------------------------------------------ # Compilers #------------------------------------------------------------------------------ -# Compiler Spec: llvm@19.1.3/dks2hxs7zxd55vu4lwnrychk52n73agw +# Compiler Spec: llvm@19.1.3/4rf6d7atkulu6wz7bucycjwtiuwqfy24 #------------------------------------------------------------------------------ if(DEFINED ENV{SPACK_CC}) - set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/clang/clang" CACHE PATH "") + set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/clang/clang" CACHE PATH "") - set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/clang/clang++" CACHE PATH "") + set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/clang/clang++" CACHE PATH "") - set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/gcc/gfortran" CACHE PATH "") + set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/gcc/gfortran" CACHE PATH "") else() @@ -75,72 +75,84 @@ set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") # TPLs #------------------------------------------------------------------------------ -set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_30_26/llvm-19.1.3" CACHE PATH "") +set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/llvm-19.1.3" CACHE PATH "") -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-dmle6tliomp27z2usvm22ukviomsvezy" CACHE PATH "") +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-gracxngtjim7b6zjsb5z4kf7qk347eo2" CACHE PATH "") -set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-jcvyunoextaorp7eqlrec6s53cnlm7cn" CACHE PATH "") +set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-pk3z5zabg2gtkur2c4mqzc5zz7z5f2tv" CACHE PATH "") -set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-qho2znbjhj2le6bbtw7vu6u3xsum2pc3" CACHE PATH "") +set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-yseuuwvugp6qd45xmxp3ok67ibvfzkff" CACHE PATH "") -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-lw4obzkj7og4qegzmwizuxvotpz4lkot" CACHE PATH "") +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-b37o2ze3w5sozwz6jmalg4pgg66jcogm" CACHE PATH "") set(LUA_DIR "/usr" CACHE PATH "") -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-tk6vqmvsga2oebnzgilq4lz57xuafkqz" CACHE PATH "") +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-7e5u3r4qt7erhbp67xbqnywbgobidj54" CACHE PATH "") -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-szryy27okevlutgru2jtvaflqbw6rgax" CACHE PATH "") +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-zbrxcsg5vgv63mpro6ar2rhm7ejx24h5" CACHE PATH "") -set(OPENCASCADE_DIR "${TPL_ROOT}/opencascade-7.8.1-fwujcloxwvdjk22xrygpdpswx4tkp3u4" CACHE PATH "") +set(OPENCASCADE_DIR "${TPL_ROOT}/opencascade-7.8.1-6fd4qesv7tghklsteqoqe2mbvayuwgsa" CACHE PATH "") -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-t7ws2osd4v4fd3bffvzozbcq6gqdlf2i" CACHE PATH "") +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-27bezbcpd5jxnvs65h3m6u2aheplxbmv" CACHE PATH "") -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-u5dbyica2utd23dhlivu3xlu5jm4kz5f" CACHE PATH "") +set(CALIPER_DIR "${TPL_ROOT}/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-b7lmqorkofkrib5foi4fzbvd3eh2tbkj" CACHE PATH "") -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-z32b7c752x5r4p2fgji5rfhxbqyltuws" CACHE PATH "") +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-ck62ywjq7i3hn5utmvio42ifdegjxgma" CACHE PATH "") -set(SCR_DIR "${TPL_ROOT}/scr-3.0.1-cgbl5sb7kix2siwcwv57xzkry6kgssgl" CACHE PATH "") +set(SCR_DIR "${TPL_ROOT}/scr-3.0.1-t3vscu7yv2wkvgff46iwigx6fof72kws" CACHE PATH "") -set(KVTREE_DIR "${TPL_ROOT}/kvtree-1.3.0-e2usbkamf4ies6sntmnlwtu2nzkltqgh" CACHE PATH "") +set(KVTREE_DIR "${TPL_ROOT}/kvtree-1.3.0-hoxrqia25kplgu63o6275e3phsxgldfr" CACHE PATH "") -set(DTCMP_DIR "${TPL_ROOT}/dtcmp-1.1.5-t25ihiw2whyfjbuyc5kbxapiscvs5wh3" CACHE PATH "") +set(DTCMP_DIR "${TPL_ROOT}/dtcmp-1.1.5-cto5znftnfq2kdwpunaegg6trpraj4ke" CACHE PATH "") -set(SPATH_DIR "${TPL_ROOT}/spath-0.2.0-4arh7twlqiyc6cvxa6i627bhvj32va76" CACHE PATH "") +set(SPATH_DIR "${TPL_ROOT}/spath-0.2.0-owqpu5cpinfj56adgrwimokhecl37hdp" CACHE PATH "") -set(AXL_DIR "${TPL_ROOT}/axl-0.7.1-bnrhlub5ov4zupowegt5eguglxs5plz6" CACHE PATH "") +set(AXL_DIR "${TPL_ROOT}/axl-0.7.1-pbcj3g7dqmuiogpb2mawnyuqiyng2vh7" CACHE PATH "") -set(LWGRP_DIR "${TPL_ROOT}/lwgrp-1.0.6-vts7nmjhqaqzp2uqcwqs5tl32ml6rpae" CACHE PATH "") +set(LWGRP_DIR "${TPL_ROOT}/lwgrp-1.0.6-fvf5w43ygbspsrft2gbc4tbrgamobo6n" CACHE PATH "") -set(ER_DIR "${TPL_ROOT}/er-0.3.0-nkyqbtlnwzhuzww6lvyqdqkyew6xzub4" CACHE PATH "") +set(ER_DIR "${TPL_ROOT}/er-0.3.0-4xpuy3lnjbc5ii2peposyxlve7exzijq" CACHE PATH "") -set(RANKSTR_DIR "${TPL_ROOT}/rankstr-0.2.0-nf3ih7rxaa4dfgqe5wujoxdtipfmqdld" CACHE PATH "") +set(RANKSTR_DIR "${TPL_ROOT}/rankstr-0.2.0-5a5trmqremlbnqljjn6u7cqndylpzuhw" CACHE PATH "") -set(REDSET_DIR "${TPL_ROOT}/redset-0.2.0-6ynap7s37t2x46ykj75s7yssdadxa7g5" CACHE PATH "") +set(REDSET_DIR "${TPL_ROOT}/redset-0.2.0-ou4lf63bu5chfljcdkaot6feubhmedoh" CACHE PATH "") -set(SHUFFILE_DIR "${TPL_ROOT}/shuffile-0.2.0-q3lg5hzi5gfpwxipsq7uceo7oqkjgy5v" CACHE PATH "") +set(SHUFFILE_DIR "${TPL_ROOT}/shuffile-0.2.0-mbm3htxivpgso6ogxf5jzdsjhzwqltnm" CACHE PATH "") -set(LIBYOGRT_DIR "${TPL_ROOT}/libyogrt-1.35-yhzbg7kgssgtbrp7hkzes5la3jmqyaxi" CACHE PATH "") +set(LIBYOGRT_DIR "${TPL_ROOT}/libyogrt-1.35-n3wzi44wyx5i63jyrn7mozyiec6nake3" CACHE PATH "") #------------------------------------------------------------------------------ -# Devtools +# Devtools & Python #------------------------------------------------------------------------------ -set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37" CACHE PATH "") +set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14" CACHE PATH "") set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/clang/clang-19.1.3/bin/clang-format" CACHE PATH "") -set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/python3" CACHE PATH "") +set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/python3" CACHE PATH "") -set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/jsonschema" CACHE PATH "") +set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/jsonschema" CACHE PATH "") set(ENABLE_DOCS ON CACHE BOOL "") -set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/sphinx-build" CACHE PATH "") +set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/sphinx-build" CACHE PATH "") + +set(YAPF_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/yapf" CACHE PATH "") set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0/bin/shroud" CACHE PATH "") -set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-d2tmb7ls2d5vgh6vhcyohecwcu6msopb/bin/cppcheck" CACHE PATH "") +set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-i3p56kpf66xzj4wm5kfqxyc4vgox7gb3/bin/cppcheck" CACHE PATH "") + +set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/doxygen-1.15.0/bin/doxygen" CACHE PATH "") + +set(PY_NANOBIND_DIR "${TPL_ROOT}/py-nanobind-2.7.0-6akjhhlga6h3jx75swovfvo76k6rw6fp/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PYTEST_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/py-pytest-9.0.0-vozuj6nkk42nhxeo5mawnux3w7bj3awe/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_NUMPY_DIR "${TPL_ROOT}/py-numpy-2.4.2-7qsjxyuuh7rh5hccdziewhwqymkmepb3/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PLUGGY_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/py-pluggy-1.6.0-6zab4pck6v7johubbhalr2waowbwpjei/lib/python3.13/site-packages" CACHE PATH "") -set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/doxygen-1.13.2/bin/doxygen" CACHE PATH "") +set(PY_INICONFIG_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_11_33_13/none-none/py-iniconfig-2.1.0-xwmbxuhk2oo3dcuizdp3z4hqbpqykkom/lib/python3.13/site-packages" CACHE PATH "") diff --git a/host-configs/docker/gcc@13.3.1.cmake b/host-configs/docker/gcc@13.3.1.cmake index ba3789d3e3..e1e9346de2 100644 --- a/host-configs/docker/gcc@13.3.1.cmake +++ b/host-configs/docker/gcc@13.3.1.cmake @@ -4,28 +4,28 @@ # CMake executable path: /usr/local/bin/cmake #------------------------------------------------------------------------------ -set(CMAKE_PREFIX_PATH "/home/axom/axom_tpls/gcc-13.3.1/blt-develop-flnqp2mcfgnsgymaf6yzrhz22yvzjtjw;/home/axom/axom_tpls/gcc-13.3.1/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-qape4nbgv2dfrr434okzfvug2hnbo7zy;/home/axom/axom_tpls/gcc-13.3.1/conduit-0.9.5-qaqzvfbhsyuf26r7pzwvkbodxkbhc4ce;/home/axom/axom_tpls/gcc-13.3.1/gmake-4.4.1-tjczf2ynnhpvawcbqcpalnwys2gg2lyz;/home/axom/axom_tpls/gcc-13.3.1/mfem-4.9.0-wixcnzqq6h4lmjqy7cwddru5izcsigsm;/home/axom/axom_tpls/gcc-13.3.1/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-vatdye3hlcis5podnfqfyp4gbipdafao;/home/axom/axom_tpls/gcc-13.3.1/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-dlv7k7vybnhfmwqh5a465szaftwfziag;/home/axom/axom_tpls/gcc-13.3.1/adiak-0.4.0-jnixqwnm6yzomk7y6c5b3lpyxeyuwsfa;/home/axom/axom_tpls/gcc-13.3.1/elfutils-0.193-5x4zh6qz6s27di5igast2pebvp2c3o2b;/home/axom/axom_tpls/gcc-13.3.1/libunwind-1.8.3-ua7hxrqqb2jh2g56voomcaaxez5sqopd;/home/axom/axom_tpls/gcc-13.3.1/hdf5-1.8.23-tgy3ysytlz3pduqd67mg2awfbhonetwm;/home/axom/axom_tpls/gcc-13.3.1/parmetis-4.0.3-itx2towtppihssp56monbeklfjwo55md;/home/axom/axom_tpls/gcc-13.3.1/hypre-2.27.0-nvbecjpz7sxoh5voibt3dgacekdkk2yw;/home/axom/axom_tpls/gcc-13.3.1/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-2foz7sirxtrijry5kitjygm6atik2r7c;/home/axom/axom_tpls/gcc-13.3.1/fmt-11.0.2-ddx3vhdjkv44pcgjxjdxn3mnrksukecb;/home/axom/axom_tpls/gcc-13.3.1/zstd-1.5.7-3f2efmy53ft33z4c3q3b3ud6j2viebme;/home/axom/axom_tpls/gcc-13.3.1/metis-5.1.0-6r2rgfbbtpfazuunu6dfuafod2vj5xg5;/home/axom/axom_tpls/gcc-13.3.1/mpich-4.2.0-xgkrn5xilxs6yr4qi7oydfsh7h42qgdb;/home/axom/axom_tpls/gcc-13.3.1/hwloc-2.12.2-ybsdkqaecewutivmgwtrp5yf53j75rau;/home/axom/axom_tpls/gcc-13.3.1/libfabric-2.4.0-x6hjxuymg2y7fto7necipdblkze755st;/home/axom/axom_tpls/gcc-13.3.1/yaksa-0.4-avq7yk45gzqhgnmnzajxuofo3xijywjt;/home/axom/axom_tpls/gcc-13.3.1/libpciaccess-0.17-nmgolbdkswy3wju5lu4spsmmhaqj3rel;/home/axom/axom_tpls/gcc-13.3.1/libxml2-2.13.5-ioievapch2djnca62jmelkfm3jv2sola;/home/axom/axom_tpls/gcc-13.3.1/ncurses-6.5-20250705-syiycw6sptzlabpov7nmen4pccrhwysg;/home/axom/axom_tpls/gcc-13.3.1/libiconv-1.18-hwetls7oc7codnjqhd55vniyymvimzic;/home/axom/axom_tpls/gcc-13.3.1/xz-5.6.3-wih3db5qawrculrfsvwsglqnoom2il2s;/home/axom/axom_tpls/gcc-13.3.1/zlib-ng-2.2.4-ft2vb2ugjfjep3rbssesfox4ndybuohq;/home/axom/axom_tpls/none-none/gcc-runtime-13.3.1-mm3jlyl7p3xtid43tsijumtt2mx65pox;/home/axom/axom_tpls/none-none/compiler-wrapper-1.0-zi6ke3figxbt6vlltwinxhvhrnky2skj" CACHE STRING "") +set(CMAKE_PREFIX_PATH "/home/axom/axom_tpls/gcc-13.3.1/blt-0.7.1-tp6erawewp4l2ewllhglzso5fnjudoja;/home/axom/axom_tpls/gcc-13.3.1/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-qollf3jglv6wxat4uffls42u2t2biu43;/home/axom/axom_tpls/gcc-13.3.1/conduit-0.9.5-e72kkuzpsp2ct2warb23dw63rjbwyuy7;/home/axom/axom_tpls/gcc-13.3.1/gmake-4.4.1-jclt3ixkhzk7gh4qz7bph3nqno2d2tan;/home/axom/axom_tpls/gcc-13.3.1/mfem-4.9.0-27y23akm3yqlnmn3y4ujuiif7ch3d42x;/home/axom/axom_tpls/gcc-13.3.1/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-xk3wk7pkfxfmczqsud2zgvoaynygae7x;/home/axom/axom_tpls/gcc-13.3.1/umpire-2025.12.0-eg7ottka4ejtla2sshmo5fbnz6ievmht;/home/axom/axom_tpls/gcc-13.3.1/adiak-0.4.0-7tvwkbkbsrz7pg7cmzjbgpakeqwxiwfn;/home/axom/axom_tpls/gcc-13.3.1/elfutils-0.193-yvyizihf3ovzcrz2xspbo3xqpcsgpciw;/home/axom/axom_tpls/gcc-13.3.1/libunwind-1.8.3-dms6jlqrs6yvgwf454ezco5mszpn4fny;/home/axom/axom_tpls/gcc-13.3.1/hdf5-1.8.23-c5fghc2avhw2ujuhxb32akojoz62ulww;/home/axom/axom_tpls/gcc-13.3.1/parmetis-4.0.3-fwggxdxmzfdyu4zuwzps2iy4ku5nlzbq;/home/axom/axom_tpls/gcc-13.3.1/hypre-2.27.0-yukxydlpq2lrtkdzhpyvnyfxo6u62dqh;/home/axom/axom_tpls/gcc-13.3.1/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-gdtpys6nyl4kfgvwd5d46hh7mrx4c64f;/home/axom/axom_tpls/gcc-13.3.1/fmt-11.0.2-auzpmart4pgyllfizbgbrmi7vo5l7imm;/home/axom/axom_tpls/gcc-13.3.1/zstd-1.5.7-ynwtbrjy4fy7fmg4mnoq7inn6j36z2lo;/home/axom/axom_tpls/gcc-13.3.1/metis-5.1.0-ngjvzo5djlp4rtpsh2rro63istec4tks;/home/axom/axom_tpls/gcc-13.3.1/mpich-4.2.0-oafwifl7wossiwmdg3osevy3h42nehm5;/home/axom/axom_tpls/gcc-13.3.1/hwloc-2.12.2-r6jiv64detpwvvobvcpbxqsgbyz4an7b;/home/axom/axom_tpls/gcc-13.3.1/libfabric-2.4.0-glityu7f5kxxo72mbpnt2h54aowe2o7j;/home/axom/axom_tpls/gcc-13.3.1/yaksa-0.4-2nqzb7ap73wiacj77ktkz5qh33s3h7cj;/home/axom/axom_tpls/gcc-13.3.1/libpciaccess-0.17-e7jficwldulh2dbp7l742wedsof3d6h5;/home/axom/axom_tpls/gcc-13.3.1/libxml2-2.13.5-wj6jpg6gipn4cjol77o5bwppiymtifjj;/home/axom/axom_tpls/gcc-13.3.1/ncurses-6.5-20250705-izsjfkqb573w7lny6vvdbt57lctv2j22;/home/axom/axom_tpls/gcc-13.3.1/libiconv-1.18-nwihe6gonhf3rig4qghahxqrdzcpxzp2;/home/axom/axom_tpls/gcc-13.3.1/xz-5.6.3-t6r2wp2e2kybjuus2yzlqap6khgwvw73;/home/axom/axom_tpls/gcc-13.3.1/zlib-ng-2.3.2-xturc74asm73dunfzuwguafjrucw75ae;/home/axom/axom_tpls/none-none/gcc-runtime-13.3.1-ahhevkdxsqek4foiubajeiisj7ryali4;/home/axom/axom_tpls/none-none/compiler-wrapper-1.0-u5fjo4cce7cqt6425ipfxnafausfog7z" CACHE STRING "") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") -set(CMAKE_BUILD_RPATH "/home/axom/axom_tpls/gcc-13.3.1/axom-develop-2ood2phuo6rrmzrhzq3s3plcecafkn2u/lib;/home/axom/axom_tpls/gcc-13.3.1/axom-develop-2ood2phuo6rrmzrhzq3s3plcecafkn2u/lib64;;" CACHE STRING "") +set(CMAKE_BUILD_RPATH "/home/axom/axom_tpls/gcc-13.3.1/axom-develop-ofy2ds6xm3ggsfnnn2bzwtfoyqooykov/lib;/home/axom/axom_tpls/gcc-13.3.1/axom-develop-ofy2ds6xm3ggsfnnn2bzwtfoyqooykov/lib64;;" CACHE STRING "") -set(CMAKE_INSTALL_RPATH "/home/axom/axom_tpls/gcc-13.3.1/axom-develop-2ood2phuo6rrmzrhzq3s3plcecafkn2u/lib;/home/axom/axom_tpls/gcc-13.3.1/axom-develop-2ood2phuo6rrmzrhzq3s3plcecafkn2u/lib64;;" CACHE STRING "") +set(CMAKE_INSTALL_RPATH "/home/axom/axom_tpls/gcc-13.3.1/axom-develop-ofy2ds6xm3ggsfnnn2bzwtfoyqooykov/lib;/home/axom/axom_tpls/gcc-13.3.1/axom-develop-ofy2ds6xm3ggsfnnn2bzwtfoyqooykov/lib64;;" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") #------------------------------------------------------------------------------ # Compilers #------------------------------------------------------------------------------ -# Compiler Spec: gcc@13.3.1/kzjnfqqy6k3yhzcf5flpyszvsork7cwg +# Compiler Spec: gcc@13.3.1/3ueirnbsml6vw26zpzmeekt6nwal4lhw #------------------------------------------------------------------------------ if(DEFINED ENV{SPACK_CC}) - set(CMAKE_C_COMPILER "/home/axom/axom_tpls/none-none/compiler-wrapper-1.0-zi6ke3figxbt6vlltwinxhvhrnky2skj/libexec/spack/gcc/gcc" CACHE PATH "") + set(CMAKE_C_COMPILER "/home/axom/axom_tpls/none-none/compiler-wrapper-1.0-u5fjo4cce7cqt6425ipfxnafausfog7z/libexec/spack/gcc/gcc" CACHE PATH "") - set(CMAKE_CXX_COMPILER "/home/axom/axom_tpls/none-none/compiler-wrapper-1.0-zi6ke3figxbt6vlltwinxhvhrnky2skj/libexec/spack/gcc/g++" CACHE PATH "") + set(CMAKE_CXX_COMPILER "/home/axom/axom_tpls/none-none/compiler-wrapper-1.0-u5fjo4cce7cqt6425ipfxnafausfog7z/libexec/spack/gcc/g++" CACHE PATH "") - set(CMAKE_Fortran_COMPILER "/home/axom/axom_tpls/none-none/compiler-wrapper-1.0-zi6ke3figxbt6vlltwinxhvhrnky2skj/libexec/spack/gcc/gfortran" CACHE PATH "") + set(CMAKE_Fortran_COMPILER "/home/axom/axom_tpls/none-none/compiler-wrapper-1.0-u5fjo4cce7cqt6425ipfxnafausfog7z/libexec/spack/gcc/gfortran" CACHE PATH "") else() @@ -47,13 +47,13 @@ set(ENABLE_FORTRAN ON CACHE BOOL "") # MPI #------------------------------------------------------------------------------ -set(MPI_C_COMPILER "/home/axom/axom_tpls/gcc-13.3.1/mpich-4.2.0-xgkrn5xilxs6yr4qi7oydfsh7h42qgdb/bin/mpicc" CACHE PATH "") +set(MPI_C_COMPILER "/home/axom/axom_tpls/gcc-13.3.1/mpich-4.2.0-oafwifl7wossiwmdg3osevy3h42nehm5/bin/mpicc" CACHE PATH "") -set(MPI_CXX_COMPILER "/home/axom/axom_tpls/gcc-13.3.1/mpich-4.2.0-xgkrn5xilxs6yr4qi7oydfsh7h42qgdb/bin/mpicxx" CACHE PATH "") +set(MPI_CXX_COMPILER "/home/axom/axom_tpls/gcc-13.3.1/mpich-4.2.0-oafwifl7wossiwmdg3osevy3h42nehm5/bin/mpicxx" CACHE PATH "") -set(MPI_Fortran_COMPILER "/home/axom/axom_tpls/gcc-13.3.1/mpich-4.2.0-xgkrn5xilxs6yr4qi7oydfsh7h42qgdb/bin/mpif90" CACHE PATH "") +set(MPI_Fortran_COMPILER "/home/axom/axom_tpls/gcc-13.3.1/mpich-4.2.0-oafwifl7wossiwmdg3osevy3h42nehm5/bin/mpif90" CACHE PATH "") -set(MPIEXEC_EXECUTABLE "/home/axom/axom_tpls/gcc-13.3.1/mpich-4.2.0-xgkrn5xilxs6yr4qi7oydfsh7h42qgdb/bin/mpirun" CACHE PATH "") +set(MPIEXEC_EXECUTABLE "/home/axom/axom_tpls/gcc-13.3.1/mpich-4.2.0-oafwifl7wossiwmdg3osevy3h42nehm5/bin/mpirun" CACHE PATH "") set(MPIEXEC_NUMPROC_FLAG "-np" CACHE STRING "") @@ -77,27 +77,27 @@ set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") set(TPL_ROOT "/home/axom/axom_tpls/gcc-13.3.1" CACHE PATH "") -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-qaqzvfbhsyuf26r7pzwvkbodxkbhc4ce" CACHE PATH "") +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-e72kkuzpsp2ct2warb23dw63rjbwyuy7" CACHE PATH "") # C2C not built -set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-wixcnzqq6h4lmjqy7cwddru5izcsigsm" CACHE PATH "") +set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-27y23akm3yqlnmn3y4ujuiif7ch3d42x" CACHE PATH "") -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-tgy3ysytlz3pduqd67mg2awfbhonetwm" CACHE PATH "") +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-c5fghc2avhw2ujuhxb32akojoz62ulww" CACHE PATH "") set(LUA_DIR "/usr" CACHE PATH "") -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-vatdye3hlcis5podnfqfyp4gbipdafao" CACHE PATH "") +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-xk3wk7pkfxfmczqsud2zgvoaynygae7x" CACHE PATH "") -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-dlv7k7vybnhfmwqh5a465szaftwfziag" CACHE PATH "") +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-eg7ottka4ejtla2sshmo5fbnz6ievmht" CACHE PATH "") # OPENCASCADE not built -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-jnixqwnm6yzomk7y6c5b3lpyxeyuwsfa" CACHE PATH "") +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-7tvwkbkbsrz7pg7cmzjbgpakeqwxiwfn" CACHE PATH "") -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-qape4nbgv2dfrr434okzfvug2hnbo7zy" CACHE PATH "") +set(CALIPER_DIR "${TPL_ROOT}/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-qollf3jglv6wxat4uffls42u2t2biu43" CACHE PATH "") -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-2foz7sirxtrijry5kitjygm6atik2r7c" CACHE PATH "") +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-gdtpys6nyl4kfgvwd5d46hh7mrx4c64f" CACHE PATH "") # scr not built diff --git a/host-configs/docker/llvm@19.0.0.cmake b/host-configs/docker/llvm@19.0.0.cmake index b0f1d56a49..515d46d6db 100644 --- a/host-configs/docker/llvm@19.0.0.cmake +++ b/host-configs/docker/llvm@19.0.0.cmake @@ -4,28 +4,28 @@ # CMake executable path: /usr/local/bin/cmake #------------------------------------------------------------------------------ -set(CMAKE_PREFIX_PATH "/home/axom/axom_tpls/llvm-19.0.0/blt-develop-foyjyqfrucbixycjt25rbulsxdjfkuue;/home/axom/axom_tpls/llvm-19.0.0/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-cuvnujomk7ouem762777uqz2hxx3h4sl;/home/axom/axom_tpls/llvm-19.0.0/conduit-0.9.5-2rj2syiqwxefblliijogdqlupmw4by3q;/home/axom/axom_tpls/llvm-19.0.0/gmake-4.4.1-emuzvx5in6soqe6xb74rsnjdonzeszgq;/home/axom/axom_tpls/llvm-19.0.0/mfem-4.9.0-favb3nc3juneeg4pso4unmm6ob5dlmxl;/home/axom/axom_tpls/llvm-19.0.0/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-4li5kka37kzoc2etkb7jeky27uca7z4o;/home/axom/axom_tpls/llvm-19.0.0/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-nre3wgoi6snxanvgnc5f27np4rriihqr;/home/axom/axom_tpls/llvm-19.0.0/adiak-0.4.0-p5a5gwlkzpbmtrbfdnjf5yhsbaeujhit;/home/axom/axom_tpls/llvm-19.0.0/elfutils-0.193-lk6ea73rczqg75irhtmaedfeigm3k545;/home/axom/axom_tpls/llvm-19.0.0/libunwind-1.8.3-wb7tvv6tpkudo5c6d5dqa5qvailvqqoi;/home/axom/axom_tpls/llvm-19.0.0/hdf5-1.8.23-k427jkpcjllzevbro2quxda5gtq4crkl;/home/axom/axom_tpls/llvm-19.0.0/parmetis-4.0.3-q5a5vl27zog44ekfgfhnriqeywl7r4em;/home/axom/axom_tpls/llvm-19.0.0/hypre-2.27.0-yatbpq2yzlznf7yxjoc3zhj57qfj234j;/home/axom/axom_tpls/llvm-19.0.0/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-s3u5u2ql34vblcn4ezdkln4vebd665za;/home/axom/axom_tpls/llvm-19.0.0/fmt-11.0.2-3upgo6ed7lbxo7i6ah7osmdl3jzgbm4x;/home/axom/axom_tpls/llvm-19.0.0/zstd-1.5.7-q3hea34yzya4u5eik2gb57fbrxykmpxt;/home/axom/axom_tpls/llvm-19.0.0/metis-5.1.0-7542llvcyay35ospiji2ktnejigtqshl;/home/axom/axom_tpls/llvm-19.0.0/mpich-4.2.0-wo6l3bjqx2zeznegryh6tkpphpwrsjkk;/home/axom/axom_tpls/none-none/gcc-runtime-13.3.1-mm3jlyl7p3xtid43tsijumtt2mx65pox;/home/axom/axom_tpls/llvm-19.0.0/hwloc-2.12.2-mow5qangackcqffljpetrtp4v4iw52pi;/home/axom/axom_tpls/llvm-19.0.0/libfabric-2.4.0-4k74fhcufo3xjoklyhkjxnqctoi2agit;/home/axom/axom_tpls/llvm-19.0.0/yaksa-0.4-qsxdevazzwq34ypgrbrnqxm7pbjq4df2;/home/axom/axom_tpls/llvm-19.0.0/libpciaccess-0.17-w5ogvh4m5cydu2qrfmk5uzsfcyholzu6;/home/axom/axom_tpls/llvm-19.0.0/libxml2-2.13.5-7ylbpyktn7jfo5tkmwg7u2hwvxlsynna;/home/axom/axom_tpls/llvm-19.0.0/ncurses-6.5-20250705-3msjc2fok52nucfdyr2e7emlremjnal3;/home/axom/axom_tpls/llvm-19.0.0/libiconv-1.18-5w3zlozsm5v7readem3v4llkf2fhm7w6;/home/axom/axom_tpls/llvm-19.0.0/xz-5.6.3-ghjnkqwcngnozzwyfq3e7qajg7fhsymd;/home/axom/axom_tpls/llvm-19.0.0/zlib-ng-2.2.4-gmbecyhpriojodztv6x2spdvckvktuwv;/home/axom/axom_tpls/none-none/compiler-wrapper-1.0-zi6ke3figxbt6vlltwinxhvhrnky2skj;/usr/lib/llvm-19" CACHE STRING "") +set(CMAKE_PREFIX_PATH "/home/axom/axom_tpls/llvm-19.0.0/blt-0.7.1-p7mm766jfnjcbcnon7lmbmjk52d7nnfy;/home/axom/axom_tpls/llvm-19.0.0/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-qv2wv4xikow5wxrhdem6c2dvkxt2cptf;/home/axom/axom_tpls/llvm-19.0.0/conduit-0.9.5-23be5eyo7aox2o6tzewawhlnjsci3pau;/home/axom/axom_tpls/llvm-19.0.0/gmake-4.4.1-xsybuyd32plkd6jcojnvdqkbwnt44ij6;/home/axom/axom_tpls/llvm-19.0.0/mfem-4.9.0-g3kaipukjvqu677tqztygnik5kzcxhfj;/home/axom/axom_tpls/llvm-19.0.0/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-dkkk27oc7p2gsrq4cslpdsv5qz7g3sbd;/home/axom/axom_tpls/llvm-19.0.0/umpire-2025.12.0-kulqmeumvx2c36r6rzz7lwndhsv3ot4i;/home/axom/axom_tpls/llvm-19.0.0/adiak-0.4.0-idbd67m2y4b4gnuxxbivm7hvesbbl4q5;/home/axom/axom_tpls/llvm-19.0.0/elfutils-0.193-437imlexpxs7pztuf7vh33f4mrvwh2i2;/home/axom/axom_tpls/llvm-19.0.0/libunwind-1.8.3-3tkxrnad3g5t5zjiodqfqne3sqfq5pzn;/home/axom/axom_tpls/llvm-19.0.0/hdf5-1.8.23-mwa7fanurwtkpebryywcggusn4gd7yg2;/home/axom/axom_tpls/llvm-19.0.0/parmetis-4.0.3-oe7i7ur4mu5sqkoet576wwcezbbodolt;/home/axom/axom_tpls/llvm-19.0.0/hypre-2.27.0-phspcafi6ten26qxkokwwij44ygoctxz;/home/axom/axom_tpls/llvm-19.0.0/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-y2k23nuv2eya2soe3fznpcgsgt2k2dai;/home/axom/axom_tpls/llvm-19.0.0/fmt-11.0.2-eutx47cvctyr7hyulz4rv4q4nfg5apzm;/home/axom/axom_tpls/llvm-19.0.0/zstd-1.5.7-ereaou2vj32kdin5v4z23qtd36yk4euw;/home/axom/axom_tpls/llvm-19.0.0/metis-5.1.0-sq3zbc3dla7ya33x67xr2evinhxbb6ey;/home/axom/axom_tpls/llvm-19.0.0/mpich-4.2.0-wxhfezauopwtrdjmf6hx32l2jh4yyb25;/home/axom/axom_tpls/none-none/gcc-runtime-13.3.1-ahhevkdxsqek4foiubajeiisj7ryali4;/home/axom/axom_tpls/llvm-19.0.0/hwloc-2.12.2-mab72jducih2myearbldanjcfr4epqcz;/home/axom/axom_tpls/llvm-19.0.0/libfabric-2.4.0-n7vbijzh3ebt3lahb5hyk7e4smcfyoxz;/home/axom/axom_tpls/llvm-19.0.0/yaksa-0.4-o3gdzqkwwkch27u7cr4yxzzjuewlg327;/home/axom/axom_tpls/llvm-19.0.0/libpciaccess-0.17-2sndua5wqv2xd2jy3ef52ehian4tpd4i;/home/axom/axom_tpls/llvm-19.0.0/libxml2-2.13.5-j3go7vs6gxvkyl7xdh476o3h3aos6zxk;/home/axom/axom_tpls/llvm-19.0.0/ncurses-6.5-20250705-qjve66dkqppk4z75pct2zhcyso2jsjhl;/home/axom/axom_tpls/llvm-19.0.0/libiconv-1.18-wwggylv5rglt7x7teuq3m7egjl27vbp5;/home/axom/axom_tpls/llvm-19.0.0/xz-5.6.3-55t47rdkjzlx64icqzp5lalnd67nsvnm;/home/axom/axom_tpls/llvm-19.0.0/zlib-ng-2.3.2-h74mdgso4hyns3yjgipxrwh3q5ngbbyt;/home/axom/axom_tpls/none-none/compiler-wrapper-1.0-u5fjo4cce7cqt6425ipfxnafausfog7z;/usr/lib/llvm-19" CACHE STRING "") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") -set(CMAKE_BUILD_RPATH "/home/axom/axom_tpls/llvm-19.0.0/axom-develop-2i37lqirgyxo45xsac7z2jmjpu5e7pmr/lib;/home/axom/axom_tpls/llvm-19.0.0/axom-develop-2i37lqirgyxo45xsac7z2jmjpu5e7pmr/lib64;;" CACHE STRING "") +set(CMAKE_BUILD_RPATH "/home/axom/axom_tpls/llvm-19.0.0/axom-develop-pue4pbqffz5ostcywjjmbqrpva3p7c2o/lib;/home/axom/axom_tpls/llvm-19.0.0/axom-develop-pue4pbqffz5ostcywjjmbqrpva3p7c2o/lib64;;" CACHE STRING "") -set(CMAKE_INSTALL_RPATH "/home/axom/axom_tpls/llvm-19.0.0/axom-develop-2i37lqirgyxo45xsac7z2jmjpu5e7pmr/lib;/home/axom/axom_tpls/llvm-19.0.0/axom-develop-2i37lqirgyxo45xsac7z2jmjpu5e7pmr/lib64;;" CACHE STRING "") +set(CMAKE_INSTALL_RPATH "/home/axom/axom_tpls/llvm-19.0.0/axom-develop-pue4pbqffz5ostcywjjmbqrpva3p7c2o/lib;/home/axom/axom_tpls/llvm-19.0.0/axom-develop-pue4pbqffz5ostcywjjmbqrpva3p7c2o/lib64;;" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") #------------------------------------------------------------------------------ # Compilers #------------------------------------------------------------------------------ -# Compiler Spec: llvm@19.0.0/3oqvzioju4r4y4mex4e5qyaiwhzshimy +# Compiler Spec: llvm@19.0.0/hpp37w5qjo4zc4cgogknua6ull7tes74 #------------------------------------------------------------------------------ if(DEFINED ENV{SPACK_CC}) - set(CMAKE_C_COMPILER "/home/axom/axom_tpls/none-none/compiler-wrapper-1.0-zi6ke3figxbt6vlltwinxhvhrnky2skj/libexec/spack/clang/clang" CACHE PATH "") + set(CMAKE_C_COMPILER "/home/axom/axom_tpls/none-none/compiler-wrapper-1.0-u5fjo4cce7cqt6425ipfxnafausfog7z/libexec/spack/clang/clang" CACHE PATH "") - set(CMAKE_CXX_COMPILER "/home/axom/axom_tpls/none-none/compiler-wrapper-1.0-zi6ke3figxbt6vlltwinxhvhrnky2skj/libexec/spack/clang/clang++" CACHE PATH "") + set(CMAKE_CXX_COMPILER "/home/axom/axom_tpls/none-none/compiler-wrapper-1.0-u5fjo4cce7cqt6425ipfxnafausfog7z/libexec/spack/clang/clang++" CACHE PATH "") - set(CMAKE_Fortran_COMPILER "/home/axom/axom_tpls/none-none/compiler-wrapper-1.0-zi6ke3figxbt6vlltwinxhvhrnky2skj/libexec/spack/gcc/gfortran" CACHE PATH "") + set(CMAKE_Fortran_COMPILER "/home/axom/axom_tpls/none-none/compiler-wrapper-1.0-u5fjo4cce7cqt6425ipfxnafausfog7z/libexec/spack/gcc/gfortran" CACHE PATH "") else() @@ -49,13 +49,13 @@ set(BLT_EXE_LINKER_FLAGS " -Wl,-rpath,/usr/lib/llvm-19/lib" CACHE STRING "Adds a # MPI #------------------------------------------------------------------------------ -set(MPI_C_COMPILER "/home/axom/axom_tpls/llvm-19.0.0/mpich-4.2.0-wo6l3bjqx2zeznegryh6tkpphpwrsjkk/bin/mpicc" CACHE PATH "") +set(MPI_C_COMPILER "/home/axom/axom_tpls/llvm-19.0.0/mpich-4.2.0-wxhfezauopwtrdjmf6hx32l2jh4yyb25/bin/mpicc" CACHE PATH "") -set(MPI_CXX_COMPILER "/home/axom/axom_tpls/llvm-19.0.0/mpich-4.2.0-wo6l3bjqx2zeznegryh6tkpphpwrsjkk/bin/mpicxx" CACHE PATH "") +set(MPI_CXX_COMPILER "/home/axom/axom_tpls/llvm-19.0.0/mpich-4.2.0-wxhfezauopwtrdjmf6hx32l2jh4yyb25/bin/mpicxx" CACHE PATH "") -set(MPI_Fortran_COMPILER "/home/axom/axom_tpls/llvm-19.0.0/mpich-4.2.0-wo6l3bjqx2zeznegryh6tkpphpwrsjkk/bin/mpif90" CACHE PATH "") +set(MPI_Fortran_COMPILER "/home/axom/axom_tpls/llvm-19.0.0/mpich-4.2.0-wxhfezauopwtrdjmf6hx32l2jh4yyb25/bin/mpif90" CACHE PATH "") -set(MPIEXEC_EXECUTABLE "/home/axom/axom_tpls/llvm-19.0.0/mpich-4.2.0-wo6l3bjqx2zeznegryh6tkpphpwrsjkk/bin/mpirun" CACHE PATH "") +set(MPIEXEC_EXECUTABLE "/home/axom/axom_tpls/llvm-19.0.0/mpich-4.2.0-wxhfezauopwtrdjmf6hx32l2jh4yyb25/bin/mpirun" CACHE PATH "") set(MPIEXEC_NUMPROC_FLAG "-np" CACHE STRING "") @@ -79,27 +79,27 @@ set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") set(TPL_ROOT "/home/axom/axom_tpls/llvm-19.0.0" CACHE PATH "") -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-2rj2syiqwxefblliijogdqlupmw4by3q" CACHE PATH "") +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-23be5eyo7aox2o6tzewawhlnjsci3pau" CACHE PATH "") # C2C not built -set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-favb3nc3juneeg4pso4unmm6ob5dlmxl" CACHE PATH "") +set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-g3kaipukjvqu677tqztygnik5kzcxhfj" CACHE PATH "") -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-k427jkpcjllzevbro2quxda5gtq4crkl" CACHE PATH "") +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-mwa7fanurwtkpebryywcggusn4gd7yg2" CACHE PATH "") set(LUA_DIR "/usr" CACHE PATH "") -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-4li5kka37kzoc2etkb7jeky27uca7z4o" CACHE PATH "") +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-dkkk27oc7p2gsrq4cslpdsv5qz7g3sbd" CACHE PATH "") -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-nre3wgoi6snxanvgnc5f27np4rriihqr" CACHE PATH "") +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-kulqmeumvx2c36r6rzz7lwndhsv3ot4i" CACHE PATH "") # OPENCASCADE not built -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-p5a5gwlkzpbmtrbfdnjf5yhsbaeujhit" CACHE PATH "") +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-idbd67m2y4b4gnuxxbivm7hvesbbl4q5" CACHE PATH "") -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-cuvnujomk7ouem762777uqz2hxx3h4sl" CACHE PATH "") +set(CALIPER_DIR "${TPL_ROOT}/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-qv2wv4xikow5wxrhdem6c2dvkxt2cptf" CACHE PATH "") -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-s3u5u2ql34vblcn4ezdkln4vebd665za" CACHE PATH "") +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-y2k23nuv2eya2soe3fznpcgsgt2k2dai" CACHE PATH "") # scr not built diff --git a/host-configs/matrix-toss_4_x86_64_ib-gcc@13.3.1_cuda.cmake b/host-configs/matrix-toss_4_x86_64_ib-gcc@13.3.1_cuda.cmake index efa45c9047..001a7314bd 100644 --- a/host-configs/matrix-toss_4_x86_64_ib-gcc@13.3.1_cuda.cmake +++ b/host-configs/matrix-toss_4_x86_64_ib-gcc@13.3.1_cuda.cmake @@ -4,28 +4,28 @@ # CMake executable path: /usr/tce/packages/cmake/cmake-3.26.3/bin/cmake #------------------------------------------------------------------------------ -set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/gcc-13.3.1/blt-develop-vkyjvzyg7n4ig7x4llo53lndvnwsrbjq;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/gcc-13.3.1/c2c-1.8.0-3bch3wbxcl3eji2wsbbbzmagowxe4lpc;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/gcc-13.3.1/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-ss6he6vnxctdifczfduoqdpfyjltt2r3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/gcc-13.3.1/conduit-0.9.5-icskqkcmikkfw2itxiq6xdt6nilzlsvr;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/gcc-13.3.1/mfem-4.9.0-lkbiphsoccgpbaqo2cujuxcf3dqb4gga;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/gcc-13.3.1/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-2u2olu3wtrgskohwge6z2r5p4pbn24xi;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/gcc-13.3.1/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-qqnegxhkanugllghjqvoqjilj2h4ouuf;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/gcc-13.3.1/adiak-0.4.0-45h4d32dvvatilujstudj3ucvmdeyi6a;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/gcc-13.3.1/libunwind-1.8.3-74hjhhtejjsdgxjpp262xlm5ow6psq4r;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/gcc-13.3.1/hdf5-1.8.23-gokrordtweyfprtzgrzsycyilhy32uc7;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/gcc-13.3.1/parmetis-4.0.3-euggsyckxbtpzv6kzq74k3ndngpw2yqh;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/gcc-13.3.1/hypre-2.27.0-ceinfx2z45d7ap3i2lif6j2qw6jw7vhf;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/gcc-13.3.1/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-idk67733aarmoow76xcm5idyfijqjntn;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/gcc-13.3.1/fmt-11.0.2-faqgdwrlrl4nwv35msienhldhqrq2vce;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/gcc-13.3.1/metis-5.1.0-ovo3o7do7zr5fxw6mi2flzy6ftfsavk2;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/none-none/gcc-runtime-13.3.1-k43mnfzd4ehqvovn4d5qq7b5f6sfetsx;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/usr/tce/packages/cmake/cmake-3.26.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/gcc-13.3.1/cppcheck-2.18.0-d2tmb7ls2d5vgh6vhcyohecwcu6msopb;/usr/tce/packages/cuda/cuda-12.9.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/doxygen-1.13.2;/usr/tce/packages/gcc/gcc-13.3.1;/usr/tce/packages/clang/clang-19.1.3;/usr/tce/packages/mvapich2/mvapich2-2.3.7-gcc-13.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5" CACHE STRING "") +set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/gcc-13.3.1/blt-0.7.1-yiu2olkumeazbrto7x4v2dv6qbefhf5a;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/gcc-13.3.1/c2c-1.8.0-jkclfdpl7igj3ur3ufnpt6dupjfvotpc;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/gcc-13.3.1/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-qekykotizhycp2p4deoltaa227sajuvj;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/gcc-13.3.1/conduit-0.9.5-xyt2d2ot4eozuhrjv7mccoe7tw6ef7ui;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/gcc-13.3.1/mfem-4.9.0-kjei2ccah6sei4jplqabrucxltyq4zfb;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/gcc-13.3.1/py-nanobind-2.7.0-szozdpwzge7ah4bsilit6fijezxqbfop;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/none-none/py-pytest-9.0.0-vozuj6nkk42nhxeo5mawnux3w7bj3awe;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/gcc-13.3.1/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-vmsmvq25y56dkomrba3g63ls5nuga6xm;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/gcc-13.3.1/umpire-2025.12.0-kjyb6uox2o7qtfna22uqzxrqck7lukbt;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/gcc-13.3.1/adiak-0.4.0-i5bahteezqmswdv2ulpfvfogmuue463q;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/gcc-13.3.1/libunwind-1.8.3-pwdmczcnf7vugfly5zk7eztefnn7kv75;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/gcc-13.3.1/hdf5-1.8.23-2pnsuxpt6r2wmdc6sqyku6ki6na4gcfl;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/gcc-13.3.1/parmetis-4.0.3-tt2yxrbsrccyglhjqcs2y2nspmt4qoqx;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/gcc-13.3.1/py-numpy-2.4.2-z4yapdkn22w6adfrl7ibucqiokgrwb7f;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/gcc-13.3.1/hypre-2.27.0-bs56wsg2yagtwcz5q5a67ov4tln54p5i;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/gcc-13.3.1/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-fm7mimsvemux42yrsmsvqw6tl4kugyzy;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/gcc-13.3.1/fmt-11.0.2-ggfpxocredbjrldu7ar33cjedhmkm3da;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/gcc-13.3.1/metis-5.1.0-3jtvhjwnhqqaf5v2na7f675qgvlusyx3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/none-none/gcc-runtime-13.3.1-zsobnkwck2glzcbukupgvgbiwwhdonys;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/usr/tce/packages/cmake/cmake-3.26.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/gcc-13.3.1/cppcheck-2.18.0-i3p56kpf66xzj4wm5kfqxyc4vgox7gb3;/usr/tce/packages/cuda/cuda-12.9.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/doxygen-1.15.0;/usr/tce/packages/gcc/gcc-13.3.1;/usr/tce/packages/clang/clang-19.1.3;/usr/tce/packages/mvapich2/mvapich2-2.3.7-gcc-13.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11" CACHE STRING "") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") -set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/gcc-13.3.1/axom-develop-cgeagxjp7rbuciiqqnlu5ajev42355xw/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/gcc-13.3.1/axom-develop-cgeagxjp7rbuciiqqnlu5ajev42355xw/lib64;;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/gcc-13.3.1/axom-develop-5sjqzzwpctcjengeuc7nl7pz6j66smdo/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/gcc-13.3.1/axom-develop-5sjqzzwpctcjengeuc7nl7pz6j66smdo/lib64;;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") -set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/gcc-13.3.1/axom-develop-cgeagxjp7rbuciiqqnlu5ajev42355xw/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/gcc-13.3.1/axom-develop-cgeagxjp7rbuciiqqnlu5ajev42355xw/lib64;;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/gcc-13.3.1/axom-develop-5sjqzzwpctcjengeuc7nl7pz6j66smdo/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/gcc-13.3.1/axom-develop-5sjqzzwpctcjengeuc7nl7pz6j66smdo/lib64;;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") #------------------------------------------------------------------------------ # Compilers #------------------------------------------------------------------------------ -# Compiler Spec: gcc@13.3.1/75lfrhqb3monlgkmkokrboaqienagc6u +# Compiler Spec: gcc@13.3.1/xrm3n2pex2en2wvm6p4ap62nieoz7kne #------------------------------------------------------------------------------ if(DEFINED ENV{SPACK_CC}) - set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/gcc/gcc" CACHE PATH "") + set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/gcc/gcc" CACHE PATH "") - set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/gcc/g++" CACHE PATH "") + set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/gcc/g++" CACHE PATH "") - set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/gcc/gfortran" CACHE PATH "") + set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/gcc/gfortran" CACHE PATH "") else() @@ -99,52 +99,64 @@ set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") # TPLs #------------------------------------------------------------------------------ -set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/gcc-13.3.1" CACHE PATH "") +set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/gcc-13.3.1" CACHE PATH "") -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-icskqkcmikkfw2itxiq6xdt6nilzlsvr" CACHE PATH "") +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-xyt2d2ot4eozuhrjv7mccoe7tw6ef7ui" CACHE PATH "") -set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-3bch3wbxcl3eji2wsbbbzmagowxe4lpc" CACHE PATH "") +set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-jkclfdpl7igj3ur3ufnpt6dupjfvotpc" CACHE PATH "") -set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-lkbiphsoccgpbaqo2cujuxcf3dqb4gga" CACHE PATH "") +set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-kjei2ccah6sei4jplqabrucxltyq4zfb" CACHE PATH "") -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-gokrordtweyfprtzgrzsycyilhy32uc7" CACHE PATH "") +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-2pnsuxpt6r2wmdc6sqyku6ki6na4gcfl" CACHE PATH "") set(LUA_DIR "/usr" CACHE PATH "") -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-2u2olu3wtrgskohwge6z2r5p4pbn24xi" CACHE PATH "") +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-vmsmvq25y56dkomrba3g63ls5nuga6xm" CACHE PATH "") -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-qqnegxhkanugllghjqvoqjilj2h4ouuf" CACHE PATH "") +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-kjyb6uox2o7qtfna22uqzxrqck7lukbt" CACHE PATH "") # OPENCASCADE not built -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-45h4d32dvvatilujstudj3ucvmdeyi6a" CACHE PATH "") +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-i5bahteezqmswdv2ulpfvfogmuue463q" CACHE PATH "") -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-ss6he6vnxctdifczfduoqdpfyjltt2r3" CACHE PATH "") +set(CALIPER_DIR "${TPL_ROOT}/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-qekykotizhycp2p4deoltaa227sajuvj" CACHE PATH "") -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-idk67733aarmoow76xcm5idyfijqjntn" CACHE PATH "") +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-fm7mimsvemux42yrsmsvqw6tl4kugyzy" CACHE PATH "") # scr not built #------------------------------------------------------------------------------ -# Devtools +# Devtools & Python #------------------------------------------------------------------------------ -set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37" CACHE PATH "") +set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14" CACHE PATH "") set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/clang/clang-19.1.3/bin/clang-format" CACHE PATH "") -set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/python3" CACHE PATH "") +set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/python3" CACHE PATH "") -set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/jsonschema" CACHE PATH "") +set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/jsonschema" CACHE PATH "") set(ENABLE_DOCS ON CACHE BOOL "") -set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/sphinx-build" CACHE PATH "") +set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/sphinx-build" CACHE PATH "") + +set(YAPF_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/yapf" CACHE PATH "") set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0/bin/shroud" CACHE PATH "") -set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-d2tmb7ls2d5vgh6vhcyohecwcu6msopb/bin/cppcheck" CACHE PATH "") +set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-i3p56kpf66xzj4wm5kfqxyc4vgox7gb3/bin/cppcheck" CACHE PATH "") + +set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/doxygen-1.15.0/bin/doxygen" CACHE PATH "") + +set(PY_NANOBIND_DIR "${TPL_ROOT}/py-nanobind-2.7.0-szozdpwzge7ah4bsilit6fijezxqbfop/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PYTEST_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/none-none/py-pytest-9.0.0-vozuj6nkk42nhxeo5mawnux3w7bj3awe/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_NUMPY_DIR "${TPL_ROOT}/py-numpy-2.4.2-z4yapdkn22w6adfrl7ibucqiokgrwb7f/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PLUGGY_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/none-none/py-pluggy-1.6.0-6zab4pck6v7johubbhalr2waowbwpjei/lib/python3.13/site-packages" CACHE PATH "") -set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/doxygen-1.13.2/bin/doxygen" CACHE PATH "") +set(PY_INICONFIG_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/none-none/py-iniconfig-2.1.0-xwmbxuhk2oo3dcuizdp3z4hqbpqykkom/lib/python3.13/site-packages" CACHE PATH "") diff --git a/host-configs/matrix-toss_4_x86_64_ib-llvm@19.1.3_cuda.cmake b/host-configs/matrix-toss_4_x86_64_ib-llvm@19.1.3_cuda.cmake index 601e285071..c439eeb3cd 100644 --- a/host-configs/matrix-toss_4_x86_64_ib-llvm@19.1.3_cuda.cmake +++ b/host-configs/matrix-toss_4_x86_64_ib-llvm@19.1.3_cuda.cmake @@ -4,28 +4,28 @@ # CMake executable path: /usr/tce/packages/cmake/cmake-3.26.3/bin/cmake #------------------------------------------------------------------------------ -set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/llvm-19.1.3/blt-develop-lv6kxkbht6tnhkesyvxpn4co7wh7yqkx;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/llvm-19.1.3/c2c-1.8.0-jcvyunoextaorp7eqlrec6s53cnlm7cn;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/llvm-19.1.3/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-ez6ccmzayktinrdnyfioiu2pagdgmrjl;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/llvm-19.1.3/conduit-0.9.5-dmle6tliomp27z2usvm22ukviomsvezy;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/llvm-19.1.3/mfem-4.9.0-46z5loc32omdkn3y3dowlufhkcdio3mb;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/llvm-19.1.3/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-ictxt2yfuoeavhslmvmtf6btksajzeue;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/llvm-19.1.3/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-3qtvx6gvfa3ftroiuctzksweq2i7vgav;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/llvm-19.1.3/adiak-0.4.0-t7ws2osd4v4fd3bffvzozbcq6gqdlf2i;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/llvm-19.1.3/libunwind-1.8.3-222s6ifq5wyaudy7h43urrshydfjig3q;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/llvm-19.1.3/hdf5-1.8.23-lw4obzkj7og4qegzmwizuxvotpz4lkot;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/llvm-19.1.3/parmetis-4.0.3-muygwq5u7gusmbn24red6rvpwbxck6l5;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/llvm-19.1.3/hypre-2.27.0-czx6rwihdfohxp4p4ssn24ykk2mpin2e;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/llvm-19.1.3/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-oqj2he2t5izbaognxgx4m5wdoenx3rqu;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/llvm-19.1.3/fmt-11.0.2-g4qwjp4qo7vxtvq3zijosapcbpnf6zja;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/none-none/gcc-runtime-13.3.1-k43mnfzd4ehqvovn4d5qq7b5f6sfetsx;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/llvm-19.1.3/metis-5.1.0-xzd22iguknjmsctpcvgd5blzwx6aq6wd;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/usr/tce/packages/cmake/cmake-3.26.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/gcc-13.3.1/cppcheck-2.18.0-d2tmb7ls2d5vgh6vhcyohecwcu6msopb;/usr/tce/packages/cuda/cuda-12.9.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/doxygen-1.13.2;/usr/tce/packages/gcc/gcc-13.3.1;/usr/tce/packages/clang/clang-19.1.3;/usr/tce/packages/mvapich2/mvapich2-2.3.7-clang-19.1.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5" CACHE STRING "") +set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/llvm-19.1.3/blt-0.7.1-577uis2w7b3ipf4v4v6y6vogmy52d6ay;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/llvm-19.1.3/c2c-1.8.0-pk3z5zabg2gtkur2c4mqzc5zz7z5f2tv;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/llvm-19.1.3/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-ftzyobuu2a4siddiotqw4652bctzj3ke;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/llvm-19.1.3/conduit-0.9.5-gracxngtjim7b6zjsb5z4kf7qk347eo2;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/llvm-19.1.3/mfem-4.9.0-vvfbyadobvw4sxcdwuulbfs2lneeczet;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/llvm-19.1.3/py-nanobind-2.7.0-6akjhhlga6h3jx75swovfvo76k6rw6fp;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/none-none/py-pytest-9.0.0-vozuj6nkk42nhxeo5mawnux3w7bj3awe;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/llvm-19.1.3/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-aibnhmtfonzvsz7owanyr6m3eelmwfvj;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/llvm-19.1.3/umpire-2025.12.0-3xllaqzq537svpt3ie6jhzoaxciuut2i;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/llvm-19.1.3/adiak-0.4.0-27bezbcpd5jxnvs65h3m6u2aheplxbmv;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/llvm-19.1.3/libunwind-1.8.3-ddv7ypujzw2wvlzabw3d42qygcbtofuq;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/llvm-19.1.3/hdf5-1.8.23-b37o2ze3w5sozwz6jmalg4pgg66jcogm;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/llvm-19.1.3/parmetis-4.0.3-slhcesf5fhsucwxtlxxana67jcrligfy;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/llvm-19.1.3/py-numpy-2.4.2-7qsjxyuuh7rh5hccdziewhwqymkmepb3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/llvm-19.1.3/hypre-2.27.0-l2mxwhcndyhn4pkbe4rthke2rlkmgdbd;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/llvm-19.1.3/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-crik3a76mg7gqb6xsqkijjk3qzlw4mcl;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/llvm-19.1.3/fmt-11.0.2-uougkyc3rcyd7punvwjtcme2zlhehpgz;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/none-none/gcc-runtime-13.3.1-zsobnkwck2glzcbukupgvgbiwwhdonys;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/llvm-19.1.3/metis-5.1.0-3jeshrn7tydsgn5zdkf3iirdhw3u3oeq;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/usr/tce/packages/cmake/cmake-3.26.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/gcc-13.3.1/cppcheck-2.18.0-i3p56kpf66xzj4wm5kfqxyc4vgox7gb3;/usr/tce/packages/cuda/cuda-12.9.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/doxygen-1.15.0;/usr/tce/packages/gcc/gcc-13.3.1;/usr/tce/packages/clang/clang-19.1.3;/usr/tce/packages/mvapich2/mvapich2-2.3.7-clang-19.1.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11" CACHE STRING "") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") -set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/llvm-19.1.3/axom-develop-r65exa7hrmchbexsx6t3ifiksm4brxeh/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/llvm-19.1.3/axom-develop-r65exa7hrmchbexsx6t3ifiksm4brxeh/lib64;;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/llvm-19.1.3-gy2lu5xbi4csr2k47emlajzfs5mlsd4g/lib/x86_64-unknown-linux-gnu;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13;/usr/tce/packages/clang/clang-19.1.3/lib;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/llvm-19.1.3/axom-develop-so3wm2mhso745nxfh2c4gcma5vgtynxi/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/llvm-19.1.3/axom-develop-so3wm2mhso745nxfh2c4gcma5vgtynxi/lib64;;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/llvm-19.1.3-gy2lu5xbi4csr2k47emlajzfs5mlsd4g/lib/x86_64-unknown-linux-gnu;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13;/usr/tce/packages/clang/clang-19.1.3/lib;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") -set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/llvm-19.1.3/axom-develop-r65exa7hrmchbexsx6t3ifiksm4brxeh/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/llvm-19.1.3/axom-develop-r65exa7hrmchbexsx6t3ifiksm4brxeh/lib64;;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/llvm-19.1.3-gy2lu5xbi4csr2k47emlajzfs5mlsd4g/lib/x86_64-unknown-linux-gnu;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13;/usr/tce/packages/clang/clang-19.1.3/lib;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/llvm-19.1.3/axom-develop-so3wm2mhso745nxfh2c4gcma5vgtynxi/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/llvm-19.1.3/axom-develop-so3wm2mhso745nxfh2c4gcma5vgtynxi/lib64;;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/llvm-19.1.3-gy2lu5xbi4csr2k47emlajzfs5mlsd4g/lib/x86_64-unknown-linux-gnu;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13;/usr/tce/packages/clang/clang-19.1.3/lib;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") #------------------------------------------------------------------------------ # Compilers #------------------------------------------------------------------------------ -# Compiler Spec: llvm@19.1.3/dks2hxs7zxd55vu4lwnrychk52n73agw +# Compiler Spec: llvm@19.1.3/4rf6d7atkulu6wz7bucycjwtiuwqfy24 #------------------------------------------------------------------------------ if(DEFINED ENV{SPACK_CC}) - set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/clang/clang" CACHE PATH "") + set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/clang/clang" CACHE PATH "") - set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/clang/clang++" CACHE PATH "") + set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/clang/clang++" CACHE PATH "") - set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/gcc/gfortran" CACHE PATH "") + set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/gcc/gfortran" CACHE PATH "") else() @@ -101,52 +101,64 @@ set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") # TPLs #------------------------------------------------------------------------------ -set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_35_03/llvm-19.1.3" CACHE PATH "") +set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/llvm-19.1.3" CACHE PATH "") -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-dmle6tliomp27z2usvm22ukviomsvezy" CACHE PATH "") +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-gracxngtjim7b6zjsb5z4kf7qk347eo2" CACHE PATH "") -set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-jcvyunoextaorp7eqlrec6s53cnlm7cn" CACHE PATH "") +set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-pk3z5zabg2gtkur2c4mqzc5zz7z5f2tv" CACHE PATH "") -set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-46z5loc32omdkn3y3dowlufhkcdio3mb" CACHE PATH "") +set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-vvfbyadobvw4sxcdwuulbfs2lneeczet" CACHE PATH "") -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-lw4obzkj7og4qegzmwizuxvotpz4lkot" CACHE PATH "") +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-b37o2ze3w5sozwz6jmalg4pgg66jcogm" CACHE PATH "") set(LUA_DIR "/usr" CACHE PATH "") -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-ictxt2yfuoeavhslmvmtf6btksajzeue" CACHE PATH "") +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-aibnhmtfonzvsz7owanyr6m3eelmwfvj" CACHE PATH "") -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-3qtvx6gvfa3ftroiuctzksweq2i7vgav" CACHE PATH "") +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-3xllaqzq537svpt3ie6jhzoaxciuut2i" CACHE PATH "") # OPENCASCADE not built -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-t7ws2osd4v4fd3bffvzozbcq6gqdlf2i" CACHE PATH "") +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-27bezbcpd5jxnvs65h3m6u2aheplxbmv" CACHE PATH "") -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-ez6ccmzayktinrdnyfioiu2pagdgmrjl" CACHE PATH "") +set(CALIPER_DIR "${TPL_ROOT}/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-ftzyobuu2a4siddiotqw4652bctzj3ke" CACHE PATH "") -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-oqj2he2t5izbaognxgx4m5wdoenx3rqu" CACHE PATH "") +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-crik3a76mg7gqb6xsqkijjk3qzlw4mcl" CACHE PATH "") # scr not built #------------------------------------------------------------------------------ -# Devtools +# Devtools & Python #------------------------------------------------------------------------------ -set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37" CACHE PATH "") +set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14" CACHE PATH "") set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/clang/clang-19.1.3/bin/clang-format" CACHE PATH "") -set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/python3" CACHE PATH "") +set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/python3" CACHE PATH "") -set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/jsonschema" CACHE PATH "") +set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/jsonschema" CACHE PATH "") set(ENABLE_DOCS ON CACHE BOOL "") -set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/sphinx-build" CACHE PATH "") +set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/sphinx-build" CACHE PATH "") + +set(YAPF_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/yapf" CACHE PATH "") set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0/bin/shroud" CACHE PATH "") -set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-d2tmb7ls2d5vgh6vhcyohecwcu6msopb/bin/cppcheck" CACHE PATH "") +set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-i3p56kpf66xzj4wm5kfqxyc4vgox7gb3/bin/cppcheck" CACHE PATH "") + +set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/doxygen-1.15.0/bin/doxygen" CACHE PATH "") + +set(PY_NANOBIND_DIR "${TPL_ROOT}/py-nanobind-2.7.0-6akjhhlga6h3jx75swovfvo76k6rw6fp/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PYTEST_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/none-none/py-pytest-9.0.0-vozuj6nkk42nhxeo5mawnux3w7bj3awe/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_NUMPY_DIR "${TPL_ROOT}/py-numpy-2.4.2-7qsjxyuuh7rh5hccdziewhwqymkmepb3/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PLUGGY_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/none-none/py-pluggy-1.6.0-6zab4pck6v7johubbhalr2waowbwpjei/lib/python3.13/site-packages" CACHE PATH "") -set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/doxygen-1.13.2/bin/doxygen" CACHE PATH "") +set(PY_INICONFIG_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_11_13_12_38/none-none/py-iniconfig-2.1.0-xwmbxuhk2oo3dcuizdp3z4hqbpqykkom/lib/python3.13/site-packages" CACHE PATH "") diff --git a/host-configs/rzadams-toss_4_x86_64_ib_cray-cce@20.0.0_hip.cmake b/host-configs/rzadams-toss_4_x86_64_ib_cray-cce@20.0.0_hip.cmake index e18a080cec..2723deaf78 100644 --- a/host-configs/rzadams-toss_4_x86_64_ib_cray-cce@20.0.0_hip.cmake +++ b/host-configs/rzadams-toss_4_x86_64_ib_cray-cce@20.0.0_hip.cmake @@ -4,28 +4,28 @@ # CMake executable path: /usr/tce/packages/cmake/cmake-3.29.2/bin/cmake #------------------------------------------------------------------------------ -set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/cce-20.0.0/blt-develop-pwsc32pfi7a4xxama2m7eknfhfjllik6;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/cce-20.0.0/c2c-1.8.0-nu3d5eyh2exon7giv52bcw2e7miwx4ey;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/cce-20.0.0/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-bimrixe6smxyacdb5goo7muovyutiaim;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/cce-20.0.0/conduit-0.9.5-n62sqaudocgfahdhi3xerhjl4cfz4cfm;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/cce-20.0.0/lua-5.4.6-cczerukzth4xrqai22ypclwsaob6oh3m;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/cce-20.0.0/mfem-4.9.0-qptl47hqr27lw4qcnhbti2zk22t3fpw3;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/cce-20.0.0/adiak-0.4.0-c2l2d4bka2a3ik25akjd6a6y5bf2nqor;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/cce-20.0.0/libunwind-1.8.3-m7dgrtoy2hs5hy5c34azf43onj2n7c2t;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/cce-20.0.0/hdf5-1.8.23-sqtvp52fpuxariizrjafw4ineangzmgb;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/cce-20.0.0/parmetis-4.0.3-6jq6nu6qr4ttj7susud47swbrdojss3s;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/cce-20.0.0/hypre-2.27.0-5jl6onx4nq7lkqxbdneoc7knei2gnwb6;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/cce-20.0.0/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-5nzacrth4amewhoeu4msnfbplkljtznz;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/cce-20.0.0/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-l7oioa3ne4kb2idk4r3gmjdqrvecc46c;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/cce-20.0.0/zlib-1.3.1-7dd5r4czl743knbjpnyifcyo3mxlbdoz;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/cce-20.0.0/metis-5.1.0-azn3bxwpfq2zvgapjo6w5pozump6i7e3;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/cce-20.0.0/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-2la2lsbddc2dh5mmtokuupqsoe24s7ip;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/cce-20.0.0/fmt-11.0.2-u3ogj3ypjupkeo6e4pcohtkfod3q2tdm;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/usr/tce/packages/cce-tce/cce-20.0.0;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.2-cce-20.0.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/doxygen-1.13.2;/opt/rocm-6.4.2;/opt/rocm-6.4.2;/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm;/opt/rocm-6.4.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/opt/rocm-6.4.2;/opt/rocm-6.4.2;/opt/rocm-6.4.2" CACHE STRING "") +set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0/blt-0.7.1-af45hpsxdxploxhqqi4irjmy4vz2omqx;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0/c2c-1.8.0-cpdkv2uxkhs3qmzqakt4sht3vuiucdwt;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-wytd46zvuquxg2rqf3zec5ldbmjeaat6;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0/conduit-0.9.5-pbrrhvrsmnewby6q3u35ceppt5fxme2p;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0/lua-5.4.8-y6z3polqakbuhn6nh6muri3rjxqmiioa;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0/mfem-4.9.0-2r7wws3ojiqvv6vk7y3ki443xke656sf;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0/py-nanobind-2.7.0-ieb2bzuz435ydpyiq2uj36yyqjbrffml;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/py-pytest-9.0.0-jfdwo62b3p36blpm54gvocrcj6afccv5;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0/adiak-0.4.0-lzgexbo5qyzepgju2acyy6d2qft443tb;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0/libunwind-1.8.3-zvteigxlopfo5tkdr2n2pglgosg42bah;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0/hdf5-1.8.23-to3lvqwzxrqzad65zbvnbtvyt4k63uxe;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0/parmetis-4.0.3-bajtzsmahjg2wvcjzo5gfb2hr5oj2elc;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0/py-numpy-2.4.2-xw5ysy75zfqlalmbmtl5phd2qip43hlo;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0/hypre-2.27.0-knkmxfbf3xcut2wmamjsmhrqf7u7xmi7;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-y7uevzr5oi5eansgqfm4ppgcdkvnni6t;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0/umpire-2025.12.0-ke2uxlxkv74lvrhujuzh3ktf3c6e7lfb;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0/zlib-1.3.1-f3sdiqmy2whvmdn2fxeol3k7oqwouays;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0/metis-5.1.0-v4d34x7btqhotktvu5bgk4iwk6h2lumb;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-a755kudv24eiizq4thcs2ca2fj7vy65x;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0/fmt-11.0.2-nzzmwf4nofjv46yeugehjo64opvfbbzr;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/usr/tce/packages/cce-tce/cce-20.0.0;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/doxygen-1.15.0;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm;/opt/rocm-6.4.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/opt/rocm-6.4.3" CACHE STRING "") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") -set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/cce-20.0.0/axom-develop-bgariutridspjv7p4wlx3n32b5va2pdl/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/cce-20.0.0/axom-develop-bgariutridspjv7p4wlx3n32b5va2pdl/lib64;;/opt/cray/pe/cce/20.0.0/cce/x86_64/lib;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0/axom-develop-csdbligyshk6zb3emr4vn5sjrrnbtobj/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0/axom-develop-csdbligyshk6zb3emr4vn5sjrrnbtobj/lib64;;/opt/cray/pe/cce/20.0.0/cce/x86_64/lib;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") -set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/cce-20.0.0/axom-develop-bgariutridspjv7p4wlx3n32b5va2pdl/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/cce-20.0.0/axom-develop-bgariutridspjv7p4wlx3n32b5va2pdl/lib64;;/opt/cray/pe/cce/20.0.0/cce/x86_64/lib;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0/axom-develop-csdbligyshk6zb3emr4vn5sjrrnbtobj/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0/axom-develop-csdbligyshk6zb3emr4vn5sjrrnbtobj/lib64;;/opt/cray/pe/cce/20.0.0/cce/x86_64/lib;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") #------------------------------------------------------------------------------ # Compilers #------------------------------------------------------------------------------ -# Compiler Spec: cce@20.0.0/qaj3yb2lw3bg5iz34y3j54ip4ngiyxf5 +# Compiler Spec: cce@20.0.0/v7nrkimihxta4odatu45wrllosgeklrd #------------------------------------------------------------------------------ if(DEFINED ENV{SPACK_CC}) - set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh/libexec/spack/cce/craycc" CACHE PATH "") + set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd/libexec/spack/cce/craycc" CACHE PATH "") - set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh/libexec/spack/cce/case-insensitive/crayCC" CACHE PATH "") + set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd/libexec/spack/cce/case-insensitive/crayCC" CACHE PATH "") - set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh/libexec/spack/cce/crayftn" CACHE PATH "") + set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd/libexec/spack/cce/crayftn" CACHE PATH "") else() @@ -47,11 +47,11 @@ set(CMAKE_CXX_FLAGS_DEBUG "-O1 -g" CACHE STRING "") # MPI #------------------------------------------------------------------------------ -set(MPI_C_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.2-cce-20.0.0/bin/mpicc" CACHE PATH "") +set(MPI_C_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.3/bin/mpicc" CACHE PATH "") -set(MPI_CXX_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.2-cce-20.0.0/bin/mpicxx" CACHE PATH "") +set(MPI_CXX_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.3/bin/mpicxx" CACHE PATH "") -set(MPI_Fortran_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.2-cce-20.0.0/bin/mpif90" CACHE PATH "") +set(MPI_Fortran_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.3/bin/mpif90" CACHE PATH "") set(MPIEXEC_EXECUTABLE "/usr/global/tools/flux_wrappers/bin/srun" CACHE PATH "") @@ -67,11 +67,11 @@ set(ENABLE_MPI ON CACHE BOOL "") # ROCm #------------------------------------------------ -set(ROCM_PATH "/opt/rocm-6.4.2" CACHE PATH "") +set(ROCM_PATH "/opt/rocm-6.4.3" CACHE PATH "") set(CMAKE_HIP_ARCHITECTURES "gfx90a;gfx942" CACHE STRING "") -set(CMAKE_HIP_COMPILER "/opt/rocm-6.4.2/bin/amdclang++" CACHE FILEPATH "") +set(CMAKE_HIP_COMPILER "/opt/rocm-6.4.3/bin/amdclang++" CACHE FILEPATH "") #------------------------------------------------------------------------------ @@ -82,11 +82,11 @@ set(CMAKE_HIP_COMPILER "/opt/rocm-6.4.2/bin/amdclang++" CACHE FILEPATH "") set(ENABLE_HIP ON CACHE BOOL "") -set(ROCM_ROOT_DIR "/opt/rocm-6.4.2" CACHE PATH "") +set(ROCM_ROOT_DIR "/opt/rocm-6.4.3" CACHE PATH "") set(BLT_CMAKE_IMPLICIT_LINK_LIBRARIES_EXCLUDE "unwind" CACHE STRING "") -set(CMAKE_EXE_LINKER_FLAGS "-lxpmem -L/opt/cray/pe/mpich/8.1.32/gtl/lib -Wl,-rpath,/opt/cray/pe/mpich/8.1.32/gtl/lib -lmpi_gtl_hsa -L/opt/rocm-6.4.2/lib/llvm/lib -Wl,-rpath,/opt/rocm-6.4.2/lib/llvm/lib -L/opt/rocm-6.4.2/lib -Wl,-rpath,/opt/rocm-6.4.2/lib -lpgmath -lompstub -L/opt/cray/pe/cce/20.0.0/cce/x86_64/lib -Wl,-rpath,/opt/cray/pe/cce/20.0.0/cce/x86_64/lib -lamdhip64 -lhsakmt -lhsa-runtime64 -lamd_comgr " CACHE STRING "") +set(CMAKE_EXE_LINKER_FLAGS "-lxpmem -L/opt/cray/pe/mpich/8.1.32/gtl/lib -Wl,-rpath,/opt/cray/pe/mpich/8.1.32/gtl/lib -lmpi_gtl_hsa -L/opt/rocm-6.4.3/lib/llvm/lib -Wl,-rpath,/opt/rocm-6.4.3/lib/llvm/lib -L/opt/rocm-6.4.3/lib -Wl,-rpath,/opt/rocm-6.4.3/lib -lpgmath -lompstub -L/opt/cray/pe/cce/20.0.0/cce/x86_64/lib -Wl,-rpath,/opt/cray/pe/cce/20.0.0/cce/x86_64/lib -lamdhip64 -lhsakmt -lhsa-runtime64 -lamd_comgr " CACHE STRING "") #------------------------------------------------ # Hardware Specifics @@ -100,52 +100,64 @@ set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") # TPLs #------------------------------------------------------------------------------ -set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/cce-20.0.0" CACHE PATH "") +set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/cce-20.0.0" CACHE PATH "") -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-n62sqaudocgfahdhi3xerhjl4cfz4cfm" CACHE PATH "") +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-pbrrhvrsmnewby6q3u35ceppt5fxme2p" CACHE PATH "") -set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-nu3d5eyh2exon7giv52bcw2e7miwx4ey" CACHE PATH "") +set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-cpdkv2uxkhs3qmzqakt4sht3vuiucdwt" CACHE PATH "") -set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-qptl47hqr27lw4qcnhbti2zk22t3fpw3" CACHE PATH "") +set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-2r7wws3ojiqvv6vk7y3ki443xke656sf" CACHE PATH "") -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-sqtvp52fpuxariizrjafw4ineangzmgb" CACHE PATH "") +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-to3lvqwzxrqzad65zbvnbtvyt4k63uxe" CACHE PATH "") -set(LUA_DIR "${TPL_ROOT}/lua-5.4.6-cczerukzth4xrqai22ypclwsaob6oh3m" CACHE PATH "") +set(LUA_DIR "${TPL_ROOT}/lua-5.4.8-y6z3polqakbuhn6nh6muri3rjxqmiioa" CACHE PATH "") -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-5nzacrth4amewhoeu4msnfbplkljtznz" CACHE PATH "") +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-y7uevzr5oi5eansgqfm4ppgcdkvnni6t" CACHE PATH "") -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-l7oioa3ne4kb2idk4r3gmjdqrvecc46c" CACHE PATH "") +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-ke2uxlxkv74lvrhujuzh3ktf3c6e7lfb" CACHE PATH "") # OPENCASCADE not built -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-c2l2d4bka2a3ik25akjd6a6y5bf2nqor" CACHE PATH "") +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-lzgexbo5qyzepgju2acyy6d2qft443tb" CACHE PATH "") -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-bimrixe6smxyacdb5goo7muovyutiaim" CACHE PATH "") +set(CALIPER_DIR "${TPL_ROOT}/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-wytd46zvuquxg2rqf3zec5ldbmjeaat6" CACHE PATH "") -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-2la2lsbddc2dh5mmtokuupqsoe24s7ip" CACHE PATH "") +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-a755kudv24eiizq4thcs2ca2fj7vy65x" CACHE PATH "") # scr not built #------------------------------------------------------------------------------ -# Devtools +# Devtools & Python #------------------------------------------------------------------------------ -set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48" CACHE PATH "") +set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25" CACHE PATH "") -set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm/bin/clang-format" CACHE PATH "") +set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm/bin/clang-format" CACHE PATH "") -set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/python3" CACHE PATH "") +set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/python3" CACHE PATH "") -set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/jsonschema" CACHE PATH "") +set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/jsonschema" CACHE PATH "") set(ENABLE_DOCS ON CACHE BOOL "") -set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/sphinx-build" CACHE PATH "") +set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/sphinx-build" CACHE PATH "") + +set(YAPF_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/yapf" CACHE PATH "") set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0/bin/shroud" CACHE PATH "") -set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w/bin/cppcheck" CACHE PATH "") +set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27/bin/cppcheck" CACHE PATH "") + +set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/doxygen-1.15.0/bin/doxygen" CACHE PATH "") + +set(PY_NANOBIND_DIR "${TPL_ROOT}/py-nanobind-2.7.0-ieb2bzuz435ydpyiq2uj36yyqjbrffml/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PYTEST_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/py-pytest-9.0.0-jfdwo62b3p36blpm54gvocrcj6afccv5/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_NUMPY_DIR "${TPL_ROOT}/py-numpy-2.4.2-xw5ysy75zfqlalmbmtl5phd2qip43hlo/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PLUGGY_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/py-pluggy-1.6.0-n4ojmtqyawxz6gipk64pup3ahwz3xqpu/lib/python3.13/site-packages" CACHE PATH "") -set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/doxygen-1.13.2/bin/doxygen" CACHE PATH "") +set(PY_INICONFIG_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/py-iniconfig-2.1.0-lf3yvch65se22jr7b5unfoxtse4ugkrk/lib/python3.13/site-packages" CACHE PATH "") diff --git a/host-configs/rzadams-toss_4_x86_64_ib_cray-llvm-amdgpu@6.3.1_hip.cmake b/host-configs/rzadams-toss_4_x86_64_ib_cray-llvm-amdgpu@6.3.1_hip.cmake index ecba83c8b5..6e6bc29eba 100644 --- a/host-configs/rzadams-toss_4_x86_64_ib_cray-llvm-amdgpu@6.3.1_hip.cmake +++ b/host-configs/rzadams-toss_4_x86_64_ib_cray-llvm-amdgpu@6.3.1_hip.cmake @@ -4,28 +4,28 @@ # CMake executable path: /usr/tce/packages/cmake/cmake-3.29.2/bin/cmake #------------------------------------------------------------------------------ -set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.3.1/blt-develop-glgaihoun6euvmdtqtlyoceslp5pdqrr;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.3.1/c2c-1.8.0-k6bzhviyoy4b4qiwcry5ngq2igehqpxz;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.3.1/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-dzlt2f4kgncqnzaehb2exy27b7nijpb4;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.3.1/conduit-0.9.5-ohicadtnuc7ou25j2wjeubibgtn3x27w;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.3.1/lua-5.4.6-waiv2xo2eqqwohqre65iu6oqzqcshbsd;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.3.1/mfem-4.9.0-xlgphhu27dvyu6t6snijepipaan6x5ee;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.3.1/adiak-0.4.0-tfjwrwri6ldtkqz5vvmaeay3tv3kju6r;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.3.1/libunwind-1.8.3-hupyutxzo74d26y5lmfsxihgfeaurjoq;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.3.1/hdf5-1.8.23-r6op3xgaaudlpritbebr2cjx5lw67q5f;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.3.1/parmetis-4.0.3-mcmehxox2f37vwp27zjzkn3i74qqnpfz;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.3.1/hypre-2.27.0-cc7jeieyge55h5axy5evcdi654jeyl5j;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.3.1/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-r33uioxc7aidenrvcb35hydewejgfr5e;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.3.1/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-5jmhwrbu2wqc6qswsjen75xoz4yymyna;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.3.1/zlib-1.3.1-xnk7wzwuyxloybgp6m2yhjyf4rhgqet3;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.3.1/metis-5.1.0-sa27v5szmjpsatve2ugwku5ok3s7mpon;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.3.1/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-7gcb7xgpawoj2eipuqary4mjrrsyznda;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.3.1/fmt-11.0.2-tm7xaljndccnw5eif5jy4fsftqm43ffl;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/doxygen-1.13.2;/opt/rocm-6.3.1;/opt/rocm-6.3.1;/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm;/opt/rocm-6.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/opt/rocm-6.3.1;/opt/rocm-6.3.1;/opt/rocm-6.3.1" CACHE STRING "") +set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.3.1/adiak-0.4.0-c4srnrz5apjetx74dt6xjah63o3a7xcx;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.3.1/blt-0.7.1-kzmxfjvxm4drr2qhspckvwee6mrlc3e5;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.3.1/c2c-1.8.0-lm64gc55hpxilmtsw7geirys3q4wacu5;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.3.1/conduit-0.9.5-wswspowegvp5byl5inc2cikljzkcqg64;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.3.1/lua-5.4.8-j7ngytniswhoa536kqfzarcraarkicbm;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.3.1/mfem-4.9.0-wetr3wqseqqobjb7be3uzrecpfewq4mr;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.3.1/py-nanobind-2.7.0-q2kwozph3gwgfyjnx43jp2gkbaghwxoj;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/py-pytest-9.0.0-jfdwo62b3p36blpm54gvocrcj6afccv5;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.3.1/hdf5-1.8.23-rb4cjthx4wz4wnpaizwmm2jycijdthqm;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.3.1/parmetis-4.0.3-ng66tt5fmjyfoiuuxyl4rxqv4ompawmd;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.3.1/py-numpy-2.4.2-zcxbrxijjc3miotq6s3kq446afrgycuu;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.3.1/hypre-2.27.0-6m2jwyzqbksxgmdznvh54ytysxyme7jy;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.3.1/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-okzhosj73rts33dgatxh4daotairh5jn;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.3.1/umpire-2025.12.0-of6o5lgmd6jgjqfwat2sbyngieagkeco;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.3.1/zlib-1.3.1-5w5muvpvct6uruxrddscblsiyizl3uoc;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.3.1/metis-5.1.0-4punmdkye6rovr3u7ph7bgj66qim77du;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.3.1/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-74scmbkik6ye7bunoclw46d6zrcfwgha;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.3.1/fmt-11.0.2-opsfnufdiedpfpob5wgbvhcrhyhzfkaq;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/doxygen-1.15.0;/opt/rocm-6.3.1;/opt/rocm-6.3.1;/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm;/opt/rocm-6.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/opt/rocm-6.3.1;/opt/rocm-6.3.1;/opt/rocm-6.3.1" CACHE STRING "") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") -set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.3.1/axom-develop-64ne2wqvozxbclbji4uxr2u2yimbfknp/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.3.1/axom-develop-64ne2wqvozxbclbji4uxr2u2yimbfknp/lib64;;/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12" CACHE STRING "") +set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.3.1/axom-develop-xoswouqk3ppxzuxtgegijd3kdoqlkvfe/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.3.1/axom-develop-xoswouqk3ppxzuxtgegijd3kdoqlkvfe/lib64;;/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12" CACHE STRING "") -set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.3.1/axom-develop-64ne2wqvozxbclbji4uxr2u2yimbfknp/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.3.1/axom-develop-64ne2wqvozxbclbji4uxr2u2yimbfknp/lib64;;/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12" CACHE STRING "") +set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.3.1/axom-develop-xoswouqk3ppxzuxtgegijd3kdoqlkvfe/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.3.1/axom-develop-xoswouqk3ppxzuxtgegijd3kdoqlkvfe/lib64;;/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") #------------------------------------------------------------------------------ # Compilers #------------------------------------------------------------------------------ -# Compiler Spec: llvm-amdgpu@6.3.1/ewmb23zt2h4lqtnvv6lsha7mdyiucmx3 +# Compiler Spec: llvm-amdgpu@6.3.1/ns2pv5bzkpjolxzmhgkckj6glqymgd7e #------------------------------------------------------------------------------ if(DEFINED ENV{SPACK_CC}) - set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh/libexec/spack/rocmcc/amdclang" CACHE PATH "") + set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd/libexec/spack/rocmcc/amdclang" CACHE PATH "") - set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh/libexec/spack/rocmcc/amdclang++" CACHE PATH "") + set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd/libexec/spack/rocmcc/amdclang++" CACHE PATH "") - set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh/libexec/spack/rocmcc/amdflang" CACHE PATH "") + set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd/libexec/spack/rocmcc/amdflang" CACHE PATH "") else() @@ -96,52 +96,64 @@ set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") # TPLs #------------------------------------------------------------------------------ -set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.3.1" CACHE PATH "") +set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.3.1" CACHE PATH "") -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-ohicadtnuc7ou25j2wjeubibgtn3x27w" CACHE PATH "") +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-wswspowegvp5byl5inc2cikljzkcqg64" CACHE PATH "") -set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-k6bzhviyoy4b4qiwcry5ngq2igehqpxz" CACHE PATH "") +set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-lm64gc55hpxilmtsw7geirys3q4wacu5" CACHE PATH "") -set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-xlgphhu27dvyu6t6snijepipaan6x5ee" CACHE PATH "") +set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-wetr3wqseqqobjb7be3uzrecpfewq4mr" CACHE PATH "") -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-r6op3xgaaudlpritbebr2cjx5lw67q5f" CACHE PATH "") +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-rb4cjthx4wz4wnpaizwmm2jycijdthqm" CACHE PATH "") -set(LUA_DIR "${TPL_ROOT}/lua-5.4.6-waiv2xo2eqqwohqre65iu6oqzqcshbsd" CACHE PATH "") +set(LUA_DIR "${TPL_ROOT}/lua-5.4.8-j7ngytniswhoa536kqfzarcraarkicbm" CACHE PATH "") -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-r33uioxc7aidenrvcb35hydewejgfr5e" CACHE PATH "") +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-okzhosj73rts33dgatxh4daotairh5jn" CACHE PATH "") -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-5jmhwrbu2wqc6qswsjen75xoz4yymyna" CACHE PATH "") +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-of6o5lgmd6jgjqfwat2sbyngieagkeco" CACHE PATH "") # OPENCASCADE not built -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-tfjwrwri6ldtkqz5vvmaeay3tv3kju6r" CACHE PATH "") +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-c4srnrz5apjetx74dt6xjah63o3a7xcx" CACHE PATH "") -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-dzlt2f4kgncqnzaehb2exy27b7nijpb4" CACHE PATH "") +# CALIPER not built -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-7gcb7xgpawoj2eipuqary4mjrrsyznda" CACHE PATH "") +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-74scmbkik6ye7bunoclw46d6zrcfwgha" CACHE PATH "") # scr not built #------------------------------------------------------------------------------ -# Devtools +# Devtools & Python #------------------------------------------------------------------------------ -set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48" CACHE PATH "") +set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25" CACHE PATH "") -set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm/bin/clang-format" CACHE PATH "") +set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm/bin/clang-format" CACHE PATH "") -set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/python3" CACHE PATH "") +set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/python3" CACHE PATH "") -set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/jsonschema" CACHE PATH "") +set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/jsonschema" CACHE PATH "") set(ENABLE_DOCS ON CACHE BOOL "") -set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/sphinx-build" CACHE PATH "") +set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/sphinx-build" CACHE PATH "") + +set(YAPF_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/yapf" CACHE PATH "") set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0/bin/shroud" CACHE PATH "") -set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w/bin/cppcheck" CACHE PATH "") +set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27/bin/cppcheck" CACHE PATH "") + +set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/doxygen-1.15.0/bin/doxygen" CACHE PATH "") + +set(PY_NANOBIND_DIR "${TPL_ROOT}/py-nanobind-2.7.0-q2kwozph3gwgfyjnx43jp2gkbaghwxoj/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PYTEST_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/py-pytest-9.0.0-jfdwo62b3p36blpm54gvocrcj6afccv5/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_NUMPY_DIR "${TPL_ROOT}/py-numpy-2.4.2-zcxbrxijjc3miotq6s3kq446afrgycuu/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PLUGGY_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/py-pluggy-1.6.0-n4ojmtqyawxz6gipk64pup3ahwz3xqpu/lib/python3.13/site-packages" CACHE PATH "") -set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/doxygen-1.13.2/bin/doxygen" CACHE PATH "") +set(PY_INICONFIG_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/py-iniconfig-2.1.0-lf3yvch65se22jr7b5unfoxtse4ugkrk/lib/python3.13/site-packages" CACHE PATH "") diff --git a/host-configs/rzadams-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.2_hip.cmake b/host-configs/rzadams-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.2_hip.cmake deleted file mode 100644 index 8703ded4f0..0000000000 --- a/host-configs/rzadams-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.2_hip.cmake +++ /dev/null @@ -1,147 +0,0 @@ -#------------------------------------------------------------------------------ -# !!!! This is a generated file, edit at own risk !!!! -#------------------------------------------------------------------------------ -# CMake executable path: /usr/tce/packages/cmake/cmake-3.29.2/bin/cmake -#------------------------------------------------------------------------------ - -set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.4.2/blt-develop-kei2jlql6ou5xgnzgg6l4zbzf7fplo25;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.4.2/c2c-1.8.0-xoebhlyceqtktuqrkhewjs4rqprgf6sb;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.4.2/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-te2ukl2lva3vrtuwcc3vfqlfjudggjlv;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.4.2/conduit-0.9.5-vluxk2dyxjp2euipxmmp5lrfwnn5rqmy;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.4.2/lua-5.4.6-ilrwi25dtsa3e2io2ktnzmiyq6va2drk;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.4.2/mfem-4.9.0-4fnvbajng4d6c63266zqdyboaajn55he;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.4.2/adiak-0.4.0-wpwqihuzni5l6g3siv4radax2sue25bz;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.4.2/libunwind-1.8.3-jieqgiira5po56srfxxucbxwau3w25pn;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.4.2/hdf5-1.8.23-5l55nhqjureqnunb5rt6ats675rmez2n;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.4.2/parmetis-4.0.3-qcjolzf7zacqngn5y7nbakmmxmbtiixh;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.4.2/hypre-2.27.0-jbqow3qk2icsbfwbue55mbzip7kssefz;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.4.2/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-ayjwwho7m3chhut5igfdk6ycvuzd4tgh;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.4.2/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-khzcgenw56jiezvsq3hfhdmhdchkmexa;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.4.2/zlib-1.3.1-eu7tohp7odrgv4ecjiufy3ouj4isw42j;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.4.2/metis-5.1.0-q25bz5xqaq77ll4bm2j5nhqol4hh2d2d;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.4.2/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-jspykahx2pbh3nddl6tz2n3arip53r4l;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.4.2/fmt-11.0.2-xgnexgwbj5cb7oevkpnunezrorc6izih;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/doxygen-1.13.2;/opt/rocm-6.4.2;/opt/rocm-6.4.2;/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm;/opt/rocm-6.4.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/opt/rocm-6.4.2;/opt/rocm-6.4.2;/opt/rocm-6.4.2" CACHE STRING "") - -set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") - -set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.4.2/axom-develop-f6fj5iovczthvodawdlfp2d6a7z5gvsx/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.4.2/axom-develop-f6fj5iovczthvodawdlfp2d6a7z5gvsx/lib64;;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") - -set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.4.2/axom-develop-f6fj5iovczthvodawdlfp2d6a7z5gvsx/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.4.2/axom-develop-f6fj5iovczthvodawdlfp2d6a7z5gvsx/lib64;;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") - -set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") - -#------------------------------------------------------------------------------ -# Compilers -#------------------------------------------------------------------------------ -# Compiler Spec: llvm-amdgpu@6.4.2/bb2nokv3ui3ksdf4t4xucxqtidlj2ds4 -#------------------------------------------------------------------------------ -if(DEFINED ENV{SPACK_CC}) - - set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh/libexec/spack/rocmcc/amdclang" CACHE PATH "") - - set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh/libexec/spack/rocmcc/amdclang++" CACHE PATH "") - - set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh/libexec/spack/rocmcc/amdflang" CACHE PATH "") - -else() - - set(CMAKE_C_COMPILER "/opt/rocm-6.4.2/llvm/bin/amdclang" CACHE PATH "") - - set(CMAKE_CXX_COMPILER "/opt/rocm-6.4.2/llvm/bin/amdclang++" CACHE PATH "") - - set(CMAKE_Fortran_COMPILER "/opt/rocm-6.4.2/llvm/bin/amdflang" CACHE PATH "") - -endif() - -set(CMAKE_Fortran_FLAGS "-Mfreeform" CACHE STRING "") - -set(ENABLE_FORTRAN ON CACHE BOOL "") - -#------------------------------------------------------------------------------ -# MPI -#------------------------------------------------------------------------------ - -set(MPI_C_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.2/bin/mpicc" CACHE PATH "") - -set(MPI_CXX_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.2/bin/mpicxx" CACHE PATH "") - -set(MPI_Fortran_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.2/bin/mpif90" CACHE PATH "") - -set(MPIEXEC_EXECUTABLE "/usr/global/tools/flux_wrappers/bin/srun" CACHE PATH "") - -set(MPIEXEC_NUMPROC_FLAG "-n" CACHE STRING "") - -set(ENABLE_MPI ON CACHE BOOL "") - -#------------------------------------------------------------------------------ -# Hardware -#------------------------------------------------------------------------------ - -#------------------------------------------------ -# ROCm -#------------------------------------------------ - -set(ROCM_PATH "/opt/rocm-6.4.2" CACHE PATH "") - -set(CMAKE_HIP_ARCHITECTURES "gfx90a;gfx942" CACHE STRING "") - -set(CMAKE_HIP_COMPILER "/opt/rocm-6.4.2/bin/amdclang++" CACHE FILEPATH "") - -#------------------------------------------------------------------------------ - -# Axom ROCm specifics - -#------------------------------------------------------------------------------ - - -set(ENABLE_HIP ON CACHE BOOL "") - -set(ROCM_ROOT_DIR "/opt/rocm-6.4.2" CACHE PATH "") - -set(CMAKE_EXE_LINKER_FLAGS "-lxpmem -L/opt/cray/pe/mpich/8.1.29/gtl/lib -Wl,-rpath,/opt/cray/pe/mpich/8.1.29/gtl/lib -lmpi_gtl_hsa -L/opt/rocm-6.4.2/lib/llvm/lib -Wl,-rpath,/opt/rocm-6.4.2/lib/llvm/lib -L/opt/rocm-6.4.2/lib -Wl,-rpath,/opt/rocm-6.4.2/lib -lpgmath -lompstub -Wl,--disable-new-dtags -lflang -lflangrti -lamdhip64 -lhsakmt -lhsa-runtime64 -lamd_comgr " CACHE STRING "") - -#------------------------------------------------ -# Hardware Specifics -#------------------------------------------------ - -set(ENABLE_OPENMP OFF CACHE BOOL "") - -set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") - -#------------------------------------------------------------------------------ -# TPLs -#------------------------------------------------------------------------------ - -set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_42_44/llvm-amdgpu-6.4.2" CACHE PATH "") - -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-vluxk2dyxjp2euipxmmp5lrfwnn5rqmy" CACHE PATH "") - -set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-xoebhlyceqtktuqrkhewjs4rqprgf6sb" CACHE PATH "") - -set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-4fnvbajng4d6c63266zqdyboaajn55he" CACHE PATH "") - -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-5l55nhqjureqnunb5rt6ats675rmez2n" CACHE PATH "") - -set(LUA_DIR "${TPL_ROOT}/lua-5.4.6-ilrwi25dtsa3e2io2ktnzmiyq6va2drk" CACHE PATH "") - -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-ayjwwho7m3chhut5igfdk6ycvuzd4tgh" CACHE PATH "") - -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-khzcgenw56jiezvsq3hfhdmhdchkmexa" CACHE PATH "") - -# OPENCASCADE not built - -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-wpwqihuzni5l6g3siv4radax2sue25bz" CACHE PATH "") - -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-te2ukl2lva3vrtuwcc3vfqlfjudggjlv" CACHE PATH "") - -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-jspykahx2pbh3nddl6tz2n3arip53r4l" CACHE PATH "") - -# scr not built - -#------------------------------------------------------------------------------ -# Devtools -#------------------------------------------------------------------------------ - -set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48" CACHE PATH "") - -set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm/bin/clang-format" CACHE PATH "") - -set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/python3" CACHE PATH "") - -set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/jsonschema" CACHE PATH "") - -set(ENABLE_DOCS ON CACHE BOOL "") - -set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/sphinx-build" CACHE PATH "") - -set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0/bin/shroud" CACHE PATH "") - -set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w/bin/cppcheck" CACHE PATH "") - -set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/doxygen-1.13.2/bin/doxygen" CACHE PATH "") - - diff --git a/host-configs/rzadams-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.3_hip.cmake b/host-configs/rzadams-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.3_hip.cmake new file mode 100644 index 0000000000..acad35209c --- /dev/null +++ b/host-configs/rzadams-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.3_hip.cmake @@ -0,0 +1,159 @@ +#------------------------------------------------------------------------------ +# !!!! This is a generated file, edit at own risk !!!! +#------------------------------------------------------------------------------ +# CMake executable path: /usr/tce/packages/cmake/cmake-3.29.2/bin/cmake +#------------------------------------------------------------------------------ + +set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3/blt-0.7.1-4kxhk7nbuiv5oh2ymh7sdimnmor36hmo;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3/c2c-1.8.0-h5kio7nseyazg4pzgvj4kxanb3plhbxm;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-rmlwpdacdtpzf4u72ctyroj72soqzf3f;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3/conduit-0.9.5-zqywrasos2vbears5hvdwxhulm3xox6q;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3/lua-5.4.8-gp4kdewsy4uiy6flsx342lgogcm7fym2;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3/mfem-4.9.0-g6vxdlgc7spurcdacgc6e5245iu2hyiw;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3/py-nanobind-2.7.0-2kp35jcpb73xuujvcz6kmg4q2npek4gg;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/py-pytest-9.0.0-jfdwo62b3p36blpm54gvocrcj6afccv5;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3/adiak-0.4.0-cropyu42jr4q6k3zar6mkma6gc2vp6tk;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3/libunwind-1.8.3-plszp43gkd75kzjcvge3qxrtb6j2budl;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3/hdf5-1.8.23-mgic2kxojd5zeivhaz473zzmzrg3gdqe;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3/parmetis-4.0.3-hd2qoczrh3vw3ejm6msitqdgecjk7xwe;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3/py-numpy-2.4.2-a3mo27shjtpliwewbm5cci2kf37crrab;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3/hypre-2.27.0-4nrl5egspbxmnkpzfym5udby6uruhn3i;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-wavyomm5hzyjf3xuyr33txmnspvxveei;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3/umpire-2025.12.0-4oytcvf556ksil4hsthjt4b5y4wdpaxw;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3/zlib-1.3.1-slqujeue3l44x3pgqbu7e2pw3lh2mj5i;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3/metis-5.1.0-puzeddu6ufhz5vpxnw7i3i2i6slsvuuj;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-3gtldngru7bva2reuel5iabyytw5fmdf;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3/fmt-11.0.2-lpnox72rqcneew5hucwzq4nmms4at525;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/doxygen-1.15.0;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm;/opt/rocm-6.4.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/opt/rocm-6.4.3" CACHE STRING "") + +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") + +set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3/axom-develop-cdngjuz7ffr3goroyietece35jivxnkv/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3/axom-develop-cdngjuz7ffr3goroyietece35jivxnkv/lib64;;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") + +set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3/axom-develop-cdngjuz7ffr3goroyietece35jivxnkv/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3/axom-develop-cdngjuz7ffr3goroyietece35jivxnkv/lib64;;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") + +set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") + +#------------------------------------------------------------------------------ +# Compilers +#------------------------------------------------------------------------------ +# Compiler Spec: llvm-amdgpu@6.4.3/u67i6xutdthzl3yti7tv3klyhyzddbkv +#------------------------------------------------------------------------------ +if(DEFINED ENV{SPACK_CC}) + + set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd/libexec/spack/rocmcc/amdclang" CACHE PATH "") + + set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd/libexec/spack/rocmcc/amdclang++" CACHE PATH "") + + set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd/libexec/spack/rocmcc/amdflang" CACHE PATH "") + +else() + + set(CMAKE_C_COMPILER "/opt/rocm-6.4.3/llvm/bin/amdclang" CACHE PATH "") + + set(CMAKE_CXX_COMPILER "/opt/rocm-6.4.3/llvm/bin/amdclang++" CACHE PATH "") + + set(CMAKE_Fortran_COMPILER "/opt/rocm-6.4.3/llvm/bin/amdflang" CACHE PATH "") + +endif() + +set(CMAKE_Fortran_FLAGS "-Mfreeform" CACHE STRING "") + +set(ENABLE_FORTRAN ON CACHE BOOL "") + +#------------------------------------------------------------------------------ +# MPI +#------------------------------------------------------------------------------ + +set(MPI_C_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.3/bin/mpicc" CACHE PATH "") + +set(MPI_CXX_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.3/bin/mpicxx" CACHE PATH "") + +set(MPI_Fortran_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.3/bin/mpif90" CACHE PATH "") + +set(MPIEXEC_EXECUTABLE "/usr/global/tools/flux_wrappers/bin/srun" CACHE PATH "") + +set(MPIEXEC_NUMPROC_FLAG "-n" CACHE STRING "") + +set(ENABLE_MPI ON CACHE BOOL "") + +#------------------------------------------------------------------------------ +# Hardware +#------------------------------------------------------------------------------ + +#------------------------------------------------ +# ROCm +#------------------------------------------------ + +set(ROCM_PATH "/opt/rocm-6.4.3" CACHE PATH "") + +set(CMAKE_HIP_ARCHITECTURES "gfx90a;gfx942" CACHE STRING "") + +set(CMAKE_HIP_COMPILER "/opt/rocm-6.4.3/bin/amdclang++" CACHE FILEPATH "") + +#------------------------------------------------------------------------------ + +# Axom ROCm specifics + +#------------------------------------------------------------------------------ + + +set(ENABLE_HIP ON CACHE BOOL "") + +set(ROCM_ROOT_DIR "/opt/rocm-6.4.3" CACHE PATH "") + +set(CMAKE_EXE_LINKER_FLAGS "-lxpmem -L/opt/cray/pe/mpich/8.1.29/gtl/lib -Wl,-rpath,/opt/cray/pe/mpich/8.1.29/gtl/lib -lmpi_gtl_hsa -L/opt/rocm-6.4.3/lib/llvm/lib -Wl,-rpath,/opt/rocm-6.4.3/lib/llvm/lib -L/opt/rocm-6.4.3/lib -Wl,-rpath,/opt/rocm-6.4.3/lib -lpgmath -lompstub -Wl,--disable-new-dtags -lflang -lflangrti -lamdhip64 -lhsakmt -lhsa-runtime64 -lamd_comgr " CACHE STRING "") + +#------------------------------------------------ +# Hardware Specifics +#------------------------------------------------ + +set(ENABLE_OPENMP OFF CACHE BOOL "") + +set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") + +#------------------------------------------------------------------------------ +# TPLs +#------------------------------------------------------------------------------ + +set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/llvm-amdgpu-6.4.3" CACHE PATH "") + +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-zqywrasos2vbears5hvdwxhulm3xox6q" CACHE PATH "") + +set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-h5kio7nseyazg4pzgvj4kxanb3plhbxm" CACHE PATH "") + +set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-g6vxdlgc7spurcdacgc6e5245iu2hyiw" CACHE PATH "") + +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-mgic2kxojd5zeivhaz473zzmzrg3gdqe" CACHE PATH "") + +set(LUA_DIR "${TPL_ROOT}/lua-5.4.8-gp4kdewsy4uiy6flsx342lgogcm7fym2" CACHE PATH "") + +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-wavyomm5hzyjf3xuyr33txmnspvxveei" CACHE PATH "") + +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-4oytcvf556ksil4hsthjt4b5y4wdpaxw" CACHE PATH "") + +# OPENCASCADE not built + +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-cropyu42jr4q6k3zar6mkma6gc2vp6tk" CACHE PATH "") + +set(CALIPER_DIR "${TPL_ROOT}/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-rmlwpdacdtpzf4u72ctyroj72soqzf3f" CACHE PATH "") + +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-3gtldngru7bva2reuel5iabyytw5fmdf" CACHE PATH "") + +# scr not built + +#------------------------------------------------------------------------------ +# Devtools & Python +#------------------------------------------------------------------------------ + +set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25" CACHE PATH "") + +set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm/bin/clang-format" CACHE PATH "") + +set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/python3" CACHE PATH "") + +set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/jsonschema" CACHE PATH "") + +set(ENABLE_DOCS ON CACHE BOOL "") + +set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/sphinx-build" CACHE PATH "") + +set(YAPF_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/yapf" CACHE PATH "") + +set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0/bin/shroud" CACHE PATH "") + +set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27/bin/cppcheck" CACHE PATH "") + +set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/doxygen-1.15.0/bin/doxygen" CACHE PATH "") + +set(PY_NANOBIND_DIR "${TPL_ROOT}/py-nanobind-2.7.0-2kp35jcpb73xuujvcz6kmg4q2npek4gg/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PYTEST_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/py-pytest-9.0.0-jfdwo62b3p36blpm54gvocrcj6afccv5/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_NUMPY_DIR "${TPL_ROOT}/py-numpy-2.4.2-a3mo27shjtpliwewbm5cci2kf37crrab/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PLUGGY_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/py-pluggy-1.6.0-n4ojmtqyawxz6gipk64pup3ahwz3xqpu/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_INICONFIG_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_37/none-none/py-iniconfig-2.1.0-lf3yvch65se22jr7b5unfoxtse4ugkrk/lib/python3.13/site-packages" CACHE PATH "") + + diff --git a/host-configs/rzvector-toss_4_x86_64_ib-gcc@13.3.1_cuda.cmake b/host-configs/rzvector-toss_4_x86_64_ib-gcc@13.3.1_cuda.cmake index 487ca22b27..c7c5bc2f42 100644 --- a/host-configs/rzvector-toss_4_x86_64_ib-gcc@13.3.1_cuda.cmake +++ b/host-configs/rzvector-toss_4_x86_64_ib-gcc@13.3.1_cuda.cmake @@ -4,28 +4,28 @@ # CMake executable path: /usr/tce/packages/cmake/cmake-3.26.3/bin/cmake #------------------------------------------------------------------------------ -set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/gcc-13.3.1/blt-develop-vkyjvzyg7n4ig7x4llo53lndvnwsrbjq;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/gcc-13.3.1/c2c-1.8.0-3bch3wbxcl3eji2wsbbbzmagowxe4lpc;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/gcc-13.3.1/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-ss6he6vnxctdifczfduoqdpfyjltt2r3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/gcc-13.3.1/conduit-0.9.5-icskqkcmikkfw2itxiq6xdt6nilzlsvr;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/gcc-13.3.1/mfem-4.9.0-lkbiphsoccgpbaqo2cujuxcf3dqb4gga;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/gcc-13.3.1/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-2u2olu3wtrgskohwge6z2r5p4pbn24xi;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/gcc-13.3.1/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-qqnegxhkanugllghjqvoqjilj2h4ouuf;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/gcc-13.3.1/adiak-0.4.0-45h4d32dvvatilujstudj3ucvmdeyi6a;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/gcc-13.3.1/libunwind-1.8.3-74hjhhtejjsdgxjpp262xlm5ow6psq4r;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/gcc-13.3.1/hdf5-1.8.23-gokrordtweyfprtzgrzsycyilhy32uc7;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/gcc-13.3.1/parmetis-4.0.3-euggsyckxbtpzv6kzq74k3ndngpw2yqh;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/gcc-13.3.1/hypre-2.27.0-ceinfx2z45d7ap3i2lif6j2qw6jw7vhf;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/gcc-13.3.1/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-idk67733aarmoow76xcm5idyfijqjntn;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/gcc-13.3.1/fmt-11.0.2-faqgdwrlrl4nwv35msienhldhqrq2vce;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/gcc-13.3.1/metis-5.1.0-ovo3o7do7zr5fxw6mi2flzy6ftfsavk2;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/none-none/gcc-runtime-13.3.1-k43mnfzd4ehqvovn4d5qq7b5f6sfetsx;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/usr/tce/packages/cmake/cmake-3.26.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/gcc-13.3.1/cppcheck-2.18.0-d2tmb7ls2d5vgh6vhcyohecwcu6msopb;/usr/tce/packages/cuda/cuda-12.9.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/doxygen-1.13.2;/usr/tce/packages/gcc/gcc-13.3.1;/usr/tce/packages/clang/clang-19.1.3;/usr/tce/packages/mvapich2/mvapich2-2.3.7-gcc-13.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5" CACHE STRING "") +set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/gcc-13.3.1/blt-0.7.1-yiu2olkumeazbrto7x4v2dv6qbefhf5a;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/gcc-13.3.1/c2c-1.8.0-jkclfdpl7igj3ur3ufnpt6dupjfvotpc;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/gcc-13.3.1/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-qekykotizhycp2p4deoltaa227sajuvj;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/gcc-13.3.1/conduit-0.9.5-xyt2d2ot4eozuhrjv7mccoe7tw6ef7ui;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/gcc-13.3.1/mfem-4.9.0-kjei2ccah6sei4jplqabrucxltyq4zfb;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/gcc-13.3.1/py-nanobind-2.7.0-szozdpwzge7ah4bsilit6fijezxqbfop;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/none-none/py-pytest-9.0.0-vozuj6nkk42nhxeo5mawnux3w7bj3awe;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/gcc-13.3.1/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-vmsmvq25y56dkomrba3g63ls5nuga6xm;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/gcc-13.3.1/umpire-2025.12.0-kjyb6uox2o7qtfna22uqzxrqck7lukbt;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/gcc-13.3.1/adiak-0.4.0-i5bahteezqmswdv2ulpfvfogmuue463q;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/gcc-13.3.1/libunwind-1.8.3-pwdmczcnf7vugfly5zk7eztefnn7kv75;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/gcc-13.3.1/hdf5-1.8.23-2pnsuxpt6r2wmdc6sqyku6ki6na4gcfl;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/gcc-13.3.1/parmetis-4.0.3-tt2yxrbsrccyglhjqcs2y2nspmt4qoqx;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/gcc-13.3.1/py-numpy-2.4.2-z4yapdkn22w6adfrl7ibucqiokgrwb7f;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/gcc-13.3.1/hypre-2.27.0-bs56wsg2yagtwcz5q5a67ov4tln54p5i;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/gcc-13.3.1/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-fm7mimsvemux42yrsmsvqw6tl4kugyzy;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/gcc-13.3.1/fmt-11.0.2-ggfpxocredbjrldu7ar33cjedhmkm3da;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/gcc-13.3.1/metis-5.1.0-3jtvhjwnhqqaf5v2na7f675qgvlusyx3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/none-none/gcc-runtime-13.3.1-zsobnkwck2glzcbukupgvgbiwwhdonys;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/usr/tce/packages/cmake/cmake-3.26.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/gcc-13.3.1/cppcheck-2.18.0-i3p56kpf66xzj4wm5kfqxyc4vgox7gb3;/usr/tce/packages/cuda/cuda-12.9.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/doxygen-1.15.0;/usr/tce/packages/gcc/gcc-13.3.1;/usr/tce/packages/clang/clang-19.1.3;/usr/tce/packages/mvapich2/mvapich2-2.3.7-gcc-13.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11" CACHE STRING "") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") -set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/gcc-13.3.1/axom-develop-qjtnt6mppu7nil7s4d6psfaja7vf3daq/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/gcc-13.3.1/axom-develop-qjtnt6mppu7nil7s4d6psfaja7vf3daq/lib64;;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/gcc-13.3.1/axom-develop-imlx7oqvp6ch6htnn3syya75lumfcxjo/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/gcc-13.3.1/axom-develop-imlx7oqvp6ch6htnn3syya75lumfcxjo/lib64;;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") -set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/gcc-13.3.1/axom-develop-qjtnt6mppu7nil7s4d6psfaja7vf3daq/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/gcc-13.3.1/axom-develop-qjtnt6mppu7nil7s4d6psfaja7vf3daq/lib64;;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/gcc-13.3.1/axom-develop-imlx7oqvp6ch6htnn3syya75lumfcxjo/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/gcc-13.3.1/axom-develop-imlx7oqvp6ch6htnn3syya75lumfcxjo/lib64;;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") #------------------------------------------------------------------------------ # Compilers #------------------------------------------------------------------------------ -# Compiler Spec: gcc@13.3.1/75lfrhqb3monlgkmkokrboaqienagc6u +# Compiler Spec: gcc@13.3.1/xrm3n2pex2en2wvm6p4ap62nieoz7kne #------------------------------------------------------------------------------ if(DEFINED ENV{SPACK_CC}) - set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/gcc/gcc" CACHE PATH "") + set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/gcc/gcc" CACHE PATH "") - set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/gcc/g++" CACHE PATH "") + set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/gcc/g++" CACHE PATH "") - set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/gcc/gfortran" CACHE PATH "") + set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/gcc/gfortran" CACHE PATH "") else() @@ -99,52 +99,64 @@ set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") # TPLs #------------------------------------------------------------------------------ -set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/gcc-13.3.1" CACHE PATH "") +set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/gcc-13.3.1" CACHE PATH "") -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-icskqkcmikkfw2itxiq6xdt6nilzlsvr" CACHE PATH "") +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-xyt2d2ot4eozuhrjv7mccoe7tw6ef7ui" CACHE PATH "") -set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-3bch3wbxcl3eji2wsbbbzmagowxe4lpc" CACHE PATH "") +set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-jkclfdpl7igj3ur3ufnpt6dupjfvotpc" CACHE PATH "") -set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-lkbiphsoccgpbaqo2cujuxcf3dqb4gga" CACHE PATH "") +set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-kjei2ccah6sei4jplqabrucxltyq4zfb" CACHE PATH "") -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-gokrordtweyfprtzgrzsycyilhy32uc7" CACHE PATH "") +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-2pnsuxpt6r2wmdc6sqyku6ki6na4gcfl" CACHE PATH "") set(LUA_DIR "/usr" CACHE PATH "") -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-2u2olu3wtrgskohwge6z2r5p4pbn24xi" CACHE PATH "") +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-vmsmvq25y56dkomrba3g63ls5nuga6xm" CACHE PATH "") -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-qqnegxhkanugllghjqvoqjilj2h4ouuf" CACHE PATH "") +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-kjyb6uox2o7qtfna22uqzxrqck7lukbt" CACHE PATH "") # OPENCASCADE not built -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-45h4d32dvvatilujstudj3ucvmdeyi6a" CACHE PATH "") +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-i5bahteezqmswdv2ulpfvfogmuue463q" CACHE PATH "") -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-ss6he6vnxctdifczfduoqdpfyjltt2r3" CACHE PATH "") +set(CALIPER_DIR "${TPL_ROOT}/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-qekykotizhycp2p4deoltaa227sajuvj" CACHE PATH "") -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-idk67733aarmoow76xcm5idyfijqjntn" CACHE PATH "") +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-fm7mimsvemux42yrsmsvqw6tl4kugyzy" CACHE PATH "") # scr not built #------------------------------------------------------------------------------ -# Devtools +# Devtools & Python #------------------------------------------------------------------------------ -set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37" CACHE PATH "") +set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14" CACHE PATH "") set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/clang/clang-19.1.3/bin/clang-format" CACHE PATH "") -set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/python3" CACHE PATH "") +set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/python3" CACHE PATH "") -set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/jsonschema" CACHE PATH "") +set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/jsonschema" CACHE PATH "") set(ENABLE_DOCS ON CACHE BOOL "") -set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/sphinx-build" CACHE PATH "") +set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/sphinx-build" CACHE PATH "") + +set(YAPF_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/yapf" CACHE PATH "") set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0/bin/shroud" CACHE PATH "") -set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-d2tmb7ls2d5vgh6vhcyohecwcu6msopb/bin/cppcheck" CACHE PATH "") +set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-i3p56kpf66xzj4wm5kfqxyc4vgox7gb3/bin/cppcheck" CACHE PATH "") + +set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/doxygen-1.15.0/bin/doxygen" CACHE PATH "") + +set(PY_NANOBIND_DIR "${TPL_ROOT}/py-nanobind-2.7.0-szozdpwzge7ah4bsilit6fijezxqbfop/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PYTEST_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/none-none/py-pytest-9.0.0-vozuj6nkk42nhxeo5mawnux3w7bj3awe/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_NUMPY_DIR "${TPL_ROOT}/py-numpy-2.4.2-z4yapdkn22w6adfrl7ibucqiokgrwb7f/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PLUGGY_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/none-none/py-pluggy-1.6.0-6zab4pck6v7johubbhalr2waowbwpjei/lib/python3.13/site-packages" CACHE PATH "") -set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/doxygen-1.13.2/bin/doxygen" CACHE PATH "") +set(PY_INICONFIG_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/none-none/py-iniconfig-2.1.0-xwmbxuhk2oo3dcuizdp3z4hqbpqykkom/lib/python3.13/site-packages" CACHE PATH "") diff --git a/host-configs/rzvector-toss_4_x86_64_ib-llvm@19.1.3_cuda.cmake b/host-configs/rzvector-toss_4_x86_64_ib-llvm@19.1.3_cuda.cmake index 4ffe1d8e27..c4d502e09a 100644 --- a/host-configs/rzvector-toss_4_x86_64_ib-llvm@19.1.3_cuda.cmake +++ b/host-configs/rzvector-toss_4_x86_64_ib-llvm@19.1.3_cuda.cmake @@ -4,28 +4,28 @@ # CMake executable path: /usr/tce/packages/cmake/cmake-3.26.3/bin/cmake #------------------------------------------------------------------------------ -set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/llvm-19.1.3/blt-develop-lv6kxkbht6tnhkesyvxpn4co7wh7yqkx;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/llvm-19.1.3/c2c-1.8.0-jcvyunoextaorp7eqlrec6s53cnlm7cn;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/llvm-19.1.3/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-ez6ccmzayktinrdnyfioiu2pagdgmrjl;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/llvm-19.1.3/conduit-0.9.5-dmle6tliomp27z2usvm22ukviomsvezy;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/llvm-19.1.3/mfem-4.9.0-46z5loc32omdkn3y3dowlufhkcdio3mb;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/llvm-19.1.3/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-ictxt2yfuoeavhslmvmtf6btksajzeue;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/llvm-19.1.3/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-3qtvx6gvfa3ftroiuctzksweq2i7vgav;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/llvm-19.1.3/adiak-0.4.0-t7ws2osd4v4fd3bffvzozbcq6gqdlf2i;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/llvm-19.1.3/libunwind-1.8.3-222s6ifq5wyaudy7h43urrshydfjig3q;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/llvm-19.1.3/hdf5-1.8.23-lw4obzkj7og4qegzmwizuxvotpz4lkot;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/llvm-19.1.3/parmetis-4.0.3-muygwq5u7gusmbn24red6rvpwbxck6l5;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/llvm-19.1.3/hypre-2.27.0-czx6rwihdfohxp4p4ssn24ykk2mpin2e;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/llvm-19.1.3/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-oqj2he2t5izbaognxgx4m5wdoenx3rqu;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/llvm-19.1.3/fmt-11.0.2-g4qwjp4qo7vxtvq3zijosapcbpnf6zja;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/none-none/gcc-runtime-13.3.1-k43mnfzd4ehqvovn4d5qq7b5f6sfetsx;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/llvm-19.1.3/metis-5.1.0-xzd22iguknjmsctpcvgd5blzwx6aq6wd;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/usr/tce/packages/cmake/cmake-3.26.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/gcc-13.3.1/cppcheck-2.18.0-d2tmb7ls2d5vgh6vhcyohecwcu6msopb;/usr/tce/packages/cuda/cuda-12.9.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/doxygen-1.13.2;/usr/tce/packages/gcc/gcc-13.3.1;/usr/tce/packages/clang/clang-19.1.3;/usr/tce/packages/mvapich2/mvapich2-2.3.7-clang-19.1.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5" CACHE STRING "") +set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/llvm-19.1.3/blt-0.7.1-577uis2w7b3ipf4v4v6y6vogmy52d6ay;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/llvm-19.1.3/c2c-1.8.0-pk3z5zabg2gtkur2c4mqzc5zz7z5f2tv;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/llvm-19.1.3/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-ftzyobuu2a4siddiotqw4652bctzj3ke;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/llvm-19.1.3/conduit-0.9.5-gracxngtjim7b6zjsb5z4kf7qk347eo2;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/llvm-19.1.3/mfem-4.9.0-vvfbyadobvw4sxcdwuulbfs2lneeczet;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/llvm-19.1.3/py-nanobind-2.7.0-6akjhhlga6h3jx75swovfvo76k6rw6fp;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/none-none/py-pytest-9.0.0-vozuj6nkk42nhxeo5mawnux3w7bj3awe;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/llvm-19.1.3/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-aibnhmtfonzvsz7owanyr6m3eelmwfvj;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/llvm-19.1.3/umpire-2025.12.0-3xllaqzq537svpt3ie6jhzoaxciuut2i;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/llvm-19.1.3/adiak-0.4.0-27bezbcpd5jxnvs65h3m6u2aheplxbmv;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/llvm-19.1.3/libunwind-1.8.3-ddv7ypujzw2wvlzabw3d42qygcbtofuq;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/llvm-19.1.3/hdf5-1.8.23-b37o2ze3w5sozwz6jmalg4pgg66jcogm;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/llvm-19.1.3/parmetis-4.0.3-slhcesf5fhsucwxtlxxana67jcrligfy;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/llvm-19.1.3/py-numpy-2.4.2-7qsjxyuuh7rh5hccdziewhwqymkmepb3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/llvm-19.1.3/hypre-2.27.0-l2mxwhcndyhn4pkbe4rthke2rlkmgdbd;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/llvm-19.1.3/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-crik3a76mg7gqb6xsqkijjk3qzlw4mcl;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/llvm-19.1.3/fmt-11.0.2-uougkyc3rcyd7punvwjtcme2zlhehpgz;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/none-none/gcc-runtime-13.3.1-zsobnkwck2glzcbukupgvgbiwwhdonys;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/llvm-19.1.3/metis-5.1.0-3jeshrn7tydsgn5zdkf3iirdhw3u3oeq;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/usr/tce/packages/cmake/cmake-3.26.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/gcc-13.3.1/cppcheck-2.18.0-i3p56kpf66xzj4wm5kfqxyc4vgox7gb3;/usr/tce/packages/cuda/cuda-12.9.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/doxygen-1.15.0;/usr/tce/packages/gcc/gcc-13.3.1;/usr/tce/packages/clang/clang-19.1.3;/usr/tce/packages/mvapich2/mvapich2-2.3.7-clang-19.1.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11" CACHE STRING "") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") -set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/llvm-19.1.3/axom-develop-l6gwyjq43s6aq6smvxp2rlmbqnr3f6n7/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/llvm-19.1.3/axom-develop-l6gwyjq43s6aq6smvxp2rlmbqnr3f6n7/lib64;;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/llvm-19.1.3-gy2lu5xbi4csr2k47emlajzfs5mlsd4g/lib/x86_64-unknown-linux-gnu;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13;/usr/tce/packages/clang/clang-19.1.3/lib;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/llvm-19.1.3/axom-develop-476ivmlyn3vhgofetdkr5fnl2sl627df/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/llvm-19.1.3/axom-develop-476ivmlyn3vhgofetdkr5fnl2sl627df/lib64;;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/llvm-19.1.3-gy2lu5xbi4csr2k47emlajzfs5mlsd4g/lib/x86_64-unknown-linux-gnu;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13;/usr/tce/packages/clang/clang-19.1.3/lib;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") -set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/llvm-19.1.3/axom-develop-l6gwyjq43s6aq6smvxp2rlmbqnr3f6n7/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/llvm-19.1.3/axom-develop-l6gwyjq43s6aq6smvxp2rlmbqnr3f6n7/lib64;;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/llvm-19.1.3-gy2lu5xbi4csr2k47emlajzfs5mlsd4g/lib/x86_64-unknown-linux-gnu;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13;/usr/tce/packages/clang/clang-19.1.3/lib;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/llvm-19.1.3/axom-develop-476ivmlyn3vhgofetdkr5fnl2sl627df/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/llvm-19.1.3/axom-develop-476ivmlyn3vhgofetdkr5fnl2sl627df/lib64;;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/llvm-19.1.3-gy2lu5xbi4csr2k47emlajzfs5mlsd4g/lib/x86_64-unknown-linux-gnu;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13;/usr/tce/packages/clang/clang-19.1.3/lib;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") #------------------------------------------------------------------------------ # Compilers #------------------------------------------------------------------------------ -# Compiler Spec: llvm@19.1.3/dks2hxs7zxd55vu4lwnrychk52n73agw +# Compiler Spec: llvm@19.1.3/4rf6d7atkulu6wz7bucycjwtiuwqfy24 #------------------------------------------------------------------------------ if(DEFINED ENV{SPACK_CC}) - set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/clang/clang" CACHE PATH "") + set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/clang/clang" CACHE PATH "") - set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/clang/clang++" CACHE PATH "") + set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/clang/clang++" CACHE PATH "") - set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/gcc/gfortran" CACHE PATH "") + set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/gcc/gfortran" CACHE PATH "") else() @@ -101,52 +101,64 @@ set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") # TPLs #------------------------------------------------------------------------------ -set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_40_52/llvm-19.1.3" CACHE PATH "") +set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/llvm-19.1.3" CACHE PATH "") -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-dmle6tliomp27z2usvm22ukviomsvezy" CACHE PATH "") +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-gracxngtjim7b6zjsb5z4kf7qk347eo2" CACHE PATH "") -set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-jcvyunoextaorp7eqlrec6s53cnlm7cn" CACHE PATH "") +set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-pk3z5zabg2gtkur2c4mqzc5zz7z5f2tv" CACHE PATH "") -set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-46z5loc32omdkn3y3dowlufhkcdio3mb" CACHE PATH "") +set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-vvfbyadobvw4sxcdwuulbfs2lneeczet" CACHE PATH "") -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-lw4obzkj7og4qegzmwizuxvotpz4lkot" CACHE PATH "") +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-b37o2ze3w5sozwz6jmalg4pgg66jcogm" CACHE PATH "") set(LUA_DIR "/usr" CACHE PATH "") -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-ictxt2yfuoeavhslmvmtf6btksajzeue" CACHE PATH "") +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-aibnhmtfonzvsz7owanyr6m3eelmwfvj" CACHE PATH "") -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-3qtvx6gvfa3ftroiuctzksweq2i7vgav" CACHE PATH "") +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-3xllaqzq537svpt3ie6jhzoaxciuut2i" CACHE PATH "") # OPENCASCADE not built -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-t7ws2osd4v4fd3bffvzozbcq6gqdlf2i" CACHE PATH "") +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-27bezbcpd5jxnvs65h3m6u2aheplxbmv" CACHE PATH "") -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-ez6ccmzayktinrdnyfioiu2pagdgmrjl" CACHE PATH "") +set(CALIPER_DIR "${TPL_ROOT}/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-ftzyobuu2a4siddiotqw4652bctzj3ke" CACHE PATH "") -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-oqj2he2t5izbaognxgx4m5wdoenx3rqu" CACHE PATH "") +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-crik3a76mg7gqb6xsqkijjk3qzlw4mcl" CACHE PATH "") # scr not built #------------------------------------------------------------------------------ -# Devtools +# Devtools & Python #------------------------------------------------------------------------------ -set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37" CACHE PATH "") +set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14" CACHE PATH "") set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/clang/clang-19.1.3/bin/clang-format" CACHE PATH "") -set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/python3" CACHE PATH "") +set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/python3" CACHE PATH "") -set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/jsonschema" CACHE PATH "") +set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/jsonschema" CACHE PATH "") set(ENABLE_DOCS ON CACHE BOOL "") -set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/sphinx-build" CACHE PATH "") +set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/sphinx-build" CACHE PATH "") + +set(YAPF_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/yapf" CACHE PATH "") set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0/bin/shroud" CACHE PATH "") -set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-d2tmb7ls2d5vgh6vhcyohecwcu6msopb/bin/cppcheck" CACHE PATH "") +set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-i3p56kpf66xzj4wm5kfqxyc4vgox7gb3/bin/cppcheck" CACHE PATH "") + +set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/doxygen-1.15.0/bin/doxygen" CACHE PATH "") + +set(PY_NANOBIND_DIR "${TPL_ROOT}/py-nanobind-2.7.0-6akjhhlga6h3jx75swovfvo76k6rw6fp/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PYTEST_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/none-none/py-pytest-9.0.0-vozuj6nkk42nhxeo5mawnux3w7bj3awe/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_NUMPY_DIR "${TPL_ROOT}/py-numpy-2.4.2-7qsjxyuuh7rh5hccdziewhwqymkmepb3/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PLUGGY_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/none-none/py-pluggy-1.6.0-6zab4pck6v7johubbhalr2waowbwpjei/lib/python3.13/site-packages" CACHE PATH "") -set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/doxygen-1.13.2/bin/doxygen" CACHE PATH "") +set(PY_INICONFIG_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_13_24_53/none-none/py-iniconfig-2.1.0-xwmbxuhk2oo3dcuizdp3z4hqbpqykkom/lib/python3.13/site-packages" CACHE PATH "") diff --git a/host-configs/rzvernal-toss_4_x86_64_ib_cray-cce@20.0.0_hip.cmake b/host-configs/rzvernal-toss_4_x86_64_ib_cray-cce@20.0.0_hip.cmake index f6ed68979b..0c4c3ff7a9 100644 --- a/host-configs/rzvernal-toss_4_x86_64_ib_cray-cce@20.0.0_hip.cmake +++ b/host-configs/rzvernal-toss_4_x86_64_ib_cray-cce@20.0.0_hip.cmake @@ -4,28 +4,28 @@ # CMake executable path: /usr/tce/packages/cmake/cmake-3.29.2/bin/cmake #------------------------------------------------------------------------------ -set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/cce-20.0.0/blt-develop-wnndhcj7j3uzrcmwcxxx7we6ao67ufx6;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/cce-20.0.0/c2c-1.8.0-uoyu6oaj5hm3akm7uyeaxpbhmshokbev;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/cce-20.0.0/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-5yccw5nektleedjvs5wectfxu7nj6fjd;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/cce-20.0.0/conduit-0.9.5-2dh3uvquzycowlp4ffz4aazgwkbizs7y;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/cce-20.0.0/lua-5.4.6-3vgz4w7orr6iwf4sqasvbuagpxwz6jbt;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/cce-20.0.0/mfem-4.9.0-73j7czkpuzzntx5ol3kz6yvhnixn63hz;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/cce-20.0.0/adiak-0.4.0-vl5b2qb7dwqt7hcmxqwnerfdsv6ezg2h;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/cce-20.0.0/libunwind-1.8.3-oaadmxe4ydkatoq56yo2fsmd3ijyttku;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/cce-20.0.0/hdf5-1.8.23-v3nnkt4hslj6z2h5d2va4nvmvaycwmuq;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/cce-20.0.0/parmetis-4.0.3-5jtv4smgso6jym3j55xgzzrhnh3vq2y5;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/cce-20.0.0/hypre-2.27.0-nlgayafg7nyxle3wg42oi5x6a7asif55;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/cce-20.0.0/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-7wckscp7eaotkpptzlsjvtqztu6piavq;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/cce-20.0.0/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-lpwqfmyudwe4hgcg2fngwu5c7oqh2257;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/cce-20.0.0/zlib-1.3.1-diuhkgywdfo2546izxh4uu3g7salnkr6;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/cce-20.0.0/metis-5.1.0-7mfvit6c5hknzy6jz6uqpthklg5h3ec7;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/cce-20.0.0/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-z6tknzstevaqveilm3uslpw7a7k7nuf7;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/cce-20.0.0/fmt-11.0.2-pzwzhrpfhytmmcetg6bogh3zdod2ss3j;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/usr/tce/packages/cce-tce/cce-20.0.0;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.2-cce-20.0.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/doxygen-1.13.2;/opt/rocm-6.4.2;/opt/rocm-6.4.2;/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm;/opt/rocm-6.4.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/opt/rocm-6.4.2;/opt/rocm-6.4.2;/opt/rocm-6.4.2" CACHE STRING "") +set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0/blt-0.7.1-tj6h3jr6fjdlxux2yd4wvdy7xwxxuh23;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0/c2c-1.8.0-xav3pjepsvpzrcqd5dcom4is4rioejzr;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-37ef6g3godgxug45i3u3x26awgovbhxa;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0/conduit-0.9.5-oyjekm66om6cx7yndhpv3yumtxgaaroi;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0/lua-5.4.8-ty6vxrgtb5lsthp7rrcy7vx3x4yknrms;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0/mfem-4.9.0-qb5a5xcb5sx6mjeqqsuhxifqeikegol3;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0/py-nanobind-2.7.0-h7v5ggotyqa5ul7kpyc2yfojjkah4ium;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/py-pytest-9.0.0-dn2hwdtaqec2dkxtx7bnvykyxacfdagj;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0/adiak-0.4.0-w7lj246x4whjefszgyhapkebe3cjd7bi;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0/libunwind-1.8.3-htd47rshpgaa6w73jemf7tycnnlkn5ws;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0/hdf5-1.8.23-vy4rnk6awhcfgte2wuwisgp3t3y4gzwy;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0/parmetis-4.0.3-jqlganykrtm62xb3ve2eetb3gltn5nki;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0/py-numpy-2.4.2-vdrslpslcsdjba3zyryp27z4tmpn3ayu;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0/hypre-2.27.0-gjrhbi2v66y2yfxgq7vegqpcawo2b35r;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-mraqiovyi37bfdy7d3cpssvqibljl3rs;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0/umpire-2025.12.0-wvhebyygqkj3vxwm6quu3rxnzjnvwjix;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0/zlib-1.3.1-6yddik2qxvkwtfcckdhbdgos7awok5za;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0/metis-5.1.0-bryzqxg7sgprevvt3ux5np2uxam4wbvp;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-s7ova7cnq6ibqaoxniya4loizwha2g3p;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0/fmt-11.0.2-vjndv6co4e6qonqazcmklw3pamvmos74;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/usr/tce/packages/cce-tce/cce-20.0.0;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/doxygen-1.15.0;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm;/opt/rocm-6.4.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/opt/rocm-6.4.3" CACHE STRING "") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") -set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/cce-20.0.0/axom-develop-pn7byon4z73u2dxiyqt5bhdft7fidrkk/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/cce-20.0.0/axom-develop-pn7byon4z73u2dxiyqt5bhdft7fidrkk/lib64;;/opt/cray/pe/cce/20.0.0/cce/x86_64/lib;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0/axom-develop-qs7aomrdxkidtsbjs23bs7ou7kg37qya/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0/axom-develop-qs7aomrdxkidtsbjs23bs7ou7kg37qya/lib64;;/opt/cray/pe/cce/20.0.0/cce/x86_64/lib;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") -set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/cce-20.0.0/axom-develop-pn7byon4z73u2dxiyqt5bhdft7fidrkk/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/cce-20.0.0/axom-develop-pn7byon4z73u2dxiyqt5bhdft7fidrkk/lib64;;/opt/cray/pe/cce/20.0.0/cce/x86_64/lib;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0/axom-develop-qs7aomrdxkidtsbjs23bs7ou7kg37qya/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0/axom-develop-qs7aomrdxkidtsbjs23bs7ou7kg37qya/lib64;;/opt/cray/pe/cce/20.0.0/cce/x86_64/lib;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") #------------------------------------------------------------------------------ # Compilers #------------------------------------------------------------------------------ -# Compiler Spec: cce@20.0.0/qaj3yb2lw3bg5iz34y3j54ip4ngiyxf5 +# Compiler Spec: cce@20.0.0/v7nrkimihxta4odatu45wrllosgeklrd #------------------------------------------------------------------------------ if(DEFINED ENV{SPACK_CC}) - set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6/libexec/spack/cce/craycc" CACHE PATH "") + set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf/libexec/spack/cce/craycc" CACHE PATH "") - set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6/libexec/spack/cce/case-insensitive/crayCC" CACHE PATH "") + set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf/libexec/spack/cce/case-insensitive/crayCC" CACHE PATH "") - set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6/libexec/spack/cce/crayftn" CACHE PATH "") + set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf/libexec/spack/cce/crayftn" CACHE PATH "") else() @@ -47,11 +47,11 @@ set(CMAKE_CXX_FLAGS_DEBUG "-O1 -g" CACHE STRING "") # MPI #------------------------------------------------------------------------------ -set(MPI_C_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.2-cce-20.0.0/bin/mpicc" CACHE PATH "") +set(MPI_C_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.3/bin/mpicc" CACHE PATH "") -set(MPI_CXX_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.2-cce-20.0.0/bin/mpicxx" CACHE PATH "") +set(MPI_CXX_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.3/bin/mpicxx" CACHE PATH "") -set(MPI_Fortran_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.2-cce-20.0.0/bin/mpif90" CACHE PATH "") +set(MPI_Fortran_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.3/bin/mpif90" CACHE PATH "") set(MPIEXEC_EXECUTABLE "/usr/global/tools/flux_wrappers/bin/srun" CACHE PATH "") @@ -67,11 +67,11 @@ set(ENABLE_MPI ON CACHE BOOL "") # ROCm #------------------------------------------------ -set(ROCM_PATH "/opt/rocm-6.4.2" CACHE PATH "") +set(ROCM_PATH "/opt/rocm-6.4.3" CACHE PATH "") set(CMAKE_HIP_ARCHITECTURES "gfx90a;gfx942" CACHE STRING "") -set(CMAKE_HIP_COMPILER "/opt/rocm-6.4.2/bin/amdclang++" CACHE FILEPATH "") +set(CMAKE_HIP_COMPILER "/opt/rocm-6.4.3/bin/amdclang++" CACHE FILEPATH "") #------------------------------------------------------------------------------ @@ -82,11 +82,11 @@ set(CMAKE_HIP_COMPILER "/opt/rocm-6.4.2/bin/amdclang++" CACHE FILEPATH "") set(ENABLE_HIP ON CACHE BOOL "") -set(ROCM_ROOT_DIR "/opt/rocm-6.4.2" CACHE PATH "") +set(ROCM_ROOT_DIR "/opt/rocm-6.4.3" CACHE PATH "") set(BLT_CMAKE_IMPLICIT_LINK_LIBRARIES_EXCLUDE "unwind" CACHE STRING "") -set(CMAKE_EXE_LINKER_FLAGS "-lxpmem -L/opt/cray/pe/mpich/8.1.32/gtl/lib -Wl,-rpath,/opt/cray/pe/mpich/8.1.32/gtl/lib -lmpi_gtl_hsa -L/opt/rocm-6.4.2/lib/llvm/lib -Wl,-rpath,/opt/rocm-6.4.2/lib/llvm/lib -L/opt/rocm-6.4.2/lib -Wl,-rpath,/opt/rocm-6.4.2/lib -lpgmath -lompstub -L/opt/cray/pe/cce/20.0.0/cce/x86_64/lib -Wl,-rpath,/opt/cray/pe/cce/20.0.0/cce/x86_64/lib -lamdhip64 -lhsakmt -lhsa-runtime64 -lamd_comgr " CACHE STRING "") +set(CMAKE_EXE_LINKER_FLAGS "-lxpmem -L/opt/cray/pe/mpich/8.1.32/gtl/lib -Wl,-rpath,/opt/cray/pe/mpich/8.1.32/gtl/lib -lmpi_gtl_hsa -L/opt/rocm-6.4.3/lib/llvm/lib -Wl,-rpath,/opt/rocm-6.4.3/lib/llvm/lib -L/opt/rocm-6.4.3/lib -Wl,-rpath,/opt/rocm-6.4.3/lib -lpgmath -lompstub -L/opt/cray/pe/cce/20.0.0/cce/x86_64/lib -Wl,-rpath,/opt/cray/pe/cce/20.0.0/cce/x86_64/lib -lamdhip64 -lhsakmt -lhsa-runtime64 -lamd_comgr " CACHE STRING "") #------------------------------------------------ # Hardware Specifics @@ -100,52 +100,64 @@ set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") # TPLs #------------------------------------------------------------------------------ -set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/cce-20.0.0" CACHE PATH "") +set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/cce-20.0.0" CACHE PATH "") -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-2dh3uvquzycowlp4ffz4aazgwkbizs7y" CACHE PATH "") +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-oyjekm66om6cx7yndhpv3yumtxgaaroi" CACHE PATH "") -set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-uoyu6oaj5hm3akm7uyeaxpbhmshokbev" CACHE PATH "") +set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-xav3pjepsvpzrcqd5dcom4is4rioejzr" CACHE PATH "") -set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-73j7czkpuzzntx5ol3kz6yvhnixn63hz" CACHE PATH "") +set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-qb5a5xcb5sx6mjeqqsuhxifqeikegol3" CACHE PATH "") -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-v3nnkt4hslj6z2h5d2va4nvmvaycwmuq" CACHE PATH "") +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-vy4rnk6awhcfgte2wuwisgp3t3y4gzwy" CACHE PATH "") -set(LUA_DIR "${TPL_ROOT}/lua-5.4.6-3vgz4w7orr6iwf4sqasvbuagpxwz6jbt" CACHE PATH "") +set(LUA_DIR "${TPL_ROOT}/lua-5.4.8-ty6vxrgtb5lsthp7rrcy7vx3x4yknrms" CACHE PATH "") -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-7wckscp7eaotkpptzlsjvtqztu6piavq" CACHE PATH "") +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-mraqiovyi37bfdy7d3cpssvqibljl3rs" CACHE PATH "") -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-lpwqfmyudwe4hgcg2fngwu5c7oqh2257" CACHE PATH "") +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-wvhebyygqkj3vxwm6quu3rxnzjnvwjix" CACHE PATH "") # OPENCASCADE not built -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-vl5b2qb7dwqt7hcmxqwnerfdsv6ezg2h" CACHE PATH "") +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-w7lj246x4whjefszgyhapkebe3cjd7bi" CACHE PATH "") -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-5yccw5nektleedjvs5wectfxu7nj6fjd" CACHE PATH "") +set(CALIPER_DIR "${TPL_ROOT}/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-37ef6g3godgxug45i3u3x26awgovbhxa" CACHE PATH "") -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-z6tknzstevaqveilm3uslpw7a7k7nuf7" CACHE PATH "") +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-s7ova7cnq6ibqaoxniya4loizwha2g3p" CACHE PATH "") # scr not built #------------------------------------------------------------------------------ -# Devtools +# Devtools & Python #------------------------------------------------------------------------------ -set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48" CACHE PATH "") +set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25" CACHE PATH "") -set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm/bin/clang-format" CACHE PATH "") +set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm/bin/clang-format" CACHE PATH "") -set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/python3" CACHE PATH "") +set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/python3" CACHE PATH "") -set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/jsonschema" CACHE PATH "") +set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/jsonschema" CACHE PATH "") set(ENABLE_DOCS ON CACHE BOOL "") -set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/sphinx-build" CACHE PATH "") +set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/sphinx-build" CACHE PATH "") + +set(YAPF_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/yapf" CACHE PATH "") set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0/bin/shroud" CACHE PATH "") -set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w/bin/cppcheck" CACHE PATH "") +set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27/bin/cppcheck" CACHE PATH "") + +set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/doxygen-1.15.0/bin/doxygen" CACHE PATH "") + +set(PY_NANOBIND_DIR "${TPL_ROOT}/py-nanobind-2.7.0-h7v5ggotyqa5ul7kpyc2yfojjkah4ium/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PYTEST_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/py-pytest-9.0.0-dn2hwdtaqec2dkxtx7bnvykyxacfdagj/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_NUMPY_DIR "${TPL_ROOT}/py-numpy-2.4.2-vdrslpslcsdjba3zyryp27z4tmpn3ayu/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PLUGGY_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/py-pluggy-1.6.0-27aoz44dedjxa6j6r6cavpqyqmpknidb/lib/python3.13/site-packages" CACHE PATH "") -set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/doxygen-1.13.2/bin/doxygen" CACHE PATH "") +set(PY_INICONFIG_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/py-iniconfig-2.1.0-7rty7n4wq6kxxrzflm7wbxqzhhc6ph7q/lib/python3.13/site-packages" CACHE PATH "") diff --git a/host-configs/rzvernal-toss_4_x86_64_ib_cray-llvm-amdgpu@6.3.1_hip.cmake b/host-configs/rzvernal-toss_4_x86_64_ib_cray-llvm-amdgpu@6.3.1_hip.cmake index 3d677fd203..46e596298d 100644 --- a/host-configs/rzvernal-toss_4_x86_64_ib_cray-llvm-amdgpu@6.3.1_hip.cmake +++ b/host-configs/rzvernal-toss_4_x86_64_ib_cray-llvm-amdgpu@6.3.1_hip.cmake @@ -4,28 +4,28 @@ # CMake executable path: /usr/tce/packages/cmake/cmake-3.29.2/bin/cmake #------------------------------------------------------------------------------ -set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.3.1/blt-develop-oxws57mp7nowwmot45kcl2njcmmyjcvt;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.3.1/c2c-1.8.0-ebatzl653bv653yovk7ea43xh5hpzyk5;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.3.1/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-477jqqgkb3xjq7zd6gtxz52y7yn4hhel;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.3.1/conduit-0.9.5-tzcfvtw7tkmkf2tav77vshtxusfx6xsp;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.3.1/lua-5.4.6-xqptwdk22cg35nkyfarzzqsvcyutlt5p;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.3.1/mfem-4.9.0-2xfwkxykfrycrgvcitrmg7srpnzuoq4i;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.3.1/adiak-0.4.0-jtrpi4k72svl5cinupo27eglfkjlj2kf;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.3.1/libunwind-1.8.3-cgi6mbcxsguzlrbuzxs7f4atpg5advc5;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.3.1/hdf5-1.8.23-dfdnqfyzl7atwcxua2vfpgqs3xnuxyhb;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.3.1/parmetis-4.0.3-e2fwaqx2br2r7sjnk7almoiwifiw2o7r;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.3.1/hypre-2.27.0-7usxyq75lzriudrypbxltays45773ame;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.3.1/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-2xsordp26quuqzzqcxv2ibthgduv23h6;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.3.1/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-ugjgrwqivl7nxmbvxo75ysrzrqsaoxsd;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.3.1/zlib-1.3.1-txqysoethmuy57ski6geeq3xcba6lqio;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.3.1/metis-5.1.0-hmecexgiuulns3lggu6w3hbl4iyt3ncy;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.3.1/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-xw4a6eck2jrxlhcdqudhdwntcmmuhwno;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.3.1/fmt-11.0.2-hdywtafnyeshc5a7wevdqngvdhh7syx4;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/doxygen-1.13.2;/opt/rocm-6.3.1;/opt/rocm-6.3.1;/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm;/opt/rocm-6.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/opt/rocm-6.3.1;/opt/rocm-6.3.1;/opt/rocm-6.3.1" CACHE STRING "") +set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.3.1/adiak-0.4.0-vlugt2gwkx5wzlwudznxg3p2plq76pjq;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.3.1/blt-0.7.1-sv74qxlkpkll7mm6dhfjagyfog254w7c;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.3.1/c2c-1.8.0-tfrrofjzn3rdvyktevespobwrpjai5j4;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.3.1/conduit-0.9.5-vnlbr73jbwhqyvh2q76csdtve3ekpncc;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.3.1/lua-5.4.8-e3i2pbc52bfhrnxbaniektzp3x5jvyxr;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.3.1/mfem-4.9.0-lzyx65dulc7kbahov4m3zy5zsopxpfiz;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.3.1/py-nanobind-2.7.0-4sgpkalsntbmuim5oltb7ue4gggt6rv5;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/py-pytest-9.0.0-dn2hwdtaqec2dkxtx7bnvykyxacfdagj;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.3.1/hdf5-1.8.23-liive5kzeooveetbjhil4ic7hi3ccsg4;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.3.1/parmetis-4.0.3-fiyw3adearn3nmxjifcqtuzwy24fshp5;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.3.1/py-numpy-2.4.2-ij66enxl4hmrmwua5bsec2yslylneqbw;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.3.1/hypre-2.27.0-cnukrpfl32kl5q6ud4wozdqbgtqoo7jx;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.3.1/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-aqopcekt2ikzah5tekoesewfzyexhz4q;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.3.1/umpire-2025.12.0-6jmr57w6t5ctmf4jgyrzb3y2j77a2clz;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.3.1/zlib-1.3.1-dsduxyfnks4bhrkpbskff35l5y36ofp7;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.3.1/metis-5.1.0-6mtxrj6jbrvyd3xpq4pvluywbndjx42w;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.3.1/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-eccm2e7wvkrekpfcvmbu6x3rtnip4oh3;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.3.1/fmt-11.0.2-kw3vpg2ajhrgi7kozhcioz3nrgc6fh3o;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/doxygen-1.15.0;/opt/rocm-6.3.1;/opt/rocm-6.3.1;/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm;/opt/rocm-6.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/opt/rocm-6.3.1;/opt/rocm-6.3.1;/opt/rocm-6.3.1" CACHE STRING "") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") -set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.3.1/axom-develop-jxfd3czjy4m4eilyzg6e6q4nmup5ltvq/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.3.1/axom-develop-jxfd3czjy4m4eilyzg6e6q4nmup5ltvq/lib64;;/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12" CACHE STRING "") +set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.3.1/axom-develop-te7am32fqfkfq6tx6o5arqikygw5j36c/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.3.1/axom-develop-te7am32fqfkfq6tx6o5arqikygw5j36c/lib64;;/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12" CACHE STRING "") -set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.3.1/axom-develop-jxfd3czjy4m4eilyzg6e6q4nmup5ltvq/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.3.1/axom-develop-jxfd3czjy4m4eilyzg6e6q4nmup5ltvq/lib64;;/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12" CACHE STRING "") +set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.3.1/axom-develop-te7am32fqfkfq6tx6o5arqikygw5j36c/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.3.1/axom-develop-te7am32fqfkfq6tx6o5arqikygw5j36c/lib64;;/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") #------------------------------------------------------------------------------ # Compilers #------------------------------------------------------------------------------ -# Compiler Spec: llvm-amdgpu@6.3.1/ewmb23zt2h4lqtnvv6lsha7mdyiucmx3 +# Compiler Spec: llvm-amdgpu@6.3.1/ns2pv5bzkpjolxzmhgkckj6glqymgd7e #------------------------------------------------------------------------------ if(DEFINED ENV{SPACK_CC}) - set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6/libexec/spack/rocmcc/amdclang" CACHE PATH "") + set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf/libexec/spack/rocmcc/amdclang" CACHE PATH "") - set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6/libexec/spack/rocmcc/amdclang++" CACHE PATH "") + set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf/libexec/spack/rocmcc/amdclang++" CACHE PATH "") - set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6/libexec/spack/rocmcc/amdflang" CACHE PATH "") + set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf/libexec/spack/rocmcc/amdflang" CACHE PATH "") else() @@ -96,52 +96,64 @@ set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") # TPLs #------------------------------------------------------------------------------ -set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.3.1" CACHE PATH "") +set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.3.1" CACHE PATH "") -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-tzcfvtw7tkmkf2tav77vshtxusfx6xsp" CACHE PATH "") +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-vnlbr73jbwhqyvh2q76csdtve3ekpncc" CACHE PATH "") -set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-ebatzl653bv653yovk7ea43xh5hpzyk5" CACHE PATH "") +set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-tfrrofjzn3rdvyktevespobwrpjai5j4" CACHE PATH "") -set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-2xfwkxykfrycrgvcitrmg7srpnzuoq4i" CACHE PATH "") +set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-lzyx65dulc7kbahov4m3zy5zsopxpfiz" CACHE PATH "") -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-dfdnqfyzl7atwcxua2vfpgqs3xnuxyhb" CACHE PATH "") +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-liive5kzeooveetbjhil4ic7hi3ccsg4" CACHE PATH "") -set(LUA_DIR "${TPL_ROOT}/lua-5.4.6-xqptwdk22cg35nkyfarzzqsvcyutlt5p" CACHE PATH "") +set(LUA_DIR "${TPL_ROOT}/lua-5.4.8-e3i2pbc52bfhrnxbaniektzp3x5jvyxr" CACHE PATH "") -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-2xsordp26quuqzzqcxv2ibthgduv23h6" CACHE PATH "") +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-aqopcekt2ikzah5tekoesewfzyexhz4q" CACHE PATH "") -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-ugjgrwqivl7nxmbvxo75ysrzrqsaoxsd" CACHE PATH "") +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-6jmr57w6t5ctmf4jgyrzb3y2j77a2clz" CACHE PATH "") # OPENCASCADE not built -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-jtrpi4k72svl5cinupo27eglfkjlj2kf" CACHE PATH "") +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-vlugt2gwkx5wzlwudznxg3p2plq76pjq" CACHE PATH "") -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-477jqqgkb3xjq7zd6gtxz52y7yn4hhel" CACHE PATH "") +# CALIPER not built -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-xw4a6eck2jrxlhcdqudhdwntcmmuhwno" CACHE PATH "") +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-eccm2e7wvkrekpfcvmbu6x3rtnip4oh3" CACHE PATH "") # scr not built #------------------------------------------------------------------------------ -# Devtools +# Devtools & Python #------------------------------------------------------------------------------ -set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48" CACHE PATH "") +set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25" CACHE PATH "") -set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm/bin/clang-format" CACHE PATH "") +set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm/bin/clang-format" CACHE PATH "") -set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/python3" CACHE PATH "") +set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/python3" CACHE PATH "") -set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/jsonschema" CACHE PATH "") +set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/jsonschema" CACHE PATH "") set(ENABLE_DOCS ON CACHE BOOL "") -set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/sphinx-build" CACHE PATH "") +set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/sphinx-build" CACHE PATH "") + +set(YAPF_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/yapf" CACHE PATH "") set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0/bin/shroud" CACHE PATH "") -set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w/bin/cppcheck" CACHE PATH "") +set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27/bin/cppcheck" CACHE PATH "") + +set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/doxygen-1.15.0/bin/doxygen" CACHE PATH "") + +set(PY_NANOBIND_DIR "${TPL_ROOT}/py-nanobind-2.7.0-4sgpkalsntbmuim5oltb7ue4gggt6rv5/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PYTEST_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/py-pytest-9.0.0-dn2hwdtaqec2dkxtx7bnvykyxacfdagj/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_NUMPY_DIR "${TPL_ROOT}/py-numpy-2.4.2-ij66enxl4hmrmwua5bsec2yslylneqbw/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PLUGGY_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/py-pluggy-1.6.0-27aoz44dedjxa6j6r6cavpqyqmpknidb/lib/python3.13/site-packages" CACHE PATH "") -set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/doxygen-1.13.2/bin/doxygen" CACHE PATH "") +set(PY_INICONFIG_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/py-iniconfig-2.1.0-7rty7n4wq6kxxrzflm7wbxqzhhc6ph7q/lib/python3.13/site-packages" CACHE PATH "") diff --git a/host-configs/rzvernal-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.2_hip.cmake b/host-configs/rzvernal-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.2_hip.cmake deleted file mode 100644 index 5860276582..0000000000 --- a/host-configs/rzvernal-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.2_hip.cmake +++ /dev/null @@ -1,147 +0,0 @@ -#------------------------------------------------------------------------------ -# !!!! This is a generated file, edit at own risk !!!! -#------------------------------------------------------------------------------ -# CMake executable path: /usr/tce/packages/cmake/cmake-3.29.2/bin/cmake -#------------------------------------------------------------------------------ - -set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.4.2/blt-develop-cnq3cm7laedurs5er2qsq65tcv4s7mfu;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.4.2/c2c-1.8.0-a6qbglkmvsrujhmz74okbcqhvzrj63m6;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.4.2/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-zfdmahinxufcljoyw75jpmbqsmilzmwn;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.4.2/conduit-0.9.5-tw3svztl6tuwm5xgkxxypth2wfn6uuys;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.4.2/lua-5.4.6-jopsczdu6xr6ynusfj7l36nni44opx7h;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.4.2/mfem-4.9.0-ry7y5nt7vqgwutxe3uo7sqntft5o77mr;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.4.2/adiak-0.4.0-s6y3w26rhudfxlzr24puf5mfo3blrfwt;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.4.2/libunwind-1.8.3-kiiwwsrjhpdtqrqphqi6bawovtjxolu7;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.4.2/hdf5-1.8.23-dwcfr6rmagvx3hwc2ysdat6tc3picboy;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.4.2/parmetis-4.0.3-yaohhh2bhrfqhthfrq5alus5myxwj7qy;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.4.2/hypre-2.27.0-iumqsnzym4ali5rsg7bggfxgeegdfvyi;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.4.2/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-2r6pwgpzaog45cm46dt7sce7a5qiy72i;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.4.2/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-5ipyjuvogd3juoetf26g372fm24wzuca;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.4.2/zlib-1.3.1-66xuh43r6fe5fkdzlb3fpsqju24hbwrx;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.4.2/metis-5.1.0-x5aebxyckgh56retcj4a7iazsy4q7ii2;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.4.2/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-lskwuepv6zzfnhpjgmltqofk5pyf2563;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.4.2/fmt-11.0.2-6qd5wbj47udcjluobpwbcz2f4e3srvpa;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/doxygen-1.13.2;/opt/rocm-6.4.2;/opt/rocm-6.4.2;/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm;/opt/rocm-6.4.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/opt/rocm-6.4.2;/opt/rocm-6.4.2;/opt/rocm-6.4.2" CACHE STRING "") - -set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") - -set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.4.2/axom-develop-hvfs73oy4mppcfpeloamyhi7f3oy5fml/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.4.2/axom-develop-hvfs73oy4mppcfpeloamyhi7f3oy5fml/lib64;;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") - -set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.4.2/axom-develop-hvfs73oy4mppcfpeloamyhi7f3oy5fml/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.4.2/axom-develop-hvfs73oy4mppcfpeloamyhi7f3oy5fml/lib64;;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") - -set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") - -#------------------------------------------------------------------------------ -# Compilers -#------------------------------------------------------------------------------ -# Compiler Spec: llvm-amdgpu@6.4.2/bb2nokv3ui3ksdf4t4xucxqtidlj2ds4 -#------------------------------------------------------------------------------ -if(DEFINED ENV{SPACK_CC}) - - set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6/libexec/spack/rocmcc/amdclang" CACHE PATH "") - - set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6/libexec/spack/rocmcc/amdclang++" CACHE PATH "") - - set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6/libexec/spack/rocmcc/amdflang" CACHE PATH "") - -else() - - set(CMAKE_C_COMPILER "/opt/rocm-6.4.2/llvm/bin/amdclang" CACHE PATH "") - - set(CMAKE_CXX_COMPILER "/opt/rocm-6.4.2/llvm/bin/amdclang++" CACHE PATH "") - - set(CMAKE_Fortran_COMPILER "/opt/rocm-6.4.2/llvm/bin/amdflang" CACHE PATH "") - -endif() - -set(CMAKE_Fortran_FLAGS "-Mfreeform" CACHE STRING "") - -set(ENABLE_FORTRAN ON CACHE BOOL "") - -#------------------------------------------------------------------------------ -# MPI -#------------------------------------------------------------------------------ - -set(MPI_C_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.2/bin/mpicc" CACHE PATH "") - -set(MPI_CXX_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.2/bin/mpicxx" CACHE PATH "") - -set(MPI_Fortran_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.2/bin/mpif90" CACHE PATH "") - -set(MPIEXEC_EXECUTABLE "/usr/global/tools/flux_wrappers/bin/srun" CACHE PATH "") - -set(MPIEXEC_NUMPROC_FLAG "-n" CACHE STRING "") - -set(ENABLE_MPI ON CACHE BOOL "") - -#------------------------------------------------------------------------------ -# Hardware -#------------------------------------------------------------------------------ - -#------------------------------------------------ -# ROCm -#------------------------------------------------ - -set(ROCM_PATH "/opt/rocm-6.4.2" CACHE PATH "") - -set(CMAKE_HIP_ARCHITECTURES "gfx90a;gfx942" CACHE STRING "") - -set(CMAKE_HIP_COMPILER "/opt/rocm-6.4.2/bin/amdclang++" CACHE FILEPATH "") - -#------------------------------------------------------------------------------ - -# Axom ROCm specifics - -#------------------------------------------------------------------------------ - - -set(ENABLE_HIP ON CACHE BOOL "") - -set(ROCM_ROOT_DIR "/opt/rocm-6.4.2" CACHE PATH "") - -set(CMAKE_EXE_LINKER_FLAGS "-lxpmem -L/opt/cray/pe/mpich/8.1.29/gtl/lib -Wl,-rpath,/opt/cray/pe/mpich/8.1.29/gtl/lib -lmpi_gtl_hsa -L/opt/rocm-6.4.2/lib/llvm/lib -Wl,-rpath,/opt/rocm-6.4.2/lib/llvm/lib -L/opt/rocm-6.4.2/lib -Wl,-rpath,/opt/rocm-6.4.2/lib -lpgmath -lompstub -Wl,--disable-new-dtags -lflang -lflangrti -lamdhip64 -lhsakmt -lhsa-runtime64 -lamd_comgr " CACHE STRING "") - -#------------------------------------------------ -# Hardware Specifics -#------------------------------------------------ - -set(ENABLE_OPENMP OFF CACHE BOOL "") - -set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") - -#------------------------------------------------------------------------------ -# TPLs -#------------------------------------------------------------------------------ - -set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_41_47/llvm-amdgpu-6.4.2" CACHE PATH "") - -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-tw3svztl6tuwm5xgkxxypth2wfn6uuys" CACHE PATH "") - -set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-a6qbglkmvsrujhmz74okbcqhvzrj63m6" CACHE PATH "") - -set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-ry7y5nt7vqgwutxe3uo7sqntft5o77mr" CACHE PATH "") - -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-dwcfr6rmagvx3hwc2ysdat6tc3picboy" CACHE PATH "") - -set(LUA_DIR "${TPL_ROOT}/lua-5.4.6-jopsczdu6xr6ynusfj7l36nni44opx7h" CACHE PATH "") - -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-2r6pwgpzaog45cm46dt7sce7a5qiy72i" CACHE PATH "") - -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-5ipyjuvogd3juoetf26g372fm24wzuca" CACHE PATH "") - -# OPENCASCADE not built - -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-s6y3w26rhudfxlzr24puf5mfo3blrfwt" CACHE PATH "") - -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-zfdmahinxufcljoyw75jpmbqsmilzmwn" CACHE PATH "") - -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-lskwuepv6zzfnhpjgmltqofk5pyf2563" CACHE PATH "") - -# scr not built - -#------------------------------------------------------------------------------ -# Devtools -#------------------------------------------------------------------------------ - -set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48" CACHE PATH "") - -set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm/bin/clang-format" CACHE PATH "") - -set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/python3" CACHE PATH "") - -set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/jsonschema" CACHE PATH "") - -set(ENABLE_DOCS ON CACHE BOOL "") - -set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/sphinx-build" CACHE PATH "") - -set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0/bin/shroud" CACHE PATH "") - -set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w/bin/cppcheck" CACHE PATH "") - -set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/doxygen-1.13.2/bin/doxygen" CACHE PATH "") - - diff --git a/host-configs/rzvernal-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.3_hip.cmake b/host-configs/rzvernal-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.3_hip.cmake new file mode 100644 index 0000000000..dbace9cbca --- /dev/null +++ b/host-configs/rzvernal-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.3_hip.cmake @@ -0,0 +1,159 @@ +#------------------------------------------------------------------------------ +# !!!! This is a generated file, edit at own risk !!!! +#------------------------------------------------------------------------------ +# CMake executable path: /usr/tce/packages/cmake/cmake-3.29.2/bin/cmake +#------------------------------------------------------------------------------ + +set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3/blt-0.7.1-2eahqqwjyauupjq3baxftq7kuv3pvdgp;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3/c2c-1.8.0-oxqhr2ybswpnzt74f4iritx263ji3uqy;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-sos5uklbsgaycb776a2ufcyje4y24yls;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3/conduit-0.9.5-cxdq4qnoptjq6lry5asb2bqodvm3zjig;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3/lua-5.4.8-lsey5vgxvpqf5j3xbrlzswrizuwm65vh;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3/mfem-4.9.0-gkcg2u6vl5yur7gvigiut76ckzxo4fry;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3/py-nanobind-2.7.0-3nchqpyclgle5w56it23ozl4ttbnrfjd;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/py-pytest-9.0.0-dn2hwdtaqec2dkxtx7bnvykyxacfdagj;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3/adiak-0.4.0-cbxp6kv6rm4f7oeczuhbplm3yb3zxb6z;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3/libunwind-1.8.3-r4b3cptnf27zp34jbrdtlrf6r6dp6n4l;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3/hdf5-1.8.23-wb7u6epuww3tretkcto7jhq2i7pffimg;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3/parmetis-4.0.3-d6ed2qesb4yprvpetx3fso35rx6amf5b;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3/py-numpy-2.4.2-t7cvohiksz7deeldwxrtqfmahcvanapb;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3/hypre-2.27.0-pxqhlqwksiscco65tsz5somb4ctdq3q2;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-5r3ukxt2ewfn2geqge37ea2fxd7kfixh;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3/umpire-2025.12.0-n4zr37loo2okonovcswffexwi5mbxnxh;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3/zlib-1.3.1-ijxa3tdiibemxtng46hrremmbytl2dqq;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3/metis-5.1.0-mubwzuka5byhpbzmwaxjhtffhst3oj3q;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-k6gr5qtzupytbr5kq2e73qesltauiqcl;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3/fmt-11.0.2-unmvs6vefcyfcfnzlie2eag5i2eib35d;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/doxygen-1.15.0;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm;/opt/rocm-6.4.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/opt/rocm-6.4.3" CACHE STRING "") + +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") + +set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3/axom-develop-2ah5imlo6grdjcijxzmnj65v5lolnzam/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3/axom-develop-2ah5imlo6grdjcijxzmnj65v5lolnzam/lib64;;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") + +set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3/axom-develop-2ah5imlo6grdjcijxzmnj65v5lolnzam/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3/axom-develop-2ah5imlo6grdjcijxzmnj65v5lolnzam/lib64;;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") + +set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") + +#------------------------------------------------------------------------------ +# Compilers +#------------------------------------------------------------------------------ +# Compiler Spec: llvm-amdgpu@6.4.3/u67i6xutdthzl3yti7tv3klyhyzddbkv +#------------------------------------------------------------------------------ +if(DEFINED ENV{SPACK_CC}) + + set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf/libexec/spack/rocmcc/amdclang" CACHE PATH "") + + set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf/libexec/spack/rocmcc/amdclang++" CACHE PATH "") + + set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf/libexec/spack/rocmcc/amdflang" CACHE PATH "") + +else() + + set(CMAKE_C_COMPILER "/opt/rocm-6.4.3/llvm/bin/amdclang" CACHE PATH "") + + set(CMAKE_CXX_COMPILER "/opt/rocm-6.4.3/llvm/bin/amdclang++" CACHE PATH "") + + set(CMAKE_Fortran_COMPILER "/opt/rocm-6.4.3/llvm/bin/amdflang" CACHE PATH "") + +endif() + +set(CMAKE_Fortran_FLAGS "-Mfreeform" CACHE STRING "") + +set(ENABLE_FORTRAN ON CACHE BOOL "") + +#------------------------------------------------------------------------------ +# MPI +#------------------------------------------------------------------------------ + +set(MPI_C_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.3/bin/mpicc" CACHE PATH "") + +set(MPI_CXX_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.3/bin/mpicxx" CACHE PATH "") + +set(MPI_Fortran_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.3/bin/mpif90" CACHE PATH "") + +set(MPIEXEC_EXECUTABLE "/usr/global/tools/flux_wrappers/bin/srun" CACHE PATH "") + +set(MPIEXEC_NUMPROC_FLAG "-n" CACHE STRING "") + +set(ENABLE_MPI ON CACHE BOOL "") + +#------------------------------------------------------------------------------ +# Hardware +#------------------------------------------------------------------------------ + +#------------------------------------------------ +# ROCm +#------------------------------------------------ + +set(ROCM_PATH "/opt/rocm-6.4.3" CACHE PATH "") + +set(CMAKE_HIP_ARCHITECTURES "gfx90a;gfx942" CACHE STRING "") + +set(CMAKE_HIP_COMPILER "/opt/rocm-6.4.3/bin/amdclang++" CACHE FILEPATH "") + +#------------------------------------------------------------------------------ + +# Axom ROCm specifics + +#------------------------------------------------------------------------------ + + +set(ENABLE_HIP ON CACHE BOOL "") + +set(ROCM_ROOT_DIR "/opt/rocm-6.4.3" CACHE PATH "") + +set(CMAKE_EXE_LINKER_FLAGS "-lxpmem -L/opt/cray/pe/mpich/8.1.29/gtl/lib -Wl,-rpath,/opt/cray/pe/mpich/8.1.29/gtl/lib -lmpi_gtl_hsa -L/opt/rocm-6.4.3/lib/llvm/lib -Wl,-rpath,/opt/rocm-6.4.3/lib/llvm/lib -L/opt/rocm-6.4.3/lib -Wl,-rpath,/opt/rocm-6.4.3/lib -lpgmath -lompstub -Wl,--disable-new-dtags -lflang -lflangrti -lamdhip64 -lhsakmt -lhsa-runtime64 -lamd_comgr " CACHE STRING "") + +#------------------------------------------------ +# Hardware Specifics +#------------------------------------------------ + +set(ENABLE_OPENMP OFF CACHE BOOL "") + +set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") + +#------------------------------------------------------------------------------ +# TPLs +#------------------------------------------------------------------------------ + +set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/llvm-amdgpu-6.4.3" CACHE PATH "") + +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-cxdq4qnoptjq6lry5asb2bqodvm3zjig" CACHE PATH "") + +set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-oxqhr2ybswpnzt74f4iritx263ji3uqy" CACHE PATH "") + +set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-gkcg2u6vl5yur7gvigiut76ckzxo4fry" CACHE PATH "") + +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-wb7u6epuww3tretkcto7jhq2i7pffimg" CACHE PATH "") + +set(LUA_DIR "${TPL_ROOT}/lua-5.4.8-lsey5vgxvpqf5j3xbrlzswrizuwm65vh" CACHE PATH "") + +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-5r3ukxt2ewfn2geqge37ea2fxd7kfixh" CACHE PATH "") + +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-n4zr37loo2okonovcswffexwi5mbxnxh" CACHE PATH "") + +# OPENCASCADE not built + +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-cbxp6kv6rm4f7oeczuhbplm3yb3zxb6z" CACHE PATH "") + +set(CALIPER_DIR "${TPL_ROOT}/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-sos5uklbsgaycb776a2ufcyje4y24yls" CACHE PATH "") + +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-k6gr5qtzupytbr5kq2e73qesltauiqcl" CACHE PATH "") + +# scr not built + +#------------------------------------------------------------------------------ +# Devtools & Python +#------------------------------------------------------------------------------ + +set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25" CACHE PATH "") + +set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm/bin/clang-format" CACHE PATH "") + +set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/python3" CACHE PATH "") + +set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/jsonschema" CACHE PATH "") + +set(ENABLE_DOCS ON CACHE BOOL "") + +set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/sphinx-build" CACHE PATH "") + +set(YAPF_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/yapf" CACHE PATH "") + +set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0/bin/shroud" CACHE PATH "") + +set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27/bin/cppcheck" CACHE PATH "") + +set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/doxygen-1.15.0/bin/doxygen" CACHE PATH "") + +set(PY_NANOBIND_DIR "${TPL_ROOT}/py-nanobind-2.7.0-3nchqpyclgle5w56it23ozl4ttbnrfjd/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PYTEST_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/py-pytest-9.0.0-dn2hwdtaqec2dkxtx7bnvykyxacfdagj/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_NUMPY_DIR "${TPL_ROOT}/py-numpy-2.4.2-t7cvohiksz7deeldwxrtqfmahcvanapb/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PLUGGY_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/py-pluggy-1.6.0-27aoz44dedjxa6j6r6cavpqyqmpknidb/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_INICONFIG_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_11_12_30/none-none/py-iniconfig-2.1.0-7rty7n4wq6kxxrzflm7wbxqzhhc6ph7q/lib/python3.13/site-packages" CACHE PATH "") + + diff --git a/host-configs/rzwhippet-toss_4_x86_64_ib-gcc@13.3.1.cmake b/host-configs/rzwhippet-toss_4_x86_64_ib-gcc@13.3.1.cmake index e3930e0f70..8002b8980e 100644 --- a/host-configs/rzwhippet-toss_4_x86_64_ib-gcc@13.3.1.cmake +++ b/host-configs/rzwhippet-toss_4_x86_64_ib-gcc@13.3.1.cmake @@ -4,28 +4,28 @@ # CMake executable path: /usr/tce/packages/cmake/cmake-3.26.3/bin/cmake #------------------------------------------------------------------------------ -set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/blt-develop-vkyjvzyg7n4ig7x4llo53lndvnwsrbjq;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/c2c-1.8.0-3bch3wbxcl3eji2wsbbbzmagowxe4lpc;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-yhzgzz2ex4ic63ogwwtds2izsvkkadh3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/conduit-0.9.5-icskqkcmikkfw2itxiq6xdt6nilzlsvr;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/mfem-4.9.0-bipzszywmjx53fi7latomyhw5665mi4h;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-xqo4atvwmb3az7u6odq3zmsdlk2j3xhe;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/scr-3.0.1-lwjvdlbifmo7m3d552nskugm6lssccnm;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-btsargdd7jlgzc76ciko62u6tg5twsaz;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/adiak-0.4.0-45h4d32dvvatilujstudj3ucvmdeyi6a;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/libunwind-1.8.3-74hjhhtejjsdgxjpp262xlm5ow6psq4r;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/hdf5-1.8.23-gokrordtweyfprtzgrzsycyilhy32uc7;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/parmetis-4.0.3-euggsyckxbtpzv6kzq74k3ndngpw2yqh;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/hypre-2.27.0-ddqcjjo7acriziqye5rracqx6pnkncj5;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/axl-0.7.1-q2rxtt4nowyjknvxudfg5vszvdgwhr57;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/dtcmp-1.1.5-4bnm6uirjgbss5vgcmahsappp7cjjquh;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/er-0.3.0-4tzpoetvdc2tohxujfxu5ctlu6ndjytt;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/libyogrt-1.35-hp6xkhmzi5wbhvc4jzqli66m4uhrqz4i;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/spath-0.2.0-yip5q3eadzz56niotmpoqf4p3hkmlrmb;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-t6jbvd33b45eq6ssp5guraifij3y7huw;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/fmt-11.0.2-faqgdwrlrl4nwv35msienhldhqrq2vce;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/metis-5.1.0-ovo3o7do7zr5fxw6mi2flzy6ftfsavk2;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/lwgrp-1.0.6-5aend7qfofhskqpuwduxvzaqcyrs6w4e;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/redset-0.2.0-ml4pwcex7h2rsooauoaoajsli7yg2po6;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/shuffile-0.2.0-6qqtnapl6yb5gq7ii6l7e4543wqumv75;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/rankstr-0.2.0-4mvhlooa4a5gqoyvwel73p4aimodhbqn;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/kvtree-1.3.0-ldkjgqadvd44hgy7djvq4xgmwmxjs4gx;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/none-none/gcc-runtime-13.3.1-k43mnfzd4ehqvovn4d5qq7b5f6sfetsx;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/usr/tce/packages/cmake/cmake-3.26.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/gcc-13.3.1/cppcheck-2.18.0-d2tmb7ls2d5vgh6vhcyohecwcu6msopb;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/doxygen-1.13.2;/usr/tce/packages/gcc/gcc-13.3.1;/usr/tce/packages/clang/clang-19.1.3;/usr/tce/packages/mvapich2/mvapich2-2.3.7-gcc-13.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5" CACHE STRING "") +set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/blt-0.7.1-yiu2olkumeazbrto7x4v2dv6qbefhf5a;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/c2c-1.8.0-jkclfdpl7igj3ur3ufnpt6dupjfvotpc;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-f4kbq52oexscd7dhlwdbffygha5losj5;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/conduit-0.9.5-xyt2d2ot4eozuhrjv7mccoe7tw6ef7ui;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/mfem-4.9.0-heih2kd5qpkalflltitlry3g4qpyx5xw;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/py-nanobind-2.7.0-szozdpwzge7ah4bsilit6fijezxqbfop;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/py-pytest-9.0.0-vozuj6nkk42nhxeo5mawnux3w7bj3awe;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-ktky5uf7luvuf4cnczifj5av5ndbajco;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/scr-3.0.1-tnom76yaaoeyob7dncuafxebkzf2fbv7;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/umpire-2025.12.0-m6o7ya6pnrpixhpygzywlzoue3zuuir3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/adiak-0.4.0-i5bahteezqmswdv2ulpfvfogmuue463q;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/libunwind-1.8.3-pwdmczcnf7vugfly5zk7eztefnn7kv75;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/hdf5-1.8.23-2pnsuxpt6r2wmdc6sqyku6ki6na4gcfl;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/parmetis-4.0.3-tt2yxrbsrccyglhjqcs2y2nspmt4qoqx;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/py-numpy-2.4.2-z4yapdkn22w6adfrl7ibucqiokgrwb7f;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/hypre-2.27.0-vwir3t6mlgbmo3mgfbiayrpbbdxsrsha;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/axl-0.7.1-yoi3m7zjahalmglnbo33aitshq6cj43q;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/dtcmp-1.1.5-ipjglgrmgotna4yza37ecwiur3rkx6wf;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/er-0.3.0-bdvz66gxhiflazj3irsv5vleaphtypqz;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/libyogrt-1.35-qwz3xpqmkwgh5byk2kiy3txbazfwwf3c;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/spath-0.2.0-pmsauxzx75wu4kyfwjf3ite5dzzaymhv;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-cc5noebugovl4o6ir2d65bx7qizwznef;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/fmt-11.0.2-ggfpxocredbjrldu7ar33cjedhmkm3da;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/metis-5.1.0-3jtvhjwnhqqaf5v2na7f675qgvlusyx3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/lwgrp-1.0.6-lkotiz6t6q3r5nmgqcfhfvdyukzdnnuu;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/redset-0.2.0-2kb4kg3ypf7l66vxdt6x2z4oqvimt3bs;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/shuffile-0.2.0-v2buhpkgx2py4m4bny4lsflaoeqbmqof;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/rankstr-0.2.0-xkzr7o47vbxkwtxppil7a7i57dhlk5gf;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/kvtree-1.3.0-py6ds6lmww6eqlhjgb4vilk6ftkxsuud;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/gcc-runtime-13.3.1-zsobnkwck2glzcbukupgvgbiwwhdonys;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/usr/tce/packages/cmake/cmake-3.26.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/gcc-13.3.1/cppcheck-2.18.0-i3p56kpf66xzj4wm5kfqxyc4vgox7gb3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/doxygen-1.15.0;/usr/tce/packages/gcc/gcc-13.3.1;/usr/tce/packages/clang/clang-19.1.3;/usr/tce/packages/mvapich2/mvapich2-2.3.7-gcc-13.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11" CACHE STRING "") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") -set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/axom-develop-ygincdbfj2qpcjz3hznn64bsr5v76e6v/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/axom-develop-ygincdbfj2qpcjz3hznn64bsr5v76e6v/lib64;;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/axom-develop-5bv7dhwiz6x5ef65d6tovswgfdjtty2l/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/axom-develop-5bv7dhwiz6x5ef65d6tovswgfdjtty2l/lib64;;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") -set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/axom-develop-ygincdbfj2qpcjz3hznn64bsr5v76e6v/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1/axom-develop-ygincdbfj2qpcjz3hznn64bsr5v76e6v/lib64;;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/axom-develop-5bv7dhwiz6x5ef65d6tovswgfdjtty2l/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1/axom-develop-5bv7dhwiz6x5ef65d6tovswgfdjtty2l/lib64;;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") #------------------------------------------------------------------------------ # Compilers #------------------------------------------------------------------------------ -# Compiler Spec: gcc@13.3.1/75lfrhqb3monlgkmkokrboaqienagc6u +# Compiler Spec: gcc@13.3.1/xrm3n2pex2en2wvm6p4ap62nieoz7kne #------------------------------------------------------------------------------ if(DEFINED ENV{SPACK_CC}) - set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/gcc/gcc" CACHE PATH "") + set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/gcc/gcc" CACHE PATH "") - set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/gcc/g++" CACHE PATH "") + set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/gcc/g++" CACHE PATH "") - set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/gcc/gfortran" CACHE PATH "") + set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/gcc/gfortran" CACHE PATH "") else() @@ -73,72 +73,84 @@ set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") # TPLs #------------------------------------------------------------------------------ -set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/gcc-13.3.1" CACHE PATH "") +set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/gcc-13.3.1" CACHE PATH "") -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-icskqkcmikkfw2itxiq6xdt6nilzlsvr" CACHE PATH "") +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-xyt2d2ot4eozuhrjv7mccoe7tw6ef7ui" CACHE PATH "") -set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-3bch3wbxcl3eji2wsbbbzmagowxe4lpc" CACHE PATH "") +set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-jkclfdpl7igj3ur3ufnpt6dupjfvotpc" CACHE PATH "") -set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-bipzszywmjx53fi7latomyhw5665mi4h" CACHE PATH "") +set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-heih2kd5qpkalflltitlry3g4qpyx5xw" CACHE PATH "") -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-gokrordtweyfprtzgrzsycyilhy32uc7" CACHE PATH "") +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-2pnsuxpt6r2wmdc6sqyku6ki6na4gcfl" CACHE PATH "") set(LUA_DIR "/usr" CACHE PATH "") -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-xqo4atvwmb3az7u6odq3zmsdlk2j3xhe" CACHE PATH "") +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-ktky5uf7luvuf4cnczifj5av5ndbajco" CACHE PATH "") -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-btsargdd7jlgzc76ciko62u6tg5twsaz" CACHE PATH "") +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-m6o7ya6pnrpixhpygzywlzoue3zuuir3" CACHE PATH "") # OPENCASCADE not built -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-45h4d32dvvatilujstudj3ucvmdeyi6a" CACHE PATH "") +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-i5bahteezqmswdv2ulpfvfogmuue463q" CACHE PATH "") -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-yhzgzz2ex4ic63ogwwtds2izsvkkadh3" CACHE PATH "") +set(CALIPER_DIR "${TPL_ROOT}/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-f4kbq52oexscd7dhlwdbffygha5losj5" CACHE PATH "") -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-t6jbvd33b45eq6ssp5guraifij3y7huw" CACHE PATH "") +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-cc5noebugovl4o6ir2d65bx7qizwznef" CACHE PATH "") -set(SCR_DIR "${TPL_ROOT}/scr-3.0.1-lwjvdlbifmo7m3d552nskugm6lssccnm" CACHE PATH "") +set(SCR_DIR "${TPL_ROOT}/scr-3.0.1-tnom76yaaoeyob7dncuafxebkzf2fbv7" CACHE PATH "") -set(KVTREE_DIR "${TPL_ROOT}/kvtree-1.3.0-ldkjgqadvd44hgy7djvq4xgmwmxjs4gx" CACHE PATH "") +set(KVTREE_DIR "${TPL_ROOT}/kvtree-1.3.0-py6ds6lmww6eqlhjgb4vilk6ftkxsuud" CACHE PATH "") -set(DTCMP_DIR "${TPL_ROOT}/dtcmp-1.1.5-4bnm6uirjgbss5vgcmahsappp7cjjquh" CACHE PATH "") +set(DTCMP_DIR "${TPL_ROOT}/dtcmp-1.1.5-ipjglgrmgotna4yza37ecwiur3rkx6wf" CACHE PATH "") -set(SPATH_DIR "${TPL_ROOT}/spath-0.2.0-yip5q3eadzz56niotmpoqf4p3hkmlrmb" CACHE PATH "") +set(SPATH_DIR "${TPL_ROOT}/spath-0.2.0-pmsauxzx75wu4kyfwjf3ite5dzzaymhv" CACHE PATH "") -set(AXL_DIR "${TPL_ROOT}/axl-0.7.1-q2rxtt4nowyjknvxudfg5vszvdgwhr57" CACHE PATH "") +set(AXL_DIR "${TPL_ROOT}/axl-0.7.1-yoi3m7zjahalmglnbo33aitshq6cj43q" CACHE PATH "") -set(LWGRP_DIR "${TPL_ROOT}/lwgrp-1.0.6-5aend7qfofhskqpuwduxvzaqcyrs6w4e" CACHE PATH "") +set(LWGRP_DIR "${TPL_ROOT}/lwgrp-1.0.6-lkotiz6t6q3r5nmgqcfhfvdyukzdnnuu" CACHE PATH "") -set(ER_DIR "${TPL_ROOT}/er-0.3.0-4tzpoetvdc2tohxujfxu5ctlu6ndjytt" CACHE PATH "") +set(ER_DIR "${TPL_ROOT}/er-0.3.0-bdvz66gxhiflazj3irsv5vleaphtypqz" CACHE PATH "") -set(RANKSTR_DIR "${TPL_ROOT}/rankstr-0.2.0-4mvhlooa4a5gqoyvwel73p4aimodhbqn" CACHE PATH "") +set(RANKSTR_DIR "${TPL_ROOT}/rankstr-0.2.0-xkzr7o47vbxkwtxppil7a7i57dhlk5gf" CACHE PATH "") -set(REDSET_DIR "${TPL_ROOT}/redset-0.2.0-ml4pwcex7h2rsooauoaoajsli7yg2po6" CACHE PATH "") +set(REDSET_DIR "${TPL_ROOT}/redset-0.2.0-2kb4kg3ypf7l66vxdt6x2z4oqvimt3bs" CACHE PATH "") -set(SHUFFILE_DIR "${TPL_ROOT}/shuffile-0.2.0-6qqtnapl6yb5gq7ii6l7e4543wqumv75" CACHE PATH "") +set(SHUFFILE_DIR "${TPL_ROOT}/shuffile-0.2.0-v2buhpkgx2py4m4bny4lsflaoeqbmqof" CACHE PATH "") -set(LIBYOGRT_DIR "${TPL_ROOT}/libyogrt-1.35-hp6xkhmzi5wbhvc4jzqli66m4uhrqz4i" CACHE PATH "") +set(LIBYOGRT_DIR "${TPL_ROOT}/libyogrt-1.35-qwz3xpqmkwgh5byk2kiy3txbazfwwf3c" CACHE PATH "") #------------------------------------------------------------------------------ -# Devtools +# Devtools & Python #------------------------------------------------------------------------------ -set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37" CACHE PATH "") +set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14" CACHE PATH "") set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/clang/clang-19.1.3/bin/clang-format" CACHE PATH "") -set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/python3" CACHE PATH "") +set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/python3" CACHE PATH "") -set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/jsonschema" CACHE PATH "") +set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/jsonschema" CACHE PATH "") set(ENABLE_DOCS ON CACHE BOOL "") -set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/sphinx-build" CACHE PATH "") +set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/sphinx-build" CACHE PATH "") + +set(YAPF_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/yapf" CACHE PATH "") set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0/bin/shroud" CACHE PATH "") -set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-d2tmb7ls2d5vgh6vhcyohecwcu6msopb/bin/cppcheck" CACHE PATH "") +set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-i3p56kpf66xzj4wm5kfqxyc4vgox7gb3/bin/cppcheck" CACHE PATH "") + +set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/doxygen-1.15.0/bin/doxygen" CACHE PATH "") + +set(PY_NANOBIND_DIR "${TPL_ROOT}/py-nanobind-2.7.0-szozdpwzge7ah4bsilit6fijezxqbfop/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PYTEST_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/py-pytest-9.0.0-vozuj6nkk42nhxeo5mawnux3w7bj3awe/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_NUMPY_DIR "${TPL_ROOT}/py-numpy-2.4.2-z4yapdkn22w6adfrl7ibucqiokgrwb7f/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PLUGGY_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/py-pluggy-1.6.0-6zab4pck6v7johubbhalr2waowbwpjei/lib/python3.13/site-packages" CACHE PATH "") -set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/doxygen-1.13.2/bin/doxygen" CACHE PATH "") +set(PY_INICONFIG_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/py-iniconfig-2.1.0-xwmbxuhk2oo3dcuizdp3z4hqbpqykkom/lib/python3.13/site-packages" CACHE PATH "") diff --git a/host-configs/rzwhippet-toss_4_x86_64_ib-intel-oneapi-compilers@2025.2.0.cmake b/host-configs/rzwhippet-toss_4_x86_64_ib-intel-oneapi-compilers@2025.2.0.cmake index 8c30521fe7..d0460445ec 100644 --- a/host-configs/rzwhippet-toss_4_x86_64_ib-intel-oneapi-compilers@2025.2.0.cmake +++ b/host-configs/rzwhippet-toss_4_x86_64_ib-intel-oneapi-compilers@2025.2.0.cmake @@ -4,28 +4,28 @@ # CMake executable path: /usr/tce/packages/cmake/cmake-3.26.3/bin/cmake #------------------------------------------------------------------------------ -set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/intel-oneapi-compilers-2025.2.0/blt-develop-scbtv5nm655fcgkpm7775x4u6wopde2o;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/intel-oneapi-compilers-2025.2.0/c2c-1.8.0-ogkaflkbghohdikxnvj4mmksdcjn2qud;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/intel-oneapi-compilers-2025.2.0/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-zjssskiaerbodbkih5epbj5fmpjq5m6p;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/intel-oneapi-compilers-2025.2.0/conduit-0.9.5-3tyhzfysh4umcgsnrp7d7p3abdbmkshp;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/intel-oneapi-compilers-2025.2.0/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-aqzabesamv77gi5i6cpgrbnka4zc4eni;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/intel-oneapi-compilers-2025.2.0/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-wps2nos3umjdrwudniuuo6xoosyp6qco;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/intel-oneapi-compilers-2025.2.0/adiak-0.4.0-svzknmon3cgc5yjd54hrxrzdc4e4htga;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/intel-oneapi-compilers-2025.2.0/libunwind-1.8.3-m7b5iissbuvvgj3ciugmytzudq5u3e3i;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/intel-oneapi-compilers-2025.2.0/hdf5-1.8.23-7sqi7ybehcspqaajunz7v6loau63ma2j;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/intel-oneapi-compilers-2025.2.0/parmetis-4.0.3-5rej7ae573vmqplcqozlpu5i6s4yipq3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/intel-oneapi-compilers-2025.2.0/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-kaem7te2437otmrrjhzhfclcq6j77pke;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/intel-oneapi-compilers-2025.2.0/fmt-11.0.2-blytd32zjrnjzszsgsvqknm24i6sdbn2;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/intel-oneapi-compilers-2025.2.0/metis-5.1.0-kkbw2eu3rzrxrtihlskhc6kwfle4ixfj;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/none-none/intel-oneapi-runtime-2025.2.0-24wotiwlsqmeinqvfb3b2qlvcjh4pcju;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/none-none/gcc-runtime-13.3.1-k43mnfzd4ehqvovn4d5qq7b5f6sfetsx;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/usr/tce/packages/cmake/cmake-3.26.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/gcc-13.3.1/cppcheck-2.18.0-d2tmb7ls2d5vgh6vhcyohecwcu6msopb;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/doxygen-1.13.2;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/intel-oneapi-compilers-2025.2.0-ngszoacyp2i5d5nawitlyuh37jswjtie/compiler/2025.2;/usr/tce/packages/intel/intel-2025.2.0;/usr/tce/packages/clang/clang-19.1.3;/usr/tce/packages/mvapich2/mvapich2-2.3.7-intel-2025.2.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5" CACHE STRING "") +set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/intel-oneapi-compilers-2025.2.0/blt-0.7.1-2n76efajatydczwltuk6plxpgoyvu6jj;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/intel-oneapi-compilers-2025.2.0/c2c-1.8.0-rl42nhoa33aux3tluna3bftevqokiiqc;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/intel-oneapi-compilers-2025.2.0/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-ti2c3tm4pc6rma2cedok5hy5vnpxmsj7;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/intel-oneapi-compilers-2025.2.0/conduit-0.9.5-z4aapemtohmue4rikzbgjhmfyexwuym4;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/intel-oneapi-compilers-2025.2.0/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-jz235wsh3nhxjuzqxse57hcojia7x4mj;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/intel-oneapi-compilers-2025.2.0/umpire-2025.12.0-2eti2r3wjt4qs772djlcgf6axs44qmko;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/intel-oneapi-compilers-2025.2.0/adiak-0.4.0-rgjvxwzjod55ialozetvkjyi3hjczviy;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/intel-oneapi-compilers-2025.2.0/libunwind-1.8.3-h42c2h7kzkiaeq63dzvt32wlhcqbcrra;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/intel-oneapi-compilers-2025.2.0/hdf5-1.8.23-74fr7atqhw4jlzxt22xi5szeqpoxcwkh;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/intel-oneapi-compilers-2025.2.0/parmetis-4.0.3-g7bp5ds3u3laspneww3scyujjwebgdzh;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/intel-oneapi-compilers-2025.2.0/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-2gq3ddrhfxqlgzr6zxbvmwpzvtqxqj25;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/intel-oneapi-compilers-2025.2.0/fmt-11.0.2-orofhwltz3p5ckiw2t7gzhkgiifetwjt;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/intel-oneapi-compilers-2025.2.0/metis-5.1.0-zschch2gorb5k7t4rmrtc3aubm663i6u;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/intel-oneapi-runtime-2025.2.0-mfk4ezunnyprzpfps5pncx2nhttsa4z3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/gcc-runtime-13.3.1-zsobnkwck2glzcbukupgvgbiwwhdonys;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/usr/tce/packages/cmake/cmake-3.26.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/gcc-13.3.1/cppcheck-2.18.0-i3p56kpf66xzj4wm5kfqxyc4vgox7gb3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/doxygen-1.15.0;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/intel-oneapi-compilers-2025.2.0-ngszoacyp2i5d5nawitlyuh37jswjtie/compiler/2025.2;/usr/tce/packages/intel/intel-2025.2.0;/usr/tce/packages/clang/clang-19.1.3;/usr/tce/packages/mvapich2/mvapich2-2.3.7-intel-2025.2.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11" CACHE STRING "") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") -set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/intel-oneapi-compilers-2025.2.0/axom-develop-mbee5akrmx5h3qn444hq24evfukehk4x/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/intel-oneapi-compilers-2025.2.0/axom-develop-mbee5akrmx5h3qn444hq24evfukehk4x/lib64;;/usr/tce/packages/intel/intel-2025.2.0/compiler/2025.2/lib;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/intel-oneapi-compilers-2025.2.0-ngszoacyp2i5d5nawitlyuh37jswjtie/compiler/2025.2/lib;/usr/tce/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/intel-oneapi-compilers-2025.2.0/axom-develop-bj7hmyynlaetqadetbi7owutac5umw3p/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/intel-oneapi-compilers-2025.2.0/axom-develop-bj7hmyynlaetqadetbi7owutac5umw3p/lib64;;/usr/tce/packages/intel/intel-2025.2.0/compiler/2025.2/lib;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/intel-oneapi-compilers-2025.2.0-ngszoacyp2i5d5nawitlyuh37jswjtie/compiler/2025.2/lib;/usr/tce/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") -set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/intel-oneapi-compilers-2025.2.0/axom-develop-mbee5akrmx5h3qn444hq24evfukehk4x/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/intel-oneapi-compilers-2025.2.0/axom-develop-mbee5akrmx5h3qn444hq24evfukehk4x/lib64;;/usr/tce/packages/intel/intel-2025.2.0/compiler/2025.2/lib;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/intel-oneapi-compilers-2025.2.0-ngszoacyp2i5d5nawitlyuh37jswjtie/compiler/2025.2/lib;/usr/tce/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/intel-oneapi-compilers-2025.2.0/axom-develop-bj7hmyynlaetqadetbi7owutac5umw3p/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/intel-oneapi-compilers-2025.2.0/axom-develop-bj7hmyynlaetqadetbi7owutac5umw3p/lib64;;/usr/tce/packages/intel/intel-2025.2.0/compiler/2025.2/lib;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/intel-oneapi-compilers-2025.2.0-ngszoacyp2i5d5nawitlyuh37jswjtie/compiler/2025.2/lib;/usr/tce/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") #------------------------------------------------------------------------------ # Compilers #------------------------------------------------------------------------------ -# Compiler Spec: intel-oneapi-compilers@2025.2.0/eve4yjde2izalfck3273wfyvpu2pilqw +# Compiler Spec: intel-oneapi-compilers@2025.2.0/pfgmabeqlm6quu3niafr24bgm7vzeeug #------------------------------------------------------------------------------ if(DEFINED ENV{SPACK_CC}) - set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/oneapi/icx" CACHE PATH "") + set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/oneapi/icx" CACHE PATH "") - set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/oneapi/icpx" CACHE PATH "") + set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/oneapi/icpx" CACHE PATH "") - set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/oneapi/ifx" CACHE PATH "") + set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/oneapi/ifx" CACHE PATH "") else() @@ -75,52 +75,54 @@ set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") # TPLs #------------------------------------------------------------------------------ -set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/intel-oneapi-compilers-2025.2.0" CACHE PATH "") +set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/intel-oneapi-compilers-2025.2.0" CACHE PATH "") -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-3tyhzfysh4umcgsnrp7d7p3abdbmkshp" CACHE PATH "") +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-z4aapemtohmue4rikzbgjhmfyexwuym4" CACHE PATH "") -set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-ogkaflkbghohdikxnvj4mmksdcjn2qud" CACHE PATH "") +set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-rl42nhoa33aux3tluna3bftevqokiiqc" CACHE PATH "") # MFEM not built -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-7sqi7ybehcspqaajunz7v6loau63ma2j" CACHE PATH "") +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-74fr7atqhw4jlzxt22xi5szeqpoxcwkh" CACHE PATH "") set(LUA_DIR "/usr" CACHE PATH "") -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-aqzabesamv77gi5i6cpgrbnka4zc4eni" CACHE PATH "") +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-jz235wsh3nhxjuzqxse57hcojia7x4mj" CACHE PATH "") -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-wps2nos3umjdrwudniuuo6xoosyp6qco" CACHE PATH "") +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-2eti2r3wjt4qs772djlcgf6axs44qmko" CACHE PATH "") # OPENCASCADE not built -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-svzknmon3cgc5yjd54hrxrzdc4e4htga" CACHE PATH "") +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-rgjvxwzjod55ialozetvkjyi3hjczviy" CACHE PATH "") -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-zjssskiaerbodbkih5epbj5fmpjq5m6p" CACHE PATH "") +set(CALIPER_DIR "${TPL_ROOT}/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-ti2c3tm4pc6rma2cedok5hy5vnpxmsj7" CACHE PATH "") -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-kaem7te2437otmrrjhzhfclcq6j77pke" CACHE PATH "") +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-2gq3ddrhfxqlgzr6zxbvmwpzvtqxqj25" CACHE PATH "") # scr not built #------------------------------------------------------------------------------ -# Devtools +# Devtools & Python #------------------------------------------------------------------------------ -set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37" CACHE PATH "") +set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14" CACHE PATH "") set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/clang/clang-19.1.3/bin/clang-format" CACHE PATH "") -set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/python3" CACHE PATH "") +set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/python3" CACHE PATH "") -set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/jsonschema" CACHE PATH "") +set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/jsonschema" CACHE PATH "") set(ENABLE_DOCS ON CACHE BOOL "") -set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/sphinx-build" CACHE PATH "") +set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/sphinx-build" CACHE PATH "") + +set(YAPF_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/yapf" CACHE PATH "") set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0/bin/shroud" CACHE PATH "") -set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-d2tmb7ls2d5vgh6vhcyohecwcu6msopb/bin/cppcheck" CACHE PATH "") +set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-i3p56kpf66xzj4wm5kfqxyc4vgox7gb3/bin/cppcheck" CACHE PATH "") -set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/doxygen-1.13.2/bin/doxygen" CACHE PATH "") +set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/doxygen-1.15.0/bin/doxygen" CACHE PATH "") diff --git a/host-configs/rzwhippet-toss_4_x86_64_ib-llvm@19.1.3.cmake b/host-configs/rzwhippet-toss_4_x86_64_ib-llvm@19.1.3.cmake index 445a851454..72b4bda224 100644 --- a/host-configs/rzwhippet-toss_4_x86_64_ib-llvm@19.1.3.cmake +++ b/host-configs/rzwhippet-toss_4_x86_64_ib-llvm@19.1.3.cmake @@ -4,28 +4,28 @@ # CMake executable path: /usr/tce/packages/cmake/cmake-3.26.3/bin/cmake #------------------------------------------------------------------------------ -set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/blt-develop-lv6kxkbht6tnhkesyvxpn4co7wh7yqkx;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/c2c-1.8.0-jcvyunoextaorp7eqlrec6s53cnlm7cn;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-u5dbyica2utd23dhlivu3xlu5jm4kz5f;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/conduit-0.9.5-dmle6tliomp27z2usvm22ukviomsvezy;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/mfem-4.9.0-qho2znbjhj2le6bbtw7vu6u3xsum2pc3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/opencascade-7.8.1-fwujcloxwvdjk22xrygpdpswx4tkp3u4;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-tk6vqmvsga2oebnzgilq4lz57xuafkqz;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/scr-3.0.1-cgbl5sb7kix2siwcwv57xzkry6kgssgl;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-szryy27okevlutgru2jtvaflqbw6rgax;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/adiak-0.4.0-t7ws2osd4v4fd3bffvzozbcq6gqdlf2i;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/libunwind-1.8.3-222s6ifq5wyaudy7h43urrshydfjig3q;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/hdf5-1.8.23-lw4obzkj7og4qegzmwizuxvotpz4lkot;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/parmetis-4.0.3-muygwq5u7gusmbn24red6rvpwbxck6l5;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/hypre-2.27.0-gk6f6jl4mtsegkjobf3lf4n74fmfcdbf;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/none-none/glx-1.4-a2eq27mib3shdyabgdpesg3jadr34yho;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/tcl-8.6.17-ouu2hfwmzya4w3xjd6ngexnntldlztob;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/axl-0.7.1-bnrhlub5ov4zupowegt5eguglxs5plz6;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/dtcmp-1.1.5-t25ihiw2whyfjbuyc5kbxapiscvs5wh3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/er-0.3.0-nkyqbtlnwzhuzww6lvyqdqkyew6xzub4;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/libyogrt-1.35-yhzbg7kgssgtbrp7hkzes5la3jmqyaxi;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/spath-0.2.0-4arh7twlqiyc6cvxa6i627bhvj32va76;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-z32b7c752x5r4p2fgji5rfhxbqyltuws;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/fmt-11.0.2-g4qwjp4qo7vxtvq3zijosapcbpnf6zja;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/metis-5.1.0-xzd22iguknjmsctpcvgd5blzwx6aq6wd;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/lwgrp-1.0.6-vts7nmjhqaqzp2uqcwqs5tl32ml6rpae;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/redset-0.2.0-6ynap7s37t2x46ykj75s7yssdadxa7g5;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/shuffile-0.2.0-q3lg5hzi5gfpwxipsq7uceo7oqkjgy5v;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/none-none/gcc-runtime-13.3.1-k43mnfzd4ehqvovn4d5qq7b5f6sfetsx;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/rankstr-0.2.0-nf3ih7rxaa4dfgqe5wujoxdtipfmqdld;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/kvtree-1.3.0-e2usbkamf4ies6sntmnlwtu2nzkltqgh;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5;/usr/tce/packages/cmake/cmake-3.26.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/gcc-13.3.1/cppcheck-2.18.0-d2tmb7ls2d5vgh6vhcyohecwcu6msopb;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/doxygen-1.13.2;/usr/tce/packages/gcc/gcc-13.3.1;/usr/tce/packages/clang/clang-19.1.3;/usr/tce/packages/mvapich2/mvapich2-2.3.7-clang-19.1.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5" CACHE STRING "") +set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/blt-0.7.1-577uis2w7b3ipf4v4v6y6vogmy52d6ay;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/c2c-1.8.0-pk3z5zabg2gtkur2c4mqzc5zz7z5f2tv;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-b7lmqorkofkrib5foi4fzbvd3eh2tbkj;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/conduit-0.9.5-gracxngtjim7b6zjsb5z4kf7qk347eo2;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/mfem-4.9.0-yseuuwvugp6qd45xmxp3ok67ibvfzkff;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/opencascade-7.8.1-6fd4qesv7tghklsteqoqe2mbvayuwgsa;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/py-nanobind-2.7.0-6akjhhlga6h3jx75swovfvo76k6rw6fp;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/py-pytest-9.0.0-vozuj6nkk42nhxeo5mawnux3w7bj3awe;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-7e5u3r4qt7erhbp67xbqnywbgobidj54;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/scr-3.0.1-t3vscu7yv2wkvgff46iwigx6fof72kws;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/umpire-2025.12.0-zbrxcsg5vgv63mpro6ar2rhm7ejx24h5;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/adiak-0.4.0-27bezbcpd5jxnvs65h3m6u2aheplxbmv;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/libunwind-1.8.3-ddv7ypujzw2wvlzabw3d42qygcbtofuq;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/hdf5-1.8.23-b37o2ze3w5sozwz6jmalg4pgg66jcogm;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/parmetis-4.0.3-slhcesf5fhsucwxtlxxana67jcrligfy;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/py-numpy-2.4.2-7qsjxyuuh7rh5hccdziewhwqymkmepb3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/hypre-2.27.0-qkqgpzdh6t7s2pakhss6qnikhwfltykn;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/glx-1.4-4kahrsr5vciz372vpdvlmvxahspecwif;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/tcl-8.6.17-yk7vfdrbz2n7cr2mc3j33ehvukl3kkbz;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/axl-0.7.1-pbcj3g7dqmuiogpb2mawnyuqiyng2vh7;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/dtcmp-1.1.5-cto5znftnfq2kdwpunaegg6trpraj4ke;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/er-0.3.0-4xpuy3lnjbc5ii2peposyxlve7exzijq;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/libyogrt-1.35-n3wzi44wyx5i63jyrn7mozyiec6nake3;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/spath-0.2.0-owqpu5cpinfj56adgrwimokhecl37hdp;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-ck62ywjq7i3hn5utmvio42ifdegjxgma;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/fmt-11.0.2-uougkyc3rcyd7punvwjtcme2zlhehpgz;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/metis-5.1.0-3jeshrn7tydsgn5zdkf3iirdhw3u3oeq;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/lwgrp-1.0.6-fvf5w43ygbspsrft2gbc4tbrgamobo6n;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/redset-0.2.0-ou4lf63bu5chfljcdkaot6feubhmedoh;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/shuffile-0.2.0-mbm3htxivpgso6ogxf5jzdsjhzwqltnm;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/gcc-runtime-13.3.1-zsobnkwck2glzcbukupgvgbiwwhdonys;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/rankstr-0.2.0-5a5trmqremlbnqljjn6u7cqndylpzuhw;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/kvtree-1.3.0-hoxrqia25kplgu63o6275e3phsxgldfr;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11;/usr/tce/packages/cmake/cmake-3.26.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/gcc-13.3.1/cppcheck-2.18.0-i3p56kpf66xzj4wm5kfqxyc4vgox7gb3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/doxygen-1.15.0;/usr/tce/packages/gcc/gcc-13.3.1;/usr/tce/packages/clang/clang-19.1.3;/usr/tce/packages/mvapich2/mvapich2-2.3.7-clang-19.1.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11" CACHE STRING "") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") -set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/axom-develop-cwpovyigrpt4mshzw4qudrdthxkva3af/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/axom-develop-cwpovyigrpt4mshzw4qudrdthxkva3af/lib64;;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/llvm-19.1.3-gy2lu5xbi4csr2k47emlajzfs5mlsd4g/lib/x86_64-unknown-linux-gnu;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13;/usr/tce/packages/clang/clang-19.1.3/lib;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/axom-develop-k6ul4e5lvhjk7rvfh2yfz7xncpqxktcq/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/axom-develop-k6ul4e5lvhjk7rvfh2yfz7xncpqxktcq/lib64;;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/llvm-19.1.3-gy2lu5xbi4csr2k47emlajzfs5mlsd4g/lib/x86_64-unknown-linux-gnu;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13;/usr/tce/packages/clang/clang-19.1.3/lib;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") -set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/axom-develop-cwpovyigrpt4mshzw4qudrdthxkva3af/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3/axom-develop-cwpovyigrpt4mshzw4qudrdthxkva3af/lib64;;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/llvm-19.1.3-gy2lu5xbi4csr2k47emlajzfs5mlsd4g/lib/x86_64-unknown-linux-gnu;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13;/usr/tce/packages/clang/clang-19.1.3/lib;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/axom-develop-k6ul4e5lvhjk7rvfh2yfz7xncpqxktcq/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3/axom-develop-k6ul4e5lvhjk7rvfh2yfz7xncpqxktcq/lib64;;/usr/tce/backend/installations/linux-rhel8-x86_64/gcc-13.3.1/llvm-19.1.3-gy2lu5xbi4csr2k47emlajzfs5mlsd4g/lib/x86_64-unknown-linux-gnu;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13;/usr/tce/packages/clang/clang-19.1.3/lib;/collab/usr/global/tools/tce4/packages/gcc/gcc-13.3.1/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") #------------------------------------------------------------------------------ # Compilers #------------------------------------------------------------------------------ -# Compiler Spec: llvm@19.1.3/dks2hxs7zxd55vu4lwnrychk52n73agw +# Compiler Spec: llvm@19.1.3/4rf6d7atkulu6wz7bucycjwtiuwqfy24 #------------------------------------------------------------------------------ if(DEFINED ENV{SPACK_CC}) - set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/clang/clang" CACHE PATH "") + set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/clang/clang" CACHE PATH "") - set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/clang/clang++" CACHE PATH "") + set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/clang/clang++" CACHE PATH "") - set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/none-none/compiler-wrapper-1.0-32dgmtd4fhqezj4ib4pbwjnwrxcuzxs7/libexec/spack/gcc/gfortran" CACHE PATH "") + set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/compiler-wrapper-1.0-uesxbqunebynqp5g2i6r3corj4oval5q/libexec/spack/gcc/gfortran" CACHE PATH "") else() @@ -75,72 +75,84 @@ set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") # TPLs #------------------------------------------------------------------------------ -set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_01_29_13_39_33/llvm-19.1.3" CACHE PATH "") +set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/llvm-19.1.3" CACHE PATH "") -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-dmle6tliomp27z2usvm22ukviomsvezy" CACHE PATH "") +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-gracxngtjim7b6zjsb5z4kf7qk347eo2" CACHE PATH "") -set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-jcvyunoextaorp7eqlrec6s53cnlm7cn" CACHE PATH "") +set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-pk3z5zabg2gtkur2c4mqzc5zz7z5f2tv" CACHE PATH "") -set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-qho2znbjhj2le6bbtw7vu6u3xsum2pc3" CACHE PATH "") +set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-yseuuwvugp6qd45xmxp3ok67ibvfzkff" CACHE PATH "") -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-lw4obzkj7og4qegzmwizuxvotpz4lkot" CACHE PATH "") +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-b37o2ze3w5sozwz6jmalg4pgg66jcogm" CACHE PATH "") set(LUA_DIR "/usr" CACHE PATH "") -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-tk6vqmvsga2oebnzgilq4lz57xuafkqz" CACHE PATH "") +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-7e5u3r4qt7erhbp67xbqnywbgobidj54" CACHE PATH "") -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-szryy27okevlutgru2jtvaflqbw6rgax" CACHE PATH "") +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-zbrxcsg5vgv63mpro6ar2rhm7ejx24h5" CACHE PATH "") -set(OPENCASCADE_DIR "${TPL_ROOT}/opencascade-7.8.1-fwujcloxwvdjk22xrygpdpswx4tkp3u4" CACHE PATH "") +set(OPENCASCADE_DIR "${TPL_ROOT}/opencascade-7.8.1-6fd4qesv7tghklsteqoqe2mbvayuwgsa" CACHE PATH "") -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-t7ws2osd4v4fd3bffvzozbcq6gqdlf2i" CACHE PATH "") +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-27bezbcpd5jxnvs65h3m6u2aheplxbmv" CACHE PATH "") -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-u5dbyica2utd23dhlivu3xlu5jm4kz5f" CACHE PATH "") +set(CALIPER_DIR "${TPL_ROOT}/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-b7lmqorkofkrib5foi4fzbvd3eh2tbkj" CACHE PATH "") -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-z32b7c752x5r4p2fgji5rfhxbqyltuws" CACHE PATH "") +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-ck62ywjq7i3hn5utmvio42ifdegjxgma" CACHE PATH "") -set(SCR_DIR "${TPL_ROOT}/scr-3.0.1-cgbl5sb7kix2siwcwv57xzkry6kgssgl" CACHE PATH "") +set(SCR_DIR "${TPL_ROOT}/scr-3.0.1-t3vscu7yv2wkvgff46iwigx6fof72kws" CACHE PATH "") -set(KVTREE_DIR "${TPL_ROOT}/kvtree-1.3.0-e2usbkamf4ies6sntmnlwtu2nzkltqgh" CACHE PATH "") +set(KVTREE_DIR "${TPL_ROOT}/kvtree-1.3.0-hoxrqia25kplgu63o6275e3phsxgldfr" CACHE PATH "") -set(DTCMP_DIR "${TPL_ROOT}/dtcmp-1.1.5-t25ihiw2whyfjbuyc5kbxapiscvs5wh3" CACHE PATH "") +set(DTCMP_DIR "${TPL_ROOT}/dtcmp-1.1.5-cto5znftnfq2kdwpunaegg6trpraj4ke" CACHE PATH "") -set(SPATH_DIR "${TPL_ROOT}/spath-0.2.0-4arh7twlqiyc6cvxa6i627bhvj32va76" CACHE PATH "") +set(SPATH_DIR "${TPL_ROOT}/spath-0.2.0-owqpu5cpinfj56adgrwimokhecl37hdp" CACHE PATH "") -set(AXL_DIR "${TPL_ROOT}/axl-0.7.1-bnrhlub5ov4zupowegt5eguglxs5plz6" CACHE PATH "") +set(AXL_DIR "${TPL_ROOT}/axl-0.7.1-pbcj3g7dqmuiogpb2mawnyuqiyng2vh7" CACHE PATH "") -set(LWGRP_DIR "${TPL_ROOT}/lwgrp-1.0.6-vts7nmjhqaqzp2uqcwqs5tl32ml6rpae" CACHE PATH "") +set(LWGRP_DIR "${TPL_ROOT}/lwgrp-1.0.6-fvf5w43ygbspsrft2gbc4tbrgamobo6n" CACHE PATH "") -set(ER_DIR "${TPL_ROOT}/er-0.3.0-nkyqbtlnwzhuzww6lvyqdqkyew6xzub4" CACHE PATH "") +set(ER_DIR "${TPL_ROOT}/er-0.3.0-4xpuy3lnjbc5ii2peposyxlve7exzijq" CACHE PATH "") -set(RANKSTR_DIR "${TPL_ROOT}/rankstr-0.2.0-nf3ih7rxaa4dfgqe5wujoxdtipfmqdld" CACHE PATH "") +set(RANKSTR_DIR "${TPL_ROOT}/rankstr-0.2.0-5a5trmqremlbnqljjn6u7cqndylpzuhw" CACHE PATH "") -set(REDSET_DIR "${TPL_ROOT}/redset-0.2.0-6ynap7s37t2x46ykj75s7yssdadxa7g5" CACHE PATH "") +set(REDSET_DIR "${TPL_ROOT}/redset-0.2.0-ou4lf63bu5chfljcdkaot6feubhmedoh" CACHE PATH "") -set(SHUFFILE_DIR "${TPL_ROOT}/shuffile-0.2.0-q3lg5hzi5gfpwxipsq7uceo7oqkjgy5v" CACHE PATH "") +set(SHUFFILE_DIR "${TPL_ROOT}/shuffile-0.2.0-mbm3htxivpgso6ogxf5jzdsjhzwqltnm" CACHE PATH "") -set(LIBYOGRT_DIR "${TPL_ROOT}/libyogrt-1.35-yhzbg7kgssgtbrp7hkzes5la3jmqyaxi" CACHE PATH "") +set(LIBYOGRT_DIR "${TPL_ROOT}/libyogrt-1.35-n3wzi44wyx5i63jyrn7mozyiec6nake3" CACHE PATH "") #------------------------------------------------------------------------------ -# Devtools +# Devtools & Python #------------------------------------------------------------------------------ -set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37" CACHE PATH "") +set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14" CACHE PATH "") set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/clang/clang-19.1.3/bin/clang-format" CACHE PATH "") -set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/python3" CACHE PATH "") +set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/python3" CACHE PATH "") -set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/jsonschema" CACHE PATH "") +set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/jsonschema" CACHE PATH "") set(ENABLE_DOCS ON CACHE BOOL "") -set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/python-3.13.5/bin/sphinx-build" CACHE PATH "") +set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/sphinx-build" CACHE PATH "") + +set(YAPF_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/python-3.13.11/bin/yapf" CACHE PATH "") set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib/shroud-0.14.0/bin/shroud" CACHE PATH "") -set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-d2tmb7ls2d5vgh6vhcyohecwcu6msopb/bin/cppcheck" CACHE PATH "") +set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-i3p56kpf66xzj4wm5kfqxyc4vgox7gb3/bin/cppcheck" CACHE PATH "") + +set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/kky5oskfhacihjb5gpy7qkeh6edlrtcb/doxygen-1.15.0/bin/doxygen" CACHE PATH "") + +set(PY_NANOBIND_DIR "${TPL_ROOT}/py-nanobind-2.7.0-6akjhhlga6h3jx75swovfvo76k6rw6fp/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PYTEST_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/py-pytest-9.0.0-vozuj6nkk42nhxeo5mawnux3w7bj3awe/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_NUMPY_DIR "${TPL_ROOT}/py-numpy-2.4.2-7qsjxyuuh7rh5hccdziewhwqymkmepb3/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PLUGGY_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/py-pluggy-1.6.0-6zab4pck6v7johubbhalr2waowbwpjei/lib/python3.13/site-packages" CACHE PATH "") -set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/qoeiu74kfjckl7xkcpsbmskffr2fq2tm/doxygen-1.13.2/bin/doxygen" CACHE PATH "") +set(PY_INICONFIG_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib/2026_03_10_09_31_34/none-none/py-iniconfig-2.1.0-xwmbxuhk2oo3dcuizdp3z4hqbpqykkom/lib/python3.13/site-packages" CACHE PATH "") diff --git a/host-configs/tioga-toss_4_x86_64_ib_cray-cce@20.0.0_hip.cmake b/host-configs/tioga-toss_4_x86_64_ib_cray-cce@20.0.0_hip.cmake index 9029447f56..480fd4ea6f 100644 --- a/host-configs/tioga-toss_4_x86_64_ib_cray-cce@20.0.0_hip.cmake +++ b/host-configs/tioga-toss_4_x86_64_ib_cray-cce@20.0.0_hip.cmake @@ -4,28 +4,28 @@ # CMake executable path: /usr/tce/packages/cmake/cmake-3.29.2/bin/cmake #------------------------------------------------------------------------------ -set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/cce-20.0.0/blt-develop-wnndhcj7j3uzrcmwcxxx7we6ao67ufx6;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/cce-20.0.0/c2c-1.8.0-uoyu6oaj5hm3akm7uyeaxpbhmshokbev;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/cce-20.0.0/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-5yccw5nektleedjvs5wectfxu7nj6fjd;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/cce-20.0.0/conduit-0.9.5-2dh3uvquzycowlp4ffz4aazgwkbizs7y;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/cce-20.0.0/lua-5.4.6-3vgz4w7orr6iwf4sqasvbuagpxwz6jbt;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/cce-20.0.0/mfem-4.9.0-73j7czkpuzzntx5ol3kz6yvhnixn63hz;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/cce-20.0.0/adiak-0.4.0-vl5b2qb7dwqt7hcmxqwnerfdsv6ezg2h;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/cce-20.0.0/libunwind-1.8.3-oaadmxe4ydkatoq56yo2fsmd3ijyttku;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/cce-20.0.0/hdf5-1.8.23-v3nnkt4hslj6z2h5d2va4nvmvaycwmuq;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/cce-20.0.0/parmetis-4.0.3-5jtv4smgso6jym3j55xgzzrhnh3vq2y5;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/cce-20.0.0/hypre-2.27.0-nlgayafg7nyxle3wg42oi5x6a7asif55;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/cce-20.0.0/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-7wckscp7eaotkpptzlsjvtqztu6piavq;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/cce-20.0.0/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-lpwqfmyudwe4hgcg2fngwu5c7oqh2257;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/cce-20.0.0/zlib-1.3.1-diuhkgywdfo2546izxh4uu3g7salnkr6;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/cce-20.0.0/metis-5.1.0-7mfvit6c5hknzy6jz6uqpthklg5h3ec7;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/cce-20.0.0/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-z6tknzstevaqveilm3uslpw7a7k7nuf7;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/cce-20.0.0/fmt-11.0.2-pzwzhrpfhytmmcetg6bogh3zdod2ss3j;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/usr/tce/packages/cce-tce/cce-20.0.0;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.2-cce-20.0.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/doxygen-1.13.2;/opt/rocm-6.4.2;/opt/rocm-6.4.2;/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm;/opt/rocm-6.4.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/opt/rocm-6.4.2;/opt/rocm-6.4.2;/opt/rocm-6.4.2" CACHE STRING "") +set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0/blt-0.7.1-tj6h3jr6fjdlxux2yd4wvdy7xwxxuh23;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0/c2c-1.8.0-xav3pjepsvpzrcqd5dcom4is4rioejzr;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-37ef6g3godgxug45i3u3x26awgovbhxa;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0/conduit-0.9.5-oyjekm66om6cx7yndhpv3yumtxgaaroi;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0/lua-5.4.8-ty6vxrgtb5lsthp7rrcy7vx3x4yknrms;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0/mfem-4.9.0-qb5a5xcb5sx6mjeqqsuhxifqeikegol3;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0/py-nanobind-2.7.0-h7v5ggotyqa5ul7kpyc2yfojjkah4ium;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/py-pytest-9.0.0-dn2hwdtaqec2dkxtx7bnvykyxacfdagj;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0/adiak-0.4.0-w7lj246x4whjefszgyhapkebe3cjd7bi;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0/libunwind-1.8.3-htd47rshpgaa6w73jemf7tycnnlkn5ws;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0/hdf5-1.8.23-vy4rnk6awhcfgte2wuwisgp3t3y4gzwy;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0/parmetis-4.0.3-jqlganykrtm62xb3ve2eetb3gltn5nki;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0/py-numpy-2.4.2-vdrslpslcsdjba3zyryp27z4tmpn3ayu;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0/hypre-2.27.0-gjrhbi2v66y2yfxgq7vegqpcawo2b35r;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-mraqiovyi37bfdy7d3cpssvqibljl3rs;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0/umpire-2025.12.0-wvhebyygqkj3vxwm6quu3rxnzjnvwjix;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0/zlib-1.3.1-6yddik2qxvkwtfcckdhbdgos7awok5za;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0/metis-5.1.0-bryzqxg7sgprevvt3ux5np2uxam4wbvp;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-s7ova7cnq6ibqaoxniya4loizwha2g3p;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0/fmt-11.0.2-vjndv6co4e6qonqazcmklw3pamvmos74;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/usr/tce/packages/cce-tce/cce-20.0.0;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/doxygen-1.15.0;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm;/opt/rocm-6.4.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/opt/rocm-6.4.3" CACHE STRING "") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") -set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/cce-20.0.0/axom-develop-pn7byon4z73u2dxiyqt5bhdft7fidrkk/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/cce-20.0.0/axom-develop-pn7byon4z73u2dxiyqt5bhdft7fidrkk/lib64;;/opt/cray/pe/cce/20.0.0/cce/x86_64/lib;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0/axom-develop-qs7aomrdxkidtsbjs23bs7ou7kg37qya/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0/axom-develop-qs7aomrdxkidtsbjs23bs7ou7kg37qya/lib64;;/opt/cray/pe/cce/20.0.0/cce/x86_64/lib;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") -set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/cce-20.0.0/axom-develop-pn7byon4z73u2dxiyqt5bhdft7fidrkk/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/cce-20.0.0/axom-develop-pn7byon4z73u2dxiyqt5bhdft7fidrkk/lib64;;/opt/cray/pe/cce/20.0.0/cce/x86_64/lib;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0/axom-develop-qs7aomrdxkidtsbjs23bs7ou7kg37qya/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0/axom-develop-qs7aomrdxkidtsbjs23bs7ou7kg37qya/lib64;;/opt/cray/pe/cce/20.0.0/cce/x86_64/lib;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") #------------------------------------------------------------------------------ # Compilers #------------------------------------------------------------------------------ -# Compiler Spec: cce@20.0.0/qaj3yb2lw3bg5iz34y3j54ip4ngiyxf5 +# Compiler Spec: cce@20.0.0/v7nrkimihxta4odatu45wrllosgeklrd #------------------------------------------------------------------------------ if(DEFINED ENV{SPACK_CC}) - set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6/libexec/spack/cce/craycc" CACHE PATH "") + set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf/libexec/spack/cce/craycc" CACHE PATH "") - set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6/libexec/spack/cce/case-insensitive/crayCC" CACHE PATH "") + set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf/libexec/spack/cce/case-insensitive/crayCC" CACHE PATH "") - set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6/libexec/spack/cce/crayftn" CACHE PATH "") + set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf/libexec/spack/cce/crayftn" CACHE PATH "") else() @@ -47,11 +47,11 @@ set(CMAKE_CXX_FLAGS_DEBUG "-O1 -g" CACHE STRING "") # MPI #------------------------------------------------------------------------------ -set(MPI_C_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.2-cce-20.0.0/bin/mpicc" CACHE PATH "") +set(MPI_C_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.3/bin/mpicc" CACHE PATH "") -set(MPI_CXX_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.2-cce-20.0.0/bin/mpicxx" CACHE PATH "") +set(MPI_CXX_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.3/bin/mpicxx" CACHE PATH "") -set(MPI_Fortran_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.2-cce-20.0.0/bin/mpif90" CACHE PATH "") +set(MPI_Fortran_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.3/bin/mpif90" CACHE PATH "") set(MPIEXEC_EXECUTABLE "/usr/global/tools/flux_wrappers/bin/srun" CACHE PATH "") @@ -67,11 +67,11 @@ set(ENABLE_MPI ON CACHE BOOL "") # ROCm #------------------------------------------------ -set(ROCM_PATH "/opt/rocm-6.4.2" CACHE PATH "") +set(ROCM_PATH "/opt/rocm-6.4.3" CACHE PATH "") set(CMAKE_HIP_ARCHITECTURES "gfx90a;gfx942" CACHE STRING "") -set(CMAKE_HIP_COMPILER "/opt/rocm-6.4.2/bin/amdclang++" CACHE FILEPATH "") +set(CMAKE_HIP_COMPILER "/opt/rocm-6.4.3/bin/amdclang++" CACHE FILEPATH "") #------------------------------------------------------------------------------ @@ -82,11 +82,11 @@ set(CMAKE_HIP_COMPILER "/opt/rocm-6.4.2/bin/amdclang++" CACHE FILEPATH "") set(ENABLE_HIP ON CACHE BOOL "") -set(ROCM_ROOT_DIR "/opt/rocm-6.4.2" CACHE PATH "") +set(ROCM_ROOT_DIR "/opt/rocm-6.4.3" CACHE PATH "") set(BLT_CMAKE_IMPLICIT_LINK_LIBRARIES_EXCLUDE "unwind" CACHE STRING "") -set(CMAKE_EXE_LINKER_FLAGS "-lxpmem -L/opt/cray/pe/mpich/8.1.32/gtl/lib -Wl,-rpath,/opt/cray/pe/mpich/8.1.32/gtl/lib -lmpi_gtl_hsa -L/opt/rocm-6.4.2/lib/llvm/lib -Wl,-rpath,/opt/rocm-6.4.2/lib/llvm/lib -L/opt/rocm-6.4.2/lib -Wl,-rpath,/opt/rocm-6.4.2/lib -lpgmath -lompstub -L/opt/cray/pe/cce/20.0.0/cce/x86_64/lib -Wl,-rpath,/opt/cray/pe/cce/20.0.0/cce/x86_64/lib -lamdhip64 -lhsakmt -lhsa-runtime64 -lamd_comgr " CACHE STRING "") +set(CMAKE_EXE_LINKER_FLAGS "-lxpmem -L/opt/cray/pe/mpich/8.1.32/gtl/lib -Wl,-rpath,/opt/cray/pe/mpich/8.1.32/gtl/lib -lmpi_gtl_hsa -L/opt/rocm-6.4.3/lib/llvm/lib -Wl,-rpath,/opt/rocm-6.4.3/lib/llvm/lib -L/opt/rocm-6.4.3/lib -Wl,-rpath,/opt/rocm-6.4.3/lib -lpgmath -lompstub -L/opt/cray/pe/cce/20.0.0/cce/x86_64/lib -Wl,-rpath,/opt/cray/pe/cce/20.0.0/cce/x86_64/lib -lamdhip64 -lhsakmt -lhsa-runtime64 -lamd_comgr " CACHE STRING "") #------------------------------------------------ # Hardware Specifics @@ -100,52 +100,64 @@ set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") # TPLs #------------------------------------------------------------------------------ -set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/cce-20.0.0" CACHE PATH "") +set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/cce-20.0.0" CACHE PATH "") -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-2dh3uvquzycowlp4ffz4aazgwkbizs7y" CACHE PATH "") +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-oyjekm66om6cx7yndhpv3yumtxgaaroi" CACHE PATH "") -set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-uoyu6oaj5hm3akm7uyeaxpbhmshokbev" CACHE PATH "") +set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-xav3pjepsvpzrcqd5dcom4is4rioejzr" CACHE PATH "") -set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-73j7czkpuzzntx5ol3kz6yvhnixn63hz" CACHE PATH "") +set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-qb5a5xcb5sx6mjeqqsuhxifqeikegol3" CACHE PATH "") -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-v3nnkt4hslj6z2h5d2va4nvmvaycwmuq" CACHE PATH "") +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-vy4rnk6awhcfgte2wuwisgp3t3y4gzwy" CACHE PATH "") -set(LUA_DIR "${TPL_ROOT}/lua-5.4.6-3vgz4w7orr6iwf4sqasvbuagpxwz6jbt" CACHE PATH "") +set(LUA_DIR "${TPL_ROOT}/lua-5.4.8-ty6vxrgtb5lsthp7rrcy7vx3x4yknrms" CACHE PATH "") -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-7wckscp7eaotkpptzlsjvtqztu6piavq" CACHE PATH "") +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-mraqiovyi37bfdy7d3cpssvqibljl3rs" CACHE PATH "") -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-lpwqfmyudwe4hgcg2fngwu5c7oqh2257" CACHE PATH "") +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-wvhebyygqkj3vxwm6quu3rxnzjnvwjix" CACHE PATH "") # OPENCASCADE not built -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-vl5b2qb7dwqt7hcmxqwnerfdsv6ezg2h" CACHE PATH "") +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-w7lj246x4whjefszgyhapkebe3cjd7bi" CACHE PATH "") -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-5yccw5nektleedjvs5wectfxu7nj6fjd" CACHE PATH "") +set(CALIPER_DIR "${TPL_ROOT}/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-37ef6g3godgxug45i3u3x26awgovbhxa" CACHE PATH "") -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-z6tknzstevaqveilm3uslpw7a7k7nuf7" CACHE PATH "") +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-s7ova7cnq6ibqaoxniya4loizwha2g3p" CACHE PATH "") # scr not built #------------------------------------------------------------------------------ -# Devtools +# Devtools & Python #------------------------------------------------------------------------------ -set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48" CACHE PATH "") +set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25" CACHE PATH "") -set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm/bin/clang-format" CACHE PATH "") +set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm/bin/clang-format" CACHE PATH "") -set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/python3" CACHE PATH "") +set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/python3" CACHE PATH "") -set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/jsonschema" CACHE PATH "") +set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/jsonschema" CACHE PATH "") set(ENABLE_DOCS ON CACHE BOOL "") -set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/sphinx-build" CACHE PATH "") +set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/sphinx-build" CACHE PATH "") + +set(YAPF_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/yapf" CACHE PATH "") set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0/bin/shroud" CACHE PATH "") -set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w/bin/cppcheck" CACHE PATH "") +set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27/bin/cppcheck" CACHE PATH "") + +set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/doxygen-1.15.0/bin/doxygen" CACHE PATH "") + +set(PY_NANOBIND_DIR "${TPL_ROOT}/py-nanobind-2.7.0-h7v5ggotyqa5ul7kpyc2yfojjkah4ium/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PYTEST_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/py-pytest-9.0.0-dn2hwdtaqec2dkxtx7bnvykyxacfdagj/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_NUMPY_DIR "${TPL_ROOT}/py-numpy-2.4.2-vdrslpslcsdjba3zyryp27z4tmpn3ayu/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PLUGGY_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/py-pluggy-1.6.0-27aoz44dedjxa6j6r6cavpqyqmpknidb/lib/python3.13/site-packages" CACHE PATH "") -set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/doxygen-1.13.2/bin/doxygen" CACHE PATH "") +set(PY_INICONFIG_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/py-iniconfig-2.1.0-7rty7n4wq6kxxrzflm7wbxqzhhc6ph7q/lib/python3.13/site-packages" CACHE PATH "") diff --git a/host-configs/tioga-toss_4_x86_64_ib_cray-llvm-amdgpu@6.3.1_hip.cmake b/host-configs/tioga-toss_4_x86_64_ib_cray-llvm-amdgpu@6.3.1_hip.cmake index ee0062b1cc..8bc3ff8312 100644 --- a/host-configs/tioga-toss_4_x86_64_ib_cray-llvm-amdgpu@6.3.1_hip.cmake +++ b/host-configs/tioga-toss_4_x86_64_ib_cray-llvm-amdgpu@6.3.1_hip.cmake @@ -4,28 +4,28 @@ # CMake executable path: /usr/tce/packages/cmake/cmake-3.29.2/bin/cmake #------------------------------------------------------------------------------ -set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.3.1/blt-develop-oxws57mp7nowwmot45kcl2njcmmyjcvt;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.3.1/c2c-1.8.0-ebatzl653bv653yovk7ea43xh5hpzyk5;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.3.1/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-477jqqgkb3xjq7zd6gtxz52y7yn4hhel;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.3.1/conduit-0.9.5-tzcfvtw7tkmkf2tav77vshtxusfx6xsp;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.3.1/lua-5.4.6-xqptwdk22cg35nkyfarzzqsvcyutlt5p;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.3.1/mfem-4.9.0-2xfwkxykfrycrgvcitrmg7srpnzuoq4i;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.3.1/adiak-0.4.0-jtrpi4k72svl5cinupo27eglfkjlj2kf;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.3.1/libunwind-1.8.3-cgi6mbcxsguzlrbuzxs7f4atpg5advc5;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.3.1/hdf5-1.8.23-dfdnqfyzl7atwcxua2vfpgqs3xnuxyhb;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.3.1/parmetis-4.0.3-e2fwaqx2br2r7sjnk7almoiwifiw2o7r;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.3.1/hypre-2.27.0-7usxyq75lzriudrypbxltays45773ame;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.3.1/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-2xsordp26quuqzzqcxv2ibthgduv23h6;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.3.1/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-ugjgrwqivl7nxmbvxo75ysrzrqsaoxsd;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.3.1/zlib-1.3.1-txqysoethmuy57ski6geeq3xcba6lqio;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.3.1/metis-5.1.0-hmecexgiuulns3lggu6w3hbl4iyt3ncy;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.3.1/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-xw4a6eck2jrxlhcdqudhdwntcmmuhwno;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.3.1/fmt-11.0.2-hdywtafnyeshc5a7wevdqngvdhh7syx4;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/doxygen-1.13.2;/opt/rocm-6.3.1;/opt/rocm-6.3.1;/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm;/opt/rocm-6.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/opt/rocm-6.3.1;/opt/rocm-6.3.1;/opt/rocm-6.3.1" CACHE STRING "") +set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.3.1/adiak-0.4.0-vlugt2gwkx5wzlwudznxg3p2plq76pjq;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.3.1/blt-0.7.1-sv74qxlkpkll7mm6dhfjagyfog254w7c;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.3.1/c2c-1.8.0-tfrrofjzn3rdvyktevespobwrpjai5j4;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.3.1/conduit-0.9.5-vnlbr73jbwhqyvh2q76csdtve3ekpncc;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.3.1/lua-5.4.8-e3i2pbc52bfhrnxbaniektzp3x5jvyxr;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.3.1/mfem-4.9.0-lzyx65dulc7kbahov4m3zy5zsopxpfiz;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.3.1/py-nanobind-2.7.0-4sgpkalsntbmuim5oltb7ue4gggt6rv5;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/py-pytest-9.0.0-dn2hwdtaqec2dkxtx7bnvykyxacfdagj;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.3.1/hdf5-1.8.23-liive5kzeooveetbjhil4ic7hi3ccsg4;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.3.1/parmetis-4.0.3-fiyw3adearn3nmxjifcqtuzwy24fshp5;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.3.1/py-numpy-2.4.2-ij66enxl4hmrmwua5bsec2yslylneqbw;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.3.1/hypre-2.27.0-cnukrpfl32kl5q6ud4wozdqbgtqoo7jx;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.3.1/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-aqopcekt2ikzah5tekoesewfzyexhz4q;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.3.1/umpire-2025.12.0-6jmr57w6t5ctmf4jgyrzb3y2j77a2clz;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.3.1/zlib-1.3.1-dsduxyfnks4bhrkpbskff35l5y36ofp7;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.3.1/metis-5.1.0-6mtxrj6jbrvyd3xpq4pvluywbndjx42w;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.3.1/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-eccm2e7wvkrekpfcvmbu6x3rtnip4oh3;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.3.1/fmt-11.0.2-kw3vpg2ajhrgi7kozhcioz3nrgc6fh3o;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/doxygen-1.15.0;/opt/rocm-6.3.1;/opt/rocm-6.3.1;/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm;/opt/rocm-6.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/opt/rocm-6.3.1;/opt/rocm-6.3.1;/opt/rocm-6.3.1" CACHE STRING "") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") -set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.3.1/axom-develop-jxfd3czjy4m4eilyzg6e6q4nmup5ltvq/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.3.1/axom-develop-jxfd3czjy4m4eilyzg6e6q4nmup5ltvq/lib64;;/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12" CACHE STRING "") +set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.3.1/axom-develop-te7am32fqfkfq6tx6o5arqikygw5j36c/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.3.1/axom-develop-te7am32fqfkfq6tx6o5arqikygw5j36c/lib64;;/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12" CACHE STRING "") -set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.3.1/axom-develop-jxfd3czjy4m4eilyzg6e6q4nmup5ltvq/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.3.1/axom-develop-jxfd3czjy4m4eilyzg6e6q4nmup5ltvq/lib64;;/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12" CACHE STRING "") +set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.3.1/axom-develop-te7am32fqfkfq6tx6o5arqikygw5j36c/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.3.1/axom-develop-te7am32fqfkfq6tx6o5arqikygw5j36c/lib64;;/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") #------------------------------------------------------------------------------ # Compilers #------------------------------------------------------------------------------ -# Compiler Spec: llvm-amdgpu@6.3.1/ewmb23zt2h4lqtnvv6lsha7mdyiucmx3 +# Compiler Spec: llvm-amdgpu@6.3.1/ns2pv5bzkpjolxzmhgkckj6glqymgd7e #------------------------------------------------------------------------------ if(DEFINED ENV{SPACK_CC}) - set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6/libexec/spack/rocmcc/amdclang" CACHE PATH "") + set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf/libexec/spack/rocmcc/amdclang" CACHE PATH "") - set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6/libexec/spack/rocmcc/amdclang++" CACHE PATH "") + set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf/libexec/spack/rocmcc/amdclang++" CACHE PATH "") - set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6/libexec/spack/rocmcc/amdflang" CACHE PATH "") + set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf/libexec/spack/rocmcc/amdflang" CACHE PATH "") else() @@ -96,52 +96,64 @@ set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") # TPLs #------------------------------------------------------------------------------ -set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.3.1" CACHE PATH "") +set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.3.1" CACHE PATH "") -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-tzcfvtw7tkmkf2tav77vshtxusfx6xsp" CACHE PATH "") +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-vnlbr73jbwhqyvh2q76csdtve3ekpncc" CACHE PATH "") -set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-ebatzl653bv653yovk7ea43xh5hpzyk5" CACHE PATH "") +set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-tfrrofjzn3rdvyktevespobwrpjai5j4" CACHE PATH "") -set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-2xfwkxykfrycrgvcitrmg7srpnzuoq4i" CACHE PATH "") +set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-lzyx65dulc7kbahov4m3zy5zsopxpfiz" CACHE PATH "") -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-dfdnqfyzl7atwcxua2vfpgqs3xnuxyhb" CACHE PATH "") +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-liive5kzeooveetbjhil4ic7hi3ccsg4" CACHE PATH "") -set(LUA_DIR "${TPL_ROOT}/lua-5.4.6-xqptwdk22cg35nkyfarzzqsvcyutlt5p" CACHE PATH "") +set(LUA_DIR "${TPL_ROOT}/lua-5.4.8-e3i2pbc52bfhrnxbaniektzp3x5jvyxr" CACHE PATH "") -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-2xsordp26quuqzzqcxv2ibthgduv23h6" CACHE PATH "") +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-aqopcekt2ikzah5tekoesewfzyexhz4q" CACHE PATH "") -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-ugjgrwqivl7nxmbvxo75ysrzrqsaoxsd" CACHE PATH "") +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-6jmr57w6t5ctmf4jgyrzb3y2j77a2clz" CACHE PATH "") # OPENCASCADE not built -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-jtrpi4k72svl5cinupo27eglfkjlj2kf" CACHE PATH "") +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-vlugt2gwkx5wzlwudznxg3p2plq76pjq" CACHE PATH "") -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-477jqqgkb3xjq7zd6gtxz52y7yn4hhel" CACHE PATH "") +# CALIPER not built -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-xw4a6eck2jrxlhcdqudhdwntcmmuhwno" CACHE PATH "") +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-eccm2e7wvkrekpfcvmbu6x3rtnip4oh3" CACHE PATH "") # scr not built #------------------------------------------------------------------------------ -# Devtools +# Devtools & Python #------------------------------------------------------------------------------ -set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48" CACHE PATH "") +set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25" CACHE PATH "") -set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm/bin/clang-format" CACHE PATH "") +set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm/bin/clang-format" CACHE PATH "") -set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/python3" CACHE PATH "") +set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/python3" CACHE PATH "") -set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/jsonschema" CACHE PATH "") +set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/jsonschema" CACHE PATH "") set(ENABLE_DOCS ON CACHE BOOL "") -set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/sphinx-build" CACHE PATH "") +set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/sphinx-build" CACHE PATH "") + +set(YAPF_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/yapf" CACHE PATH "") set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0/bin/shroud" CACHE PATH "") -set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w/bin/cppcheck" CACHE PATH "") +set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27/bin/cppcheck" CACHE PATH "") + +set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/doxygen-1.15.0/bin/doxygen" CACHE PATH "") + +set(PY_NANOBIND_DIR "${TPL_ROOT}/py-nanobind-2.7.0-4sgpkalsntbmuim5oltb7ue4gggt6rv5/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PYTEST_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/py-pytest-9.0.0-dn2hwdtaqec2dkxtx7bnvykyxacfdagj/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_NUMPY_DIR "${TPL_ROOT}/py-numpy-2.4.2-ij66enxl4hmrmwua5bsec2yslylneqbw/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PLUGGY_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/py-pluggy-1.6.0-27aoz44dedjxa6j6r6cavpqyqmpknidb/lib/python3.13/site-packages" CACHE PATH "") -set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/doxygen-1.13.2/bin/doxygen" CACHE PATH "") +set(PY_INICONFIG_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/py-iniconfig-2.1.0-7rty7n4wq6kxxrzflm7wbxqzhhc6ph7q/lib/python3.13/site-packages" CACHE PATH "") diff --git a/host-configs/tioga-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.2_hip.cmake b/host-configs/tioga-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.2_hip.cmake deleted file mode 100644 index b470528d44..0000000000 --- a/host-configs/tioga-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.2_hip.cmake +++ /dev/null @@ -1,147 +0,0 @@ -#------------------------------------------------------------------------------ -# !!!! This is a generated file, edit at own risk !!!! -#------------------------------------------------------------------------------ -# CMake executable path: /usr/tce/packages/cmake/cmake-3.29.2/bin/cmake -#------------------------------------------------------------------------------ - -set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.4.2/blt-develop-cnq3cm7laedurs5er2qsq65tcv4s7mfu;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.4.2/c2c-1.8.0-a6qbglkmvsrujhmz74okbcqhvzrj63m6;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.4.2/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-zfdmahinxufcljoyw75jpmbqsmilzmwn;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.4.2/conduit-0.9.5-tw3svztl6tuwm5xgkxxypth2wfn6uuys;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.4.2/lua-5.4.6-jopsczdu6xr6ynusfj7l36nni44opx7h;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.4.2/mfem-4.9.0-ry7y5nt7vqgwutxe3uo7sqntft5o77mr;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.4.2/adiak-0.4.0-s6y3w26rhudfxlzr24puf5mfo3blrfwt;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.4.2/libunwind-1.8.3-kiiwwsrjhpdtqrqphqi6bawovtjxolu7;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.4.2/hdf5-1.8.23-dwcfr6rmagvx3hwc2ysdat6tc3picboy;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.4.2/parmetis-4.0.3-yaohhh2bhrfqhthfrq5alus5myxwj7qy;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.4.2/hypre-2.27.0-iumqsnzym4ali5rsg7bggfxgeegdfvyi;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.4.2/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-2r6pwgpzaog45cm46dt7sce7a5qiy72i;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.4.2/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-5ipyjuvogd3juoetf26g372fm24wzuca;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.4.2/zlib-1.3.1-66xuh43r6fe5fkdzlb3fpsqju24hbwrx;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.4.2/metis-5.1.0-x5aebxyckgh56retcj4a7iazsy4q7ii2;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.4.2/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-lskwuepv6zzfnhpjgmltqofk5pyf2563;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.4.2/fmt-11.0.2-6qd5wbj47udcjluobpwbcz2f4e3srvpa;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/doxygen-1.13.2;/opt/rocm-6.4.2;/opt/rocm-6.4.2;/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm;/opt/rocm-6.4.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/opt/rocm-6.4.2;/opt/rocm-6.4.2;/opt/rocm-6.4.2" CACHE STRING "") - -set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") - -set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.4.2/axom-develop-hvfs73oy4mppcfpeloamyhi7f3oy5fml/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.4.2/axom-develop-hvfs73oy4mppcfpeloamyhi7f3oy5fml/lib64;;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") - -set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.4.2/axom-develop-hvfs73oy4mppcfpeloamyhi7f3oy5fml/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.4.2/axom-develop-hvfs73oy4mppcfpeloamyhi7f3oy5fml/lib64;;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") - -set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") - -#------------------------------------------------------------------------------ -# Compilers -#------------------------------------------------------------------------------ -# Compiler Spec: llvm-amdgpu@6.4.2/bb2nokv3ui3ksdf4t4xucxqtidlj2ds4 -#------------------------------------------------------------------------------ -if(DEFINED ENV{SPACK_CC}) - - set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6/libexec/spack/rocmcc/amdclang" CACHE PATH "") - - set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6/libexec/spack/rocmcc/amdclang++" CACHE PATH "") - - set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/none-none/compiler-wrapper-1.0-kyc2n3tmqb2nko6gmugf6hu34usl75h6/libexec/spack/rocmcc/amdflang" CACHE PATH "") - -else() - - set(CMAKE_C_COMPILER "/opt/rocm-6.4.2/llvm/bin/amdclang" CACHE PATH "") - - set(CMAKE_CXX_COMPILER "/opt/rocm-6.4.2/llvm/bin/amdclang++" CACHE PATH "") - - set(CMAKE_Fortran_COMPILER "/opt/rocm-6.4.2/llvm/bin/amdflang" CACHE PATH "") - -endif() - -set(CMAKE_Fortran_FLAGS "-Mfreeform" CACHE STRING "") - -set(ENABLE_FORTRAN ON CACHE BOOL "") - -#------------------------------------------------------------------------------ -# MPI -#------------------------------------------------------------------------------ - -set(MPI_C_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.2/bin/mpicc" CACHE PATH "") - -set(MPI_CXX_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.2/bin/mpicxx" CACHE PATH "") - -set(MPI_Fortran_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.2/bin/mpif90" CACHE PATH "") - -set(MPIEXEC_EXECUTABLE "/usr/global/tools/flux_wrappers/bin/srun" CACHE PATH "") - -set(MPIEXEC_NUMPROC_FLAG "-n" CACHE STRING "") - -set(ENABLE_MPI ON CACHE BOOL "") - -#------------------------------------------------------------------------------ -# Hardware -#------------------------------------------------------------------------------ - -#------------------------------------------------ -# ROCm -#------------------------------------------------ - -set(ROCM_PATH "/opt/rocm-6.4.2" CACHE PATH "") - -set(CMAKE_HIP_ARCHITECTURES "gfx90a;gfx942" CACHE STRING "") - -set(CMAKE_HIP_COMPILER "/opt/rocm-6.4.2/bin/amdclang++" CACHE FILEPATH "") - -#------------------------------------------------------------------------------ - -# Axom ROCm specifics - -#------------------------------------------------------------------------------ - - -set(ENABLE_HIP ON CACHE BOOL "") - -set(ROCM_ROOT_DIR "/opt/rocm-6.4.2" CACHE PATH "") - -set(CMAKE_EXE_LINKER_FLAGS "-lxpmem -L/opt/cray/pe/mpich/8.1.29/gtl/lib -Wl,-rpath,/opt/cray/pe/mpich/8.1.29/gtl/lib -lmpi_gtl_hsa -L/opt/rocm-6.4.2/lib/llvm/lib -Wl,-rpath,/opt/rocm-6.4.2/lib/llvm/lib -L/opt/rocm-6.4.2/lib -Wl,-rpath,/opt/rocm-6.4.2/lib -lpgmath -lompstub -Wl,--disable-new-dtags -lflang -lflangrti -lamdhip64 -lhsakmt -lhsa-runtime64 -lamd_comgr " CACHE STRING "") - -#------------------------------------------------ -# Hardware Specifics -#------------------------------------------------ - -set(ENABLE_OPENMP OFF CACHE BOOL "") - -set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") - -#------------------------------------------------------------------------------ -# TPLs -#------------------------------------------------------------------------------ - -set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_04/llvm-amdgpu-6.4.2" CACHE PATH "") - -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-tw3svztl6tuwm5xgkxxypth2wfn6uuys" CACHE PATH "") - -set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-a6qbglkmvsrujhmz74okbcqhvzrj63m6" CACHE PATH "") - -set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-ry7y5nt7vqgwutxe3uo7sqntft5o77mr" CACHE PATH "") - -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-dwcfr6rmagvx3hwc2ysdat6tc3picboy" CACHE PATH "") - -set(LUA_DIR "${TPL_ROOT}/lua-5.4.6-jopsczdu6xr6ynusfj7l36nni44opx7h" CACHE PATH "") - -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-2r6pwgpzaog45cm46dt7sce7a5qiy72i" CACHE PATH "") - -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-5ipyjuvogd3juoetf26g372fm24wzuca" CACHE PATH "") - -# OPENCASCADE not built - -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-s6y3w26rhudfxlzr24puf5mfo3blrfwt" CACHE PATH "") - -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-zfdmahinxufcljoyw75jpmbqsmilzmwn" CACHE PATH "") - -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-lskwuepv6zzfnhpjgmltqofk5pyf2563" CACHE PATH "") - -# scr not built - -#------------------------------------------------------------------------------ -# Devtools -#------------------------------------------------------------------------------ - -set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48" CACHE PATH "") - -set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm/bin/clang-format" CACHE PATH "") - -set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/python3" CACHE PATH "") - -set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/jsonschema" CACHE PATH "") - -set(ENABLE_DOCS ON CACHE BOOL "") - -set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/sphinx-build" CACHE PATH "") - -set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0/bin/shroud" CACHE PATH "") - -set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w/bin/cppcheck" CACHE PATH "") - -set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/doxygen-1.13.2/bin/doxygen" CACHE PATH "") - - diff --git a/host-configs/tioga-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.3_hip.cmake b/host-configs/tioga-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.3_hip.cmake new file mode 100644 index 0000000000..90732cfc93 --- /dev/null +++ b/host-configs/tioga-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.3_hip.cmake @@ -0,0 +1,159 @@ +#------------------------------------------------------------------------------ +# !!!! This is a generated file, edit at own risk !!!! +#------------------------------------------------------------------------------ +# CMake executable path: /usr/tce/packages/cmake/cmake-3.29.2/bin/cmake +#------------------------------------------------------------------------------ + +set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3/blt-0.7.1-2eahqqwjyauupjq3baxftq7kuv3pvdgp;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3/c2c-1.8.0-oxqhr2ybswpnzt74f4iritx263ji3uqy;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-sos5uklbsgaycb776a2ufcyje4y24yls;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3/conduit-0.9.5-cxdq4qnoptjq6lry5asb2bqodvm3zjig;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3/lua-5.4.8-lsey5vgxvpqf5j3xbrlzswrizuwm65vh;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3/mfem-4.9.0-gkcg2u6vl5yur7gvigiut76ckzxo4fry;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3/py-nanobind-2.7.0-3nchqpyclgle5w56it23ozl4ttbnrfjd;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/py-pytest-9.0.0-dn2hwdtaqec2dkxtx7bnvykyxacfdagj;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3/adiak-0.4.0-cbxp6kv6rm4f7oeczuhbplm3yb3zxb6z;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3/libunwind-1.8.3-r4b3cptnf27zp34jbrdtlrf6r6dp6n4l;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3/hdf5-1.8.23-wb7u6epuww3tretkcto7jhq2i7pffimg;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3/parmetis-4.0.3-d6ed2qesb4yprvpetx3fso35rx6amf5b;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3/py-numpy-2.4.2-t7cvohiksz7deeldwxrtqfmahcvanapb;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3/hypre-2.27.0-pxqhlqwksiscco65tsz5somb4ctdq3q2;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-5r3ukxt2ewfn2geqge37ea2fxd7kfixh;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3/umpire-2025.12.0-n4zr37loo2okonovcswffexwi5mbxnxh;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3/zlib-1.3.1-ijxa3tdiibemxtng46hrremmbytl2dqq;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3/metis-5.1.0-mubwzuka5byhpbzmwaxjhtffhst3oj3q;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-k6gr5qtzupytbr5kq2e73qesltauiqcl;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3/fmt-11.0.2-unmvs6vefcyfcfnzlie2eag5i2eib35d;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/doxygen-1.15.0;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm;/opt/rocm-6.4.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/opt/rocm-6.4.3" CACHE STRING "") + +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") + +set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3/axom-develop-2ah5imlo6grdjcijxzmnj65v5lolnzam/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3/axom-develop-2ah5imlo6grdjcijxzmnj65v5lolnzam/lib64;;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") + +set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3/axom-develop-2ah5imlo6grdjcijxzmnj65v5lolnzam/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3/axom-develop-2ah5imlo6grdjcijxzmnj65v5lolnzam/lib64;;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") + +set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") + +#------------------------------------------------------------------------------ +# Compilers +#------------------------------------------------------------------------------ +# Compiler Spec: llvm-amdgpu@6.4.3/u67i6xutdthzl3yti7tv3klyhyzddbkv +#------------------------------------------------------------------------------ +if(DEFINED ENV{SPACK_CC}) + + set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf/libexec/spack/rocmcc/amdclang" CACHE PATH "") + + set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf/libexec/spack/rocmcc/amdclang++" CACHE PATH "") + + set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/compiler-wrapper-1.0-r533h4sr4uzpv32pv2w4ootpawmxmmgf/libexec/spack/rocmcc/amdflang" CACHE PATH "") + +else() + + set(CMAKE_C_COMPILER "/opt/rocm-6.4.3/llvm/bin/amdclang" CACHE PATH "") + + set(CMAKE_CXX_COMPILER "/opt/rocm-6.4.3/llvm/bin/amdclang++" CACHE PATH "") + + set(CMAKE_Fortran_COMPILER "/opt/rocm-6.4.3/llvm/bin/amdflang" CACHE PATH "") + +endif() + +set(CMAKE_Fortran_FLAGS "-Mfreeform" CACHE STRING "") + +set(ENABLE_FORTRAN ON CACHE BOOL "") + +#------------------------------------------------------------------------------ +# MPI +#------------------------------------------------------------------------------ + +set(MPI_C_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.3/bin/mpicc" CACHE PATH "") + +set(MPI_CXX_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.3/bin/mpicxx" CACHE PATH "") + +set(MPI_Fortran_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.3/bin/mpif90" CACHE PATH "") + +set(MPIEXEC_EXECUTABLE "/usr/global/tools/flux_wrappers/bin/srun" CACHE PATH "") + +set(MPIEXEC_NUMPROC_FLAG "-n" CACHE STRING "") + +set(ENABLE_MPI ON CACHE BOOL "") + +#------------------------------------------------------------------------------ +# Hardware +#------------------------------------------------------------------------------ + +#------------------------------------------------ +# ROCm +#------------------------------------------------ + +set(ROCM_PATH "/opt/rocm-6.4.3" CACHE PATH "") + +set(CMAKE_HIP_ARCHITECTURES "gfx90a;gfx942" CACHE STRING "") + +set(CMAKE_HIP_COMPILER "/opt/rocm-6.4.3/bin/amdclang++" CACHE FILEPATH "") + +#------------------------------------------------------------------------------ + +# Axom ROCm specifics + +#------------------------------------------------------------------------------ + + +set(ENABLE_HIP ON CACHE BOOL "") + +set(ROCM_ROOT_DIR "/opt/rocm-6.4.3" CACHE PATH "") + +set(CMAKE_EXE_LINKER_FLAGS "-lxpmem -L/opt/cray/pe/mpich/8.1.29/gtl/lib -Wl,-rpath,/opt/cray/pe/mpich/8.1.29/gtl/lib -lmpi_gtl_hsa -L/opt/rocm-6.4.3/lib/llvm/lib -Wl,-rpath,/opt/rocm-6.4.3/lib/llvm/lib -L/opt/rocm-6.4.3/lib -Wl,-rpath,/opt/rocm-6.4.3/lib -lpgmath -lompstub -Wl,--disable-new-dtags -lflang -lflangrti -lamdhip64 -lhsakmt -lhsa-runtime64 -lamd_comgr " CACHE STRING "") + +#------------------------------------------------ +# Hardware Specifics +#------------------------------------------------ + +set(ENABLE_OPENMP OFF CACHE BOOL "") + +set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") + +#------------------------------------------------------------------------------ +# TPLs +#------------------------------------------------------------------------------ + +set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/llvm-amdgpu-6.4.3" CACHE PATH "") + +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-cxdq4qnoptjq6lry5asb2bqodvm3zjig" CACHE PATH "") + +set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-oxqhr2ybswpnzt74f4iritx263ji3uqy" CACHE PATH "") + +set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-gkcg2u6vl5yur7gvigiut76ckzxo4fry" CACHE PATH "") + +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-wb7u6epuww3tretkcto7jhq2i7pffimg" CACHE PATH "") + +set(LUA_DIR "${TPL_ROOT}/lua-5.4.8-lsey5vgxvpqf5j3xbrlzswrizuwm65vh" CACHE PATH "") + +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-5r3ukxt2ewfn2geqge37ea2fxd7kfixh" CACHE PATH "") + +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-n4zr37loo2okonovcswffexwi5mbxnxh" CACHE PATH "") + +# OPENCASCADE not built + +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-cbxp6kv6rm4f7oeczuhbplm3yb3zxb6z" CACHE PATH "") + +set(CALIPER_DIR "${TPL_ROOT}/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-sos5uklbsgaycb776a2ufcyje4y24yls" CACHE PATH "") + +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-k6gr5qtzupytbr5kq2e73qesltauiqcl" CACHE PATH "") + +# scr not built + +#------------------------------------------------------------------------------ +# Devtools & Python +#------------------------------------------------------------------------------ + +set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25" CACHE PATH "") + +set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm/bin/clang-format" CACHE PATH "") + +set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/python3" CACHE PATH "") + +set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/jsonschema" CACHE PATH "") + +set(ENABLE_DOCS ON CACHE BOOL "") + +set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/sphinx-build" CACHE PATH "") + +set(YAPF_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/yapf" CACHE PATH "") + +set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0/bin/shroud" CACHE PATH "") + +set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27/bin/cppcheck" CACHE PATH "") + +set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/doxygen-1.15.0/bin/doxygen" CACHE PATH "") + +set(PY_NANOBIND_DIR "${TPL_ROOT}/py-nanobind-2.7.0-3nchqpyclgle5w56it23ozl4ttbnrfjd/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PYTEST_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/py-pytest-9.0.0-dn2hwdtaqec2dkxtx7bnvykyxacfdagj/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_NUMPY_DIR "${TPL_ROOT}/py-numpy-2.4.2-t7cvohiksz7deeldwxrtqfmahcvanapb/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PLUGGY_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/py-pluggy-1.6.0-27aoz44dedjxa6j6r6cavpqyqmpknidb/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_INICONFIG_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_10_15_33_36/none-none/py-iniconfig-2.1.0-7rty7n4wq6kxxrzflm7wbxqzhhc6ph7q/lib/python3.13/site-packages" CACHE PATH "") + + diff --git a/host-configs/tuolumne-toss_4_x86_64_ib_cray-cce@20.0.0_hip.cmake b/host-configs/tuolumne-toss_4_x86_64_ib_cray-cce@20.0.0_hip.cmake index 6e75f26637..c9b7bdbb1f 100644 --- a/host-configs/tuolumne-toss_4_x86_64_ib_cray-cce@20.0.0_hip.cmake +++ b/host-configs/tuolumne-toss_4_x86_64_ib_cray-cce@20.0.0_hip.cmake @@ -4,28 +4,28 @@ # CMake executable path: /usr/tce/packages/cmake/cmake-3.29.2/bin/cmake #------------------------------------------------------------------------------ -set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/cce-20.0.0/blt-develop-pwsc32pfi7a4xxama2m7eknfhfjllik6;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/cce-20.0.0/c2c-1.8.0-nu3d5eyh2exon7giv52bcw2e7miwx4ey;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/cce-20.0.0/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-bimrixe6smxyacdb5goo7muovyutiaim;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/cce-20.0.0/conduit-0.9.5-n62sqaudocgfahdhi3xerhjl4cfz4cfm;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/cce-20.0.0/lua-5.4.6-cczerukzth4xrqai22ypclwsaob6oh3m;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/cce-20.0.0/mfem-4.9.0-qptl47hqr27lw4qcnhbti2zk22t3fpw3;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/cce-20.0.0/adiak-0.4.0-c2l2d4bka2a3ik25akjd6a6y5bf2nqor;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/cce-20.0.0/libunwind-1.8.3-m7dgrtoy2hs5hy5c34azf43onj2n7c2t;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/cce-20.0.0/hdf5-1.8.23-sqtvp52fpuxariizrjafw4ineangzmgb;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/cce-20.0.0/parmetis-4.0.3-6jq6nu6qr4ttj7susud47swbrdojss3s;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/cce-20.0.0/hypre-2.27.0-5jl6onx4nq7lkqxbdneoc7knei2gnwb6;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/cce-20.0.0/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-5nzacrth4amewhoeu4msnfbplkljtznz;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/cce-20.0.0/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-l7oioa3ne4kb2idk4r3gmjdqrvecc46c;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/cce-20.0.0/zlib-1.3.1-7dd5r4czl743knbjpnyifcyo3mxlbdoz;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/cce-20.0.0/metis-5.1.0-azn3bxwpfq2zvgapjo6w5pozump6i7e3;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/cce-20.0.0/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-2la2lsbddc2dh5mmtokuupqsoe24s7ip;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/cce-20.0.0/fmt-11.0.2-u3ogj3ypjupkeo6e4pcohtkfod3q2tdm;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/usr/tce/packages/cce-tce/cce-20.0.0;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.2-cce-20.0.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/doxygen-1.13.2;/opt/rocm-6.4.2;/opt/rocm-6.4.2;/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm;/opt/rocm-6.4.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/opt/rocm-6.4.2;/opt/rocm-6.4.2;/opt/rocm-6.4.2" CACHE STRING "") +set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0/blt-0.7.1-af45hpsxdxploxhqqi4irjmy4vz2omqx;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0/c2c-1.8.0-cpdkv2uxkhs3qmzqakt4sht3vuiucdwt;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-wytd46zvuquxg2rqf3zec5ldbmjeaat6;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0/conduit-0.9.5-pbrrhvrsmnewby6q3u35ceppt5fxme2p;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0/lua-5.4.8-y6z3polqakbuhn6nh6muri3rjxqmiioa;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0/mfem-4.9.0-2r7wws3ojiqvv6vk7y3ki443xke656sf;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0/py-nanobind-2.7.0-ieb2bzuz435ydpyiq2uj36yyqjbrffml;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/py-pytest-9.0.0-jfdwo62b3p36blpm54gvocrcj6afccv5;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0/adiak-0.4.0-lzgexbo5qyzepgju2acyy6d2qft443tb;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0/libunwind-1.8.3-zvteigxlopfo5tkdr2n2pglgosg42bah;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0/hdf5-1.8.23-to3lvqwzxrqzad65zbvnbtvyt4k63uxe;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0/parmetis-4.0.3-bajtzsmahjg2wvcjzo5gfb2hr5oj2elc;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0/py-numpy-2.4.2-xw5ysy75zfqlalmbmtl5phd2qip43hlo;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0/hypre-2.27.0-knkmxfbf3xcut2wmamjsmhrqf7u7xmi7;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-y7uevzr5oi5eansgqfm4ppgcdkvnni6t;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0/umpire-2025.12.0-ke2uxlxkv74lvrhujuzh3ktf3c6e7lfb;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0/zlib-1.3.1-f3sdiqmy2whvmdn2fxeol3k7oqwouays;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0/metis-5.1.0-v4d34x7btqhotktvu5bgk4iwk6h2lumb;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-a755kudv24eiizq4thcs2ca2fj7vy65x;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0/fmt-11.0.2-nzzmwf4nofjv46yeugehjo64opvfbbzr;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/usr/tce/packages/cce-tce/cce-20.0.0;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/doxygen-1.15.0;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm;/opt/rocm-6.4.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/opt/rocm-6.4.3" CACHE STRING "") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") -set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/cce-20.0.0/axom-develop-bgariutridspjv7p4wlx3n32b5va2pdl/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/cce-20.0.0/axom-develop-bgariutridspjv7p4wlx3n32b5va2pdl/lib64;;/opt/cray/pe/cce/20.0.0/cce/x86_64/lib;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0/axom-develop-csdbligyshk6zb3emr4vn5sjrrnbtobj/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0/axom-develop-csdbligyshk6zb3emr4vn5sjrrnbtobj/lib64;;/opt/cray/pe/cce/20.0.0/cce/x86_64/lib;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") -set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/cce-20.0.0/axom-develop-bgariutridspjv7p4wlx3n32b5va2pdl/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/cce-20.0.0/axom-develop-bgariutridspjv7p4wlx3n32b5va2pdl/lib64;;/opt/cray/pe/cce/20.0.0/cce/x86_64/lib;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") +set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0/axom-develop-csdbligyshk6zb3emr4vn5sjrrnbtobj/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0/axom-develop-csdbligyshk6zb3emr4vn5sjrrnbtobj/lib64;;/opt/cray/pe/cce/20.0.0/cce/x86_64/lib;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") #------------------------------------------------------------------------------ # Compilers #------------------------------------------------------------------------------ -# Compiler Spec: cce@20.0.0/qaj3yb2lw3bg5iz34y3j54ip4ngiyxf5 +# Compiler Spec: cce@20.0.0/v7nrkimihxta4odatu45wrllosgeklrd #------------------------------------------------------------------------------ if(DEFINED ENV{SPACK_CC}) - set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh/libexec/spack/cce/craycc" CACHE PATH "") + set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd/libexec/spack/cce/craycc" CACHE PATH "") - set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh/libexec/spack/cce/case-insensitive/crayCC" CACHE PATH "") + set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd/libexec/spack/cce/case-insensitive/crayCC" CACHE PATH "") - set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh/libexec/spack/cce/crayftn" CACHE PATH "") + set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd/libexec/spack/cce/crayftn" CACHE PATH "") else() @@ -47,11 +47,11 @@ set(CMAKE_CXX_FLAGS_DEBUG "-O1 -g" CACHE STRING "") # MPI #------------------------------------------------------------------------------ -set(MPI_C_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.2-cce-20.0.0/bin/mpicc" CACHE PATH "") +set(MPI_C_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.3/bin/mpicc" CACHE PATH "") -set(MPI_CXX_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.2-cce-20.0.0/bin/mpicxx" CACHE PATH "") +set(MPI_CXX_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.3/bin/mpicxx" CACHE PATH "") -set(MPI_Fortran_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.2-cce-20.0.0/bin/mpif90" CACHE PATH "") +set(MPI_Fortran_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.3/bin/mpif90" CACHE PATH "") set(MPIEXEC_EXECUTABLE "/usr/global/tools/flux_wrappers/bin/srun" CACHE PATH "") @@ -67,11 +67,11 @@ set(ENABLE_MPI ON CACHE BOOL "") # ROCm #------------------------------------------------ -set(ROCM_PATH "/opt/rocm-6.4.2" CACHE PATH "") +set(ROCM_PATH "/opt/rocm-6.4.3" CACHE PATH "") set(CMAKE_HIP_ARCHITECTURES "gfx90a;gfx942" CACHE STRING "") -set(CMAKE_HIP_COMPILER "/opt/rocm-6.4.2/bin/amdclang++" CACHE FILEPATH "") +set(CMAKE_HIP_COMPILER "/opt/rocm-6.4.3/bin/amdclang++" CACHE FILEPATH "") #------------------------------------------------------------------------------ @@ -82,11 +82,11 @@ set(CMAKE_HIP_COMPILER "/opt/rocm-6.4.2/bin/amdclang++" CACHE FILEPATH "") set(ENABLE_HIP ON CACHE BOOL "") -set(ROCM_ROOT_DIR "/opt/rocm-6.4.2" CACHE PATH "") +set(ROCM_ROOT_DIR "/opt/rocm-6.4.3" CACHE PATH "") set(BLT_CMAKE_IMPLICIT_LINK_LIBRARIES_EXCLUDE "unwind" CACHE STRING "") -set(CMAKE_EXE_LINKER_FLAGS "-lxpmem -L/opt/cray/pe/mpich/8.1.32/gtl/lib -Wl,-rpath,/opt/cray/pe/mpich/8.1.32/gtl/lib -lmpi_gtl_hsa -L/opt/rocm-6.4.2/lib/llvm/lib -Wl,-rpath,/opt/rocm-6.4.2/lib/llvm/lib -L/opt/rocm-6.4.2/lib -Wl,-rpath,/opt/rocm-6.4.2/lib -lpgmath -lompstub -L/opt/cray/pe/cce/20.0.0/cce/x86_64/lib -Wl,-rpath,/opt/cray/pe/cce/20.0.0/cce/x86_64/lib -lamdhip64 -lhsakmt -lhsa-runtime64 -lamd_comgr " CACHE STRING "") +set(CMAKE_EXE_LINKER_FLAGS "-lxpmem -L/opt/cray/pe/mpich/8.1.32/gtl/lib -Wl,-rpath,/opt/cray/pe/mpich/8.1.32/gtl/lib -lmpi_gtl_hsa -L/opt/rocm-6.4.3/lib/llvm/lib -Wl,-rpath,/opt/rocm-6.4.3/lib/llvm/lib -L/opt/rocm-6.4.3/lib -Wl,-rpath,/opt/rocm-6.4.3/lib -lpgmath -lompstub -L/opt/cray/pe/cce/20.0.0/cce/x86_64/lib -Wl,-rpath,/opt/cray/pe/cce/20.0.0/cce/x86_64/lib -lamdhip64 -lhsakmt -lhsa-runtime64 -lamd_comgr " CACHE STRING "") #------------------------------------------------ # Hardware Specifics @@ -100,52 +100,64 @@ set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") # TPLs #------------------------------------------------------------------------------ -set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/cce-20.0.0" CACHE PATH "") +set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/cce-20.0.0" CACHE PATH "") -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-n62sqaudocgfahdhi3xerhjl4cfz4cfm" CACHE PATH "") +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-pbrrhvrsmnewby6q3u35ceppt5fxme2p" CACHE PATH "") -set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-nu3d5eyh2exon7giv52bcw2e7miwx4ey" CACHE PATH "") +set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-cpdkv2uxkhs3qmzqakt4sht3vuiucdwt" CACHE PATH "") -set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-qptl47hqr27lw4qcnhbti2zk22t3fpw3" CACHE PATH "") +set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-2r7wws3ojiqvv6vk7y3ki443xke656sf" CACHE PATH "") -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-sqtvp52fpuxariizrjafw4ineangzmgb" CACHE PATH "") +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-to3lvqwzxrqzad65zbvnbtvyt4k63uxe" CACHE PATH "") -set(LUA_DIR "${TPL_ROOT}/lua-5.4.6-cczerukzth4xrqai22ypclwsaob6oh3m" CACHE PATH "") +set(LUA_DIR "${TPL_ROOT}/lua-5.4.8-y6z3polqakbuhn6nh6muri3rjxqmiioa" CACHE PATH "") -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-5nzacrth4amewhoeu4msnfbplkljtznz" CACHE PATH "") +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-y7uevzr5oi5eansgqfm4ppgcdkvnni6t" CACHE PATH "") -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-l7oioa3ne4kb2idk4r3gmjdqrvecc46c" CACHE PATH "") +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-ke2uxlxkv74lvrhujuzh3ktf3c6e7lfb" CACHE PATH "") # OPENCASCADE not built -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-c2l2d4bka2a3ik25akjd6a6y5bf2nqor" CACHE PATH "") +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-lzgexbo5qyzepgju2acyy6d2qft443tb" CACHE PATH "") -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-bimrixe6smxyacdb5goo7muovyutiaim" CACHE PATH "") +set(CALIPER_DIR "${TPL_ROOT}/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-wytd46zvuquxg2rqf3zec5ldbmjeaat6" CACHE PATH "") -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-2la2lsbddc2dh5mmtokuupqsoe24s7ip" CACHE PATH "") +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-a755kudv24eiizq4thcs2ca2fj7vy65x" CACHE PATH "") # scr not built #------------------------------------------------------------------------------ -# Devtools +# Devtools & Python #------------------------------------------------------------------------------ -set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48" CACHE PATH "") +set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25" CACHE PATH "") -set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm/bin/clang-format" CACHE PATH "") +set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm/bin/clang-format" CACHE PATH "") -set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/python3" CACHE PATH "") +set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/python3" CACHE PATH "") -set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/jsonschema" CACHE PATH "") +set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/jsonschema" CACHE PATH "") set(ENABLE_DOCS ON CACHE BOOL "") -set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/sphinx-build" CACHE PATH "") +set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/sphinx-build" CACHE PATH "") + +set(YAPF_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/yapf" CACHE PATH "") set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0/bin/shroud" CACHE PATH "") -set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w/bin/cppcheck" CACHE PATH "") +set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27/bin/cppcheck" CACHE PATH "") + +set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/doxygen-1.15.0/bin/doxygen" CACHE PATH "") + +set(PY_NANOBIND_DIR "${TPL_ROOT}/py-nanobind-2.7.0-ieb2bzuz435ydpyiq2uj36yyqjbrffml/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PYTEST_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/py-pytest-9.0.0-jfdwo62b3p36blpm54gvocrcj6afccv5/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_NUMPY_DIR "${TPL_ROOT}/py-numpy-2.4.2-xw5ysy75zfqlalmbmtl5phd2qip43hlo/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PLUGGY_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/py-pluggy-1.6.0-n4ojmtqyawxz6gipk64pup3ahwz3xqpu/lib/python3.13/site-packages" CACHE PATH "") -set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/doxygen-1.13.2/bin/doxygen" CACHE PATH "") +set(PY_INICONFIG_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/py-iniconfig-2.1.0-lf3yvch65se22jr7b5unfoxtse4ugkrk/lib/python3.13/site-packages" CACHE PATH "") diff --git a/host-configs/tuolumne-toss_4_x86_64_ib_cray-llvm-amdgpu@6.3.1_hip.cmake b/host-configs/tuolumne-toss_4_x86_64_ib_cray-llvm-amdgpu@6.3.1_hip.cmake index 3ed3364148..605a7a02c1 100644 --- a/host-configs/tuolumne-toss_4_x86_64_ib_cray-llvm-amdgpu@6.3.1_hip.cmake +++ b/host-configs/tuolumne-toss_4_x86_64_ib_cray-llvm-amdgpu@6.3.1_hip.cmake @@ -4,28 +4,28 @@ # CMake executable path: /usr/tce/packages/cmake/cmake-3.29.2/bin/cmake #------------------------------------------------------------------------------ -set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.3.1/blt-develop-glgaihoun6euvmdtqtlyoceslp5pdqrr;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.3.1/c2c-1.8.0-k6bzhviyoy4b4qiwcry5ngq2igehqpxz;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.3.1/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-dzlt2f4kgncqnzaehb2exy27b7nijpb4;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.3.1/conduit-0.9.5-ohicadtnuc7ou25j2wjeubibgtn3x27w;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.3.1/lua-5.4.6-waiv2xo2eqqwohqre65iu6oqzqcshbsd;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.3.1/mfem-4.9.0-xlgphhu27dvyu6t6snijepipaan6x5ee;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.3.1/adiak-0.4.0-tfjwrwri6ldtkqz5vvmaeay3tv3kju6r;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.3.1/libunwind-1.8.3-hupyutxzo74d26y5lmfsxihgfeaurjoq;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.3.1/hdf5-1.8.23-r6op3xgaaudlpritbebr2cjx5lw67q5f;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.3.1/parmetis-4.0.3-mcmehxox2f37vwp27zjzkn3i74qqnpfz;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.3.1/hypre-2.27.0-cc7jeieyge55h5axy5evcdi654jeyl5j;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.3.1/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-r33uioxc7aidenrvcb35hydewejgfr5e;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.3.1/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-5jmhwrbu2wqc6qswsjen75xoz4yymyna;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.3.1/zlib-1.3.1-xnk7wzwuyxloybgp6m2yhjyf4rhgqet3;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.3.1/metis-5.1.0-sa27v5szmjpsatve2ugwku5ok3s7mpon;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.3.1/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-7gcb7xgpawoj2eipuqary4mjrrsyznda;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.3.1/fmt-11.0.2-tm7xaljndccnw5eif5jy4fsftqm43ffl;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/doxygen-1.13.2;/opt/rocm-6.3.1;/opt/rocm-6.3.1;/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm;/opt/rocm-6.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/opt/rocm-6.3.1;/opt/rocm-6.3.1;/opt/rocm-6.3.1" CACHE STRING "") +set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.3.1/adiak-0.4.0-c4srnrz5apjetx74dt6xjah63o3a7xcx;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.3.1/blt-0.7.1-kzmxfjvxm4drr2qhspckvwee6mrlc3e5;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.3.1/c2c-1.8.0-lm64gc55hpxilmtsw7geirys3q4wacu5;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.3.1/conduit-0.9.5-wswspowegvp5byl5inc2cikljzkcqg64;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.3.1/lua-5.4.8-j7ngytniswhoa536kqfzarcraarkicbm;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.3.1/mfem-4.9.0-wetr3wqseqqobjb7be3uzrecpfewq4mr;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.3.1/py-nanobind-2.7.0-q2kwozph3gwgfyjnx43jp2gkbaghwxoj;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/py-pytest-9.0.0-jfdwo62b3p36blpm54gvocrcj6afccv5;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.3.1/hdf5-1.8.23-rb4cjthx4wz4wnpaizwmm2jycijdthqm;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.3.1/parmetis-4.0.3-ng66tt5fmjyfoiuuxyl4rxqv4ompawmd;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.3.1/py-numpy-2.4.2-zcxbrxijjc3miotq6s3kq446afrgycuu;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.3.1/hypre-2.27.0-6m2jwyzqbksxgmdznvh54ytysxyme7jy;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.3.1/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-okzhosj73rts33dgatxh4daotairh5jn;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.3.1/umpire-2025.12.0-of6o5lgmd6jgjqfwat2sbyngieagkeco;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.3.1/zlib-1.3.1-5w5muvpvct6uruxrddscblsiyizl3uoc;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.3.1/metis-5.1.0-4punmdkye6rovr3u7ph7bgj66qim77du;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.3.1/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-74scmbkik6ye7bunoclw46d6zrcfwgha;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.3.1/fmt-11.0.2-opsfnufdiedpfpob5wgbvhcrhyhzfkaq;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/doxygen-1.15.0;/opt/rocm-6.3.1;/opt/rocm-6.3.1;/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm;/opt/rocm-6.3.1;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/opt/rocm-6.3.1;/opt/rocm-6.3.1;/opt/rocm-6.3.1" CACHE STRING "") set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") -set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.3.1/axom-develop-64ne2wqvozxbclbji4uxr2u2yimbfknp/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.3.1/axom-develop-64ne2wqvozxbclbji4uxr2u2yimbfknp/lib64;;/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12" CACHE STRING "") +set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.3.1/axom-develop-xoswouqk3ppxzuxtgegijd3kdoqlkvfe/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.3.1/axom-develop-xoswouqk3ppxzuxtgegijd3kdoqlkvfe/lib64;;/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12" CACHE STRING "") -set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.3.1/axom-develop-64ne2wqvozxbclbji4uxr2u2yimbfknp/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.3.1/axom-develop-64ne2wqvozxbclbji4uxr2u2yimbfknp/lib64;;/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12" CACHE STRING "") +set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.3.1/axom-develop-xoswouqk3ppxzuxtgegijd3kdoqlkvfe/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.3.1/axom-develop-xoswouqk3ppxzuxtgegijd3kdoqlkvfe/lib64;;/opt/rh/gcc-toolset-12/root/usr/lib/gcc/x86_64-redhat-linux/12" CACHE STRING "") set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") #------------------------------------------------------------------------------ # Compilers #------------------------------------------------------------------------------ -# Compiler Spec: llvm-amdgpu@6.3.1/ewmb23zt2h4lqtnvv6lsha7mdyiucmx3 +# Compiler Spec: llvm-amdgpu@6.3.1/ns2pv5bzkpjolxzmhgkckj6glqymgd7e #------------------------------------------------------------------------------ if(DEFINED ENV{SPACK_CC}) - set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh/libexec/spack/rocmcc/amdclang" CACHE PATH "") + set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd/libexec/spack/rocmcc/amdclang" CACHE PATH "") - set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh/libexec/spack/rocmcc/amdclang++" CACHE PATH "") + set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd/libexec/spack/rocmcc/amdclang++" CACHE PATH "") - set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh/libexec/spack/rocmcc/amdflang" CACHE PATH "") + set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd/libexec/spack/rocmcc/amdflang" CACHE PATH "") else() @@ -96,52 +96,64 @@ set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") # TPLs #------------------------------------------------------------------------------ -set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.3.1" CACHE PATH "") +set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.3.1" CACHE PATH "") -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-ohicadtnuc7ou25j2wjeubibgtn3x27w" CACHE PATH "") +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-wswspowegvp5byl5inc2cikljzkcqg64" CACHE PATH "") -set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-k6bzhviyoy4b4qiwcry5ngq2igehqpxz" CACHE PATH "") +set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-lm64gc55hpxilmtsw7geirys3q4wacu5" CACHE PATH "") -set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-xlgphhu27dvyu6t6snijepipaan6x5ee" CACHE PATH "") +set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-wetr3wqseqqobjb7be3uzrecpfewq4mr" CACHE PATH "") -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-r6op3xgaaudlpritbebr2cjx5lw67q5f" CACHE PATH "") +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-rb4cjthx4wz4wnpaizwmm2jycijdthqm" CACHE PATH "") -set(LUA_DIR "${TPL_ROOT}/lua-5.4.6-waiv2xo2eqqwohqre65iu6oqzqcshbsd" CACHE PATH "") +set(LUA_DIR "${TPL_ROOT}/lua-5.4.8-j7ngytniswhoa536kqfzarcraarkicbm" CACHE PATH "") -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-r33uioxc7aidenrvcb35hydewejgfr5e" CACHE PATH "") +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-okzhosj73rts33dgatxh4daotairh5jn" CACHE PATH "") -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-5jmhwrbu2wqc6qswsjen75xoz4yymyna" CACHE PATH "") +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-of6o5lgmd6jgjqfwat2sbyngieagkeco" CACHE PATH "") # OPENCASCADE not built -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-tfjwrwri6ldtkqz5vvmaeay3tv3kju6r" CACHE PATH "") +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-c4srnrz5apjetx74dt6xjah63o3a7xcx" CACHE PATH "") -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-dzlt2f4kgncqnzaehb2exy27b7nijpb4" CACHE PATH "") +# CALIPER not built -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-7gcb7xgpawoj2eipuqary4mjrrsyznda" CACHE PATH "") +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-74scmbkik6ye7bunoclw46d6zrcfwgha" CACHE PATH "") # scr not built #------------------------------------------------------------------------------ -# Devtools +# Devtools & Python #------------------------------------------------------------------------------ -set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48" CACHE PATH "") +set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25" CACHE PATH "") -set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm/bin/clang-format" CACHE PATH "") +set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm/bin/clang-format" CACHE PATH "") -set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/python3" CACHE PATH "") +set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/python3" CACHE PATH "") -set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/jsonschema" CACHE PATH "") +set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/jsonschema" CACHE PATH "") set(ENABLE_DOCS ON CACHE BOOL "") -set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/sphinx-build" CACHE PATH "") +set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/sphinx-build" CACHE PATH "") + +set(YAPF_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/yapf" CACHE PATH "") set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0/bin/shroud" CACHE PATH "") -set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w/bin/cppcheck" CACHE PATH "") +set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27/bin/cppcheck" CACHE PATH "") + +set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/doxygen-1.15.0/bin/doxygen" CACHE PATH "") + +set(PY_NANOBIND_DIR "${TPL_ROOT}/py-nanobind-2.7.0-q2kwozph3gwgfyjnx43jp2gkbaghwxoj/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PYTEST_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/py-pytest-9.0.0-jfdwo62b3p36blpm54gvocrcj6afccv5/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_NUMPY_DIR "${TPL_ROOT}/py-numpy-2.4.2-zcxbrxijjc3miotq6s3kq446afrgycuu/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PLUGGY_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/py-pluggy-1.6.0-n4ojmtqyawxz6gipk64pup3ahwz3xqpu/lib/python3.13/site-packages" CACHE PATH "") -set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/doxygen-1.13.2/bin/doxygen" CACHE PATH "") +set(PY_INICONFIG_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/py-iniconfig-2.1.0-lf3yvch65se22jr7b5unfoxtse4ugkrk/lib/python3.13/site-packages" CACHE PATH "") diff --git a/host-configs/tuolumne-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.2_hip.cmake b/host-configs/tuolumne-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.2_hip.cmake deleted file mode 100644 index 93a7d27b6a..0000000000 --- a/host-configs/tuolumne-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.2_hip.cmake +++ /dev/null @@ -1,147 +0,0 @@ -#------------------------------------------------------------------------------ -# !!!! This is a generated file, edit at own risk !!!! -#------------------------------------------------------------------------------ -# CMake executable path: /usr/tce/packages/cmake/cmake-3.29.2/bin/cmake -#------------------------------------------------------------------------------ - -set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.4.2/blt-develop-kei2jlql6ou5xgnzgg6l4zbzf7fplo25;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.4.2/c2c-1.8.0-xoebhlyceqtktuqrkhewjs4rqprgf6sb;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.4.2/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-te2ukl2lva3vrtuwcc3vfqlfjudggjlv;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.4.2/conduit-0.9.5-vluxk2dyxjp2euipxmmp5lrfwnn5rqmy;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.4.2/lua-5.4.6-ilrwi25dtsa3e2io2ktnzmiyq6va2drk;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.4.2/mfem-4.9.0-4fnvbajng4d6c63266zqdyboaajn55he;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.4.2/adiak-0.4.0-wpwqihuzni5l6g3siv4radax2sue25bz;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.4.2/libunwind-1.8.3-jieqgiira5po56srfxxucbxwau3w25pn;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.4.2/hdf5-1.8.23-5l55nhqjureqnunb5rt6ats675rmez2n;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.4.2/parmetis-4.0.3-qcjolzf7zacqngn5y7nbakmmxmbtiixh;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.4.2/hypre-2.27.0-jbqow3qk2icsbfwbue55mbzip7kssefz;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.4.2/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-ayjwwho7m3chhut5igfdk6ycvuzd4tgh;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.4.2/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-khzcgenw56jiezvsq3hfhdmhdchkmexa;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.4.2/zlib-1.3.1-eu7tohp7odrgv4ecjiufy3ouj4isw42j;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.4.2/metis-5.1.0-q25bz5xqaq77ll4bm2j5nhqol4hh2d2d;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.4.2/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-jspykahx2pbh3nddl6tz2n3arip53r4l;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.4.2/fmt-11.0.2-xgnexgwbj5cb7oevkpnunezrorc6izih;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/doxygen-1.13.2;/opt/rocm-6.4.2;/opt/rocm-6.4.2;/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm;/opt/rocm-6.4.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5;/opt/rocm-6.4.2;/opt/rocm-6.4.2;/opt/rocm-6.4.2" CACHE STRING "") - -set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") - -set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.4.2/axom-develop-f6fj5iovczthvodawdlfp2d6a7z5gvsx/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.4.2/axom-develop-f6fj5iovczthvodawdlfp2d6a7z5gvsx/lib64;;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") - -set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.4.2/axom-develop-f6fj5iovczthvodawdlfp2d6a7z5gvsx/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.4.2/axom-develop-f6fj5iovczthvodawdlfp2d6a7z5gvsx/lib64;;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") - -set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") - -#------------------------------------------------------------------------------ -# Compilers -#------------------------------------------------------------------------------ -# Compiler Spec: llvm-amdgpu@6.4.2/bb2nokv3ui3ksdf4t4xucxqtidlj2ds4 -#------------------------------------------------------------------------------ -if(DEFINED ENV{SPACK_CC}) - - set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh/libexec/spack/rocmcc/amdclang" CACHE PATH "") - - set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh/libexec/spack/rocmcc/amdclang++" CACHE PATH "") - - set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/none-none/compiler-wrapper-1.0-gsjte4xjarvat5o7b7sdeufsa3qr7mjh/libexec/spack/rocmcc/amdflang" CACHE PATH "") - -else() - - set(CMAKE_C_COMPILER "/opt/rocm-6.4.2/llvm/bin/amdclang" CACHE PATH "") - - set(CMAKE_CXX_COMPILER "/opt/rocm-6.4.2/llvm/bin/amdclang++" CACHE PATH "") - - set(CMAKE_Fortran_COMPILER "/opt/rocm-6.4.2/llvm/bin/amdflang" CACHE PATH "") - -endif() - -set(CMAKE_Fortran_FLAGS "-Mfreeform" CACHE STRING "") - -set(ENABLE_FORTRAN ON CACHE BOOL "") - -#------------------------------------------------------------------------------ -# MPI -#------------------------------------------------------------------------------ - -set(MPI_C_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.2/bin/mpicc" CACHE PATH "") - -set(MPI_CXX_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.2/bin/mpicxx" CACHE PATH "") - -set(MPI_Fortran_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.2/bin/mpif90" CACHE PATH "") - -set(MPIEXEC_EXECUTABLE "/usr/global/tools/flux_wrappers/bin/srun" CACHE PATH "") - -set(MPIEXEC_NUMPROC_FLAG "-n" CACHE STRING "") - -set(ENABLE_MPI ON CACHE BOOL "") - -#------------------------------------------------------------------------------ -# Hardware -#------------------------------------------------------------------------------ - -#------------------------------------------------ -# ROCm -#------------------------------------------------ - -set(ROCM_PATH "/opt/rocm-6.4.2" CACHE PATH "") - -set(CMAKE_HIP_ARCHITECTURES "gfx90a;gfx942" CACHE STRING "") - -set(CMAKE_HIP_COMPILER "/opt/rocm-6.4.2/bin/amdclang++" CACHE FILEPATH "") - -#------------------------------------------------------------------------------ - -# Axom ROCm specifics - -#------------------------------------------------------------------------------ - - -set(ENABLE_HIP ON CACHE BOOL "") - -set(ROCM_ROOT_DIR "/opt/rocm-6.4.2" CACHE PATH "") - -set(CMAKE_EXE_LINKER_FLAGS "-lxpmem -L/opt/cray/pe/mpich/8.1.29/gtl/lib -Wl,-rpath,/opt/cray/pe/mpich/8.1.29/gtl/lib -lmpi_gtl_hsa -L/opt/rocm-6.4.2/lib/llvm/lib -Wl,-rpath,/opt/rocm-6.4.2/lib/llvm/lib -L/opt/rocm-6.4.2/lib -Wl,-rpath,/opt/rocm-6.4.2/lib -lpgmath -lompstub -Wl,--disable-new-dtags -lflang -lflangrti -lamdhip64 -lhsakmt -lhsa-runtime64 -lamd_comgr " CACHE STRING "") - -#------------------------------------------------ -# Hardware Specifics -#------------------------------------------------ - -set(ENABLE_OPENMP OFF CACHE BOOL "") - -set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") - -#------------------------------------------------------------------------------ -# TPLs -#------------------------------------------------------------------------------ - -set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_01_29_13_36_58/llvm-amdgpu-6.4.2" CACHE PATH "") - -set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-vluxk2dyxjp2euipxmmp5lrfwnn5rqmy" CACHE PATH "") - -set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-xoebhlyceqtktuqrkhewjs4rqprgf6sb" CACHE PATH "") - -set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-4fnvbajng4d6c63266zqdyboaajn55he" CACHE PATH "") - -set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-5l55nhqjureqnunb5rt6ats675rmez2n" CACHE PATH "") - -set(LUA_DIR "${TPL_ROOT}/lua-5.4.6-ilrwi25dtsa3e2io2ktnzmiyq6va2drk" CACHE PATH "") - -set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-ayjwwho7m3chhut5igfdk6ycvuzd4tgh" CACHE PATH "") - -set(UMPIRE_DIR "${TPL_ROOT}/umpire-git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9_develop-khzcgenw56jiezvsq3hfhdmhdchkmexa" CACHE PATH "") - -# OPENCASCADE not built - -set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-wpwqihuzni5l6g3siv4radax2sue25bz" CACHE PATH "") - -set(CALIPER_DIR "${TPL_ROOT}/caliper-git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598_master-te2ukl2lva3vrtuwcc3vfqlfjudggjlv" CACHE PATH "") - -set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-jspykahx2pbh3nddl6tz2n3arip53r4l" CACHE PATH "") - -# scr not built - -#------------------------------------------------------------------------------ -# Devtools -#------------------------------------------------------------------------------ - -set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48" CACHE PATH "") - -set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm/bin/clang-format" CACHE PATH "") - -set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/python3" CACHE PATH "") - -set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/jsonschema" CACHE PATH "") - -set(ENABLE_DOCS ON CACHE BOOL "") - -set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/python-3.13.5/bin/sphinx-build" CACHE PATH "") - -set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0/bin/shroud" CACHE PATH "") - -set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w/bin/cppcheck" CACHE PATH "") - -set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/7qllb33pi46obvxaz6lidqsy2qlr3wkt/doxygen-1.13.2/bin/doxygen" CACHE PATH "") - - diff --git a/host-configs/tuolumne-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.3_hip.cmake b/host-configs/tuolumne-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.3_hip.cmake new file mode 100644 index 0000000000..2b5c73bb42 --- /dev/null +++ b/host-configs/tuolumne-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.3_hip.cmake @@ -0,0 +1,159 @@ +#------------------------------------------------------------------------------ +# !!!! This is a generated file, edit at own risk !!!! +#------------------------------------------------------------------------------ +# CMake executable path: /usr/tce/packages/cmake/cmake-3.29.2/bin/cmake +#------------------------------------------------------------------------------ + +set(CMAKE_PREFIX_PATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3/blt-0.7.1-4kxhk7nbuiv5oh2ymh7sdimnmor36hmo;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3/c2c-1.8.0-h5kio7nseyazg4pzgvj4kxanb3plhbxm;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-rmlwpdacdtpzf4u72ctyroj72soqzf3f;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3/conduit-0.9.5-zqywrasos2vbears5hvdwxhulm3xox6q;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3/lua-5.4.8-gp4kdewsy4uiy6flsx342lgogcm7fym2;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3/mfem-4.9.0-g6vxdlgc7spurcdacgc6e5245iu2hyiw;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3/py-nanobind-2.7.0-2kp35jcpb73xuujvcz6kmg4q2npek4gg;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/py-pytest-9.0.0-jfdwo62b3p36blpm54gvocrcj6afccv5;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3/adiak-0.4.0-cropyu42jr4q6k3zar6mkma6gc2vp6tk;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3/libunwind-1.8.3-plszp43gkd75kzjcvge3qxrtb6j2budl;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3/hdf5-1.8.23-mgic2kxojd5zeivhaz473zzmzrg3gdqe;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3/parmetis-4.0.3-hd2qoczrh3vw3ejm6msitqdgecjk7xwe;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3/py-numpy-2.4.2-a3mo27shjtpliwewbm5cci2kf37crrab;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3/hypre-2.27.0-4nrl5egspbxmnkpzfym5udby6uruhn3i;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-wavyomm5hzyjf3xuyr33txmnspvxveei;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3/umpire-2025.12.0-4oytcvf556ksil4hsthjt4b5y4wdpaxw;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3/zlib-1.3.1-slqujeue3l44x3pgqbu7e2pw3lh2mj5i;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3/metis-5.1.0-puzeddu6ufhz5vpxnw7i3i2i6slsvuuj;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-3gtldngru7bva2reuel5iabyytw5fmdf;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3/fmt-11.0.2-lpnox72rqcneew5hucwzq4nmms4at525;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/usr/tce/packages/cmake/cmake-3.29.2;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27;/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/doxygen-1.15.0;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm;/opt/rocm-6.4.3;/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/opt/rocm-6.4.3;/opt/rocm-6.4.3" CACHE STRING "") + +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH "ON" CACHE STRING "") + +set(CMAKE_BUILD_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3/axom-develop-cdngjuz7ffr3goroyietece35jivxnkv/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3/axom-develop-cdngjuz7ffr3goroyietece35jivxnkv/lib64;;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") + +set(CMAKE_INSTALL_RPATH "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3/axom-develop-cdngjuz7ffr3goroyietece35jivxnkv/lib;/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3/axom-develop-cdngjuz7ffr3goroyietece35jivxnkv/lib64;;/opt/rh/gcc-toolset-13/root/usr/lib/gcc/x86_64-redhat-linux/13" CACHE STRING "") + +set(CMAKE_BUILD_TYPE "Release" CACHE STRING "") + +#------------------------------------------------------------------------------ +# Compilers +#------------------------------------------------------------------------------ +# Compiler Spec: llvm-amdgpu@6.4.3/u67i6xutdthzl3yti7tv3klyhyzddbkv +#------------------------------------------------------------------------------ +if(DEFINED ENV{SPACK_CC}) + + set(CMAKE_C_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd/libexec/spack/rocmcc/amdclang" CACHE PATH "") + + set(CMAKE_CXX_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd/libexec/spack/rocmcc/amdclang++" CACHE PATH "") + + set(CMAKE_Fortran_COMPILER "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/compiler-wrapper-1.0-pypgv2tridcfdliq3cjhfecu23umxcjd/libexec/spack/rocmcc/amdflang" CACHE PATH "") + +else() + + set(CMAKE_C_COMPILER "/opt/rocm-6.4.3/llvm/bin/amdclang" CACHE PATH "") + + set(CMAKE_CXX_COMPILER "/opt/rocm-6.4.3/llvm/bin/amdclang++" CACHE PATH "") + + set(CMAKE_Fortran_COMPILER "/opt/rocm-6.4.3/llvm/bin/amdflang" CACHE PATH "") + +endif() + +set(CMAKE_Fortran_FLAGS "-Mfreeform" CACHE STRING "") + +set(ENABLE_FORTRAN ON CACHE BOOL "") + +#------------------------------------------------------------------------------ +# MPI +#------------------------------------------------------------------------------ + +set(MPI_C_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.3/bin/mpicc" CACHE PATH "") + +set(MPI_CXX_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.3/bin/mpicxx" CACHE PATH "") + +set(MPI_Fortran_COMPILER "/usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.3/bin/mpif90" CACHE PATH "") + +set(MPIEXEC_EXECUTABLE "/usr/global/tools/flux_wrappers/bin/srun" CACHE PATH "") + +set(MPIEXEC_NUMPROC_FLAG "-n" CACHE STRING "") + +set(ENABLE_MPI ON CACHE BOOL "") + +#------------------------------------------------------------------------------ +# Hardware +#------------------------------------------------------------------------------ + +#------------------------------------------------ +# ROCm +#------------------------------------------------ + +set(ROCM_PATH "/opt/rocm-6.4.3" CACHE PATH "") + +set(CMAKE_HIP_ARCHITECTURES "gfx90a;gfx942" CACHE STRING "") + +set(CMAKE_HIP_COMPILER "/opt/rocm-6.4.3/bin/amdclang++" CACHE FILEPATH "") + +#------------------------------------------------------------------------------ + +# Axom ROCm specifics + +#------------------------------------------------------------------------------ + + +set(ENABLE_HIP ON CACHE BOOL "") + +set(ROCM_ROOT_DIR "/opt/rocm-6.4.3" CACHE PATH "") + +set(CMAKE_EXE_LINKER_FLAGS "-lxpmem -L/opt/cray/pe/mpich/8.1.29/gtl/lib -Wl,-rpath,/opt/cray/pe/mpich/8.1.29/gtl/lib -lmpi_gtl_hsa -L/opt/rocm-6.4.3/lib/llvm/lib -Wl,-rpath,/opt/rocm-6.4.3/lib/llvm/lib -L/opt/rocm-6.4.3/lib -Wl,-rpath,/opt/rocm-6.4.3/lib -lpgmath -lompstub -Wl,--disable-new-dtags -lflang -lflangrti -lamdhip64 -lhsakmt -lhsa-runtime64 -lamd_comgr " CACHE STRING "") + +#------------------------------------------------ +# Hardware Specifics +#------------------------------------------------ + +set(ENABLE_OPENMP OFF CACHE BOOL "") + +set(ENABLE_GTEST_DEATH_TESTS ON CACHE BOOL "") + +#------------------------------------------------------------------------------ +# TPLs +#------------------------------------------------------------------------------ + +set(TPL_ROOT "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/llvm-amdgpu-6.4.3" CACHE PATH "") + +set(CONDUIT_DIR "${TPL_ROOT}/conduit-0.9.5-zqywrasos2vbears5hvdwxhulm3xox6q" CACHE PATH "") + +set(C2C_DIR "${TPL_ROOT}/c2c-1.8.0-h5kio7nseyazg4pzgvj4kxanb3plhbxm" CACHE PATH "") + +set(MFEM_DIR "${TPL_ROOT}/mfem-4.9.0-g6vxdlgc7spurcdacgc6e5245iu2hyiw" CACHE PATH "") + +set(HDF5_DIR "${TPL_ROOT}/hdf5-1.8.23-mgic2kxojd5zeivhaz473zzmzrg3gdqe" CACHE PATH "") + +set(LUA_DIR "${TPL_ROOT}/lua-5.4.8-gp4kdewsy4uiy6flsx342lgogcm7fym2" CACHE PATH "") + +set(RAJA_DIR "${TPL_ROOT}/raja-git.3b8b59a1e9be2e1066c0d77372b3bf5956e6d6e2_develop-wavyomm5hzyjf3xuyr33txmnspvxveei" CACHE PATH "") + +set(UMPIRE_DIR "${TPL_ROOT}/umpire-2025.12.0-4oytcvf556ksil4hsthjt4b5y4wdpaxw" CACHE PATH "") + +# OPENCASCADE not built + +set(ADIAK_DIR "${TPL_ROOT}/adiak-0.4.0-cropyu42jr4q6k3zar6mkma6gc2vp6tk" CACHE PATH "") + +set(CALIPER_DIR "${TPL_ROOT}/caliper-git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c_master-rmlwpdacdtpzf4u72ctyroj72soqzf3f" CACHE PATH "") + +set(CAMP_DIR "${TPL_ROOT}/camp-git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325_main-3gtldngru7bva2reuel5iabyytw5fmdf" CACHE PATH "") + +# scr not built + +#------------------------------------------------------------------------------ +# Devtools & Python +#------------------------------------------------------------------------------ + +set(DEVTOOLS_ROOT "/collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25" CACHE PATH "") + +set(CLANGFORMAT_EXECUTABLE "/usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm/bin/clang-format" CACHE PATH "") + +set(Python_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/python3" CACHE PATH "") + +set(JSONSCHEMA_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/jsonschema" CACHE PATH "") + +set(ENABLE_DOCS ON CACHE BOOL "") + +set(SPHINX_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/sphinx-build" CACHE PATH "") + +set(YAPF_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/python-3.13.11/bin/yapf" CACHE PATH "") + +set(SHROUD_EXECUTABLE "/collab/usr/gapps/shroud/public/toss_4_x86_64_ib_cray/shroud-0.14.0/bin/shroud" CACHE PATH "") + +set(CPPCHECK_EXECUTABLE "${DEVTOOLS_ROOT}/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27/bin/cppcheck" CACHE PATH "") + +set(DOXYGEN_EXECUTABLE "${DEVTOOLS_ROOT}/._view/ywmag65dnysd7p4dhlmcoaaqqxfzgz5a/doxygen-1.15.0/bin/doxygen" CACHE PATH "") + +set(PY_NANOBIND_DIR "${TPL_ROOT}/py-nanobind-2.7.0-2kp35jcpb73xuujvcz6kmg4q2npek4gg/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PYTEST_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/py-pytest-9.0.0-jfdwo62b3p36blpm54gvocrcj6afccv5/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_NUMPY_DIR "${TPL_ROOT}/py-numpy-2.4.2-a3mo27shjtpliwewbm5cci2kf37crrab/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_PLUGGY_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/py-pluggy-1.6.0-n4ojmtqyawxz6gipk64pup3ahwz3xqpu/lib/python3.13/site-packages" CACHE PATH "") + +set(PY_INICONFIG_DIR "/usr/WS1/axom/libs/toss_4_x86_64_ib_cray/2026_03_11_08_14_36/none-none/py-iniconfig-2.1.0-lf3yvch65se22jr7b5unfoxtse4ugkrk/lib/python3.13/site-packages" CACHE PATH "") + + diff --git a/scripts/benchmarks/mir_concentric_circles.py b/scripts/benchmarks/mir_concentric_circles.py index c4280bef47..c59c47eb7e 100644 --- a/scripts/benchmarks/mir_concentric_circles.py +++ b/scripts/benchmarks/mir_concentric_circles.py @@ -13,14 +13,23 @@ def lrun(np): # Parallel options use 4 ranks per node since that is how many GPUs there are. runs = { - "build-rzansel-blueos_3_ppc64le_ib_p9-clang@10.0.1.2_cuda-release" : {"policies":["seq", "omp", "cuda"], "launch":lrun}, - "build-rzwhippet-toss_4_x86_64_ib-clang@14.0.6-release" : {"policies":["seq", "omp"], "launch":srun}, - "build-rzwhippet-toss_4_x86_64_ib-gcc@10.3.1-release" : {"policies":["seq", "omp"], "launch":srun}, - "build-rzwhippet-toss_4_x86_64_ib-intel@2022.1.0-release" : {"policies":["seq", "omp"], "launch":srun}, - "build-rzvernal-toss_4_x86_64_ib_cray-rocmcc@6.2.1_hip-release" : {"policies":["seq", "hip"], "launch":srun}, - "build-rzvernal-toss_4_x86_64_ib_cray-clang@17.0.0_hip-release" : {"policies":["seq", "hip"], "launch":srun}, - "build-rzadams-toss_4_x86_64_ib_cray-cce@18.0.0_hip-release" :{"policies":["seq", "hip"], "launch":flux_run}, - "build-rzadams-toss_4_x86_64_ib_cray-rocmcc@6.2.1_hip-release" :{"policies":["seq", "hip"], "launch":flux_run} + "build-dane-toss_4_x86_64_ib-gcc@13.3.1-release" : {"policies":["seq", "omp"], "launch":srun}, + "build-dane-toss_4_x86_64_ib-intel-oneapi-compilers@2025.2.0-release" : {"policies":["seq", "omp"], "launch":srun}, + "build-dane-toss_4_x86_64_ib-llvm@19.1.3-release" : {"policies":["seq", "omp"], "launch":srun}, + "build-matrix-toss_4_x86_64_ib-gcc@13.3.1_cuda-release" : {"policies":["seq", "omp", "cuda"], "launch":srun}, + "build-matrix-toss_4_x86_64_ib-llvm@19.1.3_cuda-release" : {"policies":["seq", "omp", "cuda"], "launch":srun}, + "build-rzwhippet-toss_4_x86_64_ib-llvm@19.1.3-release" : {"policies":["seq", "omp"], "launch":srun}, + "build-rzwhippet-toss_4_x86_64_ib-gcc@13.3.1-release" : {"policies":["seq", "omp"], "launch":srun}, + "build-rzwhippet-toss_4_x86_64_ib-intel-oneapi-compilers@2025.2.0-release" : {"policies":["seq", "omp"], "launch":srun}, + "build-rzvernal-toss_4_x86_64_ib_cray-cce@20.0.0_hip-release" : {"policies":["seq", "hip"], "launch":srun}, + "build-rzvernal-toss_4_x86_64_ib_cray-llvm-amdgpu@6.3.1_hip-release" : {"policies":["seq", "hip"], "launch":srun}, + "build-rzvernal-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.2_hip-release" : {"policies":["seq", "hip"], "launch":srun}, + "build-rzadams-toss_4_x86_64_ib_cray-cce@20.0.0_hip-release" :{"policies":["seq", "hip"], "launch":flux_run}, + "build-rzadams-toss_4_x86_64_ib_cray-llvm-amdgpu@6.3.1_hip-release" :{"policies":["seq", "hip"], "launch":flux_run}, + "build-rzadams-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.2_hip-release" :{"policies":["seq", "hip"], "launch":flux_run}, + "build-tioga-toss_4_x86_64_ib_cray-cce@20.0.0_hip-release" :{"policies":["seq", "hip"], "launch":flux_run}, + "build-tioga-toss_4_x86_64_ib_cray-llvm-amdgpu@6.3.1_hip-release" :{"policies":["seq", "hip"], "launch":flux_run}, + "build-tioga-toss_4_x86_64_ib_cray-llvm-amdgpu@6.4.2_hip-release" :{"policies":["seq", "hip"], "launch":flux_run} } def generate(params): @@ -40,6 +49,10 @@ def generate(params): f.write("CONCENTRIC_CIRCLES=./examples/mir_concentric_circles\n") f.write("CONCENTRIC_CIRCLES_MPI=./examples/mir_concentric_circles_mpi\n\n") + f.write("export OMP_PLACES=cores\n") + f.write("export OMP_PROC_BIND=spread\n") + f.write("export OMP_DYNAMIC=FALSE\n") + dimension = params["dimension"] trials = params["trials"] for s in params["sizes"]: @@ -68,7 +81,10 @@ def read_timings(filename, searchKey): retval = "" # no data try: lines = open(filename, "rt").readlines() - print(f"Reading {filename}") + msg = "" + if searchKey.find("Algorithm") == -1: + msg = f" Getting '{searchKey}' value." + print(f"Reading {filename}.{msg}") for line in lines: pos = line.find(searchKey) if pos != -1: @@ -113,10 +129,7 @@ def average(value, trials): avg = value return avg - # Measure just the MIR algorithm - searchKey = "EquizAlgorithm" - if params["method"] == "elvira": - searchKey = "ElviraAlgorithm" + searchKey = params["searchKey"] columns = [] # Add NumZones column (either square or cube of s, depending on dimension) @@ -184,9 +197,17 @@ def make_csv(params, outputfile): f.write(f"{line}\n") f.close() -def seriesName(name): +def seriesName(name, includeCompiler = False): policies = {"SEQ" : "Serial", "OMP": "OpenMP", "CUDA" : "CUDA", "HIP" : "HIP"} - newName = name[:name.find("-")] + if includeCompiler: + d0 = name.find("-") + d1 = name.rfind("-") + s0 = name.rfind(" ") + hostName = name[:d0] + compName = name[d1 + 1:s0] + newName = f"{hostName} {compName}" + else: + newName = name[:name.find("-")] for p in policies.keys(): if name[-len(p) - 1:] == " " + p: newName = newName + " " + policies[p] @@ -197,8 +218,15 @@ def lineProps(name): """ Make line properties when given a series name. """ - hostColor = {"rzansel" : "g", "rzwhippet" : "r", "rzvernal" : "o", "rzadams" : "b"} - policyStyle = {"seq" : "--", "omp": ":", "cuda" : "-", "hip" : "-"} + red = "#ff0000" + green = "#00aa00" + blue = "#0000ff" + orange = "#ff6622" + #magenta = "#ff00ff" + #purple = "#8811aa" + hostColor = {"rzwhippet" : red, "rzvernal" : green, "rzadams" : blue, + "dane" : red, "matrix" : green, "tioga": orange, "tuolumne" : blue} + policyStyle = {"seq" : "-", "omp": ":", "cuda" : "--", "hip" : "--"} policyMark = {"seq" : "o", "omp": "s", "cuda" : "^", "hip" : "^"} color = "b" style = "-" @@ -214,6 +242,25 @@ def lineProps(name): break return color, style, mark +def hex_to_rgb(hex_color: str): + """ + Convert a color in "#rrggbb" (or "rrggbb") format to an (r, g, b) tuple. + """ + s = hex_color.strip() + if s.startswith("#"): + s = s[1:] + if len(s) != 6: + raise ValueError(f"Expected 6 hex digits, got {len(s)}: {hex_color!r}") + + try: + r = int(s[0:2], 16) + g = int(s[2:4], 16) + b = int(s[4:6], 16) + except ValueError as e: + raise ValueError(f"Invalid hex color: {hex_color!r}") from e + + return (r, g, b) + def plot(params): """ Read the available timing files and plot them. @@ -233,22 +280,78 @@ def make_series(col1, col2): break return x,y + def rgbToColor(r,g,b): + return "#%02x%02x%02x" % (r,g,b) + + def lightenColor(r,g,b): + def clamp255(value): + if value > 255: + return 255 + return int(value) + scale = 1.3 + return rgbToColor(clamp255(r * scale), clamp255(g * scale), clamp255(b * scale)) + + def darkenColor(r,g,b): + scale = 0.7 + return rgbToColor(int(r * scale), int(g * scale), int(b * scale)) + + def modifyColor(color, index): + if index == 0: + return color + r,g,b = hex_to_rgb(color) + if index == 1: + return darkenColor(r,g,b) + return lightenColor(r,g,b) + + def valid_column(column): + valid = False + for i in range(1, len(column)): + if column[i] != "": + valid = True + return valid + + # Make columns from the data columns = make_columns(params) + # Count how many plots would use the normal legend name + counts = {} + for c in range(1, len(columns)): + if not valid_column(columns[c]): + continue + sn = seriesName(columns[c][0]) + if sn in counts: + count, _ = counts[sn] + counts[sn] = (count + 1, 0) + else: + counts[sn] = (1, 0) + import matplotlib.pyplot as plt + seriesLegendNames = {} for c in range(1, len(columns)): x, y = make_series(columns[0][1:], columns[c][1:]) if len(x) > 0: color, style, mark = lineProps(columns[c][0]) - plt.plot(x, y, marker=mark, linestyle=style, color=color, linewidth=2., label=seriesName(columns[c][0])) + sn = seriesName(columns[c][0]) + if counts[sn][0] > 1: + oldsn = sn + sn = seriesName(columns[c][0], True) + color = modifyColor(color, counts[oldsn][1]) + counts[oldsn] = (counts[oldsn][0], counts[oldsn][1] + 1) + seriesLegendNames[c] = sn + plt.plot(x, y, marker=mark, linestyle=style, color=color, linewidth=2., label=sn) dimension = params["dimension"] method = params["method"] + searchKey = params["searchKey"] + if searchKey.find("Algorithm") != -1: + # more concise + searchKey = method + doLabels = params["labels"] # Add labels and title plt.xlabel('Number of Zones', fontsize=24) plt.ylabel('Time (s)', fontsize=24) - plt.title(f'{dimension}D MIR Timings ({method})', fontsize=28) + plt.title(f'{dimension}D MIR Timings ({searchKey})', fontsize=28) xlabels = make_series(columns[0][1:], columns[0][1:])[0] plt.xticks(ticks=xlabels, labels=xlabels, fontsize=18) plt.yticks(fontsize=18) @@ -268,6 +371,65 @@ def make_series(col1, col2): print(f"There was an error, probably because the benchmark is still running. {columns}") raise + # Add labels + if doLabels and len(columns) >= 2: + def findIndex(seq, value): + eps = 1.e-8 + for i in range(len(seq)): + if math.fabs(value - seq[i]) < eps: + return i + return -1 + + # Group the related series. + seriesGroups = {} + seriesSer = {} + for c in seriesLegendNames.keys(): + sn = seriesLegendNames[c] + host = sn[:sn.rfind(" ")] + if host in seriesGroups: + seriesGroups[host].append(c) + else: + seriesGroups[host] = [c] + if sn.find("Serial") != -1: + seriesSer[host] = c + + # Go through groups + for host in seriesGroups: + if not host in seriesSer: + continue + + # The serial column + cser = seriesSer[host] + + # Compare other columns against the serial column + for c in seriesGroups[host]: + if cser == c: + continue + + x1, y1 = make_series(columns[0][1:], columns[cser][1:]) + x2, y2 = make_series(columns[0][1:], columns[c][1:]) + xa = [] + ya = [] + labels = [] + idx = 0 + for i in range(len(x1)): + # Where series 1 (SEQ) > series 2 (OMP) + j = findIndex(x2, x1[i]) + if j != -1 and y1[i] > y2[j]: + xa.append(x2[j]) + ya.append(y2[j]) + labels.append(f"{math.trunc(100. * y1[i] / y2[i]) / 100.:.2f}x") + plt.annotate( + labels[idx], + (xa[idx], ya[idx]), + xytext=(6, -6), textcoords="offset points", # pixel offset + ha="left", va="bottom", + fontsize=10, + bbox=dict(boxstyle="round,pad=0.2", fc="white", ec="none", alpha=0.8), + arrowprops=dict(arrowstyle="-", color="0.3", lw=0.8) + ) + idx = idx + 1 + # Show the plot plt.grid(True) plt.show() @@ -319,6 +481,13 @@ def get_params(): required=False ) + parser.add_argument( + "--key", + type=str, + help="Name of the caliper timings to extract from the logs", + required=False + ) + parser.add_argument( "--trials", type=int, @@ -326,6 +495,13 @@ def get_params(): required=False ) + parser.add_argument( + "--labels", + action="store_true", + help="Boolean flag to indicate whether to draw speedup labels", + required=False + ) + args = parser.parse_args() # Convert the comma-separated string into a tuple of integers @@ -369,6 +545,20 @@ def get_params(): else: params["trials"] = 1 + if args.labels is not None: + params["labels"] = args.labels + else: + params["labels"] = False + + if args.key is not None: + params["searchKey"] = args.key + else: + # Default to MIR algorithm timings + if params["method"] == "elvira": + params["searchKey"] = "ElviraAlgorithm" + else: + params["searchKey"] = "EquizAlgorithm" + # Generate some sizes. sides = (50, 100, 200, 500, 1000, 1500, 2000, 4000, 8000) if params["dimension"] == 3: diff --git a/scripts/github-actions/linux-build_and_test.sh b/scripts/github-actions/linux-build_and_test.sh index b0c472e16b..a7a780ffe6 100755 --- a/scripts/github-actions/linux-build_and_test.sh +++ b/scripts/github-actions/linux-build_and_test.sh @@ -45,7 +45,7 @@ if [[ "$DO_BUILD" == "yes" ]] ; then fi echo "~~~~~~ RUNNING TESTS ~~~~~~~~" - make CTEST_OUTPUT_ON_FAILURE=1 test ARGS='-T Test -VV -j$NUM_BUILD_PROCS' + make CTEST_OUTPUT_ON_FAILURE=1 test ARGS='-T Test --output-on-failure -j$NUM_BUILD_PROCS' if [[ "${DO_BENCHMARKS}" == "yes" ]] ; then echo "~~~~~~ RUNNING BENCHMARKS ~~~~~~~~" diff --git a/scripts/spack/configs/toss_4_x86_64_ib/spack.yaml b/scripts/spack/configs/toss_4_x86_64_ib/spack.yaml index 886a36b207..c21897f732 100644 --- a/scripts/spack/configs/toss_4_x86_64_ib/spack.yaml +++ b/scripts/spack/configs/toss_4_x86_64_ib/spack.yaml @@ -356,13 +356,13 @@ spack: buildable: false externals: - spec: cppcheck@2.18.0 - prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/gcc-13.3.1/cppcheck-2.18.0-d2tmb7ls2d5vgh6vhcyohecwcu6msopb/ + prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/gcc-13.3.1/cppcheck-2.18.0-i3p56kpf66xzj4wm5kfqxyc4vgox7gb3/ doxygen: - version: [1.13.2] + version: [1.15.0] buildable: false externals: - - spec: doxygen@1.13.2 - prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/doxygen-1.13.2 + - spec: doxygen@1.15.0 + prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/doxygen-1.15.0 py-shroud: version: [0.14.0] buildable: false @@ -374,41 +374,20 @@ spack: buildable: false externals: - spec: py-sphinx@4.4.0 - prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5/ + prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11/ python: buildable: false externals: - - spec: python@3.13.5 - prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5/ - - # Other python externals built by devtools for conduit - py-pytest: - buildable: false - externals: - - spec: py-pytest@8.2.1 - prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5/ + - spec: python@3.13.11 + prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11/ py-jsonschema: buildable: false externals: - spec: py-jsonschema@4.17.3 - prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5/ - python-venv: - buildable: false - externals: - - spec: python-venv@1.0 - prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5/ - py-pyproject-metadata: + prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11/ + py-yapf: buildable: false externals: - - spec: py-pyproject-metadata@0.17.1 - prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5/ - py-meson-python: - buildable: false - externals: - - spec: py-meson-python@0.16.0 - prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5/ - py-numpy: - buildable: false - externals: - - spec: py-numpy@2.3.2 - prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2025_09_25_11_33_37/view/python-3.13.5/ + - spec: py-yapf@0.43.0 + prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib/2026_02_17_14_42_14/view/python-3.13.11/ + diff --git a/scripts/spack/configs/toss_4_x86_64_ib_cray/spack.yaml b/scripts/spack/configs/toss_4_x86_64_ib_cray/spack.yaml index f4b9c5b75d..dd49d5ba25 100644 --- a/scripts/spack/configs/toss_4_x86_64_ib_cray/spack.yaml +++ b/scripts/spack/configs/toss_4_x86_64_ib_cray/spack.yaml @@ -23,15 +23,15 @@ spack: - ../versions.yaml toolchains: - rocm_6_4_2: + rocm_6_4_3: - spec: fflags=-Mfreeform - - spec: '%c=llvm-amdgpu@6.4.2' + - spec: '%c=llvm-amdgpu@6.4.3' when: '%c' - - spec: '%cxx=llvm-amdgpu@6.4.2' + - spec: '%cxx=llvm-amdgpu@6.4.3' when: '%cxx' - - spec: '%fortran=llvm-amdgpu@6.4.2' + - spec: '%fortran=llvm-amdgpu@6.4.3' when: '%fortran' - - spec: '%cray-mpich@8.1.29.rocm_6_4_2' + - spec: '%cray-mpich@8.1.29.rocm_6.4.3' when: '%mpi' rocm_6_3_1: - spec: fflags=-Mfreeform @@ -80,13 +80,13 @@ spack: fortran: /opt/rocm-6.3.1/llvm/bin/amdflang environment: {} extra_rpaths: [] - - spec: llvm-amdgpu@6.4.2 - prefix: /opt/rocm-6.4.2 + - spec: llvm-amdgpu@6.4.3 + prefix: /opt/rocm-6.4.3 extra_attributes: compilers: - c: /opt/rocm-6.4.2/llvm/bin/amdclang - cxx: /opt/rocm-6.4.2/llvm/bin/amdclang++ - fortran: /opt/rocm-6.4.2/llvm/bin/amdflang + c: /opt/rocm-6.4.3/llvm/bin/amdclang + cxx: /opt/rocm-6.4.3/llvm/bin/amdclang++ + fortran: /opt/rocm-6.4.3/llvm/bin/amdflang environment: {} extra_rpaths: [] cce: @@ -103,69 +103,75 @@ spack: hip: - # version: [6.3.1, 6.4.2] + # version: [6.3.1, 6.4.3] buildable: false externals: - spec: hip@6.3.1 prefix: /opt/rocm-6.3.1 - - spec: hip@6.4.2 - prefix: /opt/rocm-6.4.2 + - spec: hip@6.4.3 + prefix: /opt/rocm-6.4.3 hipblas: buildable: false externals: - spec: hipblas@6.3.1 prefix: /opt/rocm-6.3.1 - - spec: hipblas@6.4.2 - prefix: /opt/rocm-6.4.2 + - spec: hipblas@6.4.3 + prefix: /opt/rocm-6.4.3 hipsparse: buildable: false externals: - spec: hipsparse@6.3.1 prefix: /opt/rocm-6.3.1 - - spec: hipsparse@6.4.2 - prefix: /opt/rocm-6.4.2 + - spec: hipsparse@6.4.3 + prefix: /opt/rocm-6.4.3 hsa-rocr-dev: buildable: false externals: - spec: hsa-rocr-dev@6.3.1 prefix: /opt/rocm-6.3.1/ - - spec: hsa-rocr-dev@6.4.2 - prefix: /opt/rocm-6.4.2 + - spec: hsa-rocr-dev@6.4.3 + prefix: /opt/rocm-6.4.3 rocblas: buildable: false externals: - spec: rocblas@6.3.1 prefix: /opt/rocm-6.3.1/ - - spec: rocblas@6.4.2 - prefix: /opt/rocm-6.4.2/ + - spec: rocblas@6.4.3 + prefix: /opt/rocm-6.4.3/ rocminfo: buildable: false externals: - spec: rocminfo@6.3.1 prefix: /opt/rocm-6.3.1 - - spec: rocminfo@6.4.2 - prefix: /opt/rocm-6.4.2 + - spec: rocminfo@6.4.3 + prefix: /opt/rocm-6.4.3 rocprim: buildable: false externals: - spec: rocprim@6.3.1 prefix: /opt/rocm-6.3.1/ - - spec: rocprim@6.4.2 - prefix: /opt/rocm-6.4.2 + - spec: rocprim@6.4.3 + prefix: /opt/rocm-6.4.3 rocm-device-libs: buildable: false externals: - spec: rocm-device-libs@6.3.1 prefix: /opt/rocm-6.3.1/ - - spec: rocm-device-libs@6.4.2 - prefix: /opt/rocm-6.4.2 + - spec: rocm-device-libs@6.4.3 + prefix: /opt/rocm-6.4.3 + + rocprofiler-sdk: + buildable: false + externals: + - spec: rocprofiler-sdk@6.4.3 + prefix: /opt/rocm-6.4.3 # Lock down which MPI we are using mpi: @@ -176,10 +182,10 @@ spack: externals: - spec: cray-mpich@8.1.29.rocm_6_3_1+slurm prefix: /usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.3.1/ - - spec: cray-mpich@8.1.29.rocm_6_4_2+slurm - prefix: /usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.2/ + - spec: cray-mpich@8.1.29.rocm_6_4_3+slurm + prefix: /usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.29-rocmcc-6.4.3/ - spec: cray-mpich@8.1.32.cce_20+slurm - prefix: /usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.2-cce-20.0.0/ + prefix: /usr/tce/packages/cray-mpich-tce/cray-mpich-8.1.32-rocmcc-6.4.3/ # blas is a bit more complicated because its a virtual package so fake it with # the following per spack docs @@ -405,59 +411,38 @@ spack: buildable: false externals: - spec: cppcheck@2.18.0 - prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/gcc-13.3.1/cppcheck-2.18.0-prdufaymm4rf6ugi5f2miqbjclhekg6w + prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/gcc-13.3.1/cppcheck-2.18.0-n6kdcwtwlrc3u3t47t7gokpyd4h6mc27 doxygen: - version: [1.13.2] + version: [1.15.0] buildable: false externals: - - spec: doxygen@1.13.2 - prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/doxygen-1.13.2 + - spec: doxygen@1.15.0 + prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/doxygen-1.15.0 py-sphinx: version: [8.0.2] buildable: false externals: - spec: py-sphinx@8.0.2 - prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5 + prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11 python: buildable: false externals: - - spec: python@3.13.5 - prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5 + - spec: python@3.13.11 + prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11 llvm: version: [19.0.0] buildable: false externals: - spec: llvm@19.0.0 - prefix: /usr/tce/packages/rocmcc/rocmcc-6.4.2-magic/llvm + prefix: /usr/tce/packages/rocmcc/rocmcc-6.4.3-magic/llvm - # Other python externals built by devtools for conduit - py-pytest: - buildable: false - externals: - - spec: py-pytest@8.2.1 - prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5 py-jsonschema: buildable: false externals: - spec: py-jsonschema@4.17.3 - prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5 - python-venv: - buildable: false - externals: - - spec: python-venv@1.0 - prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5 - py-pyproject-metadata: - buildable: false - externals: - - spec: py-pyproject-metadata@0.17.1 - prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5 - py-meson-python: - buildable: false - externals: - - spec: py-meson-python@0.16.0 - prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5 - py-numpy: + prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11 + py-yapf: buildable: false externals: - - spec: py-numpy@2.3.2 - prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2025_09_25_12_05_48/view/python-3.13.5 + - spec: py-yapf@0.43.0 + prefix: /collab/usr/gapps/axom/devtools/toss_4_x86_64_ib_cray/2026_02_17_15_20_25/view/python-3.13.11 diff --git a/scripts/spack/configs/versions.yaml b/scripts/spack/configs/versions.yaml index 0a680d628c..cd91af6af0 100644 --- a/scripts/spack/configs/versions.yaml +++ b/scripts/spack/configs/versions.yaml @@ -6,11 +6,11 @@ packages: adiak: require: - spec: "@0.4.0" - # 2.14.0 + # Newer commit than 2.14.0 that fixes rocprofiler dependency caliper: require: - - spec: "@git.9ab0e64d2e328d1fdff2ffebb53f30a899d6a598=master" - # v2025.12.0 + - spec: "@git.7e5b7a5c0eacc077f9b842abf41c9fc7b996ce0c=master" + # v2025.12 camp: require: - spec: "@git.a8caefa9f4c811b1a114b4ed2c9b681d40f12325=main" @@ -36,7 +36,6 @@ packages: scr: require: - spec: "@3.0.1" - # v2025.12.0 umpire: require: - - spec: "@git.0372fbd6e1f17d7e6dd72693f8b857f3ec7559e9=develop" + - spec: "@2025.12.0" diff --git a/scripts/spack/devtools.json b/scripts/spack/devtools.json index 897b90d4ca..e260821364 100644 --- a/scripts/spack/devtools.json +++ b/scripts/spack/devtools.json @@ -4,10 +4,10 @@ "package_source_dir": "../..", "package_final_phase": "", "spack_url": "https://github.com/spack/spack.git", -"spack_commit": "734c5db2121b01c373eed6538e452f18887e9e44", +"spack_commit": "2e2169d5282d166f63e3ee4db8d4446c43cefa8a", "spack_configs_path": "scripts/spack/devtools_configs", "spack_packages_url": "https://github.com/spack/spack-packages.git", -"spack_packages_commit": "a75a7f75182ffc7a51c6ca7f0fec4bf9b2705be8", +"spack_packages_commit": "17ea6a6d483fc0bde1b2cca96ddaad0a10f2ef69", "spack_packages_path": "scripts/spack/packages", "spack_concretizer": "clingo" } diff --git a/scripts/spack/devtools_configs/toss_4_x86_64_ib/spack.yaml b/scripts/spack/devtools_configs/toss_4_x86_64_ib/spack.yaml index f9a03e4e02..53bfc446b5 100644 --- a/scripts/spack/devtools_configs/toss_4_x86_64_ib/spack.yaml +++ b/scripts/spack/devtools_configs/toss_4_x86_64_ib/spack.yaml @@ -18,7 +18,7 @@ spack: view: default: root: ../view - select: [llvm, cppcheck, doxygen, py-sphinx, python, ^python] + select: [llvm, cppcheck, doxygen, py-sphinx, py-yapf, python, ^python] projections: all: '{name}-{version}' @@ -78,7 +78,7 @@ spack: mvapich2: buildable: false externals: - - spec: mvapich2@2.3.7.gcc_13~alloca~cuda~debug~hwloc_graphics~hwlocv2+regcache+wrapperrpath build_system=autotools ch3_rank_bits=32 fabrics=mrail file_systems=auto process_managers=slurm threads=multiple + - spec: mvapich2@2.3.7.gcc_13~alloca~cuda~debug~hwloc_graphics~hwlocv2+regcache+wrapperrpath ch3_rank_bits=32 fabrics=mrail file_systems=auto process_managers=slurm threads=multiple prefix: /usr/tce/packages/mvapich2/mvapich2-2.3.7-gcc-13.3.1 netlib-lapack: diff --git a/scripts/spack/packages/axom/package.py b/scripts/spack/packages/axom/package.py index 0a5b6eb156..13d65d0872 100644 --- a/scripts/spack/packages/axom/package.py +++ b/scripts/spack/packages/axom/package.py @@ -39,15 +39,20 @@ from spack.package import * -def get_spec_path(spec, package_name, path_replacements={}, use_bin=False): +def get_spec_path(spec, package_name, path_replacements={}, use_bin=False, use_lib=False): """Extracts the prefix path for the given spack package path_replacements is a dictionary with string replacements for the path. """ - if not use_bin: - path = spec[package_name].prefix - else: + if use_bin and use_lib: + raise ValueError("Only one of use_bin or use_lib can be True") + + if use_bin: path = spec[package_name].prefix.bin + elif use_lib: + path = spec[package_name].prefix.lib + else: + path = spec[package_name].prefix path = os.path.realpath(path) @@ -73,6 +78,7 @@ class Axom(CachedCMakePackage, CudaPackage, ROCmPackage): version("main", branch="main") version("develop", branch="develop") + version("0.13.0", tag="v0.13.0", commit="d00f6c66ef390ad746ae840f1074d982513611ac") version("0.12.0", tag="v0.12.0", commit="297544010a3dfb98145a1a85f09f9c648c00a18c") version("0.11.0", tag="v0.11.0", commit="685960486aa55d3a74a821ee02f6d9d9a3e67ab1") version("0.10.1", tag="v0.10.1", commit="6626ee1c5668176fb64dd9a52dec3e8596b3ba6b") @@ -121,9 +127,10 @@ class Axom(CachedCMakePackage, CudaPackage, ROCmPackage): variant( "profiling", default=False, - when="@:0.12.0", + when="@:0.12", description="Build with hooks for Adiak/Caliper performance analysis. " - "Deprecated -- use the adiak and/or caliper variants directly.", + "Deprecated -- use the adiak and/or caliper variants directly " + "versions 0.13.0 and onwards.", ) # variant for Axom components @@ -132,15 +139,16 @@ class Axom(CachedCMakePackage, CudaPackage, ROCmPackage): description=( "Comma separated list of Axom components to enable. " "'all' enables all components; 'none' disables all components " - "Missing dependencies will be added (e.g. we'll add `sidre` and `conduit` for `components=inlet`)" + "Missing dependencies will be added (e.g. we'll add `sidre` " + "and `conduit` for `components=inlet`)" ), values=any_combination_of("all", *_AXOM_COMPONENTS).with_default("all"), ) # variants for package dependencies - variant("adiak", default=False, description="Build with adiak") + variant("adiak", default=False, when="@0.13:", description="Build with adiak") + variant("caliper", default=False, when="@0.13:", description="Build with caliper") variant("c2c", default=False, description="Build with c2c") - variant("caliper", default=False, description="Build with caliper") variant("conduit", default=True, description="Build with conduit") variant("hdf5", default=True, description="Build with hdf5") variant("lua", default=True, description="Build with Lua") @@ -170,6 +178,8 @@ class Axom(CachedCMakePackage, CudaPackage, ROCmPackage): depends_on("blt", type="build") depends_on("blt@0.5.1:0.5.3", type="build", when="@0.6.1:0.8") depends_on("blt@0.6.2:", type="build", when="@0.9:") + depends_on("blt@0.7", type="build", when="@0.11:") + depends_on("blt@0.7.1:", type="build", when="@0.12:") depends_on("mpi", when="+mpi") @@ -180,9 +190,6 @@ class Axom(CachedCMakePackage, CudaPackage, ROCmPackage): depends_on("conduit+{0}".format(_var), when="+{0}".format(_var)) depends_on("conduit~{0}".format(_var), when="~{0}".format(_var)) - depends_on("conduit+python", when="+devtools") - depends_on("conduit~python", when="~devtools") - depends_on("hdf5", when="+hdf5") depends_on("lua", when="+lua") @@ -192,6 +199,7 @@ class Axom(CachedCMakePackage, CudaPackage, ROCmPackage): with when("+umpire"): depends_on("umpire") + depends_on("umpire@2025.12:", when="@0.13:") depends_on("umpire@2025.09.0:", when="@0.10:") depends_on("umpire@2024.02.0:", when="@0.9:") depends_on("umpire@2022.03.0:2023.06", when="@0.7.0:0.8") @@ -202,6 +210,7 @@ class Axom(CachedCMakePackage, CudaPackage, ROCmPackage): with when("+raja"): depends_on("raja") + depends_on("raja@2025.12.1:", when="@0.13:") depends_on("raja@2025.09.0:", when="@0.10:") depends_on("raja@2024.02.0:", when="@0.9:") depends_on("raja@2022.03.0:2023.06", when="@0.7.0:0.8") @@ -210,18 +219,31 @@ class Axom(CachedCMakePackage, CudaPackage, ROCmPackage): depends_on("raja~openmp", when="~openmp") depends_on("raja+openmp", when="+openmp") - # we're planning to remove support for the profiling variant, but still need to support it for now + # we're planning to remove support for the profiling variant, + # but still need to support it for now depends_on("adiak", when="+adiak") depends_on("caliper", when="+caliper") with when("+profiling"): depends_on("adiak") depends_on("caliper") - with when("^adiak"): + depends_on("caliper+cuda", when="+cuda") + depends_on("caliper~cuda", when="~cuda") + + depends_on("caliper+rocm", when="+rocm") + depends_on("caliper~rocm", when="~rocm") + + for dep in ["adiak", "caliper"]: + depends_on(f"{dep}+mpi", when="+mpi") + depends_on(f"{dep}~mpi", when="~mpi") + depends_on(f"{dep}+shared", when="+shared") + depends_on(f"{dep}~shared", when="~shared") + + with when("+adiak"): for fwd in ("mpi", "shared"): depends_on(f"adiak+{fwd}", when=f"+{fwd}") - with when("^caliper"): + with when("+caliper"): for fwd in ("cuda", "rocm", "mpi", "shared"): depends_on(f"caliper+{fwd}", when=f"+{fwd}") @@ -229,14 +251,17 @@ class Axom(CachedCMakePackage, CudaPackage, ROCmPackage): ext_cuda_dep = f"+cuda cuda_arch={val}" depends_on(f"raja {ext_cuda_dep}", when=f"+raja {ext_cuda_dep}") depends_on(f"umpire {ext_cuda_dep}", when=f"+umpire {ext_cuda_dep}") - depends_on(f"caliper {ext_cuda_dep}", when=f"^caliper {ext_cuda_dep}") + depends_on(f"caliper {ext_cuda_dep}", when=f"+caliper {ext_cuda_dep}") + depends_on(f"caliper {ext_cuda_dep}", when=f"+profiling {ext_cuda_dep}") + depends_on(f"mfem {ext_cuda_dep}", when=f"+mfem {ext_cuda_dep}") for val in ROCmPackage.amdgpu_targets: ext_rocm_dep = f"+rocm amdgpu_target={val}" depends_on(f"raja {ext_rocm_dep}", when=f"+raja {ext_rocm_dep}") depends_on(f"umpire {ext_rocm_dep}", when=f"+umpire {ext_rocm_dep}") - depends_on(f"caliper {ext_rocm_dep}", when=f"^caliper {ext_rocm_dep}") + depends_on(f"caliper {ext_rocm_dep}", when=f"+caliper {ext_rocm_dep}") + depends_on(f"caliper {ext_rocm_dep}", when=f"+profiling {ext_rocm_dep}") depends_on(f"mfem {ext_rocm_dep}", when=f"+mfem {ext_rocm_dep}") depends_on("rocprim", when="+rocm") @@ -251,6 +276,13 @@ class Axom(CachedCMakePackage, CudaPackage, ROCmPackage): depends_on("python", when="+python") + # Python + with when("+python"): + depends_on("py-nanobind@2.7.0") + depends_on("py-pytest") + depends_on("py-numpy") + depends_on("conduit+python") + # Devtools with when("+devtools"): depends_on("cppcheck") @@ -259,8 +291,8 @@ class Axom(CachedCMakePackage, CudaPackage, ROCmPackage): depends_on("python") depends_on("py-sphinx") depends_on("py-shroud") - depends_on("py-pytest") depends_on("py-jsonschema") + depends_on("py-yapf") # Need clang@19 for clang-format # (ENABLE_CLANGFORMAT will be OFF if not the exact version) @@ -271,14 +303,12 @@ class Axom(CachedCMakePackage, CudaPackage, ROCmPackage): # ----------------------------------------------------------------------- # Hard inter-component dependencies taken from Axom's dependency graph. requires(f"components={','.join(_AXOM_COMPONENTS)}", when="components=all") - for c in _AXOM_COMPONENTS: - conflicts(f"components={c}", when="components=none") - requires("components=slic,spin,primal", when="components=bump") + requires("components=sidre,slic,spin,primal", when="components=bump") requires("components=sidre,slic,primal", when="components=inlet") requires("components=sidre,slic,inlet,primal", when="components=klee") requires("components=slic,slam", when="components=mint") - requires("components=bump,slic,slam,primal", when="components=mir") + requires("components=bump,sidre,slic,slam,primal", when="components=mir") requires("components=slic,slam", when="components=multimat") requires("components=slic", when="components=primal") requires("components=slic,slam,primal,mint,spin", when="components=quest") @@ -313,10 +343,6 @@ class Axom(CachedCMakePackage, CudaPackage, ROCmPackage): conflicts("~umpire", when="+cuda") conflicts("~umpire", when="+rocm") - # The 'profiling' variant is deprecated after v0.12, but spack doesn't - # give a reasonable error/warning message if it is set - conflicts("+profiling", when="@develop") - conflicts("^blt@:0.3.6", when="+rocm") def flag_handler(self, name, flags): @@ -655,7 +681,7 @@ def initconfig_package_entries(self): ################################## entries.append("#------------------{0}".format("-" * 60)) - entries.append("# Devtools") + entries.append("# Devtools & Python") entries.append("#------------------{0}\n".format("-" * 60)) # Add common prefix to path replacement list @@ -673,6 +699,7 @@ def initconfig_package_entries(self): entries.append(cmake_cache_option("ENABLE_CLANGFORMAT", False)) if spec.satisfies("+python") or spec.satisfies("+devtools"): + # Get path to python executable python_bin_dir = get_spec_path(spec, "python", path_replacements, use_bin=True) entries.append(cmake_cache_path("Python_EXECUTABLE", pjoin(python_bin_dir, "python3"))) @@ -690,6 +717,12 @@ def initconfig_package_entries(self): cmake_cache_path("SPHINX_EXECUTABLE", pjoin(sphinx_bin_dir, "sphinx-build")) ) + if spec.satisfies("^py-yapf"): + yapf_bin_dir = get_spec_path(spec, "py-yapf", path_replacements, use_bin=True) + entries.append( + cmake_cache_path("YAPF_EXECUTABLE", pjoin(yapf_bin_dir, "yapf")) + ) + if spec.satisfies("^py-shroud"): shroud_bin_dir = get_spec_path(spec, "py-shroud", path_replacements, use_bin=True) entries.append(cmake_cache_path("SHROUD_EXECUTABLE", pjoin(shroud_bin_dir, "shroud"))) @@ -701,6 +734,14 @@ def initconfig_package_entries(self): cmake_cache_path("%s_EXECUTABLE" % dep.upper(), pjoin(dep_bin_dir, dep)) ) + if spec.satisfies("+python"): + # pytest requires pluggy and iniconfig + for dep in ("py-nanobind", "py-pytest", "py-numpy", "py-pluggy", "py-iniconfig"): + if spec.satisfies("^{0}".format(dep)): + dep_dir = get_spec_path(spec, dep, path_replacements, use_lib=True) + py_libdir = join_path(dep_dir, f"python{spec['python'].version.up_to(2)}", "site-packages") + entries.append(cmake_cache_path("%s_DIR" % dep.upper().replace("-", "_"), py_libdir)) + return entries def cmake_args(self): diff --git a/scripts/spack/packages/axomdevtools/package.py b/scripts/spack/packages/axomdevtools/package.py index 51f8558ccd..fb01ac7660 100644 --- a/scripts/spack/packages/axomdevtools/package.py +++ b/scripts/spack/packages/axomdevtools/package.py @@ -20,17 +20,18 @@ class Axomdevtools(BundlePackage): # 3.13 is bugfix/stable release depends_on("python@3.13") - depends_on("doxygen") + + # 1.15.0 is latest release that compiles + depends_on("doxygen@1.15.0") + depends_on("cppcheck+rules") depends_on("graphviz") depends_on("py-sphinx") depends_on("py-shroud") depends_on("py-sphinxcontrib-jquery") + depends_on("py-yapf@0.43.0") # 4.18 builds py-rpds-py, which then needs rust... depends_on("py-jsonschema@4.17") - depends_on("py-nanobind@2.7.0") - depends_on("py-pytest") - depends_on("py-numpy") depends_on("llvm+clang@19") diff --git a/scripts/spack/packages/conduit/package.py b/scripts/spack/packages/conduit/package.py deleted file mode 100644 index cba8ef1969..0000000000 --- a/scripts/spack/packages/conduit/package.py +++ /dev/null @@ -1,9 +0,0 @@ -import os - -from spack.package import * -from spack_repo.builtin.packages.conduit.package import Conduit as BuiltinConduit - -class Conduit(BuiltinConduit): - version("0.9.5", sha256="d93294efbf0936da5a27941e13486aa1a04a74a59285786a2303eed19a24265a") - version("0.9.4", sha256="c9edfb2ff09890084313ad9c2d83bfb7c10e70b696980762d1ae1488f9f08e6c") - version("0.9.3", sha256="2968fa8df6e6c43800c019a008ef064ee9995dc2ff448b72dc5017c188a2e6d4") diff --git a/scripts/spack/radiuss-spack-configs b/scripts/spack/radiuss-spack-configs deleted file mode 160000 index b39030f680..0000000000 --- a/scripts/spack/radiuss-spack-configs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b39030f680263f6c15c7dfe510fa6ffdb9482136 diff --git a/scripts/spack/specs.json b/scripts/spack/specs.json index 0aca4b996c..733749cc41 100644 --- a/scripts/spack/specs.json +++ b/scripts/spack/specs.json @@ -15,31 +15,34 @@ "__comment__":"##############################################################################", "__comment__":"# mfem disabled for intel (icpx compiler error)", + "__comment__":"# python disabled for intel (mixed compiler conduit/caliper MPI spack compiler error)", "__comment__":"# Configs are for dane/rzwhippet", + "__comment__":"# Order matters - if ~python spec is built last this removes view of python", "toss_4_x86_64_ib": - [ "+devtools+hdf5+mfem+c2c+scr+adiak+caliper %gcc_13", - "+devtools+hdf5+mfem+c2c+scr+adiak+caliper+opencascade %clang_19", - "+devtools+hdf5~mfem+c2c+adiak+caliper %intel_25" ], + [ "~python+devtools+hdf5~mfem+c2c+adiak+caliper %intel_25", + "+python+devtools+hdf5+mfem+c2c+scr+adiak+caliper %gcc_13", + "+python+devtools+hdf5+mfem+c2c+scr+adiak+caliper+opencascade %clang_19"], "__comment__":"# Configs are for rzvector", "rzvector": - [ "+devtools+mfem+c2c+adiak+caliper+cuda cuda_arch=90 %gcc_13", - "+devtools+mfem+c2c+adiak+caliper+cuda cuda_arch=90 %clang_19"], + [ "+python+devtools+mfem+c2c+adiak+caliper+cuda cuda_arch=90 %gcc_13", + "+python+devtools+mfem+c2c+adiak+caliper+cuda cuda_arch=90 %clang_19"], "__comment__":"# Configs are for matrix", "matrix": - [ "+devtools+mfem+c2c+adiak+caliper+cuda cuda_arch=90 %gcc_13", - "+devtools+mfem+c2c+adiak+caliper+cuda cuda_arch=90 %clang_19"], + [ "+python+devtools+mfem+c2c+adiak+caliper+cuda cuda_arch=90 %gcc_13", + "+python+devtools+mfem+c2c+adiak+caliper+cuda cuda_arch=90 %clang_19"], "__comment__":"# Use amdgpu_target=gfx942 for rzadams", "__comment__":"# Use amdgpu_target=gfx90a for tioga/rzvernal", "__comment__":"# Use amdgpu_target=gfx908 for rznevada", "__comment__":"# -Wno-int-conversion flag needed for building HDF5", + "__comment__":"# caliper disabled for rocm@6.3.1, fails to compile", "toss_4_x86_64_ib_cray": - [ "+devtools~openmp+mfem+c2c+adiak+caliper+rocm amdgpu_target=gfx942,gfx90a %rocm_6_4_2 ^hip@6.4.2 ^hipblas@6.4.2 ^hipsparse@6.4.2 ^hsa-rocr-dev@6.4.2 ^rocprim@6.4.2 ^mfem+raja+umpire ^raja~openmp+rocm ^umpire~openmp+rocm ^hdf5 cflags=-Wno-int-conversion", - "+devtools~openmp+mfem+c2c+adiak+caliper+rocm amdgpu_target=gfx942,gfx90a %rocm_6_3_1 ^hip@6.3.1 ^hipblas@6.3.1 ^hipsparse@6.3.1 ^hsa-rocr-dev@6.3.1 ^rocprim@6.3.1 ^mfem+raja+umpire ^raja~openmp+rocm ^umpire~openmp+rocm ^hdf5 cflags=-Wno-int-conversion", - "+devtools~openmp+mfem+c2c+adiak+caliper+rocm amdgpu_target=gfx942,gfx90a %cce_20 ^hip@6.4.2 ^hipblas@6.4.2 ^hipsparse@6.4.2 ^hsa-rocr-dev@6.4.2 ^rocprim@6.4.2 ^mfem+raja+umpire ^raja~openmp+rocm ^umpire~openmp+rocm ^hdf5 cflags=-Wno-int-conversion" ], + [ "+python+devtools~openmp+mfem+c2c+adiak+caliper+rocm amdgpu_target=gfx942,gfx90a %rocm_6_4_3 ^hip@6.4.3 ^hipblas@6.4.3 ^hipsparse@6.4.3 ^hsa-rocr-dev@6.4.3 ^rocprim@6.4.3 ^mfem+raja+umpire ^raja~openmp+rocm ^umpire~openmp+rocm ^hdf5 cflags=-Wno-int-conversion", + "+python+devtools~openmp+mfem+c2c+adiak~caliper+rocm amdgpu_target=gfx942,gfx90a %rocm_6_3_1 ^hip@6.3.1 ^hipblas@6.3.1 ^hipsparse@6.3.1 ^hsa-rocr-dev@6.3.1 ^rocprim@6.3.1 ^mfem+raja+umpire ^raja~openmp+rocm ^umpire~openmp+rocm ^hdf5 cflags=-Wno-int-conversion", + "+python+devtools~openmp+mfem+c2c+adiak+caliper+rocm amdgpu_target=gfx942,gfx90a %cce_20 ^hip@6.4.3 ^hipblas@6.4.3 ^hipsparse@6.4.3 ^hsa-rocr-dev@6.4.3 ^rocprim@6.4.3 ^caliper~shared ^mfem+raja+umpire ^raja~openmp+rocm ^umpire~openmp+rocm ^hdf5 cflags=-Wno-int-conversion" ], "darwin-x86_64": - [ "clang@9.0.0+devtools+mfem" ] + [ "+python+devtools+mfem %clang@9.0.0" ] } diff --git a/src/.style.yapf b/src/.style.yapf new file mode 100755 index 0000000000..115b513d4e --- /dev/null +++ b/src/.style.yapf @@ -0,0 +1,10 @@ +[style] +# Base style +based_on_style = pep8 + +# Column / line length +column_limit = 100 + +split_before_logical_operator = true + +spaces_around_power_operator = true diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b4f315aca6..362e28914d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -55,8 +55,7 @@ if (“${PROJECT_SOURCE_DIR}” STREQUAL “${CMAKE_SOURCE_DIR}”) VALGRIND ASTYLE CMAKEFORMAT - UNCRUSTIFY - YAPF) + UNCRUSTIFY) foreach(_tool ${_unused_blt_tools}) set(ENABLE_${_tool} OFF CACHE BOOL "") endforeach() @@ -69,7 +68,8 @@ if (“${PROJECT_SOURCE_DIR}” STREQUAL “${CMAKE_SOURCE_DIR}”) CLANGAPPLYREPLACEMENTS CPPCHECK DOXYGEN - SPHINX) + SPHINX + YAPF) foreach(_tool ${_used_blt_tools}) if(NOT ${_tool}_EXECUTABLE) set(ENABLE_${_tool} OFF CACHE BOOL "") @@ -79,6 +79,7 @@ if (“${PROJECT_SOURCE_DIR}” STREQUAL “${CMAKE_SOURCE_DIR}”) endforeach() set(BLT_REQUIRED_CLANGFORMAT_VERSION "19" CACHE STRING "") + set(BLT_REQUIRED_YAPF_VERSION "0.43.0" CACHE STRING "") configure_file(${CMAKE_CURRENT_SOURCE_DIR}/.clang-tidy ${CMAKE_CURRENT_BINARY_DIR}/.clang-tidy COPYONLY) diff --git a/src/axom/bump/BlendData.hpp b/src/axom/bump/BlendData.hpp index cd517ae1b0..22ab0e2cf5 100644 --- a/src/axom/bump/BlendData.hpp +++ b/src/axom/bump/BlendData.hpp @@ -64,6 +64,19 @@ struct BlendData CoeffView m_blendCoeffView {}; //!< Weights that make up blend groups. }; +/*! + * \brief Return the number of blend groups in the BlendData (the number of values produced from the BlendData) + * + * \param blend The BlendData we're querying. + * + * \return The number of blend groups in the BlendData. + */ +AXOM_HOST_DEVICE +inline axom::IndexType numberOfValues(const BlendData &blend) +{ + return blend.m_blendGroupSizesView.size(); +} + } // end namespace bump } // end namespace axom diff --git a/src/axom/bump/CMakeLists.txt b/src/axom/bump/CMakeLists.txt index 370130235d..d897086be7 100644 --- a/src/axom/bump/CMakeLists.txt +++ b/src/axom/bump/CMakeLists.txt @@ -11,7 +11,7 @@ # Check necessary dependencies #------------------------------------------------------------------------------ axom_component_requires(NAME BUMP - COMPONENTS SLIC SPIN PRIMAL + COMPONENTS SLIC SIDRE SPIN PRIMAL TPLS Conduit) #------------------------------------------------------------------------------ @@ -37,6 +37,7 @@ set(bump_headers extraction/TableManager.hpp data/MeshTester.hpp io/save.hpp + utilities/conduit_array_view.hpp utilities/blueprint_utilities.hpp utilities/conduit_memory.hpp utilities/conduit_traits.hpp @@ -123,6 +124,7 @@ set(bump_sources extraction/tables/cutting/CutCasesWedge.cpp data/MeshTester.cpp io/save.cpp + utilities/conduit_memory.cpp utilities/conduit_traits.cpp utilities/blueprint_utilities.cpp views/MaterialView.cpp @@ -133,7 +135,7 @@ set(bump_sources #------------------------------------------------------------------------------ # Build and install the library #------------------------------------------------------------------------------ -set(bump_depends_on core slic spin primal conduit::conduit) +set(bump_depends_on core slic spin sidre primal conduit::conduit) blt_list_append( TO bump_depends_on ELEMENTS RAJA IF RAJA_FOUND ) axom_add_library( @@ -155,4 +157,3 @@ axom_install_component(NAME bump if (AXOM_ENABLE_TESTS) add_subdirectory(tests) endif() - diff --git a/src/axom/bump/CoordsetBlender.hpp b/src/axom/bump/CoordsetBlender.hpp index 6203108ee6..68c6c49442 100644 --- a/src/axom/bump/CoordsetBlender.hpp +++ b/src/axom/bump/CoordsetBlender.hpp @@ -13,6 +13,7 @@ #include "axom/bump/BlendData.hpp" #include "axom/primal/geometry/Point.hpp" #include "axom/primal/geometry/Vector.hpp" +#include "axom/sidre/core/ConduitMemory.hpp" #include "axom/slic.hpp" #include @@ -53,7 +54,8 @@ class CoordsetBlender void execute(const BlendData &blend, const CoordsetViewType &view, const conduit::Node &n_input, - conduit::Node &n_output) const + conduit::Node &n_output, + int allocator_id = axom::execution_space::allocatorID()) const { using value_type = typename CoordsetViewType::value_type; using PointType = typename CoordsetViewType::PointType; @@ -67,8 +69,7 @@ class CoordsetBlender const auto nComponents = axes.size(); SLIC_ASSERT(PointType::DIMENSION == nComponents); - // Get the ID of a Conduit allocator that will allocate through Axom with device allocator allocatorID. - utils::ConduitAllocateThroughAxom c2a; + const auto conduitAllocatorId = axom::sidre::ConduitMemory::axomAllocIdToConduit(allocator_id); n_output.reset(); n_output["type"] = "explicit"; @@ -85,7 +86,7 @@ class CoordsetBlender { // Allocate data in the Conduit node and make a view. conduit::Node &comp = n_values[axes[i]]; - comp.set_allocator(c2a.getConduitAllocatorID()); + comp.set_allocator(conduitAllocatorId); comp.set(conduit::DataType(utils::cpp2conduit::id, outputSize)); compViews[i] = utils::make_array_view(comp); } diff --git a/src/axom/bump/CoordsetExtents.hpp b/src/axom/bump/CoordsetExtents.hpp index 1bd1a325f0..7102543f11 100644 --- a/src/axom/bump/CoordsetExtents.hpp +++ b/src/axom/bump/CoordsetExtents.hpp @@ -150,7 +150,30 @@ class CoordsetExtents * * \param coordsetView The coordset view that wraps the coordset to be examined. */ - CoordsetExtents(const CoordsetView &coordsetView) : m_coordsetView(coordsetView) { } + CoordsetExtents(const CoordsetView &coordsetView) + : m_coordsetView(coordsetView) + , m_allocator_id(axom::execution_space::allocatorID()) + { } + + /*! + * \brief Set the allocator id to use when allocating memory. + * + * \param allocator_id The allocator id to use when allocating memory. + */ + void setAllocatorID(int allocator_id) + { + SLIC_ERROR_IF(!axom::isValidAllocatorID(allocator_id), "Invalid allocator id."); + SLIC_ERROR_IF(!axom::execution_space::usesAllocId(allocator_id), + "Allocator id is not compatible with execution space."); + m_allocator_id = allocator_id; + } + + /*! + * \brief Get the allocator id to use when allocating memory. + * + * \return The allocator id to use when allocating memory. + */ + int getAllocatorID() const { return m_allocator_id; } /*! * \brief Compute the spatial extents of the coordset and bring results to the host. @@ -159,7 +182,7 @@ class CoordsetExtents */ void execute(double extents[NVALUES]) const { - const int allocatorID = axom::execution_space::allocatorID(); + const int allocatorID = getAllocatorID(); axom::Array deviceExtents(NVALUES, NVALUES, allocatorID); auto deviceExtentsView = deviceExtents.view(); computeExtents(deviceExtentsView); @@ -187,6 +210,7 @@ class CoordsetExtents } CoordsetView m_coordsetView; + int m_allocator_id; }; } // end namespace bump diff --git a/src/axom/bump/CoordsetSlicer.hpp b/src/axom/bump/CoordsetSlicer.hpp index 30c0534bf1..35cc3dfaac 100644 --- a/src/axom/bump/CoordsetSlicer.hpp +++ b/src/axom/bump/CoordsetSlicer.hpp @@ -7,9 +7,11 @@ #define AXOM_BUMP_COORDSET_SLICER_HPP_ #include "axom/core.hpp" +#include "axom/slic.hpp" #include "axom/bump/utilities/conduit_memory.hpp" #include "axom/bump/utilities/conduit_traits.hpp" #include "axom/bump/FieldSlicer.hpp" +#include "axom/sidre/core/ConduitMemory.hpp" #include @@ -33,7 +35,30 @@ class CoordsetSlicer { public: /// Constructor - CoordsetSlicer(const CoordsetView &coordsetView) : m_coordsetView(coordsetView) { } + CoordsetSlicer(const CoordsetView &coordsetView) + : m_coordsetView(coordsetView) + , m_allocator_id(axom::execution_space::allocatorID()) + { } + + /*! + * \brief Set the allocator id to use when allocating memory. + * + * \param allocator_id The allocator id to use when allocating memory. + */ + void setAllocatorID(int allocator_id) + { + SLIC_ERROR_IF(!axom::isValidAllocatorID(allocator_id), "Invalid allocator id."); + SLIC_ERROR_IF(!axom::execution_space::usesAllocId(allocator_id), + "Allocator id is not compatible with execution space."); + m_allocator_id = allocator_id; + } + + /*! + * \brief Get the allocator id to use when allocating memory. + * + * \return The allocator id to use when allocating memory. + */ + int getAllocatorID() const { return m_allocator_id; } /*! * \brief Execute the slice on the \a n_input coordset and store the new sliced coordset in \a n_output. @@ -58,8 +83,8 @@ class CoordsetSlicer SLIC_ASSERT(PointType::DIMENSION == nComponents); SLIC_ASSERT(slice.m_indicesView.size() > 0); - // Get the ID of a Conduit allocator that will allocate through Axom with device allocator allocatorID. - utils::ConduitAllocateThroughAxom c2a; + const auto conduitAllocatorId = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); n_output.reset(); n_output["type"] = "explicit"; @@ -74,7 +99,7 @@ class CoordsetSlicer { // Allocate data in the Conduit node and make a view. conduit::Node &comp = n_values[axes[i]]; - comp.set_allocator(c2a.getConduitAllocatorID()); + comp.set_allocator(conduitAllocatorId); comp.set(conduit::DataType(utils::cpp2conduit::id, outputSize)); compViews[i] = utils::make_array_view(comp); } @@ -98,6 +123,7 @@ class CoordsetSlicer private: CoordsetView m_coordsetView; + int m_allocator_id; }; } // end namespace bump diff --git a/src/axom/bump/ExtractZones.hpp b/src/axom/bump/ExtractZones.hpp index 8fa7750497..91657ada3a 100644 --- a/src/axom/bump/ExtractZones.hpp +++ b/src/axom/bump/ExtractZones.hpp @@ -8,12 +8,14 @@ #define AXOM_BUMP_EXTRACT_ZONES_HPP #include "axom/core.hpp" +#include "axom/slic.hpp" #include "axom/bump/CoordsetBlender.hpp" #include "axom/bump/CoordsetSlicer.hpp" #include "axom/bump/FieldSlicer.hpp" #include "axom/bump/MatsetSlicer.hpp" #include "axom/bump/Options.hpp" #include "axom/bump/views/view_traits.hpp" +#include "axom/sidre/core/ConduitMemory.hpp" namespace axom { @@ -45,6 +47,7 @@ class ExtractZones : m_topologyView(topoView) , m_coordsetView(coordsetView) , m_zoneSlice() + , m_allocator_id(axom::execution_space::allocatorID()) { } /*! @@ -53,6 +56,26 @@ class ExtractZones */ virtual ~ExtractZones() = default; + /*! + * \brief Set the allocator id to use when allocating memory. + * + * \param allocator_id The allocator id to use when allocating memory. + */ + void setAllocatorID(int allocator_id) + { + SLIC_ERROR_IF(!axom::isValidAllocatorID(allocator_id), "Invalid allocator id."); + SLIC_ERROR_IF(!axom::execution_space::usesAllocId(allocator_id), + "Allocator id is not compatible with execution space."); + m_allocator_id = allocator_id; + } + + /*! + * \brief Get the allocator id to use when allocating memory. + * + * \return The allocator id to use when allocating memory. + */ + int getAllocatorID() const { return m_allocator_id; } + /*! * \brief Select zones from the input mesh by id and output them in the output mesh. * @@ -139,13 +162,14 @@ class ExtractZones // Make originalElements. if(makeOriginalZones) { - utils::ConduitAllocateThroughAxom c2a; + const auto conduitAllocatorId = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); conduit::Node &n_outFields = n_output["fields"]; conduit::Node &n_origElements = n_outFields[opts.originalElementsField()]; n_origElements["topology"] = newTopoName; n_origElements["association"] = "element"; - n_origElements["values"].set_allocator(c2a.getConduitAllocatorID()); + n_origElements["values"].set_allocator(conduitAllocatorId); n_origElements["values"].set( conduit::DataType(utils::cpp2conduit::id, selectedZonesView.size())); axom::copy(n_origElements["values"].data_ptr(), @@ -185,9 +209,10 @@ class ExtractZones // We need to make a zone slice array that contains selectedZonesView, plus extra indices. if(m_zoneSlice.size() == 0) { - const int allocatorID = axom::execution_space::allocatorID(); + const int allocatorID = getAllocatorID(); const auto n = selectedZonesView.size() + extra.zones; - m_zoneSlice = axom::Array(n, n, allocatorID); + m_zoneSlice = + axom::Array(axom::ArrayOptions::Uninitialized(), n, n, allocatorID); view = m_zoneSlice.view(); axom::copy(view.data(), selectedZonesView.data(), @@ -252,32 +277,48 @@ class ExtractZones axom::Array &nodeSlice) const { AXOM_ANNOTATE_SCOPE("nodeMap"); - const int allocatorID = axom::execution_space::allocatorID(); + const int allocatorID = getAllocatorID(); const auto nnodes = m_coordsetView.numberOfNodes(); // Figure out the topology size based on selected zones. - axom::ReduceSum connsize_reduce(0); - const TopologyView deviceTopologyView(m_topologyView); - axom::for_all( - selectedZonesView.size(), - AXOM_LAMBDA(axom::IndexType szIndex) { - const auto zoneIndex = selectedZonesView[szIndex]; - const auto zone = deviceTopologyView.zone(zoneIndex); - connsize_reduce += zone.numberOfNodes(); - }); - const auto newConnSize = connsize_reduce.get(); + axom::IndexType newConnSize {}; + if constexpr(!TopologyView::ShapeType::is_variable_size()) + { + // If all shapes are the same size then we do not have to examine each zone. + newConnSize = selectedZonesView.size() * TopologyView::ShapeType::numberOfNodes(); + } + else + { + axom::ReduceSum connsize_reduce(0); + const TopologyView deviceTopologyView(m_topologyView); + axom::for_all( + selectedZonesView.size(), + AXOM_LAMBDA(axom::IndexType szIndex) { + const auto zoneIndex = selectedZonesView[szIndex]; + const auto zone = deviceTopologyView.zone(zoneIndex); + connsize_reduce += zone.numberOfNodes(); + }); + newConnSize = connsize_reduce.get(); + } + if(!selectedZonesView.empty()) + { + SLIC_ERROR_IF(newConnSize == 0, "ReduceSum returned 0 for newConnSize."); + } Sizes sizes {}; sizes.nodes = nnodes; sizes.zones = selectedZonesView.size(); sizes.connectivity = newConnSize; - nodeSlice = - axom::Array(sizes.nodes + extra.nodes, sizes.nodes + extra.nodes, allocatorID); + const auto nodeSliceSize = sizes.nodes + extra.nodes; + nodeSlice = axom::Array(axom::ArrayOptions::Uninitialized(), + nodeSliceSize, + nodeSliceSize, + allocatorID); auto nodeSliceView = nodeSlice.view(); axom::for_all( - sizes.nodes + extra.nodes, + nodeSliceSize, AXOM_LAMBDA(axom::IndexType index) { nodeSliceView[index] = (index < sizes.nodes) ? index : 0; }); @@ -304,11 +345,16 @@ class ExtractZones axom::Array &nodeSlice) const { AXOM_ANNOTATE_SCOPE("compactNodeMap"); - const int allocatorID = axom::execution_space::allocatorID(); + const int allocatorID = getAllocatorID(); + + if(selectedZonesView.empty()) + { + SLIC_INFO("No selected zones were given."); + } // We need to figure out which nodes to keep. const auto nnodes = m_coordsetView.numberOfNodes(); - axom::Array mask(nnodes, nnodes, allocatorID); + axom::Array mask(axom::ArrayOptions::Uninitialized(), nnodes, nnodes, allocatorID); auto maskView = mask.view(); mask.fill(0); @@ -329,23 +375,42 @@ class ExtractZones connsize_reduce += nids; }); const auto newConnSize = connsize_reduce.get(); - - // Count the used nodes. - axom::ReduceSum mask_reduce(0); - axom::for_all( - nnodes, - AXOM_LAMBDA(axom::IndexType index) { mask_reduce += maskView[index]; }); - const int newNumNodes = mask_reduce.get(); + if(!selectedZonesView.empty()) + { + SLIC_ERROR_IF(newConnSize == 0, "ReduceSum returned 0 for newConnSize."); + } // Make a compact list of nodes. - axom::Array maskOffsets(nnodes, nnodes, allocatorID); + axom::Array maskOffsets(axom::ArrayOptions::Uninitialized(), nnodes, nnodes, allocatorID); auto maskOffsetsView = maskOffsets.view(); axom::exclusive_scan(maskView, maskOffsetsView); + // Count the used nodes. + int newNumNodes {}; + if constexpr(axom::execution_space::onDevice()) + { + axom::ReduceSum mask_reduce(0); + axom::for_all( + nnodes, + AXOM_LAMBDA(axom::IndexType index) { mask_reduce += maskView[index]; }); + newNumNodes = mask_reduce.get(); + } + else + { + newNumNodes = maskOffsetsView[nnodes - 1] + maskView[nnodes - 1]; + } + if(nnodes > 0) + { + SLIC_ERROR_IF(newNumNodes == 0, "ReduceSum returned 0 for newNumNodes."); + } + // Make an array of original node ids that we can use to "slice" the nodal data. - old2new = axom::Array(nnodes, nnodes, allocatorID); - nodeSlice = - axom::Array(newNumNodes + extra.nodes, newNumNodes + extra.nodes, allocatorID); + old2new = + axom::Array(axom::ArrayOptions::Uninitialized(), nnodes, nnodes, allocatorID); + nodeSlice = axom::Array(axom::ArrayOptions::Uninitialized(), + newNumNodes + extra.nodes, + newNumNodes + extra.nodes, + allocatorID); auto old2newView = old2new.view(); auto nodeSliceView = nodeSlice.view(); axom::for_all( @@ -394,7 +459,8 @@ class ExtractZones { AXOM_ANNOTATE_SCOPE("makeTopology"); namespace utils = axom::bump::utilities; - utils::ConduitAllocateThroughAxom c2a; + const auto conduitAllocatorId = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); const std::string shape = outputShape(n_topo); if(shape == "polyhedron") @@ -413,19 +479,19 @@ class ExtractZones n_newTopo["elements/shape"] = outputShape(n_topo); conduit::Node &n_conn = n_newTopo["elements/connectivity"]; - n_conn.set_allocator(c2a.getConduitAllocatorID()); + n_conn.set_allocator(conduitAllocatorId); n_conn.set(conduit::DataType(utils::cpp2conduit::id, dataSizes.connectivity + extra.connectivity)); auto connView = utils::make_array_view(n_conn); conduit::Node &n_sizes = n_newTopo["elements/sizes"]; - n_sizes.set_allocator(c2a.getConduitAllocatorID()); + n_sizes.set_allocator(conduitAllocatorId); n_sizes.set( conduit::DataType(utils::cpp2conduit::id, dataSizes.zones + extra.zones)); auto sizesView = utils::make_array_view(n_sizes); conduit::Node &n_offsets = n_newTopo["elements/offsets"]; - n_offsets.set_allocator(c2a.getConduitAllocatorID()); + n_offsets.set_allocator(conduitAllocatorId); n_offsets.set( conduit::DataType(utils::cpp2conduit::id, dataSizes.zones + extra.zones)); auto offsetsView = utils::make_array_view(n_offsets); @@ -501,7 +567,7 @@ class ExtractZones auto shapesView = utils::make_array_view(n_shapes); conduit::Node &n_newShapes = n_newTopo["elements/shapes"]; - n_newShapes.set_allocator(c2a.getConduitAllocatorID()); + n_newShapes.set_allocator(conduitAllocatorId); n_newShapes.set(conduit::DataType(utils::cpp2conduit::id, dataSizes.zones + extra.zones)); auto newShapesView = utils::make_array_view(n_newShapes); @@ -537,6 +603,7 @@ class ExtractZones AXOM_ANNOTATE_SCOPE("makeCoordset"); // _bump_utilities_coordsetslicer_begin axom::bump::CoordsetSlicer cs(m_coordsetView); + cs.setAllocatorID(getAllocatorID()); n_newCoordset.reset(); cs.execute(nodeSlice, n_coordset, n_newCoordset); // _bump_utilities_coordsetslicer_end @@ -567,6 +634,7 @@ class ExtractZones const std::string association = n_field["association"].as_string(); conduit::Node &n_newField = n_newFields[n_field.name()]; axom::bump::FieldSlicer fs; + fs.setAllocatorID(getAllocatorID()); if(association == "element") { fs.execute(zoneSlice, n_field, n_newField); @@ -658,6 +726,7 @@ class ExtractZones TopologyView m_topologyView; CoordsetView m_coordsetView; axom::Array m_zoneSlice; + int m_allocator_id; }; /*! @@ -783,6 +852,7 @@ class ExtractZonesAndMatset : public ExtractZones ms(m_matsetView); + ms.setAllocatorID(this->getAllocatorID()); SliceData zSlice; zSlice.m_indicesView = selectedZonesView; ms.execute(zSlice, n_matset, n_newMatset); diff --git a/src/axom/bump/ExtractZonesAndMatsetPolyhedral.hpp b/src/axom/bump/ExtractZonesAndMatsetPolyhedral.hpp index a0164c3fe9..1cf9a2fd33 100644 --- a/src/axom/bump/ExtractZonesAndMatsetPolyhedral.hpp +++ b/src/axom/bump/ExtractZonesAndMatsetPolyhedral.hpp @@ -13,6 +13,7 @@ #include "axom/bump/CoordsetSlicer.hpp" #include "axom/bump/FieldSlicer.hpp" #include "axom/bump/MatsetSlicer.hpp" +#include "axom/sidre/core/ConduitMemory.hpp" namespace axom { @@ -89,8 +90,8 @@ class ExtractZonesAndMatsetPolyhedral { AXOM_ANNOTATE_SCOPE("makeTopology(polyhedral)"); namespace utils = axom::bump::utilities; - const int allocatorID = axom::execution_space::allocatorID(); - utils::ConduitAllocateThroughAxom c2a; + const int allocatorID = this->getAllocatorID(); + const auto conduitAllocatorId = axom::sidre::ConduitMemory::axomAllocIdToConduit(allocatorID); // We know that we have a 3D structured mesh for which we need to make a // polyhedral output topology. @@ -135,7 +136,7 @@ class ExtractZonesAndMatsetPolyhedral numSelectedZones, AXOM_LAMBDA(axom::IndexType szIndex) { const auto zoneIndex = selectedZonesView[szIndex]; - const auto logicalIndex = deviceTopologyView.indexing().IndexToLogicalIndex(zoneIndex); + const auto logicalIndex = deviceTopologyView.indexing().indexToLogicalIndex(zoneIndex); int faceCount = 0; std::uint8_t zf = ZoneEmpty; @@ -164,7 +165,7 @@ class ExtractZonesAndMatsetPolyhedral // Get the index of the face neighbor. auto logicalNeighbor(logicalIndex); logicalNeighbor[dim] += delta; - const auto neighbor = deviceTopologyView.indexing().LogicalIndexToIndex(logicalNeighbor); + const auto neighbor = deviceTopologyView.indexing().logicalIndexToIndex(logicalNeighbor); // If that neighbor is NOT selected, we need to make the face. makeFace = (zoneFlagsView[neighbor] & ZoneSelected) == 0; @@ -179,6 +180,10 @@ class ExtractZonesAndMatsetPolyhedral faceCount_reduce += faceCount; }); const int faceCount = faceCount_reduce.get(); + if(numSelectedZones > 0) + { + SLIC_ERROR_IF(faceCount == 0, "ReduceSum returned 0 for faceCount."); + } AXOM_ANNOTATE_END("identify"); //-------------------------------------------------------------------------- @@ -198,34 +203,34 @@ class ExtractZonesAndMatsetPolyhedral n_newTopo["subelements/shape"] = "polygonal"; conduit::Node &n_conn = n_newTopo["elements/connectivity"]; - n_conn.set_allocator(c2a.getConduitAllocatorID()); + n_conn.set_allocator(conduitAllocatorId); n_conn.set( conduit::DataType(utils::cpp2conduit::id, numSelectedZones * FacesPerHex)); auto connView = utils::make_array_view(n_conn); conduit::Node &n_sizes = n_newTopo["elements/sizes"]; - n_sizes.set_allocator(c2a.getConduitAllocatorID()); + n_sizes.set_allocator(conduitAllocatorId); n_sizes.set(conduit::DataType(utils::cpp2conduit::id, numSelectedZones)); auto sizesView = utils::make_array_view(n_sizes); conduit::Node &n_offsets = n_newTopo["elements/offsets"]; - n_offsets.set_allocator(c2a.getConduitAllocatorID()); + n_offsets.set_allocator(conduitAllocatorId); n_offsets.set(conduit::DataType(utils::cpp2conduit::id, numSelectedZones)); auto offsetsView = utils::make_array_view(n_offsets); conduit::Node &n_se_conn = n_newTopo["subelements/connectivity"]; - n_se_conn.set_allocator(c2a.getConduitAllocatorID()); + n_se_conn.set_allocator(conduitAllocatorId); n_se_conn.set( conduit::DataType(utils::cpp2conduit::id, faceCount * PointsPerQuad)); auto seConnView = utils::make_array_view(n_se_conn); conduit::Node &n_se_sizes = n_newTopo["subelements/sizes"]; - n_se_sizes.set_allocator(c2a.getConduitAllocatorID()); + n_se_sizes.set_allocator(conduitAllocatorId); n_se_sizes.set(conduit::DataType(utils::cpp2conduit::id, faceCount)); auto seSizesView = utils::make_array_view(n_se_sizes); conduit::Node &n_se_offsets = n_newTopo["subelements/offsets"]; - n_se_offsets.set_allocator(c2a.getConduitAllocatorID()); + n_se_offsets.set_allocator(conduitAllocatorId); n_se_offsets.set(conduit::DataType(utils::cpp2conduit::id, faceCount)); auto seOffsetsView = utils::make_array_view(n_se_offsets); @@ -317,9 +322,9 @@ class ExtractZonesAndMatsetPolyhedral // Get the index of the relevant neighbor. const int dim = queryFace >> 1; // x y z x y z const int delta = (fi < 3) ? -1 : 1; - auto logicalNeighbor = deviceTopologyView.indexing().IndexToLogicalIndex(zoneIndex); + auto logicalNeighbor = deviceTopologyView.indexing().indexToLogicalIndex(zoneIndex); logicalNeighbor[dim] += delta; - const auto neighbor = deviceTopologyView.indexing().LogicalIndexToIndex(logicalNeighbor); + const auto neighbor = deviceTopologyView.indexing().logicalIndexToIndex(logicalNeighbor); // Get whether the neighbor defines the face companion. const auto nzf = zoneFlagsView[neighbor]; diff --git a/src/axom/bump/ExtrudeMesh.hpp b/src/axom/bump/ExtrudeMesh.hpp index e198330b94..0af63b6564 100644 --- a/src/axom/bump/ExtrudeMesh.hpp +++ b/src/axom/bump/ExtrudeMesh.hpp @@ -10,6 +10,7 @@ #include "axom/core.hpp" #include "axom/bump.hpp" #include "axom/slic.hpp" +#include "axom/sidre/core/ConduitMemory.hpp" #include @@ -44,8 +45,29 @@ class ExtrudeMesh ExtrudeMesh(const TopologyView &topoView, const CoordsetView &coordsetView) : m_topologyView(topoView) , m_coordsetView(coordsetView) + , m_allocator_id(axom::execution_space::allocatorID()) { } + /*! + * \brief Set the allocator id to use when allocating memory. + * + * \param allocator_id The allocator id to use when allocating memory. + */ + void setAllocatorID(int allocator_id) + { + SLIC_ERROR_IF(!axom::isValidAllocatorID(allocator_id), "Invalid allocator id."); + SLIC_ERROR_IF(!axom::execution_space::usesAllocId(allocator_id), + "Allocator id is not compatible with execution space."); + m_allocator_id = allocator_id; + } + + /*! + * \brief Get the allocator id to use when allocating memory. + * + * \return The allocator id to use when allocating memory. + */ + int getAllocatorID() const { return m_allocator_id; } + /*! * \brief Execute the extrusion algorithm. * @@ -89,6 +111,7 @@ class ExtrudeMesh const TopologyView topoView = m_topologyView; axom::ReduceSum connSizeReduce(0); axom::ReduceBitOr zoneTypeReduce(0); + constexpr int ErrorBit = 1 << ((sizeof(int) * 8) - 1); axom::for_all( m_topologyView.numberOfZones(), AXOM_LAMBDA(axom::IndexType zi) { @@ -105,17 +128,29 @@ class ExtrudeMesh break; default: SLIC_ASSERT("Unsupported zone type"); + // For release builds + zoneTypeReduce |= ErrorBit; } }); AXOM_ANNOTATE_END("counts"); const auto shapes = zoneTypeReduce.get(); + if(m_topologyView.numberOfZones() > 0 && shapes == 0) + { + SLIC_ERROR("No tri or quad shapes detected."); + } + if((shapes & ErrorBit) > 0) + { + SLIC_ERROR("Unsupported zone type."); + } const axom::IndexType totalConnSize = static_cast(nz - 1) * connSizeReduce.get(); + SLIC_ERROR_IF(totalConnSize == 0, "Invalid connectivity size."); const axom::IndexType totalZones = static_cast(nz - 1) * m_topologyView.numberOfZones(); const axom::IndexType totalNodes = static_cast(nz) * m_coordsetView.numberOfNodes(); - utils::ConduitAllocateThroughAxom c2a; + const auto conduitAllocatorId = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); // Create the new coordset. AXOM_ANNOTATE_BEGIN("coordset"); @@ -127,7 +162,7 @@ class ExtrudeMesh for(int d = 0; d < 3; d++) { conduit::Node &n_value = n_outputCoordset[coordNames[d]]; - n_value.set_allocator(c2a.getConduitAllocatorID()); + n_value.set_allocator(conduitAllocatorId); n_value.set(conduit::DataType(utils::cpp2conduit::id, totalNodes)); values[d] = utils::make_array_view(n_value); } @@ -183,10 +218,10 @@ class ExtrudeMesh conduit::Node &n_offsets = n_outputTopo["elements/offsets"]; using ConnectivityType = typename TopologyView::ConnectivityType; - n_connectivity.set_allocator(c2a.getConduitAllocatorID()); - n_shapes.set_allocator(c2a.getConduitAllocatorID()); - n_sizes.set_allocator(c2a.getConduitAllocatorID()); - n_offsets.set_allocator(c2a.getConduitAllocatorID()); + n_connectivity.set_allocator(conduitAllocatorId); + n_shapes.set_allocator(conduitAllocatorId); + n_sizes.set_allocator(conduitAllocatorId); + n_offsets.set_allocator(conduitAllocatorId); n_connectivity.set(conduit::DataType(utils::cpp2conduit::id, totalConnSize)); n_shapes.set(conduit::DataType(utils::cpp2conduit::id, totalZones)); @@ -354,12 +389,13 @@ class ExtrudeMesh conduit::Node &n_sizes = n_outputMatset["sizes"]; conduit::Node &n_offsets = n_outputMatset["offsets"]; - utils::ConduitAllocateThroughAxom c2a; - n_material_ids.set_allocator(c2a.getConduitAllocatorID()); - n_volume_fractions.set_allocator(c2a.getConduitAllocatorID()); - n_indices.set_allocator(c2a.getConduitAllocatorID()); - n_sizes.set_allocator(c2a.getConduitAllocatorID()); - n_offsets.set_allocator(c2a.getConduitAllocatorID()); + const auto conduitAllocatorId = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); + n_material_ids.set_allocator(conduitAllocatorId); + n_volume_fractions.set_allocator(conduitAllocatorId); + n_indices.set_allocator(conduitAllocatorId); + n_sizes.set_allocator(conduitAllocatorId); + n_offsets.set_allocator(conduitAllocatorId); n_material_ids.set(conduit::DataType(n_src_material_ids.dtype().id(), n_src_material_ids.dtype().number_of_elements() * (nz - 1))); @@ -374,39 +410,39 @@ class ExtrudeMesh n_src_offsets.dtype().number_of_elements() * (nz - 1))); // Extrude the old arrays into the new arrays. - views::FloatNode_to_ArrayView_same(n_src_volume_fractions, - n_volume_fractions, - [&](auto srcVolumeFractionsView, auto volumeFractionsView) { - views::IndexNode_to_ArrayView_same( - n_src_material_ids, - n_src_indices, - n_src_sizes, - n_src_offsets, - n_material_ids, - n_indices, - n_sizes, - n_offsets, - [&](auto srcMaterialIdsView, - auto srcIndicesView, - auto srcSizesView, - auto srcOffsetsView, - auto materialIdsView, - auto indicesView, - auto sizesView, - auto offsetsView) { - copyMatsetData(srcVolumeFractionsView, - volumeFractionsView, - srcMaterialIdsView, - srcIndicesView, - srcSizesView, - srcOffsetsView, - materialIdsView, - indicesView, - sizesView, - offsetsView, - nz); - }); - }); + views::floatNodeToArrayViewSame(n_src_volume_fractions, + n_volume_fractions, + [&](auto srcVolumeFractionsView, auto volumeFractionsView) { + views::indexNodeToArrayViewSame(n_src_material_ids, + n_src_indices, + n_src_sizes, + n_src_offsets, + n_material_ids, + n_indices, + n_sizes, + n_offsets, + [&](auto srcMaterialIdsView, + auto srcIndicesView, + auto srcSizesView, + auto srcOffsetsView, + auto materialIdsView, + auto indicesView, + auto sizesView, + auto offsetsView) { + copyMatsetData( + srcVolumeFractionsView, + volumeFractionsView, + srcMaterialIdsView, + srcIndicesView, + srcSizesView, + srcOffsetsView, + materialIdsView, + indicesView, + sizesView, + offsetsView, + nz); + }); + }); } /*! @@ -458,6 +494,7 @@ class ExtrudeMesh TopologyView m_topologyView; CoordsetView m_coordsetView; + int m_allocator_id; }; } // namespace bump diff --git a/src/axom/bump/FieldBlender.hpp b/src/axom/bump/FieldBlender.hpp index be85df088e..58548d62b6 100644 --- a/src/axom/bump/FieldBlender.hpp +++ b/src/axom/bump/FieldBlender.hpp @@ -7,11 +7,13 @@ #define AXOM_BUMP_FIELD_BLENDER_HPP_ #include "axom/core.hpp" +#include "axom/slic.hpp" #include "axom/bump/views/NodeArrayView.hpp" #include "axom/bump/utilities/utilities.hpp" #include "axom/bump/utilities/conduit_memory.hpp" #include "axom/bump/BlendData.hpp" #include "axom/bump/IndexingPolicies.hpp" +#include "axom/sidre/core/ConduitMemory.hpp" #include @@ -70,13 +72,36 @@ class FieldBlender { public: /// Constructor - FieldBlender() : m_indexing() { } + FieldBlender() : m_indexing(), m_allocator_id(axom::execution_space::allocatorID()) { } /*! * \brief Constructor * \param indexing An object used to transform node indices. */ - FieldBlender(const IndexingPolicy &indexing) : m_indexing(indexing) { } + FieldBlender(const IndexingPolicy &indexing) + : m_indexing(indexing) + , m_allocator_id(axom::execution_space::allocatorID()) + { } + + /*! + * \brief Set the allocator id to use when allocating memory. + * + * \param allocator_id The allocator id to use when allocating memory. + */ + void setAllocatorID(int allocator_id) + { + SLIC_ERROR_IF(!axom::isValidAllocatorID(allocator_id), "Invalid allocator id."); + SLIC_ERROR_IF(!axom::execution_space::usesAllocId(allocator_id), + "Allocator id is not compatible with execution space."); + m_allocator_id = allocator_id; + } + + /*! + * \brief Get the allocator id to use when allocating memory. + * + * \return The allocator id to use when allocating memory. + */ + int getAllocatorID() const { return m_allocator_id; } /*! * \brief Create a new blended field from the \a n_input field and place it in \a n_output. @@ -93,9 +118,10 @@ class FieldBlender const conduit::Node &n_input_values = n_input["values"]; conduit::Node &n_output_values = n_output["values"]; - if(n_input_values.number_of_children() > 0) + const conduit::index_t nc = n_input_values.number_of_children(); + if(nc > 0) { - for(conduit::index_t i = 0; i < n_input_values.number_of_children(); i++) + for(conduit::index_t i = 0; i < nc; i++) { const conduit::Node &n_comp = n_input_values[i]; conduit::Node &n_out_comp = n_output_values[n_comp.name()]; @@ -126,80 +152,80 @@ class FieldBlender { // We're allowing selectedIndicesView to be used to select specific blend // groups. If the user did not provide that, use all blend groups. - const auto origSize = blend.m_originalIdsView.size(); - const auto blendSize = SelectionPolicy::size(blend); - const auto outputSize = origSize + blendSize; + const auto orig_size = blend.m_originalIdsView.size(); + const auto blend_size = SelectionPolicy::size(blend); + const auto output_size = orig_size + blend_size; - // Allocate Conduit data through Axom. - utilities::ConduitAllocateThroughAxom c2a; - n_output_values.set_allocator(c2a.getConduitAllocatorID()); - n_output_values.set(conduit::DataType(n_values.dtype().id(), outputSize)); + const auto conduit_allocator_id = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); + n_output_values.set_allocator(conduit_allocator_id); + n_output_values.set(conduit::DataType(n_values.dtype().id(), output_size)); - views::Node_to_ArrayView_same(n_values, n_output_values, [&](auto compView, auto outView) { - blendSingleComponentImpl(blend, compView, outView); + views::nodeToArrayViewSame(n_values, n_output_values, [&](auto comp_view, auto out_view) { + blendSingleComponentImpl(blend, comp_view, out_view); }); } /*! * \brief Slice the source view and copy values into the output view. * - * \param valuesView The source values view. - * \param outputView The output values view. + * \param comp_view The source values view. + * \param out_view The output values view. * * \note This method was broken out into a template member method since nvcc * would not instantiate the lambda for axom::for_all() from an anonymous * lambda. */ template - void blendSingleComponentImpl(const BlendData &blend, SrcView compView, OutputView outView) const + void blendSingleComponentImpl(const BlendData &blend, SrcView comp_view, OutputView out_view) const { - using value_type = typename decltype(compView)::value_type; + using value_type = typename decltype(comp_view)::value_type; using accum_type = typename utilities::accumulation_traits::type; // We're allowing selectedIndicesView to be used to select specific blend // groups. If the user did not provide that, use all blend groups. - const auto origSize = blend.m_originalIdsView.size(); - const auto blendSize = SelectionPolicy::size(blend); - // const auto outputSize = origSize + blendSize; + const auto orig_size = blend.m_originalIdsView.size(); + const auto blend_size = SelectionPolicy::size(blend); + // const auto output_size = orig_size + blend_size; - const IndexingPolicy deviceIndexing(m_indexing); - const BlendData deviceBlend(blend); + const IndexingPolicy device_indexing(m_indexing); + const BlendData device_blend(blend); // Copy over some original values to the start of the array. axom::for_all( - origSize, + orig_size, AXOM_LAMBDA(axom::IndexType index) { - const auto srcIndex = deviceBlend.m_originalIdsView[index]; - outView[index] = compView[srcIndex]; + const auto src_index = device_blend.m_originalIdsView[index]; + out_view[index] = comp_view[src_index]; }); // Append blended values to the end of the array. axom::for_all( - blendSize, + blend_size, AXOM_LAMBDA(axom::IndexType bgid) { // Get the blend group index we want. - const auto selectedIndex = SelectionPolicy::selectedIndex(deviceBlend, bgid); - const auto start = deviceBlend.m_blendGroupStartView[selectedIndex]; - const auto nValues = deviceBlend.m_blendGroupSizesView[selectedIndex]; - const auto destIndex = origSize + bgid; - if(nValues == 1) + const auto selected_index = SelectionPolicy::selectedIndex(device_blend, bgid); + const auto start = device_blend.m_blendGroupStartView[selected_index]; + const auto n_values = device_blend.m_blendGroupSizesView[selected_index]; + const auto dest_index = orig_size + bgid; + if(n_values == 1) { - const auto index = deviceBlend.m_blendIdsView[start]; - const auto srcIndex = deviceIndexing[index]; - outView[destIndex] = compView[srcIndex]; + const auto index = device_blend.m_blendIdsView[start]; + const auto src_index = device_indexing[index]; + out_view[dest_index] = comp_view[src_index]; } else { - const auto end = start + nValues; + const auto end = start + n_values; accum_type blended = 0; for(IndexType i = start; i < end; i++) { - const auto index = deviceBlend.m_blendIdsView[i]; - const auto weight = deviceBlend.m_blendCoeffView[i]; - const auto srcIndex = deviceIndexing[index]; - blended += static_cast(compView[srcIndex]) * weight; + const auto index = device_blend.m_blendIdsView[i]; + const auto weight = device_blend.m_blendCoeffView[i]; + const auto src_index = device_indexing[index]; + blended += static_cast(comp_view[src_index]) * weight; } - outView[destIndex] = static_cast(blended); + out_view[dest_index] = static_cast(blended); } }); } @@ -210,6 +236,7 @@ class FieldBlender #endif IndexingPolicy m_indexing {}; + int m_allocator_id; }; } // end namespace bump diff --git a/src/axom/bump/FieldSlicer.hpp b/src/axom/bump/FieldSlicer.hpp index ac38a19d01..8e083c0c6a 100644 --- a/src/axom/bump/FieldSlicer.hpp +++ b/src/axom/bump/FieldSlicer.hpp @@ -7,9 +7,11 @@ #define AXOM_BUMP_FIELD_SLICER_HPP_ #include "axom/core.hpp" +#include "axom/slic.hpp" #include "axom/bump/views/NodeArrayView.hpp" #include "axom/bump/utilities/conduit_memory.hpp" #include "axom/bump/IndexingPolicies.hpp" +#include "axom/sidre/core/ConduitMemory.hpp" #include @@ -25,6 +27,16 @@ struct SliceData axom::ArrayView m_indicesView; }; +/*! + * \brief Return the number of values produced from the SliceData. + * + * \param slice The SliceData we're querying. + * + * \return The number of values made from the SliceData. + */ +AXOM_HOST_DEVICE +inline axom::IndexType numberOfValues(const SliceData &slice) { return slice.m_indicesView.size(); } + /*! * \accelerated * \class FieldSlicer @@ -40,13 +52,36 @@ class FieldSlicer { public: /// Constructor - FieldSlicer() : m_indexing() { } + FieldSlicer() : m_indexing(), m_allocator_id(axom::execution_space::allocatorID()) { } /*! * \brief Constructor * \param indexing An object used to transform node indices. */ - FieldSlicer(const IndexingPolicy &indexing) : m_indexing(indexing) { } + FieldSlicer(const IndexingPolicy &indexing) + : m_indexing(indexing) + , m_allocator_id(axom::execution_space::allocatorID()) + { } + + /*! + * \brief Set the allocator id to use when allocating memory. + * + * \param allocator_id The allocator id to use when allocating memory. + */ + void setAllocatorID(int allocator_id) + { + SLIC_ERROR_IF(!axom::isValidAllocatorID(allocator_id), "Invalid allocator id."); + SLIC_ERROR_IF(!axom::execution_space::usesAllocId(allocator_id), + "Allocator id is not compatible with execution space."); + m_allocator_id = allocator_id; + } + + /*! + * \brief Get the allocator id to use when allocating memory. + * + * \return The allocator id to use when allocating memory. + */ + int getAllocatorID() const { return m_allocator_id; } /*! * \brief Execute the slice on the \a n_input field and store the new sliced field in \a n_output. @@ -65,9 +100,10 @@ class FieldSlicer const conduit::Node &n_input_values = n_input["values"]; conduit::Node &n_output_values = n_output["values"]; - if(n_input_values.number_of_children() > 0) + const conduit::index_t nc = n_input_values.number_of_children(); + if(nc > 0) { - for(conduit::index_t i = 0; i < n_input_values.number_of_children(); i++) + for(conduit::index_t i = 0; i < nc; i++) { const conduit::Node &n_comp = n_input_values[i]; conduit::Node &n_out_comp = n_output_values[n_comp.name()]; @@ -97,39 +133,41 @@ class FieldSlicer conduit::Node &n_output_values) const { namespace utils = axom::bump::utilities; - const auto outputSize = slice.m_indicesView.size(); + const auto output_size = slice.m_indicesView.size(); - // Allocate Conduit data through Axom. - utils::ConduitAllocateThroughAxom c2a; - n_output_values.set_allocator(c2a.getConduitAllocatorID()); - n_output_values.set(conduit::DataType(n_values.dtype().id(), outputSize)); + const auto conduit_allocator_id = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); + n_output_values.set_allocator(conduit_allocator_id); + n_output_values.set(conduit::DataType(n_values.dtype().id(), output_size)); - views::Node_to_ArrayView_same(n_values, n_output_values, [&](auto valuesView, auto outputView) { - sliceSingleComponentImpl(slice, valuesView, outputView); + views::nodeToArrayViewSame(n_values, n_output_values, [&](auto values_view, auto output_view) { + sliceSingleComponentImpl(slice, values_view, output_view); }); } /*! * \brief Slice the source view and copy values into the output view. * - * \param valuesView The source values view. - * \param outputView The output values view. + * \param values_view The source values view. + * \param output_view The output values view. * * \note This method was broken out into a template member method since nvcc * would not instantiate the lambda for axom::for_all() from an anonymous * lambda. */ template - void sliceSingleComponentImpl(const SliceData &slice, ValuesView valuesView, OutputView outputView) const + void sliceSingleComponentImpl(const SliceData &slice, + ValuesView values_view, + OutputView output_view) const { - IndexingPolicy deviceIndexing(m_indexing); - SliceData deviceSlice(slice); + IndexingPolicy device_indexing(m_indexing); + SliceData device_slice(slice); axom::for_all( - outputView.size(), + output_view.size(), AXOM_LAMBDA(axom::IndexType index) { - const auto zoneIndex = deviceSlice.m_indicesView[index]; - const auto transformedIndex = deviceIndexing[zoneIndex]; - outputView[index] = valuesView[transformedIndex]; + const auto zone_index = device_slice.m_indicesView[index]; + const auto transformed_index = device_indexing[zone_index]; + output_view[index] = values_view[transformed_index]; }); } @@ -139,6 +177,7 @@ class FieldSlicer #endif IndexingPolicy m_indexing {}; + int m_allocator_id; }; } // end namespace bump diff --git a/src/axom/bump/IndexingPolicies.hpp b/src/axom/bump/IndexingPolicies.hpp index ccdd666b55..2df4362a02 100644 --- a/src/axom/bump/IndexingPolicies.hpp +++ b/src/axom/bump/IndexingPolicies.hpp @@ -59,7 +59,7 @@ struct SSElementFieldIndexing AXOM_HOST_DEVICE inline axom::IndexType operator[](axom::IndexType index) const { - return m_indexing.LocalToGlobal(index); + return m_indexing.localToGlobal(index); } Indexing m_indexing {}; @@ -94,13 +94,13 @@ struct SSVertexFieldIndexing inline axom::IndexType operator[](axom::IndexType index) const { // Make the global index into a global logical in the topo. - const auto topoGlobalLogical = m_topoIndexing.GlobalToGlobal(index); + const auto topoGlobalLogical = m_topoIndexing.globalToGlobal(index); // Make the global logical into a local logical in the topo. - const auto topoLocalLogical = m_topoIndexing.GlobalToLocal(topoGlobalLogical); + const auto topoLocalLogical = m_topoIndexing.globalToLocal(topoGlobalLogical); // Make the global logical index in the field. - const auto fieldGlobalLogical = m_fieldIndexing.LocalToGlobal(topoLocalLogical); + const auto fieldGlobalLogical = m_fieldIndexing.localToGlobal(topoLocalLogical); // Make the global index in the field. - const auto fieldGlobalIndex = m_fieldIndexing.GlobalToGlobal(fieldGlobalLogical); + const auto fieldGlobalIndex = m_fieldIndexing.globalToGlobal(fieldGlobalLogical); return fieldGlobalIndex; } diff --git a/src/axom/bump/MakePointMesh.hpp b/src/axom/bump/MakePointMesh.hpp index 77cfc4d30d..3ba6c3a4a5 100644 --- a/src/axom/bump/MakePointMesh.hpp +++ b/src/axom/bump/MakePointMesh.hpp @@ -7,9 +7,11 @@ #define AXOM_BUMP_MAKE_POINT_MESH_ #include "axom/core.hpp" +#include "axom/slic.hpp" #include "axom/bump/utilities/conduit_memory.hpp" #include "axom/bump/MakeZoneCenters.hpp" #include "axom/bump/Options.hpp" +#include "axom/sidre/core/ConduitMemory.hpp" #include @@ -34,8 +36,29 @@ struct MakePointMesh MakePointMesh(const TopologyView &topologyView, const CoordsetView &coordsetView) : m_topologyView(topologyView) , m_coordsetView(coordsetView) + , m_allocator_id(axom::execution_space::allocatorID()) { } + /*! + * \brief Set the allocator id to use when allocating memory. + * + * \param allocator_id The allocator id to use when allocating memory. + */ + void setAllocatorID(int allocator_id) + { + SLIC_ERROR_IF(!axom::isValidAllocatorID(allocator_id), "Invalid allocator id."); + SLIC_ERROR_IF(!axom::execution_space::usesAllocId(allocator_id), + "Allocator id is not compatible with execution space."); + m_allocator_id = allocator_id; + } + + /*! + * \brief Get the allocator id to use when allocating memory. + * + * \return The allocator id to use when allocating memory. + */ + int getAllocatorID() const { return m_allocator_id; } + /*! * \brief Create a new field from the input topology and place it in \a n_output. * @@ -53,7 +76,7 @@ struct MakePointMesh conduit::Node &n_output) const { const auto numZones = m_topologyView.numberOfZones(); - const int allocatorID = axom::execution_space::allocatorID(); + const int allocatorID = getAllocatorID(); // Select all zones. axom::Array selectedZones(numZones, numZones, allocatorID); auto selectedZonesView = selectedZones.view(); @@ -82,12 +105,14 @@ struct MakePointMesh AXOM_ANNOTATE_SCOPE("ConvertToPointMesh"); namespace utils = axom::bump::utilities; using ConnectivityType = typename TopologyView::ConnectivityType; - utils::ConduitAllocateThroughAxom c2a; + const auto conduitAllocatorId = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); Options opts(n_options); // Make zone centers to use for the new coordset. MakeZoneCenters zc(m_topologyView, m_coordsetView); conduit::Node zcfield; + zc.setAllocatorID(getAllocatorID()); zc.execute(selectedZonesView, n_topology, n_coordset, zcfield); // Make the zone centers be the new coordset values in the output coordset. @@ -105,17 +130,17 @@ struct MakePointMesh n_output_topo["coordset"] = opts.coordsetName(n_coordset.name()); n_output_topo["elements/shape"] = "point"; conduit::Node &n_conn = n_output_topo["elements/connectivity"]; - n_conn.set_allocator(c2a.getConduitAllocatorID()); + n_conn.set_allocator(conduitAllocatorId); n_conn.set(conduit::DataType(utils::cpp2conduit::id, numPoints)); auto connectivity = utils::make_array_view(n_conn); conduit::Node &n_sizes = n_output_topo["elements/sizes"]; - n_sizes.set_allocator(c2a.getConduitAllocatorID()); + n_sizes.set_allocator(conduitAllocatorId); n_sizes.set(conduit::DataType(utils::cpp2conduit::id, numPoints)); auto sizes = utils::make_array_view(n_sizes); conduit::Node &n_offsets = n_output_topo["elements/offsets"]; - n_offsets.set_allocator(c2a.getConduitAllocatorID()); + n_offsets.set_allocator(conduitAllocatorId); n_offsets.set(conduit::DataType(utils::cpp2conduit::id, numPoints)); auto offsets = utils::make_array_view(n_offsets); AXOM_ANNOTATE_END("allocate"); @@ -135,6 +160,7 @@ struct MakePointMesh private: TopologyView m_topologyView; CoordsetView m_coordsetView; + int m_allocator_id; }; } // end namespace bump diff --git a/src/axom/bump/MakePolyhedralTopology.hpp b/src/axom/bump/MakePolyhedralTopology.hpp index cb3da65695..5d5fca7d52 100644 --- a/src/axom/bump/MakePolyhedralTopology.hpp +++ b/src/axom/bump/MakePolyhedralTopology.hpp @@ -7,9 +7,11 @@ #define AXOM_BUMP_MAKE_POLYHEDRAL_TOPOLOGY_HPP_ #include "axom/core.hpp" +#include "axom/slic.hpp" #include "axom/bump/utilities/utilities.hpp" #include "axom/bump/utilities/conduit_memory.hpp" #include "axom/bump/utilities/conduit_traits.hpp" +#include "axom/sidre/core/ConduitMemory.hpp" #include @@ -37,7 +39,30 @@ class MakePolyhedralTopology * * \param topologyView The topology view that wraps the input topology. */ - MakePolyhedralTopology(const TopologyView &topologyView) : m_topologyView(topologyView) { } + MakePolyhedralTopology(const TopologyView &topologyView) + : m_topologyView(topologyView) + , m_allocator_id(axom::execution_space::allocatorID()) + { } + + /*! + * \brief Set the allocator id to use when allocating memory. + * + * \param allocator_id The allocator id to use when allocating memory. + */ + void setAllocatorID(int allocator_id) + { + SLIC_ERROR_IF(!axom::isValidAllocatorID(allocator_id), "Invalid allocator id."); + SLIC_ERROR_IF(!axom::execution_space::usesAllocId(allocator_id), + "Allocator id is not compatible with execution space."); + m_allocator_id = allocator_id; + } + + /*! + * \brief Get the allocator id to use when allocating memory. + * + * \return The allocator id to use when allocating memory. + */ + int getAllocatorID() const { return m_allocator_id; } /** * \brief Make a polyhedral unstructured representation of a topology. @@ -52,9 +77,9 @@ class MakePolyhedralTopology { AXOM_ANNOTATE_SCOPE("MakePolyhedralTopology"); namespace utils = axom::bump::utilities; - utils::ConduitAllocateThroughAxom c2a; - const auto allocatorID = axom::execution_space::allocatorID(); + const auto allocatorID = getAllocatorID(); + const auto conduitAllocatorId = axom::sidre::ConduitMemory::axomAllocIdToConduit(allocatorID); const auto nzones = m_topologyView.numberOfZones(); //-------------------------------------------------------------------------- @@ -66,12 +91,12 @@ class MakePolyhedralTopology // This node is the number of faces in each zone. conduit::Node &n_elem_sizes = n_newTopo["elements/sizes"]; - n_elem_sizes.set_allocator(c2a.getConduitAllocatorID()); + n_elem_sizes.set_allocator(conduitAllocatorId); n_elem_sizes.set(conduit::DataType(utils::cpp2conduit::id, nzones)); auto elem_sizes = utils::make_array_view(n_elem_sizes); conduit::Node &n_elem_offsets = n_newTopo["elements/offsets"]; - n_elem_offsets.set_allocator(c2a.getConduitAllocatorID()); + n_elem_offsets.set_allocator(conduitAllocatorId); n_elem_offsets.set(conduit::DataType(utils::cpp2conduit::id, nzones)); auto elem_offsets = utils::make_array_view(n_elem_offsets); AXOM_ANNOTATE_END("allocate"); @@ -103,6 +128,11 @@ class MakePolyhedralTopology }); const axom::IndexType totalFaces = reduceTotalFaces.get(); const axom::IndexType totalFaceStorage = reduceTotalFaceStorage.get(); + if(nzones > 0) + { + SLIC_ERROR_IF(totalFaces == 0, "ReduceSum returned 0 for totalFaces."); + SLIC_ERROR_IF(totalFaceStorage == 0, "ReduceSum returned 0 for totalFaceStorage."); + } AXOM_ANNOTATE_END("counting"); //-------------------------------------------------------------------------- @@ -115,7 +145,7 @@ class MakePolyhedralTopology //-------------------------------------------------------------------------- AXOM_ANNOTATE_BEGIN("elements"); conduit::Node &n_elem_conn = n_newTopo["elements/connectivity"]; - n_elem_conn.set_allocator(c2a.getConduitAllocatorID()); + n_elem_conn.set_allocator(conduitAllocatorId); n_elem_conn.set(conduit::DataType(utils::cpp2conduit::id, totalFaces)); auto elem_conn = utils::make_array_view(n_elem_conn); axom::for_all( @@ -127,17 +157,17 @@ class MakePolyhedralTopology AXOM_ANNOTATE_BEGIN("subelements"); // Allocate subelement connectivity conduit::Node &n_se_conn = n_newTopo["subelements/connectivity"]; - n_se_conn.set_allocator(c2a.getConduitAllocatorID()); + n_se_conn.set_allocator(conduitAllocatorId); n_se_conn.set(conduit::DataType(utils::cpp2conduit::id, totalFaceStorage)); auto se_conn = utils::make_array_view(n_se_conn); conduit::Node &n_se_sizes = n_newTopo["subelements/sizes"]; - n_se_sizes.set_allocator(c2a.getConduitAllocatorID()); + n_se_sizes.set_allocator(conduitAllocatorId); n_se_sizes.set(conduit::DataType(utils::cpp2conduit::id, totalFaces)); auto se_sizes = utils::make_array_view(n_se_sizes); conduit::Node &n_se_offsets = n_newTopo["subelements/offsets"]; - n_se_offsets.set_allocator(c2a.getConduitAllocatorID()); + n_se_offsets.set_allocator(conduitAllocatorId); n_se_offsets.set(conduit::DataType(utils::cpp2conduit::id, totalFaces)); auto se_offsets = utils::make_array_view(n_se_offsets); @@ -168,6 +198,7 @@ class MakePolyhedralTopology } TopologyView m_topologyView; + int m_allocator_id; }; } // end namespace bump diff --git a/src/axom/bump/MakeUnstructured.hpp b/src/axom/bump/MakeUnstructured.hpp index c8431d9e85..5a2777f566 100644 --- a/src/axom/bump/MakeUnstructured.hpp +++ b/src/axom/bump/MakeUnstructured.hpp @@ -11,6 +11,7 @@ #include "axom/bump/utilities/utilities.hpp" #include "axom/bump/utilities/conduit_memory.hpp" #include "axom/bump/views/dispatch_structured_topology.hpp" +#include "axom/sidre/core/ConduitMemory.hpp" #include @@ -42,11 +43,12 @@ class MakeUnstructured static void execute(const conduit::Node &topo, const conduit::Node &coordset, const std::string &topoName, - conduit::Node &mesh) + conduit::Node &mesh, + int allocator_id = axom::execution_space::allocatorID()) { const std::string type = topo.fetch_existing("type").as_string(); + const auto conduitAllocatorId = axom::sidre::ConduitMemory::axomAllocIdToConduit(allocator_id); namespace utils = axom::bump::utilities; - utils::ConduitAllocateThroughAxom c2a; mesh["coordsets"][coordset.name()].set_external(coordset); conduit::Node &n_newtopo = mesh["topologies"][topoName]; @@ -62,9 +64,9 @@ class MakeUnstructured conduit::Node &n_newconn = n_newtopo["elements/connectivity"]; conduit::Node &n_newsizes = n_newtopo["elements/sizes"]; conduit::Node &n_newoffsets = n_newtopo["elements/offsets"]; - n_newconn.set_allocator(c2a.getConduitAllocatorID()); - n_newsizes.set_allocator(c2a.getConduitAllocatorID()); - n_newoffsets.set_allocator(c2a.getConduitAllocatorID()); + n_newconn.set_allocator(conduitAllocatorId); + n_newsizes.set_allocator(conduitAllocatorId); + n_newoffsets.set_allocator(conduitAllocatorId); axom::bump::views::dispatch_structured_topologies( topo, diff --git a/src/axom/bump/MakeZoneCenters.hpp b/src/axom/bump/MakeZoneCenters.hpp index bcc664c259..8d455b594a 100644 --- a/src/axom/bump/MakeZoneCenters.hpp +++ b/src/axom/bump/MakeZoneCenters.hpp @@ -12,6 +12,7 @@ #include "axom/bump/utilities/blueprint_utilities.hpp" #include "axom/primal/geometry/Point.hpp" #include "axom/primal/geometry/Vector.hpp" +#include "axom/sidre/core/ConduitMemory.hpp" #include "axom/slic.hpp" #include @@ -42,8 +43,29 @@ class MakeZoneCenters MakeZoneCenters(const TopologyView &topologyView, const CoordsetView &coordsetView) : m_topologyView(topologyView) , m_coordsetView(coordsetView) + , m_allocator_id(axom::execution_space::allocatorID()) { } + /*! + * \brief Set the allocator id to use when allocating memory. + * + * \param allocator_id The allocator id to use when allocating memory. + */ + void setAllocatorID(int allocator_id) + { + SLIC_ERROR_IF(!axom::isValidAllocatorID(allocator_id), "Invalid allocator id."); + SLIC_ERROR_IF(!axom::execution_space::usesAllocId(allocator_id), + "Allocator id is not compatible with execution space."); + m_allocator_id = allocator_id; + } + + /*! + * \brief Get the allocator id to use when allocating memory. + * + * \return The allocator id to use when allocating memory. + */ + int getAllocatorID() const { return m_allocator_id; } + /*! * \brief Create a new field from the input topology and place it in \a n_output. * @@ -60,7 +82,7 @@ class MakeZoneCenters conduit::Node &n_outputField) const { const auto numZones = m_topologyView.numberOfZones(); - const int allocatorID = axom::execution_space::allocatorID(); + const int allocatorID = getAllocatorID(); // Select all zones. axom::Array selectedZones(numZones, numZones, allocatorID); auto selectedZonesView = selectedZones.view(); @@ -104,8 +126,8 @@ class MakeZoneCenters const auto nComponents = axes.size(); SLIC_ASSERT(PointType::DIMENSION == nComponents); - // Get the ID of a Conduit allocator that will allocate through Axom with device allocator allocatorID. - utils::ConduitAllocateThroughAxom c2a; + const auto conduitAllocatorId = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); n_outputField.reset(); n_outputField["association"] = "element"; @@ -121,7 +143,7 @@ class MakeZoneCenters { // Allocate data in the Conduit node and make a view. conduit::Node &comp = n_values[axes[i]]; - comp.set_allocator(c2a.getConduitAllocatorID()); + comp.set_allocator(conduitAllocatorId); comp.set(conduit::DataType(utils::cpp2conduit::id, outputSize)); compViews[i] = utils::make_array_view(comp); } @@ -158,6 +180,7 @@ class MakeZoneCenters private: TopologyView m_topologyView; CoordsetView m_coordsetView; + int m_allocator_id; }; } // end namespace bump diff --git a/src/axom/bump/MakeZoneVolumes.hpp b/src/axom/bump/MakeZoneVolumes.hpp index 5b1e15fbe3..ce494d64be 100644 --- a/src/axom/bump/MakeZoneVolumes.hpp +++ b/src/axom/bump/MakeZoneVolumes.hpp @@ -7,9 +7,11 @@ #define AXOM_BUMP_MAKE_ZONE_VOLUMES_HPP_ #include "axom/core.hpp" +#include "axom/slic.hpp" #include "axom/bump/utilities/conduit_memory.hpp" #include "axom/bump/utilities/conduit_traits.hpp" #include "axom/bump/PrimalAdaptor.hpp" +#include "axom/sidre/core/ConduitMemory.hpp" #include @@ -42,8 +44,29 @@ class MakeZoneVolumes MakeZoneVolumes(const TopologyView &topologyView, const CoordsetView &coordsetView) : m_topologyView(topologyView) , m_coordsetView(coordsetView) + , m_allocator_id(axom::execution_space::allocatorID()) { } + /*! + * \brief Set the allocator id to use when allocating memory. + * + * \param allocator_id The allocator id to use when allocating memory. + */ + void setAllocatorID(int allocator_id) + { + SLIC_ERROR_IF(!axom::isValidAllocatorID(allocator_id), "Invalid allocator id."); + SLIC_ERROR_IF(!axom::execution_space::usesAllocId(allocator_id), + "Allocator id is not compatible with execution space."); + m_allocator_id = allocator_id; + } + + /*! + * \brief Get the allocator id to use when allocating memory. + * + * \return The allocator id to use when allocating memory. + */ + int getAllocatorID() const { return m_allocator_id; } + /*! * \brief Create a new field from the input topology and place it in \a n_output. * @@ -56,9 +79,9 @@ class MakeZoneVolumes const conduit::Node &AXOM_UNUSED_PARAM(n_coordset), conduit::Node &n_outputField) const { - // Get the ID of a Conduit allocator that will allocate through Axom with device allocator allocatorID. namespace utils = axom::bump::utilities; - utils::ConduitAllocateThroughAxom c2a; + const auto conduitAllocatorId = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); // Determine output size. const auto outputSize = m_topologyView.numberOfZones(); @@ -68,7 +91,7 @@ class MakeZoneVolumes n_outputField["association"] = "element"; n_outputField["topology"] = n_topology.name(); conduit::Node &n_values = n_outputField["values"]; - n_values.set_allocator(c2a.getConduitAllocatorID()); + n_values.set_allocator(conduitAllocatorId); n_values.set(conduit::DataType(utils::cpp2conduit::id, outputSize)); auto valuesView = utils::make_array_view(n_values); @@ -92,6 +115,7 @@ class MakeZoneVolumes private: TopologyView m_topologyView; CoordsetView m_coordsetView; + int m_allocator_id; }; } // end namespace bump diff --git a/src/axom/bump/MatsetSlicer.hpp b/src/axom/bump/MatsetSlicer.hpp index 6c2a8cc4ef..3bd39bebb6 100644 --- a/src/axom/bump/MatsetSlicer.hpp +++ b/src/axom/bump/MatsetSlicer.hpp @@ -8,9 +8,11 @@ #define AXOM_BUMP_MATSET_SLICER_HPP #include "axom/core.hpp" +#include "axom/slic.hpp" #include "axom/bump/utilities/conduit_memory.hpp" #include "axom/bump/utilities/conduit_traits.hpp" #include "axom/bump/FieldSlicer.hpp" +#include "axom/sidre/core/ConduitMemory.hpp" #include @@ -34,7 +36,30 @@ class MatsetSlicer /*! * \brief Constructor. */ - MatsetSlicer(const MatsetView &matsetView) : m_matsetView(matsetView) { } + MatsetSlicer(const MatsetView &matsetView) + : m_matsetView(matsetView) + , m_allocator_id(axom::execution_space::allocatorID()) + { } + + /*! + * \brief Set the allocator id to use when allocating memory. + * + * \param allocator_id The allocator id to use when allocating memory. + */ + void setAllocatorID(int allocator_id) + { + SLIC_ERROR_IF(!axom::isValidAllocatorID(allocator_id), "Invalid allocator id."); + SLIC_ERROR_IF(!axom::execution_space::usesAllocId(allocator_id), + "Allocator id is not compatible with execution space."); + m_allocator_id = allocator_id; + } + + /*! + * \brief Get the allocator id to use when allocating memory. + * + * \return The allocator id to use when allocating memory. + */ + int getAllocatorID() const { return m_allocator_id; } /*! * \brief Slice the input matset and output a new matset. @@ -59,54 +84,88 @@ class MatsetSlicer if(n_matset.has_child(keys[i])) n_newMatset[keys[i]] = n_matset.fetch_existing(keys[i]); } - utils::ConduitAllocateThroughAxom c2a; + const auto conduitAllocatorId = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); // Allocate sizes/offsets. + AXOM_ANNOTATE_BEGIN("alloc"); conduit::Node &n_sizes = n_newMatset["sizes"]; - n_sizes.set_allocator(c2a.getConduitAllocatorID()); + n_sizes.set_allocator(conduitAllocatorId); n_sizes.set(conduit::DataType(utils::cpp2conduit::id, selectedZonesView.size())); auto sizesView = utils::make_array_view(n_sizes); conduit::Node &n_offsets = n_newMatset["offsets"]; - n_offsets.set_allocator(c2a.getConduitAllocatorID()); + n_offsets.set_allocator(conduitAllocatorId); n_offsets.set(conduit::DataType(utils::cpp2conduit::id, selectedZonesView.size())); auto offsetsView = utils::make_array_view(n_offsets); + AXOM_ANNOTATE_END("alloc"); // Figure out overall size of the matset zones we're keeping. + AXOM_ANNOTATE_BEGIN("size"); MatsetView deviceMatsetView(m_matsetView); const axom::ArrayView deviceSelectedZonesView(selectedZonesView); - axom::for_all( - selectedZonesView.size(), - AXOM_LAMBDA(axom::IndexType index) { - const auto nmats = deviceMatsetView.numberOfMaterials(deviceSelectedZonesView[index]); - sizesView[index] = nmats; - }); - axom::ReduceSum size_reduce(0); - axom::for_all( - sizesView.size(), - AXOM_LAMBDA(axom::IndexType index) { size_reduce += sizesView[index]; }); - axom::exclusive_scan(sizesView, offsetsView); + axom::IndexType totalSize {}; + if constexpr(axom::execution_space::onDevice()) + { + axom::ReduceSum size_reduce(0); + axom::for_all( + selectedZonesView.size(), + AXOM_LAMBDA(axom::IndexType index) { + const auto nmats = deviceMatsetView.numberOfMaterials(deviceSelectedZonesView[index]); + sizesView[index] = nmats; + size_reduce += nmats; + }); + totalSize = size_reduce.get(); + } + else + { + axom::for_all( + selectedZonesView.size(), + AXOM_LAMBDA(axom::IndexType index) { + const auto nmats = deviceMatsetView.numberOfMaterials(deviceSelectedZonesView[index]); + sizesView[index] = nmats; + }); + } + AXOM_ANNOTATE_END("size"); - // Allocate data for the rest of the matset. - const auto totalSize = size_reduce.get(); - SLIC_ASSERT(totalSize > 0); + { + AXOM_ANNOTATE_SCOPE("scan"); + axom::exclusive_scan(sizesView, offsetsView); + } + + AXOM_ANNOTATE_BEGIN("alloc2"); + if constexpr(!axom::execution_space::onDevice()) + { + if(sizesView.size() > 0) + { + const auto lastIndex = sizesView.size() - 1; + totalSize = offsetsView[lastIndex] + sizesView[lastIndex]; + } + } + // Allocate data for the rest of the matset. + if(sizesView.size() > 0) + { + SLIC_ERROR_IF(totalSize == 0, "ReduceSum returned 0 for totalSize."); + } conduit::Node &n_indices = n_newMatset["indices"]; - n_indices.set_allocator(c2a.getConduitAllocatorID()); + n_indices.set_allocator(conduitAllocatorId); n_indices.set(conduit::DataType(utils::cpp2conduit::id, totalSize)); auto indicesView = utils::make_array_view(n_indices); conduit::Node &n_material_ids = n_newMatset["material_ids"]; - n_material_ids.set_allocator(c2a.getConduitAllocatorID()); + n_material_ids.set_allocator(conduitAllocatorId); n_material_ids.set(conduit::DataType(utils::cpp2conduit::id, totalSize)); auto materialIdsView = utils::make_array_view(n_material_ids); conduit::Node &n_volume_fractions = n_newMatset["volume_fractions"]; - n_volume_fractions.set_allocator(c2a.getConduitAllocatorID()); + n_volume_fractions.set_allocator(conduitAllocatorId); n_volume_fractions.set(conduit::DataType(utils::cpp2conduit::id, totalSize)); auto volumeFractionsView = utils::make_array_view(n_volume_fractions); + AXOM_ANNOTATE_END("alloc2"); // Fill in the matset data with the zones we're keeping. + AXOM_ANNOTATE_BEGIN("copy"); axom::for_all( selectedZonesView.size(), AXOM_LAMBDA(axom::IndexType index) { @@ -122,10 +181,12 @@ class MatsetSlicer indicesView[destIndex] = destIndex; } }); + AXOM_ANNOTATE_END("copy"); } private: MatsetView m_matsetView; + int m_allocator_id; }; } // end namespace bump diff --git a/src/axom/bump/MergeCoordsetPoints.hpp b/src/axom/bump/MergeCoordsetPoints.hpp index 787b1d1314..804b3e63a7 100644 --- a/src/axom/bump/MergeCoordsetPoints.hpp +++ b/src/axom/bump/MergeCoordsetPoints.hpp @@ -93,7 +93,30 @@ class MergeCoordsetPoints * * \param coordsetView The coordset view that wraps the coordset to be modified. */ - MergeCoordsetPoints(const CoordsetView &coordsetView) : m_coordsetView(coordsetView) { } + MergeCoordsetPoints(const CoordsetView &coordsetView) + : m_coordsetView(coordsetView) + , m_allocator_id(axom::execution_space::allocatorID()) + { } + + /*! + * \brief Set the allocator id to use when allocating memory. + * + * \param allocator_id The allocator id to use when allocating memory. + */ + void setAllocatorID(int allocator_id) + { + SLIC_ERROR_IF(!axom::isValidAllocatorID(allocator_id), "Invalid allocator id."); + SLIC_ERROR_IF(!axom::execution_space::usesAllocId(allocator_id), + "Allocator id is not compatible with execution space."); + m_allocator_id = allocator_id; + } + + /*! + * \brief Get the allocator id to use when allocating memory. + * + * \return The allocator id to use when allocating memory. + */ + int getAllocatorID() const { return m_allocator_id; } /*! * \brief Merge the coordset points using a tolerance and pass out an array of the @@ -129,7 +152,7 @@ class MergeCoordsetPoints axom::Array &old2new) const { namespace utils = axom::bump::utilities; - const int allocatorID = axom::execution_space::allocatorID(); + const int allocatorID = getAllocatorID(); // If the coordset is not explicit then there is nothing to do. if(n_coordset["type"].as_string() != "explicit") @@ -165,7 +188,10 @@ class MergeCoordsetPoints // Make points unique. axom::Array uniqueNames; - axom::bump::Unique::execute(coordNamesView, uniqueNames, selectedIds); + axom::bump::Unique::execute(coordNamesView, + uniqueNames, + selectedIds, + allocatorID); const auto uniqueNamesView = uniqueNames.view(); const auto selectedIdsView = selectedIds.view(); AXOM_ANNOTATE_END("unique"); @@ -198,6 +224,7 @@ class MergeCoordsetPoints // Use the selectedIds to slice the coordset to make a new coordset that // replaces the old one. CoordsetSlicer css(m_coordsetView); + css.setAllocatorID(allocatorID); SliceData slice; slice.m_indicesView = selectedIdsView; conduit::Node n_sliced; @@ -298,7 +325,7 @@ class MergeCoordsetPoints namespace utils = axom::bump::utilities; AXOM_ANNOTATE_SCOPE(axom::fmt::format("createNames<{}>", utils::cpp2conduit::name)); - const int allocatorID = axom::execution_space::allocatorID(); + const int allocatorID = getAllocatorID(); const auto nnodes = m_coordsetView.numberOfNodes(); const double neg_tolerance = -tolerance; @@ -335,6 +362,7 @@ class MergeCoordsetPoints } CoordsetView m_coordsetView; + int m_allocator_id; }; } // end namespace bump diff --git a/src/axom/bump/MergeMeshes.hpp b/src/axom/bump/MergeMeshes.hpp index 06a6dc079f..ceea86a1bd 100644 --- a/src/axom/bump/MergeMeshes.hpp +++ b/src/axom/bump/MergeMeshes.hpp @@ -17,6 +17,7 @@ #include "axom/bump/utilities/conduit_traits.hpp" #include "axom/bump/MakePolyhedralTopology.hpp" #include "axom/bump/MergePolyhedralFaces.hpp" +#include "axom/sidre/core/ConduitMemory.hpp" #include @@ -34,7 +35,7 @@ struct MeshInput conduit::Node *m_input {nullptr}; //!< Pointer to Blueprint mesh. axom::ArrayView m_nodeMapView {}; //!< Map for mesh nodeIds to nodeIds in final mesh. axom::ArrayView m_nodeSliceView {}; //!< Node ids to be extracted and added to final mesh. - std::string topologyName {}; //!< The name of the topology to use. + std::string m_topologyName {}; //!< The name of the topology to use. }; /*! @@ -46,6 +47,27 @@ template class MergeMeshes { public: + MergeMeshes() : m_allocator_id(axom::execution_space::allocatorID()) { } + + /*! + * \brief Set the allocator id to use when allocating memory. + * + * \param allocator_id The allocator id to use when allocating memory. + */ + void setAllocatorID(int allocator_id) + { + SLIC_ERROR_IF(!axom::isValidAllocatorID(allocator_id), "Invalid allocator id."); + SLIC_ERROR_IF(!axom::execution_space::usesAllocId(allocator_id), + "Allocator id is not compatible with execution space."); + m_allocator_id = allocator_id; + } + + /*! + * \brief Get the allocator id to use when allocating memory. + * + * \return The allocator id to use when allocating memory. + */ + int getAllocatorID() const { return m_allocator_id; } /*! * \brief Merge the input Blueprint meshes into a single Blueprint mesh. * @@ -88,10 +110,10 @@ class MergeMeshes */ struct FieldInformation { - std::string topology; - std::string association; - int dtype; - std::vector components; + std::string m_topology; + std::string m_association; + int m_dtype; + std::vector m_components; }; /*! @@ -111,11 +133,11 @@ class MergeMeshes { if(inputs[i].m_input == nullptr) return false; - if(inputs[i].topologyName.empty()) + if(inputs[i].m_topologyName.empty()) { // If we did not specify which topology, make sure that there is only 1. const char *keys[] = {"coordsets", "topologies", "matsets"}; - if(inputs[i].topologyName.empty()) + if(inputs[i].m_topologyName.empty()) { for(int k = 0; k < 3; k++) { @@ -161,7 +183,7 @@ class MergeMeshes */ void singleInput(const std::vector &inputs, conduit::Node &output) const { - axom::bump::utilities::copy(output, *(inputs[0].m_input)); + axom::bump::utilities::copy(output, *(inputs[0].m_input), getAllocatorID()); } /*! @@ -174,9 +196,9 @@ class MergeMeshes */ const conduit::Node &getTopology(const MeshInput &input) const { - if(!input.topologyName.empty()) + if(!input.m_topologyName.empty()) { - return input.m_input->fetch_existing("topologies/" + input.topologyName); + return input.m_input->fetch_existing("topologies/" + input.m_topologyName); } return input.m_input->fetch_existing("topologies")[0]; } @@ -223,6 +245,8 @@ class MergeMeshes { AXOM_ANNOTATE_SCOPE("mergeCoordset"); namespace utils = axom::bump::utilities; + const auto conduitAllocatorId = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); const axom::IndexType totalNodes = countNodes(inputs); conduit::Node &n_newCoordsets = output["coordsets"]; conduit::Node *n_newValuesPtr = nullptr; @@ -241,8 +265,6 @@ class MergeMeshes // Make all of the components the first time. if(i == 0) { - utils::ConduitAllocateThroughAxom c2a; - conduit::Node &n_newCoordset = n_newCoordsets[n_srcCoordset.name()]; n_newCoordset["type"] = "explicit"; conduit::Node &n_newValues = n_newCoordset["values"]; @@ -253,13 +275,13 @@ class MergeMeshes { const conduit::Node &n_srcComp = n_srcValues[c]; conduit::Node &n_comp = n_newValues[n_srcComp.name()]; - n_comp.set_allocator(c2a.getConduitAllocatorID()); + n_comp.set_allocator(conduitAllocatorId); n_comp.set(conduit::DataType(n_srcComp.dtype().id(), totalNodes)); } } // Copy this input's coordinates into the new coordset. - axom::bump::views::FloatNode_to_ArrayView(n_srcValues[0], [&](auto comp0) { + axom::bump::views::floatNodeToArrayView(n_srcValues[0], [&](auto comp0) { using FloatType = typename decltype(comp0)::value_type; for(int c = 0; c < nComps; c++) { @@ -409,7 +431,7 @@ class MergeMeshes // array, we sum the sizes. This is needed because connectivity might // have unused elements in it. axom::IndexType connLength = 0; - axom::bump::views::IndexNode_to_ArrayView(n_size, [&](auto sizesView) { + axom::bump::views::indexNodeToArrayView(n_size, [&](auto sizesView) { connLength = sumArrayView(sizesView); }); totalConnLength += connLength; @@ -430,7 +452,12 @@ class MergeMeshes using value_type = typename ViewType::value_type; axom::ReduceSum sum(0); axom::for_all(view.size(), AXOM_LAMBDA(axom::IndexType index) { sum += view[index]; }); - return static_cast(sum.get()); + const auto total = static_cast(sum.get()); + if(view.size() > 0) + { + SLIC_ERROR_IF(total == 0, "ReduceSum returned 0 for total."); + } + return total; } /*! @@ -508,6 +535,8 @@ class MergeMeshes conduit::Node &output) const { namespace utils = axom::bump::utilities; + const auto conduitAllocatorId = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); AXOM_ANNOTATE_SCOPE("mergeTopologiesUnstructured"); axom::IndexType totalConnLen = 0, totalZones = 0; @@ -536,8 +565,6 @@ class MergeMeshes // Make all of the elements the first time. if(i == 0) { - utils::ConduitAllocateThroughAxom c2a; - std::string newTopoName(n_srcTopo.name()); if(n_options.has_child("topologyName")) { @@ -550,15 +577,15 @@ class MergeMeshes n_newTopo["coordset"] = n_srcTopo["coordset"].as_string(); conduit::Node &n_newConn = n_newTopo["elements/connectivity"]; - n_newConn.set_allocator(c2a.getConduitAllocatorID()); + n_newConn.set_allocator(conduitAllocatorId); n_newConn.set(conduit::DataType(n_srcConn.dtype().id(), totalConnLen)); conduit::Node &n_newSizes = n_newTopo["elements/sizes"]; - n_newSizes.set_allocator(c2a.getConduitAllocatorID()); + n_newSizes.set_allocator(conduitAllocatorId); n_newSizes.set(conduit::DataType(n_srcSizes.dtype().id(), totalZones)); conduit::Node &n_newOffsets = n_newTopo["elements/offsets"]; - n_newOffsets.set_allocator(c2a.getConduitAllocatorID()); + n_newOffsets.set_allocator(conduitAllocatorId); n_newOffsets.set(conduit::DataType(n_srcConn.dtype().id(), totalZones)); if(shape_map.size() > 1) @@ -571,7 +598,7 @@ class MergeMeshes n_shape_map[it->first] = it->second; conduit::Node &n_newShapes = n_newTopo["elements/shapes"]; - n_newShapes.set_allocator(c2a.getConduitAllocatorID()); + n_newShapes.set_allocator(conduitAllocatorId); n_newShapes.set(conduit::DataType(n_srcConn.dtype().id(), totalZones)); } else @@ -581,7 +608,7 @@ class MergeMeshes } // Copy this input's connectivity into the new topology. - axom::bump::views::IndexNode_to_ArrayView_same( + axom::bump::views::indexNodeToArrayViewSame( n_srcConn, n_srcSizes, n_srcOffsets, @@ -605,7 +632,7 @@ class MergeMeshes }); // Copy this input's sizes into the new topology. - axom::bump::views::IndexNode_to_ArrayView(n_srcSizes, [&](auto srcSizesView) { + axom::bump::views::indexNodeToArrayView(n_srcSizes, [&](auto srcSizesView) { using ConnType = typename decltype(srcSizesView)::value_type; conduit::Node &n_newSizes = n_newTopoPtr->fetch_existing("elements/sizes"); auto sizesView = utils::make_array_view(n_newSizes); @@ -624,7 +651,7 @@ class MergeMeshes { const conduit::Node &n_srcShapes = n_srcTopo.fetch_existing("elements/shapes"); - axom::bump::views::IndexNode_to_ArrayView(n_srcShapes, [&](auto srcShapesView) { + axom::bump::views::indexNodeToArrayView(n_srcShapes, [&](auto srcShapesView) { using ConnType = typename decltype(srcShapesView)::value_type; conduit::Node &n_newShapes = n_newTopoPtr->fetch_existing("elements/shapes"); auto shapesView = utils::make_array_view(n_newShapes); @@ -640,7 +667,7 @@ class MergeMeshes const conduit::Node &n_srcSizes = n_srcTopo.fetch_existing("elements/sizes"); axom::IndexType nz = n_srcSizes.dtype().number_of_elements(); conduit::Node &n_newShapes = n_newTopoPtr->fetch_existing("elements/shapes"); - axom::bump::views::IndexNode_to_ArrayView(n_newShapes, [&](auto shapesView) { + axom::bump::views::indexNodeToArrayView(n_newShapes, [&](auto shapesView) { const int shapeId = axom::bump::views::shapeNameToID(srcShape); mergeTopology_default_shapes(shapesOffset, shapesView, nz, shapeId); shapesOffset += nz; @@ -651,7 +678,7 @@ class MergeMeshes // Make new offsets from the sizes. conduit::Node &n_newSizes = n_newTopoPtr->fetch_existing("elements/sizes"); - axom::bump::views::IndexNode_to_ArrayView(n_newSizes, [&](auto sizesView) { + axom::bump::views::indexNodeToArrayView(n_newSizes, [&](auto sizesView) { using ConnType = typename decltype(sizesView)::value_type; conduit::Node &n_newOffsets = n_newTopoPtr->fetch_existing("elements/offsets"); auto offsetsView = utils::make_array_view(n_newOffsets); @@ -682,7 +709,7 @@ class MergeMeshes // Make a new mesh input node and a topology node under it. phInputs[i].m_input = new conduit::Node; - phInputs[i].topologyName = inputs[i].topologyName; + phInputs[i].m_topologyName = inputs[i].m_topologyName; conduit::Node &n_phTopo = phInputs[i].m_input->operator[]("topologies/" + n_srcTopo.name()); conduit::Node &n_phCoordset = phInputs[i].m_input->operator[]("coordsets/" + n_srcCoordset.name()); @@ -700,7 +727,7 @@ class MergeMeshes // Convert the mesh to polyhedral. const std::string shape = n_srcTopo.fetch_existing("elements/shape").as_string(); const conduit::Node &n_elem_conn = n_srcTopo.fetch_existing("elements/connectivity"); - views::IndexNode_to_ArrayView(n_elem_conn, [&](auto connView) { + views::indexNodeToArrayView(n_elem_conn, [&](auto connView) { using ConnectivityType = typename decltype(connView)::value_type; if(shape == views::TetTraits::name()) @@ -733,7 +760,7 @@ class MergeMeshes } else if(shape == "mixed") { - const int allocatorID = axom::execution_space::allocatorID(); + const int allocatorID = getAllocatorID(); axom::Array values, ids; auto shapeMap = views::buildShapeMap(n_srcTopo, values, ids, allocatorID); views::UnstructuredTopologyMixedShapeView topologyView( @@ -766,10 +793,11 @@ class MergeMeshes // Make a polyhedral mesh from the input mesh. MakePolyhedralTopology makePH(topologyView); + makePH.setAllocatorID(getAllocatorID()); makePH.execute(n_srcTopo, n_phTopo); // Improve the mesh by merging like faces. - MergePolyhedralFaces::execute(n_phTopo); + MergePolyhedralFaces::execute(n_phTopo, getAllocatorID()); } /*! @@ -824,6 +852,8 @@ class MergeMeshes conduit::Node &output) const { namespace utils = axom::bump::utilities; + const auto conduitAllocatorId = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); AXOM_ANNOTATE_SCOPE("mergeTopologiesPolyhedralInner"); axom::IndexType totalElemConnLen = 0, totalElemZones = 0; @@ -852,8 +882,6 @@ class MergeMeshes // Make all of the elements the first time. if(i == 0) { - utils::ConduitAllocateThroughAxom c2a; - // Get new topo name. std::string newTopoName(n_srcTopo.name()); if(n_options.has_child("topologyName")) @@ -872,32 +900,32 @@ class MergeMeshes // Allocate some bulk data. conduit::Node &n_newConn = n_newTopo["elements/connectivity"]; - n_newConn.set_allocator(c2a.getConduitAllocatorID()); + n_newConn.set_allocator(conduitAllocatorId); n_newConn.set(conduit::DataType(n_srcConn.dtype().id(), totalElemConnLen)); conduit::Node &n_newSizes = n_newTopo["elements/sizes"]; - n_newSizes.set_allocator(c2a.getConduitAllocatorID()); + n_newSizes.set_allocator(conduitAllocatorId); n_newSizes.set(conduit::DataType(n_srcSizes.dtype().id(), totalElemZones)); conduit::Node &n_newOffsets = n_newTopo["elements/offsets"]; - n_newOffsets.set_allocator(c2a.getConduitAllocatorID()); + n_newOffsets.set_allocator(conduitAllocatorId); n_newOffsets.set(conduit::DataType(n_srcOffsets.dtype().id(), totalElemZones)); conduit::Node &n_newSEConn = n_newTopo["subelements/connectivity"]; - n_newSEConn.set_allocator(c2a.getConduitAllocatorID()); + n_newSEConn.set_allocator(conduitAllocatorId); n_newSEConn.set(conduit::DataType(n_srcSEConn.dtype().id(), totalSEConnLen)); conduit::Node &n_newSESizes = n_newTopo["subelements/sizes"]; - n_newSESizes.set_allocator(c2a.getConduitAllocatorID()); + n_newSESizes.set_allocator(conduitAllocatorId); n_newSESizes.set(conduit::DataType(n_srcSESizes.dtype().id(), totalSEZones)); conduit::Node &n_newSEOffsets = n_newTopo["subelements/offsets"]; - n_newSEOffsets.set_allocator(c2a.getConduitAllocatorID()); + n_newSEOffsets.set_allocator(conduitAllocatorId); n_newSEOffsets.set(conduit::DataType(n_srcSEOffsets.dtype().id(), totalSEZones)); } // Copy this input's element connectivity into the new topology. - axom::bump::views::IndexNode_to_ArrayView_same( + axom::bump::views::indexNodeToArrayViewSame( n_srcConn, n_srcSizes, n_srcOffsets, @@ -923,7 +951,7 @@ class MergeMeshes }); // Copy this input's sizes into the new topology. - axom::bump::views::IndexNode_to_ArrayView(n_srcSizes, [&](auto srcSizesView) { + axom::bump::views::indexNodeToArrayView(n_srcSizes, [&](auto srcSizesView) { using ConnType = typename decltype(srcSizesView)::value_type; conduit::Node &n_newSizes = n_newTopoPtr->fetch_existing("elements/sizes"); auto sizesView = utils::make_array_view(n_newSizes); @@ -934,7 +962,7 @@ class MergeMeshes }); // Copy this input's subelement connectivity into the new topology. - axom::bump::views::IndexNode_to_ArrayView_same( + axom::bump::views::indexNodeToArrayViewSame( n_srcSEConn, n_srcSESizes, n_srcSEOffsets, @@ -959,7 +987,7 @@ class MergeMeshes }); // Copy this input's subelement sizes into the new topology. - axom::bump::views::IndexNode_to_ArrayView(n_srcSESizes, [&](auto srcSESizesView) { + axom::bump::views::indexNodeToArrayView(n_srcSESizes, [&](auto srcSESizesView) { using ConnType = typename decltype(srcSESizesView)::value_type; conduit::Node &n_newSESizes = n_newTopoPtr->fetch_existing("subelements/sizes"); auto seSizesView = utils::make_array_view(n_newSESizes); @@ -973,7 +1001,7 @@ class MergeMeshes // Make new offsets from the sizes. conduit::Node &n_newSizes = n_newTopoPtr->fetch_existing("elements/sizes"); conduit::Node &n_newSESizes = n_newTopoPtr->fetch_existing("subelements/sizes"); - axom::bump::views::IndexNode_to_ArrayView_same( + axom::bump::views::indexNodeToArrayViewSame( n_newSizes, n_newSESizes, [&](auto sizesView, auto seSizesView) { @@ -1011,11 +1039,14 @@ class MergeMeshes ConnectivityView srcOffsetsView) const { using value_type = typename ConnectivityView::value_type; - const int allocatorID = axom::execution_space::allocatorID(); + const int allocatorID = getAllocatorID(); // Compress out any gaps in the offsets by making new offsets from the sizes. // This makes the code able to handle meshes that have gaps in its connectivity array. - axom::Array actualOffsets(srcSizesView.size(), srcSizesView.size(), allocatorID); + axom::Array actualOffsets(axom::ArrayOptions::Uninitialized(), + srcSizesView.size(), + srcSizesView.size(), + allocatorID); auto actualOffsetsView = actualOffsets.view(); axom::exclusive_scan(srcSizesView, actualOffsetsView); @@ -1029,7 +1060,8 @@ class MergeMeshes AXOM_LAMBDA(axom::IndexType index) { const auto destOffset = connOffset + actualOffsetsView[index]; const auto srcOffset = srcOffsetsView[index]; - for(value_type j = 0; j < srcSizesView[index]; j++) + const value_type jmax = srcSizesView[index]; + for(value_type j = 0; j < jmax; j++) { const auto nodeId = srcConnView[srcOffset + j]; const auto newNodeId = nodeMapView[nodeId]; @@ -1044,7 +1076,8 @@ class MergeMeshes AXOM_LAMBDA(axom::IndexType index) { const auto destOffset = connOffset + actualOffsetsView[index]; const auto srcOffset = srcOffsetsView[index]; - for(value_type j = 0; j < srcSizesView[index]; j++) + const value_type jmax = srcSizesView[index]; + for(value_type j = 0; j < jmax; j++) { connView[destOffset + j] = coordOffset + srcConnView[srcOffset + j]; } @@ -1145,19 +1178,19 @@ class MergeMeshes const conduit::Node &n_field = n_fields[c]; const conduit::Node &n_values = n_field.fetch_existing("values"); FieldInformation fi; - fi.topology = n_field.fetch_existing("topology").as_string(); - fi.association = n_field.fetch_existing("association").as_string(); + fi.m_topology = n_field.fetch_existing("topology").as_string(); + fi.m_association = n_field.fetch_existing("association").as_string(); if(n_values.number_of_children() > 0) { for(conduit::index_t comp = 0; comp < n_values.number_of_children(); comp++) { - fi.components.push_back(n_values[comp].name()); - fi.dtype = n_values[comp].dtype().id(); + fi.m_components.push_back(n_values[comp].name()); + fi.m_dtype = n_values[comp].dtype().id(); } } else { - fi.dtype = n_values.dtype().id(); + fi.m_dtype = n_values.dtype().id(); } fieldInfo[n_field.name()] = fi; } @@ -1165,47 +1198,49 @@ class MergeMeshes } // Make new fields - utils::ConduitAllocateThroughAxom c2a; + const auto conduitAllocatorId = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); conduit::Node &n_newFields = output["fields"]; for(auto it = fieldInfo.begin(); it != fieldInfo.end(); it++) { conduit::Node &n_newField = n_newFields[it->first]; - n_newField["association"] = it->second.association; - n_newField["topology"] = it->second.topology; + n_newField["association"] = it->second.m_association; + n_newField["topology"] = it->second.m_topology; conduit::Node &n_values = n_newField["values"]; - if(it->second.components.empty()) + if(it->second.m_components.empty()) { // Scalar conduit::Node &n_values = n_newField["values"]; - n_values.set_allocator(c2a.getConduitAllocatorID()); + n_values.set_allocator(conduitAllocatorId); const std::string srcPath("fields/" + it->first + "/values"); - if(it->second.association == "element") + if(it->second.m_association == "element") { - n_values.set(conduit::DataType(it->second.dtype, totalZones)); + n_values.set(conduit::DataType(it->second.m_dtype, totalZones)); copyZonal(inputs, n_values, srcPath); } - else if(it->second.association == "vertex") + else if(it->second.m_association == "vertex") { - n_values.set(conduit::DataType(it->second.dtype, totalNodes)); + n_values.set(conduit::DataType(it->second.m_dtype, totalNodes)); copyNodal(inputs, n_values, srcPath); } } else { // Vector - for(size_t ci = 0; ci < it->second.components.size(); ci++) + for(size_t ci = 0; ci < it->second.m_components.size(); ci++) { - conduit::Node &n_comp = n_values[it->second.components[ci]]; - n_comp.set_allocator(c2a.getConduitAllocatorID()); - const std::string srcPath("fields/" + it->first + "/values/" + it->second.components[ci]); - if(it->second.association == "element") + conduit::Node &n_comp = n_values[it->second.m_components[ci]]; + n_comp.set_allocator(conduitAllocatorId); + const std::string srcPath("fields/" + it->first + "/values/" + + it->second.m_components[ci]); + if(it->second.m_association == "element") { - n_comp.set(conduit::DataType(it->second.dtype, totalZones)); + n_comp.set(conduit::DataType(it->second.m_dtype, totalZones)); copyZonal(inputs, n_comp, srcPath); } - else if(it->second.association == "vertex") + else if(it->second.m_association == "vertex") { - n_comp.set(conduit::DataType(it->second.dtype, totalNodes)); + n_comp.set(conduit::DataType(it->second.m_dtype, totalNodes)); copyNodal(inputs, n_comp, srcPath); } } @@ -1233,13 +1268,13 @@ class MergeMeshes if(inputs[i].m_input->has_path(srcPath)) { const conduit::Node &n_src_values = inputs[i].m_input->fetch_existing(srcPath); - axom::bump::views::Node_to_ArrayView(n_values, n_src_values, [&](auto destView, auto srcView) { + axom::bump::views::nodeToArrayView(n_values, n_src_values, [&](auto destView, auto srcView) { copyZonal_copy(nzones, offset, destView, srcView); }); } else { - axom::bump::views::Node_to_ArrayView(n_values, [&](auto destView) { + axom::bump::views::nodeToArrayView(n_values, [&](auto destView) { fillValues(nzones, offset, destView); }); } @@ -1309,13 +1344,13 @@ class MergeMeshes { const conduit::Node &n_src_values = inputs[i].m_input->fetch_existing(srcPath); - axom::bump::views::Node_to_ArrayView(n_src_values, n_values, [&](auto srcView, auto destView) { + axom::bump::views::nodeToArrayView(n_src_values, n_values, [&](auto srcView, auto destView) { copyNodal_copy(inputs[i].m_nodeSliceView, nnodes, offset, destView, srcView); }); } else { - axom::bump::views::Node_to_ArrayView(n_values, [&](auto destView) { + axom::bump::views::nodeToArrayView(n_values, [&](auto destView) { fillValues(nnodes, offset, destView); }); } @@ -1371,6 +1406,8 @@ class MergeMeshes { // Do nothing. } + + int m_allocator_id; }; /*! @@ -1403,13 +1440,13 @@ class DispatchAnyMatset FuncType &&func) { // Support various types of material data. - axom::bump::views::IndexNode_to_ArrayView_same( + axom::bump::views::indexNodeToArrayViewSame( n_material_ids, n_sizes, n_offsets, n_indices, [&](auto materialIdsView, auto sizesView, auto offsetsView, auto indicesView) { - axom::bump::views::FloatNode_to_ArrayView(n_volume_fractions, [&](auto volumeFractionsView) { + axom::bump::views::floatNodeToArrayView(n_volume_fractions, [&](auto volumeFractionsView) { // Invoke a function that can use these views. func(materialIdsView, sizesView, offsetsView, indicesView, volumeFractionsView); }); @@ -1516,7 +1553,8 @@ class MergeMeshesAndMatsets : public MergeMeshes { AXOM_ANNOTATE_SCOPE("mergeMatset"); namespace utils = axom::bump::utilities; - utils::ConduitAllocateThroughAxom c2a; + const auto conduitAllocatorId = + axom::sidre::ConduitMemory::axomAllocIdToConduit(this->getAllocatorID()); // Make a pass through the inputs and make a list of the material names. bool hasMatsets = false, defaultMaterial = false; @@ -1534,9 +1572,9 @@ class MergeMeshesAndMatsets : public MergeMeshes auto matInfo = axom::bump::views::materials(n_matset); for(const auto &info : matInfo) { - if(allMats.find(info.name) == allMats.end()) + if(allMats.find(info.m_name) == allMats.end()) { - allMats[info.name] = nmats++; + allMats[info.m_name] = nmats++; } } hasMatsets = true; @@ -1593,23 +1631,23 @@ class MergeMeshesAndMatsets : public MergeMeshes conduit::Node &n_newMatset = output["matsets/" + matsetName]; n_newMatset["topology"] = topoName; conduit::Node &n_volume_fractions = n_newMatset["volume_fractions"]; - n_volume_fractions.set_allocator(c2a.getConduitAllocatorID()); + n_volume_fractions.set_allocator(conduitAllocatorId); n_volume_fractions.set(conduit::DataType(ftype, totalMatCount)); conduit::Node &n_material_ids = n_newMatset["material_ids"]; - n_material_ids.set_allocator(c2a.getConduitAllocatorID()); + n_material_ids.set_allocator(conduitAllocatorId); n_material_ids.set(conduit::DataType(itype, totalMatCount)); conduit::Node &n_sizes = n_newMatset["sizes"]; - n_sizes.set_allocator(c2a.getConduitAllocatorID()); + n_sizes.set_allocator(conduitAllocatorId); n_sizes.set(conduit::DataType(itype, totalZones)); conduit::Node &n_offsets = n_newMatset["offsets"]; - n_offsets.set_allocator(c2a.getConduitAllocatorID()); + n_offsets.set_allocator(conduitAllocatorId); n_offsets.set(conduit::DataType(itype, totalZones)); conduit::Node &n_indices = n_newMatset["indices"]; - n_indices.set_allocator(c2a.getConduitAllocatorID()); + n_indices.set_allocator(conduitAllocatorId); n_indices.set(conduit::DataType(itype, totalMatCount)); AXOM_ANNOTATE_END("allocate"); @@ -1718,7 +1756,12 @@ class MergeMeshesAndMatsets : public MergeMeshes const auto nmats = matsetView.numberOfMaterials(zoneIndex); matCount_reduce += nmats; }); - return matCount_reduce.get(); + const auto count = matCount_reduce.get(); + if(nzones > 0) + { + SLIC_ERROR_IF(count == 0, "ReduceSum returned 0 for count."); + } + return count; } /*! @@ -1818,10 +1861,10 @@ class MergeMeshesAndMatsets : public MergeMeshes std::map localToAll; for(const auto &info : localMaterialMap) { - const auto it = allMats.find(info.name); + const auto it = allMats.find(info.m_name); SLIC_ASSERT(it != allMats.end()); MatID matno = it->second; - localToAll[info.number] = matno; + localToAll[info.m_number] = matno; } std::vector localVec, allVec; for(auto it = localToAll.begin(); it != localToAll.end(); it++) @@ -1830,7 +1873,7 @@ class MergeMeshesAndMatsets : public MergeMeshes allVec.push_back(it->second); } // Put maps on device. - const int allocatorID = axom::execution_space::allocatorID(); + const int allocatorID = this->getAllocatorID(); axom::Array local(localVec.size(), localVec.size(), allocatorID); axom::Array all(allVec.size(), allVec.size(), allocatorID); axom::copy(local.data(), localVec.data(), sizeof(MatID) * local.size()); diff --git a/src/axom/bump/MergePolyhedralFaces.hpp b/src/axom/bump/MergePolyhedralFaces.hpp index f0a7e3c5dd..2ad307957a 100644 --- a/src/axom/bump/MergePolyhedralFaces.hpp +++ b/src/axom/bump/MergePolyhedralFaces.hpp @@ -11,6 +11,7 @@ #include "axom/bump/utilities/conduit_memory.hpp" #include "axom/bump/HashNaming.hpp" #include "axom/bump/Unique.hpp" +#include "axom/sidre/core/ConduitMemory.hpp" #include @@ -47,14 +48,15 @@ class MergePolyhedralFaces * * \param n_topology The topology to modify. */ - static void execute(conduit::Node &n_topo) + static void execute(conduit::Node &n_topo, + int allocator_id = axom::execution_space::allocatorID()) { SLIC_ASSERT(n_topo.fetch_existing("elements/shape").as_string() == "polyhedral"); namespace utils = axom::bump::utilities; AXOM_ANNOTATE_SCOPE("MergePolyhedralFaces"); - utils::ConduitAllocateThroughAxom c2a; - const auto allocatorID = axom::execution_space::allocatorID(); + const auto allocatorID = allocator_id; + const auto conduitAllocatorId = axom::sidre::ConduitMemory::axomAllocIdToConduit(allocatorID); // Get the data from the topology and make views. conduit::Node &n_elem_conn = n_topo["elements/connectivity"]; @@ -78,6 +80,10 @@ class MergePolyhedralFaces se_conn.size(), AXOM_LAMBDA(axom::IndexType index) { reduceMaxNodeId.max(se_conn[index]); }); const auto maxNodeId = reduceMaxNodeId.get(); + if(se_conn.size() > 0 && maxNodeId == 0) + { + SLIC_INFO("ReduceSum returned 0 for maxNodeId."); + } AXOM_ANNOTATE_END("maxnode"); //-------------------------------------------------------------------------- @@ -128,7 +134,10 @@ class MergePolyhedralFaces axom::Array selectedFaces; // Make faces unique. - axom::bump::Unique::execute(faceNamesView, uniqueKeys, selectedFaces); + axom::bump::Unique::execute(faceNamesView, + uniqueKeys, + selectedFaces, + allocatorID); const auto uniqueKeysView = uniqueKeys.view(); const auto selectedFacesView = selectedFaces.view(); AXOM_ANNOTATE_END("unique"); @@ -136,13 +145,13 @@ class MergePolyhedralFaces //-------------------------------------------------------------------------- AXOM_ANNOTATE_BEGIN("rewriting_subelements"); conduit::Node n_new_se_sizes; - n_new_se_sizes.set_allocator(c2a.getConduitAllocatorID()); + n_new_se_sizes.set_allocator(conduitAllocatorId); n_new_se_sizes.set( conduit::DataType(utils::cpp2conduit::id, selectedFaces.size())); auto new_se_sizes = utils::make_array_view(n_new_se_sizes); conduit::Node n_new_se_offsets; - n_new_se_offsets.set_allocator(c2a.getConduitAllocatorID()); + n_new_se_offsets.set_allocator(conduitAllocatorId); n_new_se_offsets.set( conduit::DataType(utils::cpp2conduit::id, selectedFaces.size())); auto new_se_offsets = utils::make_array_view(n_new_se_offsets); @@ -157,11 +166,15 @@ class MergePolyhedralFaces reduceNewSizes += size; }); const axom::IndexType newSEConnSize = reduceNewSizes.get(); + if(selectedFaces.size() > 0) + { + SLIC_ERROR_IF(newSEConnSize == 0, "ReduceSum returned 0 for newSEConnSize."); + } axom::exclusive_scan(new_se_sizes, new_se_offsets); // Allocate new_se_conn to contain the new face definitions. conduit::Node n_new_se_conn; - n_new_se_conn.set_allocator(c2a.getConduitAllocatorID()); + n_new_se_conn.set_allocator(conduitAllocatorId); n_new_se_conn.set(conduit::DataType(utils::cpp2conduit::id, newSEConnSize)); auto new_se_conn = utils::make_array_view(n_new_se_conn); @@ -194,6 +207,10 @@ class MergePolyhedralFaces elem_sizes.size(), AXOM_LAMBDA(axom::IndexType index) { reduceConnSize += elem_sizes[index]; }); const auto totalConnSize = reduceConnSize.get(); + if(elem_sizes.size() > 0) + { + SLIC_ERROR_IF(totalConnSize == 0, "ReduceSum returned 0 for totalConnSize."); + } if(totalConnSize == elem_conn.size()) { @@ -220,12 +237,12 @@ class MergePolyhedralFaces // contains gaps. We can rewrite it and the offsets. conduit::Node n_new_elem_conn; - n_new_elem_conn.set_allocator(c2a.getConduitAllocatorID()); + n_new_elem_conn.set_allocator(conduitAllocatorId); n_new_elem_conn.set(conduit::DataType(utils::cpp2conduit::id, totalConnSize)); auto new_elem_conn = utils::make_array_view(n_new_elem_conn); conduit::Node n_new_elem_offsets; - n_new_elem_offsets.set_allocator(c2a.getConduitAllocatorID()); + n_new_elem_offsets.set_allocator(conduitAllocatorId); n_new_elem_offsets.set( conduit::DataType(utils::cpp2conduit::id, elem_sizes.size())); auto new_elem_offsets = utils::make_array_view(n_new_elem_offsets); diff --git a/src/axom/bump/MinMax.hpp b/src/axom/bump/MinMax.hpp index 94ae8c456d..673ab017d7 100644 --- a/src/axom/bump/MinMax.hpp +++ b/src/axom/bump/MinMax.hpp @@ -44,7 +44,7 @@ struct MinMax SLIC_ASSERT(n.dtype().number_of_elements() > 0); std::pair retval; - axom::bump::views::Node_to_ArrayView(n, [&](auto nview) { retval = execute(nview); }); + axom::bump::views::nodeToArrayView(n, [&](auto nview) { retval = execute(nview); }); return retval; } diff --git a/src/axom/bump/NodeToZoneRelationBuilder.hpp b/src/axom/bump/NodeToZoneRelationBuilder.hpp index 24b470b980..e5a7098e8f 100644 --- a/src/axom/bump/NodeToZoneRelationBuilder.hpp +++ b/src/axom/bump/NodeToZoneRelationBuilder.hpp @@ -10,13 +10,16 @@ #include "axom/core.hpp" #include "axom/slic.hpp" #include "axom/bump/utilities/conduit_memory.hpp" +#include "axom/bump/utilities/utilities.hpp" #include "axom/bump/views/dispatch_unstructured_topology.hpp" #include "axom/bump/MakeUnstructured.hpp" +#include "axom/sidre/core/ConduitMemory.hpp" #include #include #include +#include #include #include @@ -27,10 +30,10 @@ namespace bump namespace details { /*! - * \brief Build the node to zone relation. + * \brief Implementation for building the node to zone relation. */ template -struct BuildRelation +struct BuildRelationImpl { /*! * \brief Given views that contain the nodes and zones, sort the zones using the @@ -44,108 +47,205 @@ struct BuildRelation * * \note axom::sort_pairs can be slow if there are a lot of nodes (depends on ExecSpace too). */ - static void execute(ViewType nodesView, ViewType zonesView, ViewType sizesView, ViewType offsetsView) + static void execute(ViewType nodesView, + ViewType zonesView, + ViewType sizesView, + ViewType offsetsView, + int allocator_id) { AXOM_ANNOTATE_SCOPE("FillZonesAndOffsets"); SLIC_ASSERT(nodesView.size() == zonesView.size()); using value_type = typename ViewType::value_type; - const int allocatorID = axom::execution_space::allocatorID(); + using MaskType = typename axom::bump::utilities::mask_traits::type; + const int allocatorID = allocator_id; - // Make a copy of the nodes that we'll use as keys. + AXOM_ANNOTATE_BEGIN("alloc"); const auto n = nodesView.size(); - axom::Array keys(n, n, allocatorID); + axom::Array keys(axom::ArrayOptions::Uninitialized(), n, n, allocatorID); + axom::Array mask(axom::ArrayOptions::Uninitialized(), n, n, allocatorID); + axom::Array dest_offsets(axom::ArrayOptions::Uninitialized(), n, n, allocatorID); + AXOM_ANNOTATE_END("alloc"); + + // Make a copy of the nodes that we'll use as keys. auto keysView = keys.view(); - axom::for_all(n, AXOM_LAMBDA(axom::IndexType i) { keysView[i] = nodesView[i]; }); + { + AXOM_ANNOTATE_SCOPE("init"); + axom::for_all(n, AXOM_LAMBDA(axom::IndexType i) { keysView[i] = nodesView[i]; }); + } // Sort the keys, zones in place. This sorts the zonesView which we want for output. - axom::sort_pairs(keysView, zonesView); + { + AXOM_ANNOTATE_SCOPE("sort"); + axom::sort_pairs(keysView, zonesView); + } // Make a mask array for where differences occur. - axom::Array mask(n, n, allocatorID); auto maskView = mask.view(); - axom::for_all( - n, - AXOM_LAMBDA(axom::IndexType i) { - maskView[i] = (i >= 1) ? ((keysView[i] != keysView[i - 1]) ? 1 : 0) : 1; - }); + { + AXOM_ANNOTATE_SCOPE("mask"); + axom::for_all( + n, + AXOM_LAMBDA(axom::IndexType i) { + maskView[i] = (i >= 1) ? ((keysView[i] != keysView[i - 1]) ? MaskType {1} : MaskType {0}) + : MaskType {1}; + }); + } // Do a scan on the mask array to build an offset array. - axom::Array dest_offsets(n, n, allocatorID); auto dest_offsetsView = dest_offsets.view(); - axom::exclusive_scan(maskView, dest_offsetsView); + { + AXOM_ANNOTATE_SCOPE("scan"); + axom::exclusive_scan(maskView, dest_offsetsView); + } // Build the offsets to each node's zone ids. - axom::for_all( - offsetsView.size(), - AXOM_LAMBDA(axom::IndexType i) { offsetsView[i] = 0; }); - axom::for_all( - n, - AXOM_LAMBDA(axom::IndexType i) { - if(maskView[i]) - { - offsetsView[dest_offsetsView[i]] = i; - } - }); + { + AXOM_ANNOTATE_SCOPE("offsets"); + axom::for_all( + offsetsView.size(), + AXOM_LAMBDA(axom::IndexType i) { offsetsView[i] = 0; }); + axom::for_all( + n, + AXOM_LAMBDA(axom::IndexType i) { + if(maskView[i]) + { + offsetsView[dest_offsetsView[i]] = i; + } + }); + } // Compute sizes from offsets. - const value_type totalSize = nodesView.size(); - axom::for_all( - offsetsView.size(), - AXOM_LAMBDA(axom::IndexType i) { - sizesView[i] = (i < offsetsView.size() - 1) ? (offsetsView[i + 1] - offsetsView[i]) - : (totalSize - offsetsView[i]); - }); + { + AXOM_ANNOTATE_SCOPE("sizes"); + const value_type totalSize = nodesView.size(); + const auto offsetsViewSize_minus_1 = offsetsView.size() - 1; + axom::for_all( + offsetsView.size(), + AXOM_LAMBDA(axom::IndexType i) { + sizesView[i] = (i < offsetsViewSize_minus_1) ? (offsetsView[i + 1] - offsetsView[i]) + : (totalSize - offsetsView[i]); + }); + } } }; /// Partial specialization for axom::SEQ_EXEC. template -struct BuildRelation +struct BuildRelationImpl { - static void execute(ViewType nodesView, ViewType zonesView, ViewType sizesView, ViewType offsetsView) + using ExecSpace = axom::SEQ_EXEC; + + static void execute(ViewType nodesView, + ViewType zonesView, + ViewType sizesView, + ViewType offsetsView, + int allocator_id = axom::execution_space::allocatorID()) { AXOM_ANNOTATE_SCOPE("FillZonesAndOffsets"); + SLIC_ASSERT(nodesView.size() == zonesView.size()); using value_type = typename ViewType::value_type; - using ExecSpace = axom::SEQ_EXEC; - const int allocatorID = execution_space::allocatorID(); - // Count how many times a node is used. - axom::for_all( - sizesView.size(), - AXOM_LAMBDA(axom::IndexType index) { sizesView[index] = 0; }); - axom::for_all( - nodesView.size(), - AXOM_LAMBDA(axom::IndexType index) { - // Works because ExecSpace=SEQ_EXEC. - sizesView[nodesView[index]]++; - }); + // NOTE: Make it more "native" for a little more performance. + + const auto sizesViewSize = sizesView.size(); + memset(sizesView.data(), 0, sizesViewSize * sizeof(value_type)); + // Make sizes + const auto nodesViewSize = nodesView.size(); + for(axom::IndexType index = 0; index < nodesViewSize; index++) + { + sizesView[nodesView[index]]++; + } // Make offsets - axom::exclusive_scan(sizesView, offsetsView); + value_type offset = 0; + for(axom::IndexType i = 0; i < sizesViewSize; i++) + { + offsetsView[i] = offset; + offset += sizesView[i]; + } - axom::for_all( - sizesView.size(), - AXOM_LAMBDA(axom::IndexType index) { sizesView[index] = 0; }); + memset(sizesView.data(), 0, sizesViewSize * sizeof(value_type)); // Make a copy of zonesView so we can reorganize zonesView. - axom::Array zcopy(zonesView.size(), zonesView.size(), allocatorID); - axom::copy(zcopy.data(), zonesView.data(), zonesView.size() * sizeof(value_type)); + axom::Array zcopy(axom::ArrayOptions::Uninitialized(), + zonesView.size(), + zonesView.size(), + allocator_id); + memcpy(zcopy.data(), zonesView.data(), zonesView.size() * sizeof(value_type)); auto zcopyView = zcopy.view(); // Fill in zonesView, sizesView with each node's zones. - axom::for_all( - nodesView.size(), - AXOM_LAMBDA(axom::IndexType index) { - const auto ni = nodesView[index]; - const auto destOffset = offsetsView[ni] + sizesView[ni]; - zonesView[destOffset] = zcopyView[index]; - // Works because ExecSpace=SEQ_EXEC. - sizesView[ni]++; - }); + for(axom::IndexType index = 0; index < nodesViewSize; index++) + { + const auto ni = nodesView[index]; + const auto destOffset = offsetsView[ni] + sizesView[ni]; + zonesView[destOffset] = zcopyView[index]; + sizesView[ni]++; + } } }; +/*! + * \brief Interface for building node to zone relation. + */ +template +struct BuildRelation +{ + /*! + * \brief Given views that contain the nodes and zones, sort the zones using the + * node numbers to produce a list of zones for each node and an offsets array + * that points to the start of each list of zones. + * + * \param[in] nodesView A view that contains the set of all of the nodes in the topology (the connectivity) + * \param[inout] zonesView A view (same size as \a nodesView) that contains the zone number of each node. + * \param[out] sizesView A view that we fill with sizes. + * \param[out] offsetsView A view that we fill with offsets so offsetsView[i] points to the start of the i'th list in \a zonesView. + */ + static inline void execute(ViewType nodesView, + ViewType zonesView, + ViewType sizesView, + ViewType offsetsView, + int allocator_id = axom::execution_space::allocatorID()) + { + BuildRelationImpl::execute(nodesView, + zonesView, + sizesView, + offsetsView, + allocator_id); + } +}; + +#if defined(AXOM_RUNTIME_POLICY_USE_OPENMP) +/// Partial specialization for axom::OMP_EXEC +template +struct BuildRelation +{ + /*! + * \brief Given views that contain the nodes and zones, sort the zones using the + * node numbers to produce a list of zones for each node and an offsets array + * that points to the start of each list of zones. + * + * \param[in] nodesView A view that contains the set of all of the nodes in the topology (the connectivity) + * \param[inout] zonesView A view (same size as \a nodesView) that contains the zone number of each node. + * \param[out] sizesView A view that we fill with sizes. + * \param[out] offsetsView A view that we fill with offsets so offsetsView[i] points to the start of the i'th list in \a zonesView. + */ + static void execute(ViewType nodesView, + ViewType zonesView, + ViewType sizesView, + ViewType offsetsView, + int allocator_id = axom::execution_space::allocatorID()) + { + // Call serial implementation for now because it is faster. + BuildRelationImpl::execute(nodesView, + zonesView, + sizesView, + offsetsView, + allocator_id); + } +}; +#endif } // end namespace details /*! @@ -157,6 +257,28 @@ template class NodeToZoneRelationBuilder { public: + NodeToZoneRelationBuilder() : m_allocator_id(axom::execution_space::allocatorID()) { } + + /*! + * \brief Set the allocator id to use when allocating memory. + * + * \param allocator_id The allocator id to use when allocating memory. + */ + void setAllocatorID(int allocator_id) + { + SLIC_ERROR_IF(!axom::isValidAllocatorID(allocator_id), "Invalid allocator id."); + SLIC_ERROR_IF(!axom::execution_space::usesAllocId(allocator_id), + "Allocator id is not compatible with execution space."); + m_allocator_id = allocator_id; + } + + /*! + * \brief Get the allocator id to use when allocating memory. + * + * \return The allocator id to use when allocating memory. + */ + int getAllocatorID() const { return m_allocator_id; } + /*! * \brief Build a node to zone relation and store the resulting O2M relation in the \a relation conduit node. * @@ -166,12 +288,10 @@ class NodeToZoneRelationBuilder */ void execute(const conduit::Node &topo, const conduit::Node &coordset, conduit::Node &relation) { - namespace utils = axom::bump::utilities; const std::string type = topo.fetch_existing("type").as_string(); - // Get the ID of a Conduit allocator that will allocate through Axom with device allocator allocatorID. - utils::ConduitAllocateThroughAxom c2a; - const int conduitAllocatorID = c2a.getConduitAllocatorID(); + const auto conduitAllocatorID = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); conduit::Node &n_zones = relation["zones"]; conduit::Node &n_sizes = relation["sizes"]; @@ -212,15 +332,14 @@ class NodeToZoneRelationBuilder n_offsets.set(conduit::DataType(intTypeId, nnodes)); // Make zones for each node - views::IndexNode_to_ArrayView_same( - n_zones, - n_topo_sizes, - n_topo_offsets, - [&](auto zonesView, auto sizesView, auto offsetsView) { - fillZonesMixed(nzones, zonesView, sizesView, offsetsView); - }); - - views::IndexNode_to_ArrayView_same( + views::indexNodeToArrayViewSame(n_zones, + n_topo_sizes, + n_topo_offsets, + [&](auto zonesView, auto sizesView, auto offsetsView) { + fillZonesMixed(nzones, zonesView, sizesView, offsetsView); + }); + + views::indexNodeToArrayViewSame( n_connectivity, n_zones, n_sizes, @@ -231,7 +350,8 @@ class NodeToZoneRelationBuilder details::BuildRelation::execute(connectivityView, zonesView, sizesView, - offsetsView); + offsetsView, + getAllocatorID()); }); } else @@ -244,7 +364,7 @@ class NodeToZoneRelationBuilder n_sizes.set(conduit::DataType(intTypeId, nnodes)); n_offsets.set(conduit::DataType(intTypeId, nnodes)); - views::IndexNode_to_ArrayView_same( + views::indexNodeToArrayViewSame( n_connectivity, n_zones, n_sizes, @@ -258,7 +378,8 @@ class NodeToZoneRelationBuilder details::BuildRelation::execute(connectivityView, zonesView, sizesView, - offsetsView); + offsetsView, + getAllocatorID()); }); } } @@ -267,7 +388,7 @@ class NodeToZoneRelationBuilder // These are all structured topos of some sort. Make an unstructured representation and recurse. conduit::Node mesh; - MakeUnstructured::execute(topo, coordset, "newtopo", mesh); + MakeUnstructured::execute(topo, coordset, "newtopo", mesh, getAllocatorID()); // Recurse using the unstructured mesh. execute(mesh.fetch_existing("topologies/newtopo"), coordset, relation); @@ -302,10 +423,9 @@ class NodeToZoneRelationBuilder axom::IndexType nnodes, int intTypeId) const { - namespace utils = axom::bump::utilities; - utils::ConduitAllocateThroughAxom c2a; - const int conduitAllocatorID = c2a.getConduitAllocatorID(); - const auto allocatorID = axom::execution_space::allocatorID(); + const auto conduitAllocatorID = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); + const auto allocatorID = getAllocatorID(); const auto nzones = topoView.numberOfZones(); axom::Array sizes(nzones, nzones, allocatorID); @@ -323,6 +443,10 @@ class NodeToZoneRelationBuilder count += uniqueIds.size(); }); const auto connSize = count.get(); + if(topoView.numberOfZones() > 0) + { + SLIC_ERROR_IF(connSize == 0, "ReduceSum returned 0 for connSize."); + } // Do a scan on the size array to build an offset array. axom::Array offsets(nzones, nzones, allocatorID); @@ -339,7 +463,7 @@ class NodeToZoneRelationBuilder n_sizes.set(conduit::DataType(intTypeId, nnodes)); n_offsets.set(conduit::DataType(intTypeId, nnodes)); - views::IndexNode_to_ArrayView_same( + views::indexNodeToArrayViewSame( n_conn, n_zones, n_sizes, @@ -352,7 +476,8 @@ class NodeToZoneRelationBuilder details::BuildRelation::execute(connectivityView, zonesView, sizesView, - offsetsView); + offsetsView, + getAllocatorID()); }); } @@ -435,6 +560,9 @@ class NodeToZoneRelationBuilder connSize, AXOM_LAMBDA(axom::IndexType index) { zonesView[index] = index / nodesPerShape; }); } + +private: + int m_allocator_id; }; } // end namespace bump diff --git a/src/axom/bump/PrimalAdaptor.hpp b/src/axom/bump/PrimalAdaptor.hpp index 0e361bfbf1..9c1a2bc222 100644 --- a/src/axom/bump/PrimalAdaptor.hpp +++ b/src/axom/bump/PrimalAdaptor.hpp @@ -132,7 +132,7 @@ struct AdaptPolyhedron // Sort the ids. const axom::IndexType nnodes = uniqueNodeIds.size(); StaticArray ids; - SLIC_ASSERT(nnodes < Polyhedron::MAX_VERTS); + SLIC_ASSERT(nnodes <= Polyhedron::MAX_VERTS); for(axom::IndexType i = 0; i < nnodes; i++) { ids.push_back(uniqueNodeIds[i]); @@ -326,6 +326,17 @@ struct PrimalAdaptor typename AdaptPolyhedron::PolyhedralRepresentation; using BoundingBox = axom::primal::BoundingBox; + /*! + * \brief Constructor + * + * \param topologyView The topology view to use for initialization. + * \param coordsetView The coordset view to use for initialization. + */ + AXOM_HOST_DEVICE PrimalAdaptor(const TopologyView &topologyView, const CoordsetView &coordsetView) + : m_topologyView(topologyView) + , m_coordsetView(coordsetView) + { } + /*! * \brief Return the number of zones in the associated topology view. * \return The number of zones in the associated topology view. @@ -436,11 +447,11 @@ struct PrimalAdaptor (std::is_same>::value || std::is_same>::value || std::is_same>::value), - VariableShape>::type + axom::bump::VariableShape>::type getShape(axom::IndexType zi) const { const auto zone = m_topologyView.zone(zi); - VariableShape shape; + axom::bump::VariableShape shape; shape.m_shapeId = zone.id(); for(int i = 0; i < zone.numberOfNodes(); i++) { diff --git a/src/axom/bump/RecenterField.hpp b/src/axom/bump/RecenterField.hpp index c529c31f9f..303a6d8679 100644 --- a/src/axom/bump/RecenterField.hpp +++ b/src/axom/bump/RecenterField.hpp @@ -8,8 +8,10 @@ #define AXOM_BUMP_RECENTER_FIELD_HPP_ #include "axom/core.hpp" +#include "axom/slic.hpp" #include "axom/bump/views/NodeArrayView.hpp" #include "axom/bump/utilities/utilities.hpp" +#include "axom/sidre/core/ConduitMemory.hpp" #include #include @@ -28,20 +30,41 @@ template class RecenterField { public: + RecenterField() : m_allocator_id(axom::execution_space::allocatorID()) { } + + /*! + * \brief Set the allocator id to use when allocating memory. + * + * \param allocator_id The allocator id to use when allocating memory. + */ + void setAllocatorID(int allocator_id) + { + SLIC_ERROR_IF(!axom::isValidAllocatorID(allocator_id), "Invalid allocator id."); + SLIC_ERROR_IF(!axom::execution_space::usesAllocId(allocator_id), + "Allocator id is not compatible with execution space."); + m_allocator_id = allocator_id; + } + + /*! + * \brief Get the allocator id to use when allocating memory. + * + * \return The allocator id to use when allocating memory. + */ + int getAllocatorID() const { return m_allocator_id; } /*! * \brief Convert the input field to a different association type using the o2mrelation and store the new field in the output field. * * \param field The input field. * \param relation The node that contains an o2mrelation with nodes to zones. - * \param outField[out] The node that will contain the new field. + * \param out_field[out] The node that will contain the new field. */ - void execute(const conduit::Node &field, const conduit::Node &relation, conduit::Node &outField) const + void execute(const conduit::Node &field, const conduit::Node &relation, conduit::Node &out_field) const { const std::string association = field.fetch_existing("association").as_string(); // Assume that we're flipping the association. - outField["association"] = (association == "element") ? "vertex" : "element"; - outField["topology"] = field["topology"]; + out_field["association"] = (association == "element") ? "vertex" : "element"; + out_field["topology"] = field["topology"]; // Make output values. const conduit::Node &n_values = field["values"]; @@ -50,12 +73,12 @@ class RecenterField for(conduit::index_t c = 0; c < n_values.number_of_children(); c++) { const conduit::Node &n_comp = n_values[c]; - recenterSingleComponent(n_comp, relation, outField["values"][n_comp.name()]); + recenterSingleComponent(n_comp, relation, out_field["values"][n_comp.name()]); } } else { - recenterSingleComponent(n_values, relation, outField["values"]); + recenterSingleComponent(n_values, relation, out_field["values"]); } } @@ -83,19 +106,19 @@ class RecenterField const conduit::Node &n_relvalues = relation[data_paths[0]]; const conduit::Node &n_sizes = relation["sizes"]; const conduit::Node &n_offsets = relation["offsets"]; - views::IndexNode_to_ArrayView_same( + views::indexNodeToArrayViewSame( n_relvalues, n_sizes, n_offsets, - [&](auto relView, auto sizesView, auto offsetsView) { - // Allocate Conduit data through Axom. - const auto relSize = sizesView.size(); - utils::ConduitAllocateThroughAxom c2a; - n_out.set_allocator(c2a.getConduitAllocatorID()); - n_out.set(conduit::DataType(n_comp.dtype().id(), relSize)); - - views::Node_to_ArrayView_same(n_out, n_comp, [&](auto outView, auto compView) { - recenterSingleComponentImpl(relView, sizesView, offsetsView, outView, compView); + [&](auto rel_view, auto sizes_view, auto offsets_view) { + const auto conduit_allocator_id = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); + const auto rel_size = sizes_view.size(); + n_out.set_allocator(conduit_allocator_id); + n_out.set(conduit::DataType(n_comp.dtype().id(), rel_size)); + + views::nodeToArrayViewSame(n_out, n_comp, [&](auto out_view, auto comp_view) { + recenterSingleComponentImpl(rel_view, sizes_view, offsets_view, out_view, comp_view); }); }); } @@ -103,38 +126,41 @@ class RecenterField /*! * \brief Recenter a single field component. * - * \param relView The view that contains the ids for the relation. - * \param sizesView The view that contains the sizes for the relation. - * \param offsetsView The view that contains the offsets for the relation. - * \param outView The view that contains the out data. - * \param compView The view that contains the source data. + * \param rel_view The view that contains the ids for the relation. + * \param sizes_view The view that contains the sizes for the relation. + * \param offsets_view The view that contains the offsets for the relation. + * \param out_view The view that contains the out data. + * \param comp_view The view that contains the source data. */ template - void recenterSingleComponentImpl(IndexView relView, - IndexView sizesView, - IndexView offsetsView, - DataView outView, - DataView compView) const + void recenterSingleComponentImpl(IndexView rel_view, + IndexView sizes_view, + IndexView offsets_view, + DataView out_view, + DataView comp_view) const { using Precision = typename DataView::value_type; using AccumType = typename axom::bump::utilities::accumulation_traits::type; - const auto relSize = sizesView.size(); + const auto rel_size = sizes_view.size(); axom::for_all( - relSize, - AXOM_LAMBDA(axom::IndexType relIndex) { - const auto n = static_cast(sizesView[relIndex]); - const auto offset = offsetsView[relIndex]; + rel_size, + AXOM_LAMBDA(axom::IndexType rel_index) { + const auto n = static_cast(sizes_view[rel_index]); + const auto offset = offsets_view[rel_index]; AccumType sum {}; for(axom::IndexType i = 0; i < n; i++) { - const auto id = relView[offset + i]; - sum += static_cast(compView[id]); + const auto id = rel_view[offset + i]; + sum += static_cast(comp_view[id]); } - outView[relIndex] = static_cast(sum / n); + out_view[rel_index] = static_cast(sum / n); }); } + +private: + int m_allocator_id; }; } // end namespace bump diff --git a/src/axom/bump/SelectedZones.hpp b/src/axom/bump/SelectedZones.hpp index e1455f1bfd..0cfd8a222b 100644 --- a/src/axom/bump/SelectedZones.hpp +++ b/src/axom/bump/SelectedZones.hpp @@ -30,7 +30,7 @@ class SelectedZones * * \param nzones The total number of zones in the associated topology. * \param n_options The node that contains the options. - * \param selectionKey The name of the node with the selection data in the options. + * \param selection_key The name of the node with the selection data in the options. * * The n_options node contains options that influence how the class runs. * The options can contain a "selectedZones" node that contains an array of @@ -44,11 +44,13 @@ class SelectedZones */ SelectedZones(axom::IndexType nzones, const conduit::Node &n_options, - const std::string &selectionKey = std::string("selectedZones")) - : m_selectionKey(selectionKey) + const std::string &selection_key = std::string("selectedZones"), + int allocator_id = axom::execution_space::allocatorID()) + : m_selectionKey(selection_key) , m_selectedZones() , m_selectedZonesView() , m_sorted(true) + , m_allocator_id(allocator_id) { buildSelectedZones(nzones, n_options); } @@ -64,8 +66,10 @@ class SelectedZones /*! * \brief Return a view that contains the list of selected zone ids for the mesh. * \return A view that contains the list of selected zone ids for the mesh. + * + * \note Return a copy of the view. */ - const axom::ArrayView &view() const { return m_selectedZonesView; } + const axom::ArrayView view() const { return m_selectedZonesView; } /*! * \brief Return the selection key for the options. @@ -94,20 +98,18 @@ class SelectedZones */ void buildSelectedZones(axom::IndexType nzones, const conduit::Node &n_options) { - const auto allocatorID = axom::execution_space::allocatorID(); - if(n_options.has_path(m_selectionKey)) { // Store the zone list in m_selectedZones. - int badValueCount = 0; - views::IndexNode_to_ArrayView(n_options[m_selectionKey], [&](auto zonesView) { + int bad_value_count = 0; + views::indexNodeToArrayView(n_options[m_selectionKey], [&](auto zones_view) { // It probably does not make sense to request more zones than we have in the mesh. - SLIC_ASSERT(zonesView.size() <= nzones); + SLIC_ASSERT(zones_view.size() <= nzones); - badValueCount = buildSelectedZones(zonesView, nzones); + bad_value_count = buildSelectedZones(zones_view, nzones); }); - if(badValueCount > 0) + if(bad_value_count > 0) { SLIC_ERROR(axom::fmt::format("Out of range {} values.", m_selectionKey)); } @@ -115,18 +117,18 @@ class SelectedZones else { // Select all zones. - m_selectedZones = axom::Array(nzones, nzones, allocatorID); - auto szView = m_selectedZonesView = m_selectedZones.view(); + m_selectedZones = axom::Array(nzones, nzones, m_allocator_id); + auto sz_view = m_selectedZonesView = m_selectedZones.view(); axom::for_all( nzones, - AXOM_LAMBDA(axom::IndexType zoneIndex) { szView[zoneIndex] = zoneIndex; }); + AXOM_LAMBDA(axom::IndexType zone_index) { sz_view[zone_index] = zone_index; }); } } /*! * \brief Help build the selected zones, converting them to axom::IndexType and sorting them. * - * \param zonesView The view that contains the source zone ids. + * \param zones_view The view that contains the source zone ids. * \param nzones The number of zones in the mesh. * * \return The number of invalid zone ids. @@ -136,31 +138,31 @@ class SelectedZones * lambda. */ template - int buildSelectedZones(ZonesViewType zonesView, axom::IndexType nzones) + int buildSelectedZones(ZonesViewType zones_view, axom::IndexType nzones) { - const auto allocatorID = axom::execution_space::allocatorID(); - m_selectedZones = axom::Array(zonesView.size(), zonesView.size(), allocatorID); - auto szView = m_selectedZonesView = m_selectedZones.view(); + m_selectedZones = + axom::Array(zones_view.size(), zones_view.size(), m_allocator_id); + auto sz_view = m_selectedZonesView = m_selectedZones.view(); axom::for_all( - szView.size(), - AXOM_LAMBDA(axom::IndexType index) { szView[index] = zonesView[index]; }); + sz_view.size(), + AXOM_LAMBDA(axom::IndexType index) { sz_view[index] = zones_view[index]; }); // Check that the selected zone values are in range. - axom::ReduceSum errReduce(0); + axom::ReduceSum err_reduce(0); axom::for_all( - szView.size(), + sz_view.size(), AXOM_LAMBDA(axom::IndexType index) { - const int err = (szView[index] < 0 || szView[index] >= nzones) ? 1 : 0; - errReduce += err; + const int err = (sz_view[index] < 0 || sz_view[index] >= nzones) ? 1 : 0; + err_reduce += err; }); if(m_sorted) { // Make sure the selectedZones are sorted. - axom::sort(szView); + axom::sort(sz_view); } - return errReduce.get(); + return err_reduce.get(); } // The following members are protected (unless using CUDA) @@ -172,6 +174,7 @@ class SelectedZones axom::Array m_selectedZones; // Storage for a list of selected zone ids. axom::ArrayView m_selectedZonesView; bool m_sorted; + int m_allocator_id; }; } // end namespace bump diff --git a/src/axom/bump/TopologyMapper.hpp b/src/axom/bump/TopologyMapper.hpp index b63ef02766..ebdbb2cb59 100644 --- a/src/axom/bump/TopologyMapper.hpp +++ b/src/axom/bump/TopologyMapper.hpp @@ -16,6 +16,7 @@ #include "axom/bump/PrimalAdaptor.hpp" #include "axom/bump/VariableShape.hpp" #include "axom/bump/utilities/utilities.hpp" +#include "axom/sidre/core/ConduitMemory.hpp" #include #include @@ -25,6 +26,27 @@ // Uncomment to emit debugging messages //#define AXOM_DEBUG_TOPOLOGY_MAPPER +#if defined(AXOM_DEVICE_CODE) && defined(AXOM_USE_HIP) + #define AXOM_TM_ASSERT_OR_RETURN(CONDITION) \ + do \ + { \ + if(!(CONDITION)) \ + { \ + return; \ + } \ + } while(false) +#else + #define AXOM_TM_ASSERT_OR_RETURN(CONDITION) \ + do \ + { \ + SLIC_ASSERT(CONDITION); \ + if(!(CONDITION)) \ + { \ + return; \ + } \ + } while(false) +#endif + namespace axom { namespace bump @@ -46,8 +68,8 @@ AXOM_HOST_DEVICE double shapeOverlap(const axom::primal::Polygon::allocatorID()) { } + /*! + * \brief Set the allocator id to use when allocating memory. + * + * \param allocator_id The allocator id to use when allocating memory. + */ + void setAllocatorID(int allocator_id) + { + SLIC_ERROR_IF(!axom::isValidAllocatorID(allocator_id), "Invalid allocator id."); + SLIC_ERROR_IF(!axom::execution_space::usesAllocId(allocator_id), + "Allocator id is not compatible with execution space."); + m_allocator_id = allocator_id; + } + + /*! + * \brief Get the allocator id to use when allocating memory. + * + * \return The allocator id to use when allocating memory. + */ + int getAllocatorID() const { return m_allocator_id; } + /** * \brief Intersect the source and target topologies and map the source * material onto the target mesh. @@ -490,7 +533,7 @@ class TopologyMapper using MatIntType = typename SrcMatsetView::IndexType; using MatFloatType = typename SrcMatsetView::FloatType; - const int allocatorID = axom::execution_space::allocatorID(); + const int allocatorID = getAllocatorID(); const char *SRC_MATSET_NAME = "source/matsetName"; const char *SRC_SELECTED_ZONES = "source/selectedZones"; @@ -501,7 +544,7 @@ class TopologyMapper // Make sure options are in the right memory space in case we are given lists of // selected zone ids. conduit::Node n_options_copy; - utils::copy(n_options_copy, n_options); + utils::copy(n_options_copy, n_options, getAllocatorID()); // Ensure required options exist. const char *required[] = {SRC_MATSET_NAME, TARGET_TOPOLOGY_NAME, TARGET_MATSET_NAME}; @@ -541,12 +584,19 @@ class TopologyMapper using src_value_type = typename SrcCoordsetView::value_type; AXOM_ANNOTATE_BEGIN("bbox"); const auto srcView = m_srcView; - SelectedZones srcSelection(srcView.numberOfZones(), n_options_copy, SRC_SELECTED_ZONES); + SelectedZones srcSelection(srcView.numberOfZones(), + n_options_copy, + SRC_SELECTED_ZONES, + allocatorID); srcSelection.setSorted(false); const auto srcSelectionView = srcSelection.view(); const axom::IndexType nSrcZones = srcSelectionView.size(); axom::Array srcBoundingBoxes(nSrcZones, nSrcZones, allocatorID); auto srcBoundingBoxesView = srcBoundingBoxes.view(); + if(!n_options_copy.has_path(SRC_SELECTED_ZONES)) + { + SLIC_ASSERT(nSrcZones == srcSelectionView.size()); + } axom::for_all( nSrcZones, AXOM_LAMBDA(axom::IndexType index) { @@ -563,9 +613,16 @@ class TopologyMapper AXOM_ANNOTATE_BEGIN("target"); const auto targetView = m_targetView; const auto nTargetZones = targetView.numberOfZones(); - SelectedZones targetSelection(nTargetZones, n_options_copy, TARGET_SELECTED_ZONES); + SelectedZones targetSelection(nTargetZones, + n_options_copy, + TARGET_SELECTED_ZONES, + allocatorID); targetSelection.setSorted(false); const auto targetSelectionView = targetSelection.view(); + if(!n_options_copy.has_path(TARGET_SELECTED_ZONES)) + { + SLIC_ASSERT(nTargetZones == targetSelectionView.size()); + } AXOM_ANNOTATE_END("target"); // ------------------------------------------------------------------------- @@ -573,12 +630,13 @@ class TopologyMapper axom::spin::BVH bvh; bvh.setAllocatorID(allocatorID); bvh.initialize(srcBoundingBoxesView, srcBoundingBoxesView.size()); + axom::synchronize(); AXOM_ANNOTATE_END("build"); // ------------------------------------------------------------------------- // Set up storage for a new matset. AXOM_ANNOTATE_BEGIN("allocation"); - utils::ConduitAllocateThroughAxom c2a; + const auto conduitAllocatorId = axom::sidre::ConduitMemory::axomAllocIdToConduit(allocatorID); // Make target matset. conduit::Node &n_targetMatset = n_targetMesh["matsets/" + targetMatsetName]; @@ -592,11 +650,11 @@ class TopologyMapper conduit::Node &n_offsets = n_targetMatset["offsets"]; // Allocate memory for the output matset. - n_volume_fractions.set_allocator(c2a.getConduitAllocatorID()); - n_material_ids.set_allocator(c2a.getConduitAllocatorID()); - n_indices.set_allocator(c2a.getConduitAllocatorID()); - n_sizes.set_allocator(c2a.getConduitAllocatorID()); - n_offsets.set_allocator(c2a.getConduitAllocatorID()); + n_volume_fractions.set_allocator(conduitAllocatorId); + n_material_ids.set_allocator(conduitAllocatorId); + n_indices.set_allocator(conduitAllocatorId); + n_sizes.set_allocator(conduitAllocatorId); + n_offsets.set_allocator(conduitAllocatorId); n_volume_fractions.set( conduit::DataType(utils::cpp2conduit::id, numMaterialSlots * nTargetZones)); @@ -604,16 +662,23 @@ class TopologyMapper conduit::DataType(utils::cpp2conduit::id, numMaterialSlots * nTargetZones)); n_sizes.set(conduit::DataType(utils::cpp2conduit::id, nTargetZones)); n_offsets.set(conduit::DataType(utils::cpp2conduit::id, nTargetZones)); - // n_indices are allocated later + // n_indices allocated later // Wrap the output matset data in some array views. auto material_ids = utils::make_array_view(n_material_ids); auto volume_fractions = utils::make_array_view(n_volume_fractions); auto sizes = utils::make_array_view(n_sizes); auto offsets = utils::make_array_view(n_offsets); - volume_fractions.fill(MatFloatType(0.)); - material_ids.fill(MaterialEmpty); - sizes.fill(MatIntType(0)); + // Initialize the expected values. + axom::for_all( + numMaterialSlots * nTargetZones, + AXOM_LAMBDA(axom::IndexType index) { + volume_fractions[index] = MatFloatType {0}; + material_ids[index] = MaterialEmpty; + }); + axom::for_all( + nTargetZones, + AXOM_LAMBDA(axom::IndexType index) { sizes[index] = MatIntType {0}; }); AXOM_ANNOTATE_END("allocation"); // ------------------------------------------------------------------------- @@ -624,11 +689,9 @@ class TopologyMapper axom::for_all( targetSelectionView.size(), AXOM_LAMBDA(axom::IndexType index) { - SLIC_ASSERT(index >= 0 && index < targetSelectionView.size()); - // Get the target zone as a primal shape. const axom::IndexType zi = targetSelectionView[index]; - SLIC_ASSERT(zi >= 0 && zi < targetView.numberOfZones()); + AXOM_TM_ASSERT_OR_RETURN(zi >= 0 && zi < targetView.numberOfZones()); const auto targetBBox = targetView.getBoundingBox(zi); const auto targetShape = targetView.getShape(zi); @@ -643,10 +706,12 @@ class TopologyMapper // Handle intersection in-depth of the bounding boxes intersected. auto handleIntersection = [&](std::int32_t currentNode, const std::int32_t *leafNodes) { const auto srcBboxIndex = leafNodes[currentNode]; - SLIC_ASSERT(srcBboxIndex >= 0 && srcBboxIndex < srcSelectionView.size()); + + // This should not happen but check that we're not given bad values. + AXOM_TM_ASSERT_OR_RETURN(srcBboxIndex >= 0 && srcBboxIndex < srcSelectionView.size()); const auto srcZone = srcSelectionView[srcBboxIndex]; - SLIC_ASSERT(srcZone >= 0 && srcZone < srcView.numberOfZones()); + AXOM_TM_ASSERT_OR_RETURN(srcZone >= 0 && srcZone < srcView.numberOfZones()); #if defined(AXOM_DEBUG_TOPOLOGY_MAPPER) && !defined(AXOM_DEVICE_CODE) std::cout << "handleIntersection: targetZone=" << zi << ", srcZone=" << srcZone << std::endl; @@ -747,9 +812,9 @@ class TopologyMapper // If the zone was not completely covered by other materials, increment // its size to include the empty material and set its VF. constexpr MatFloatType MatTolerance = 1.e-6; - if(sizes[index] == 0 || (1. - vfSum) > MatTolerance) + if(sizes[index] == 0 || (MatFloatType {1} - vfSum) > MatTolerance) { - vfs[sizes[index]] = 1. - vfSum; + vfs[sizes[index]] = MatFloatType {1} - vfSum; sizes[index]++; emptyCount += 1; } @@ -762,6 +827,10 @@ class TopologyMapper n_targetMatset["material_map"]["empty"] = MaterialEmpty; } totalSize = reduceSize.get(); + if(nTargetZones > 0) + { + SLIC_ERROR_IF(totalSize == 0, "ReduceSum returned 0 for totalSize."); + } } // ------------------------------------------------------------------------- @@ -773,8 +842,8 @@ class TopologyMapper // The volume_fractions and material_ids arrays contain gaps that we can compress out. conduit::Node n_new_volume_fractions, n_new_material_ids; - n_new_volume_fractions.set_allocator(c2a.getConduitAllocatorID()); - n_new_material_ids.set_allocator(c2a.getConduitAllocatorID()); + n_new_volume_fractions.set_allocator(conduitAllocatorId); + n_new_material_ids.set_allocator(conduitAllocatorId); n_new_volume_fractions.set(conduit::DataType(utils::cpp2conduit::id, totalSize)); n_new_material_ids.set(conduit::DataType(utils::cpp2conduit::id, totalSize)); auto new_volume_fractions = utils::make_array_view(n_new_volume_fractions); @@ -802,9 +871,12 @@ class TopologyMapper SrcShapeView m_srcView; SrcMatsetView m_srcMatsetView; TargetShapeView m_targetView; + int m_allocator_id; }; } // namespace bump } // namespace axom +#undef AXOM_TM_ASSERT_OR_RETURN + #endif diff --git a/src/axom/bump/Unique.hpp b/src/axom/bump/Unique.hpp index 8b9d430fcc..2a5311cd67 100644 --- a/src/axom/bump/Unique.hpp +++ b/src/axom/bump/Unique.hpp @@ -9,6 +9,7 @@ #include "axom/core.hpp" #include "axom/slic.hpp" +#include "axom/bump/utilities/utilities.hpp" #include #include @@ -30,21 +31,34 @@ namespace detail * \brief Print a container. * * \param name The name to print for the container. - * \param container The container whose data will be printed. + * \param container The container (usually a view) whose data will be printed. */ -template +template void printContainer(const std::string &name, const ContainerType &container) { - std::cout << name << "=["; - for(axom::IndexType i = 0; i < container.size(); i++) + using value_type = typename ContainerType::value_type; + using printed_type = + typename std::conditional, int, value_type>::type; + + if constexpr(axom::execution_space::onDevice()) + { + axom::Array hostData(container.size(), container.size()); + axom::copy(hostData.data(), container.data(), sizeof(value_type) * container.size()); + printContainer(name, hostData); + } + else { - if(i > 0) + std::cout << name << "=["; + for(axom::IndexType i = 0; i < container.size(); i++) { - std::cout << ", "; + if(i > 0) + { + std::cout << ", "; + } + std::cout << static_cast(container[i]); } - std::cout << container[i]; + std::cout << "]\n"; } - std::cout << "]\n"; } /*! @@ -104,14 +118,15 @@ struct Unique */ static void execute(const axom::ArrayView keys_orig_view, axom::Array &skeys, - axom::Array &sindices) + axom::Array &sindices, + int allocator_id = axom::execution_space::allocatorID()) { - const int allocatorID = axom::execution_space::allocatorID(); + const int allocatorID = allocator_id; // Make a copy of the keys and make original indices. const auto n = keys_orig_view.size(); - axom::Array keys(n, n, allocatorID); - axom::Array indices(n, n, allocatorID); + axom::Array keys(axom::ArrayOptions::Uninitialized(), n, n, allocatorID); + axom::Array indices(axom::ArrayOptions::Uninitialized(), n, n, allocatorID); auto keys_view = keys.view(); auto indices_view = indices.view(); axom::for_all( @@ -122,25 +137,25 @@ struct Unique }); #if defined(AXOM_DEBUG_UNIQUE) // Input values - if(!axom::execution_space::onDevice()) - { - detail::printContainer("keys", keys_view); - detail::printContainer("indices", indices_view); - } + detail::printContainer("keys", keys_view); + detail::printContainer("indices", indices_view); #endif // Sort the keys, indices in place. axom::stable_sort_pairs(keys_view, indices_view); // Make a mask array for where differences occur. - axom::Array mask(n, n, allocatorID); + using MaskType = typename axom::bump::utilities::mask_traits::type; + axom::Array mask(axom::ArrayOptions::Uninitialized(), n, n, allocatorID); auto mask_view = mask.view(); axom::ReduceSum mask_sum(0); axom::for_all( n, AXOM_LAMBDA(axom::IndexType i) { - const axom::IndexType m = (i >= 1) ? ((keys_view[i] != keys_view[i - 1]) ? 1 : 0) : 1; + const MaskType m = (i >= 1) + ? ((keys_view[i] != keys_view[i - 1]) ? MaskType {1} : MaskType {0}) + : MaskType {1}; mask_view[i] = m; - mask_sum += m; + mask_sum += static_cast(m); }); // Do a scan on the mask array to build an offset array. @@ -150,19 +165,17 @@ struct Unique #if defined(AXOM_DEBUG_UNIQUE) // Post-sorting values. - if(!axom::execution_space::onDevice()) - { - detail::printContainer("sorted_keys", keys_view); - detail::printContainer("sorted_indices", indices_view); - detail::printContainer("mask", mask_view); - detail::printContainer("offsets", offsets_view); - } + detail::printContainer("sorted_keys", keys_view); + detail::printContainer("sorted_indices", indices_view); + detail::printContainer("mask", mask_view); + detail::printContainer("offsets", offsets_view); #endif // Allocate the output arrays. const axom::IndexType newsize = mask_sum.get(); - skeys = axom::Array(newsize, newsize, allocatorID); - sindices = axom::Array(newsize, newsize, allocatorID); + skeys = axom::Array(axom::ArrayOptions::Uninitialized(), newsize, newsize, allocatorID); + sindices = + axom::Array(axom::ArrayOptions::Uninitialized(), newsize, newsize, allocatorID); // Iterate over the mask/offsets to store values at the right // offset in the new array. @@ -180,11 +193,8 @@ struct Unique #if defined(AXOM_DEBUG_UNIQUE) // Output values - if(!axom::execution_space::onDevice()) - { - detail::printContainer("skeys", skeys_view); - detail::printContainer("sindices", sindices_view); - } + detail::printContainer("skeys", skeys_view); + detail::printContainer("sindices", sindices_view); #endif } }; @@ -204,7 +214,8 @@ struct Unique */ static void execute(const axom::ArrayView &keys_orig_view, axom::Array &skeys, - axom::Array &sindices) + axom::Array &sindices, + int allocator_id = axom::execution_space::allocatorID()) { // Make unique values and store the indices. std::unordered_map unique_map; @@ -230,9 +241,10 @@ struct Unique // Allocate the output arrays and populate them const axom::IndexType newsize = unique_vector.size(); - const int allocatorID = axom::execution_space::allocatorID(); - skeys = axom::Array(newsize, newsize, allocatorID); - sindices = axom::Array(newsize, newsize, allocatorID); + const int allocatorID = allocator_id; + skeys = axom::Array(axom::ArrayOptions::Uninitialized(), newsize, newsize, allocatorID); + sindices = + axom::Array(axom::ArrayOptions::Uninitialized(), newsize, newsize, allocatorID); for(axom::IndexType index = 0; index < newsize; ++index) { diff --git a/src/axom/bump/ZoneListBuilder.hpp b/src/axom/bump/ZoneListBuilder.hpp index 6810910fbb..9f65e3bb6b 100644 --- a/src/axom/bump/ZoneListBuilder.hpp +++ b/src/axom/bump/ZoneListBuilder.hpp @@ -8,6 +8,7 @@ #define AXOM_BUMP_ZONELIST_BUILDER_HPP #include "axom/core.hpp" +#include "axom/slic.hpp" #include @@ -26,6 +27,8 @@ namespace bump template class ZoneListBuilder { + using MaskType = typename axom::bump::utilities::mask_traits::type; + public: using SelectedZonesView = axom::ArrayView; using ZoneType = typename TopologyView::ShapeType; @@ -39,8 +42,29 @@ class ZoneListBuilder ZoneListBuilder(const TopologyView &topoView, const MatsetView &matsetView) : m_topologyView(topoView) , m_matsetView(matsetView) + , m_allocator_id(axom::execution_space::allocatorID()) { } + /*! + * \brief Set the allocator id to use when allocating memory. + * + * \param allocator_id The allocator id to use when allocating memory. + */ + void setAllocatorID(int allocator_id) + { + SLIC_ERROR_IF(!axom::isValidAllocatorID(allocator_id), "Invalid allocator id."); + SLIC_ERROR_IF(!axom::execution_space::usesAllocId(allocator_id), + "Allocator id is not compatible with execution space."); + m_allocator_id = allocator_id; + } + + /*! + * \brief Get the allocator id to use when allocating memory. + * + * \return The allocator id to use when allocating memory. + */ + int getAllocatorID() const { return m_allocator_id; } + /*! * \brief Build the list of clean and mixed zones using the number of materials * per zone, maxed to the nodes. @@ -58,13 +82,15 @@ class ZoneListBuilder axom::Array &cleanIndices, axom::Array &mixedIndices) const { - AXOM_ANNOTATE_SCOPE("ZoneListBuilder"); - const int allocatorID = axom::execution_space::allocatorID(); + AXOM_ANNOTATE_SCOPE("ZoneListBuilder.1"); + const int allocatorID = getAllocatorID(); AXOM_ANNOTATE_BEGIN("nMatsPerNode"); - axom::Array nMatsPerNode(nnodes, nnodes, allocatorID); - nMatsPerNode.fill(0); + axom::Array nMatsPerNode(axom::ArrayOptions::Uninitialized(), nnodes, nnodes, allocatorID); auto nMatsPerNodeView = nMatsPerNode.view(); + axom::for_all( + nnodes, + AXOM_LAMBDA(axom::IndexType nodeIndex) { nMatsPerNodeView[nodeIndex] = 1; }); // Determine max number of materials a node might touch. MatsetView deviceMatsetView(m_matsetView); @@ -72,58 +98,93 @@ class ZoneListBuilder axom::for_all( m_topologyView.numberOfZones(), AXOM_LAMBDA(axom::IndexType zoneIndex) { - const auto zone = deviceTopologyView.zone(zoneIndex); - const auto matZoneIndex = zoneIndex; - const int nmats = deviceMatsetView.numberOfMaterials(matZoneIndex); - - const auto nnodesThisZone = zone.numberOfNodes(); - int *nodeData = nMatsPerNodeView.data(); - for(axom::IndexType i = 0; i < nnodesThisZone; i++) + const int nmats = deviceMatsetView.numberOfMaterials(zoneIndex); + if(nmats > 1) { - const auto nodeId = zone.getId(i); - int *nodePtr = nodeData + nodeId; - axom::atomicMax(nodePtr, nmats); + const auto zone = deviceTopologyView.zone(zoneIndex); + const auto nnodesThisZone = zone.numberOfNodes(); + int *nodeData = nMatsPerNodeView.data(); + for(axom::IndexType i = 0; i < nnodesThisZone; i++) + { + const auto nodeId = zone.getId(i); + int *nodePtr = nodeData + nodeId; + axom::atomicMax(nodePtr, nmats); + } } }); + axom::synchronize(); AXOM_ANNOTATE_END("nMatsPerNode"); // Now, mark all zones that have 1 mat per node as clean. AXOM_ANNOTATE_BEGIN("mask"); const auto nzones = m_topologyView.numberOfZones(); - axom::Array mask(nzones, nzones, allocatorID); + axom::Array mask(axom::ArrayOptions::Uninitialized(), nzones, nzones, allocatorID); auto maskView = mask.view(); - axom::ReduceSum mask_reduce(0); axom::for_all( - m_topologyView.numberOfZones(), + nzones, AXOM_LAMBDA(axom::IndexType zoneIndex) { const auto zone = deviceTopologyView.zone(zoneIndex); - bool clean = true; + MaskType clean {1}; const axom::IndexType nnodesThisZone = zone.numberOfNodes(); - for(axom::IndexType i = 0; i < nnodesThisZone && clean; i++) + const auto &zoneNodeIds = zone.getIdsStorage(); + for(axom::IndexType i = 0; i < nnodesThisZone; i++) { - const auto nodeId = zone.getId(i); - clean &= (nMatsPerNodeView[nodeId] == 1); + const auto nodeId = zoneNodeIds[i]; + clean &= (nMatsPerNodeView[nodeId] == 1) ? MaskType {1} : MaskType {0}; } - const int ival = clean ? 1 : 0; - maskView[zoneIndex] = ival; - mask_reduce += ival; + maskView[zoneIndex] = clean; }); AXOM_ANNOTATE_END("mask"); - const int nClean = mask_reduce.get(); + axom::IndexType nClean = 0; + axom::Array maskOffsets; + axom::ArrayView maskOffsetsView; + if(nzones > 0) + { + AXOM_ANNOTATE_SCOPE("numClean"); + if constexpr(axom::execution_space::onDevice()) + { + // On device, use a reduction on maskView to count clean zones. + axom::ReduceSum mask_reduce(0); + axom::for_all( + nzones, + AXOM_LAMBDA(axom::IndexType zoneIndex) { + mask_reduce += static_cast(maskView[zoneIndex]); + }); + nClean = mask_reduce.get(); + } + else + { + // Off device, do the offset scan early and use the results to compute + // nClean instead of a reduction. + AXOM_ANNOTATE_SCOPE("offsets"); + maskOffsets = + axom::Array(axom::ArrayOptions::Uninitialized(), nzones, nzones, allocatorID); + maskOffsetsView = maskOffsets.view(); + axom::exclusive_scan(maskView, maskOffsetsView); + + nClean = maskOffsetsView[nzones - 1] + static_cast(maskView[nzones - 1]); + } + } + if(nClean > 0) { - AXOM_ANNOTATE_BEGIN("offsets"); - axom::Array maskOffsets(nzones, nzones, allocatorID); - auto maskOffsetsView = maskOffsets.view(); - axom::exclusive_scan(maskView, maskOffsetsView); - AXOM_ANNOTATE_END("offsets"); + // Compute maskOffsets if we did not do it yet. + if(maskOffsets.empty()) + { + AXOM_ANNOTATE_SCOPE("offsets"); + maskOffsets = + axom::Array(axom::ArrayOptions::Uninitialized(), nzones, nzones, allocatorID); + maskOffsetsView = maskOffsets.view(); + axom::exclusive_scan(maskView, maskOffsetsView); + } // Make the output cleanIndices array. AXOM_ANNOTATE_BEGIN("cleanIndices"); - cleanIndices = axom::Array(nClean, nClean, allocatorID); + cleanIndices = + axom::Array(axom::ArrayOptions::Uninitialized(), nClean, nClean, allocatorID); auto cleanIndicesView = cleanIndices.view(); axom::for_all( nzones, @@ -139,10 +200,13 @@ class ZoneListBuilder AXOM_ANNOTATE_BEGIN("mixedIndices"); axom::for_all( nzones, - AXOM_LAMBDA(axom::IndexType index) { maskView[index] = (maskView[index] == 1) ? 0 : 1; }); + AXOM_LAMBDA(axom::IndexType index) { + maskView[index] = (maskView[index] == MaskType {1}) ? MaskType {0} : MaskType {1}; + }); axom::exclusive_scan(maskView, maskOffsetsView); const int nMixed = nzones - nClean; - mixedIndices = axom::Array(nMixed, nMixed, allocatorID); + mixedIndices = + axom::Array(axom::ArrayOptions::Uninitialized(), nMixed, nMixed, allocatorID); auto mixedIndicesView = mixedIndices.view(); axom::for_all( nzones, @@ -160,7 +224,8 @@ class ZoneListBuilder cleanIndices = axom::Array(); // There were no clean, so it must all be mixed. - mixedIndices = axom::Array(nzones, nzones, allocatorID); + mixedIndices = + axom::Array(axom::ArrayOptions::Uninitialized(), nzones, nzones, allocatorID); auto mixedIndicesView = mixedIndices.view(); axom::for_all( nzones, @@ -173,7 +238,8 @@ class ZoneListBuilder * per zone, maxed to the nodes. Limit the number of zones. * * \param nnodes The number of nodes in the topology's coordset. - * \param selectedZonesView A view containing the zone indices we're considering. + * \param selectedZonesView A view containing the zone indices we're considering. We pass + * it by value so it can be captured into lambdas. * \param[out] cleanIndices An array that will contain the list of clean material zone ids. * \param[out] mixedIndices An array that will contain the list of mixed material zone ids. * @@ -183,19 +249,21 @@ class ZoneListBuilder * considered mixed as we might have to split those zones. */ void execute(axom::IndexType nnodes, - const SelectedZonesView &selectedZonesView, + const SelectedZonesView selectedZonesView, axom::Array &cleanIndices, axom::Array &mixedIndices) const { - AXOM_ANNOTATE_SCOPE("ZoneListBuilder"); + AXOM_ANNOTATE_SCOPE("ZoneListBuilder.2"); SLIC_ASSERT(selectedZonesView.size() > 0); - const int allocatorID = axom::execution_space::allocatorID(); + const int allocatorID = getAllocatorID(); AXOM_ANNOTATE_BEGIN("nMatsPerNode"); - axom::Array nMatsPerNode(nnodes, nnodes, allocatorID); - nMatsPerNode.fill(0); + axom::Array nMatsPerNode(axom::ArrayOptions::Uninitialized(), nnodes, nnodes, allocatorID); auto nMatsPerNodeView = nMatsPerNode.view(); + axom::for_all( + nnodes, + AXOM_LAMBDA(axom::IndexType nodeIndex) { nMatsPerNodeView[nodeIndex] = 1; }); // Determine max number of materials a node might touch. MatsetView deviceMatsetView(m_matsetView); @@ -204,17 +272,18 @@ class ZoneListBuilder selectedZonesView.size(), AXOM_LAMBDA(axom::IndexType szIndex) { const auto zoneIndex = selectedZonesView[szIndex]; - const auto zone = deviceTopologyView.zone(zoneIndex); - const auto matZoneIndex = zoneIndex; - const int nmats = deviceMatsetView.numberOfMaterials(matZoneIndex); - - const auto nnodesThisZone = zone.numberOfNodes(); - int *nodeData = nMatsPerNodeView.data(); - for(axom::IndexType i = 0; i < nnodesThisZone; i++) + const int nmats = deviceMatsetView.numberOfMaterials(zoneIndex); + if(nmats > 1) { - const auto nodeId = zone.getId(i); - int *nodePtr = nodeData + nodeId; - axom::atomicMax(nodePtr, nmats); + const auto zone = deviceTopologyView.zone(zoneIndex); + const auto nnodesThisZone = zone.numberOfNodes(); + int *nodeData = nMatsPerNodeView.data(); + for(axom::IndexType i = 0; i < nnodesThisZone; i++) + { + const auto nodeId = zone.getId(i); + int *nodePtr = nodeData + nodeId; + axom::atomicMax(nodePtr, nmats); + } } }); AXOM_ANNOTATE_END("nMatsPerNode"); @@ -222,41 +291,73 @@ class ZoneListBuilder // Now, mark all selected zones that have 1 mat per node as clean. AXOM_ANNOTATE_BEGIN("mask"); const auto nzones = selectedZonesView.size(); - axom::Array mask(nzones, nzones, allocatorID); + axom::Array mask(axom::ArrayOptions::Uninitialized(), nzones, nzones, allocatorID); auto maskView = mask.view(); - axom::ReduceSum mask_reduce(0); axom::for_all( - selectedZonesView.size(), + nzones, AXOM_LAMBDA(axom::IndexType szIndex) { const auto zoneIndex = selectedZonesView[szIndex]; const auto zone = deviceTopologyView.zone(zoneIndex); - bool clean = true; + MaskType clean {1}; const axom::IndexType nnodesThisZone = zone.numberOfNodes(); - for(axom::IndexType i = 0; i < nnodesThisZone && clean; i++) + for(axom::IndexType i = 0; i < nnodesThisZone; i++) { const auto nodeId = zone.getId(i); - clean &= (nMatsPerNodeView[nodeId] == 1); + clean &= (nMatsPerNodeView[nodeId] == 1) ? MaskType {1} : MaskType {0}; } - const int ival = clean ? 1 : 0; - maskView[szIndex] = ival; - mask_reduce += ival; + maskView[szIndex] = clean; }); AXOM_ANNOTATE_END("mask"); - const int nClean = mask_reduce.get(); + axom::IndexType nClean = 0; + axom::Array maskOffsets; + axom::ArrayView maskOffsetsView; + if(nzones > 0) + { + AXOM_ANNOTATE_SCOPE("numClean"); + if constexpr(axom::execution_space::onDevice()) + { + // On device, use a reduction on maskView to count clean zones. + axom::ReduceSum mask_reduce(0); + axom::for_all( + nzones, + AXOM_LAMBDA(axom::IndexType szIndex) { + mask_reduce += static_cast(maskView[szIndex]); + }); + nClean = mask_reduce.get(); + } + else + { + // Off device, do the offset scan early and use the results to compute + // nClean instead of a reduction. + AXOM_ANNOTATE_SCOPE("offsets"); + maskOffsets = + axom::Array(axom::ArrayOptions::Uninitialized(), nzones, nzones, allocatorID); + maskOffsetsView = maskOffsets.view(); + axom::exclusive_scan(maskView, maskOffsetsView); + + nClean = maskOffsetsView[nzones - 1] + static_cast(maskView[nzones - 1]); + } + } + if(nClean > 0) { - AXOM_ANNOTATE_BEGIN("offsets"); - axom::Array maskOffsets(nzones, nzones, allocatorID); - auto maskOffsetsView = maskOffsets.view(); - axom::exclusive_scan(maskView, maskOffsetsView); - AXOM_ANNOTATE_END("offsets"); + // Compute maskOffsets if we did not do it yet. + if(maskOffsets.empty()) + { + AXOM_ANNOTATE_SCOPE("offsets"); + maskOffsets = + axom::Array(axom::ArrayOptions::Uninitialized(), nzones, nzones, allocatorID); + maskOffsetsView = maskOffsets.view(); + axom::exclusive_scan(maskView, maskOffsetsView); + } // Make the output cleanIndices array. AXOM_ANNOTATE_BEGIN("cleanIndices"); - cleanIndices = axom::Array(nClean, nClean, allocatorID); + cleanIndices = + axom::Array(axom::ArrayOptions::Uninitialized(), nClean, nClean, allocatorID); auto cleanIndicesView = cleanIndices.view(); axom::for_all( nzones, @@ -272,10 +373,13 @@ class ZoneListBuilder AXOM_ANNOTATE_BEGIN("mixedIndices"); axom::for_all( nzones, - AXOM_LAMBDA(axom::IndexType index) { maskView[index] = (maskView[index] == 1) ? 0 : 1; }); + AXOM_LAMBDA(axom::IndexType index) { + maskView[index] = (maskView[index] == MaskType {1}) ? MaskType {0} : MaskType {1}; + }); axom::exclusive_scan(maskView, maskOffsetsView); const int nMixed = nzones - nClean; - mixedIndices = axom::Array(nMixed, nMixed, allocatorID); + mixedIndices = + axom::Array(axom::ArrayOptions::Uninitialized(), nMixed, nMixed, allocatorID); auto mixedIndicesView = mixedIndices.view(); axom::for_all( nzones, @@ -293,7 +397,8 @@ class ZoneListBuilder cleanIndices = axom::Array(); // There were no clean, so it must all be mixed. - mixedIndices = axom::Array(nzones, nzones, allocatorID); + mixedIndices = + axom::Array(axom::ArrayOptions::Uninitialized(), nzones, nzones, allocatorID); auto mixedIndicesView = mixedIndices.view(); axom::for_all( nzones, @@ -306,20 +411,22 @@ class ZoneListBuilder * per zone. This method essentially partitions the input selectedZonesView * into clean and mixed lists. * - * \param selectedZonesView A view containing the zone indices we're considering. + * \param selectedZonesView A view containing the zone indices we're considering. We pass + * it by value so it can be captured into lambdas. * \param[out] cleanIndices An array that will contain the list of clean material zone ids. * \param[out] mixedIndices An array that will contain the list of mixed material zone ids. * */ - void execute(const SelectedZonesView &selectedZonesView, + void execute(const SelectedZonesView selectedZonesView, axom::Array &cleanIndices, axom::Array &mixedIndices) const { - const int allocatorID = axom::execution_space::allocatorID(); + AXOM_ANNOTATE_SCOPE("ZoneListBuilder.3"); + const int allocatorID = getAllocatorID(); AXOM_ANNOTATE_BEGIN("mask"); const auto nzones = selectedZonesView.size(); - axom::Array mask(nzones, nzones, allocatorID); + axom::Array mask(axom::ArrayOptions::Uninitialized(), nzones, nzones, allocatorID); auto maskView = mask.view(); axom::ReduceSum mask_reduce(0); const MatsetView deviceMatsetView(m_matsetView); @@ -331,7 +438,7 @@ class ZoneListBuilder // clean zone == 1, mixed zone = 0 const int ival = (deviceMatsetView.numberOfMaterials(matZoneIndex) == 1) ? 1 : 0; - maskView[szIndex] = ival; + maskView[szIndex] = static_cast(ival); mask_reduce += ival; }); AXOM_ANNOTATE_END("mask"); @@ -342,12 +449,15 @@ class ZoneListBuilder { AXOM_ANNOTATE_SCOPE("mixedIndices"); - axom::Array maskOffsets(nzones, nzones, allocatorID); + axom::Array maskOffsets(axom::ArrayOptions::Uninitialized(), nzones, nzones, allocatorID); auto maskOffsetsView = maskOffsets.view(); axom::exclusive_scan(maskView, maskOffsetsView); // Fill in clean zone ids. - cleanIndices = axom::Array(numCleanZones, numCleanZones, allocatorID); + cleanIndices = axom::Array(axom::ArrayOptions::Uninitialized(), + numCleanZones, + numCleanZones, + allocatorID); auto cleanIndicesView = cleanIndices.view(); axom::for_all( nzones, @@ -356,13 +466,16 @@ class ZoneListBuilder { cleanIndicesView[maskOffsetsView[szIndex]] = selectedZonesView[szIndex]; } - maskView[szIndex] = (maskView[szIndex] > 0) ? 0 : 1; + maskView[szIndex] = (maskView[szIndex] > 0) ? MaskType {0} : MaskType {1}; }); axom::exclusive_scan(maskView, maskOffsetsView); // Fill in mixed zone ids. - mixedIndices = axom::Array(numMixedZones, numMixedZones, allocatorID); + mixedIndices = axom::Array(axom::ArrayOptions::Uninitialized(), + numMixedZones, + numMixedZones, + allocatorID); auto mixedIndicesView = mixedIndices.view(); axom::for_all( nzones, @@ -378,7 +491,8 @@ class ZoneListBuilder AXOM_ANNOTATE_SCOPE("cleanIndices"); // There were no mixed, so it must all be clean. - cleanIndices = axom::Array(nzones, nzones, allocatorID); + cleanIndices = + axom::Array(axom::ArrayOptions::Uninitialized(), nzones, nzones, allocatorID); auto cleanIndicesView = cleanIndices.view(); axom::for_all( nzones, @@ -393,7 +507,8 @@ class ZoneListBuilder cleanIndices = axom::Array(); // There were no clean, so it must all be mixed. - mixedIndices = axom::Array(nzones, nzones, allocatorID); + mixedIndices = + axom::Array(axom::ArrayOptions::Uninitialized(), nzones, nzones, allocatorID); auto mixedIndicesView = mixedIndices.view(); axom::for_all( nzones, @@ -404,6 +519,7 @@ class ZoneListBuilder private: TopologyView m_topologyView; MatsetView m_matsetView; + int m_allocator_id; }; } // end namespace bump diff --git a/src/axom/bump/data/MeshTester.cpp b/src/axom/bump/data/MeshTester.cpp index 8672ed39e6..f6ae816e9e 100644 --- a/src/axom/bump/data/MeshTester.cpp +++ b/src/axom/bump/data/MeshTester.cpp @@ -421,21 +421,21 @@ static void addCircleMaterial(const TopoView& topoView, center[1] = circleCenter[1]; const TopoView deviceTopologyView(topoView); - axom::for_all( - topoView.numberOfZones(), - AXOM_LAMBDA(axom::IndexType zoneIndex) { - const auto zone = deviceTopologyView.zone(zoneIndex); - // NOTE: node ordering shuffled because function takes different node ordering. - auto vf = calculatePercentOverlapMonteCarlo(numSamples, - center, - circleRadius, - coordsetView[zone.getId(3)], - coordsetView[zone.getId(0)], - coordsetView[zone.getId(1)], - coordsetView[zone.getId(2)]); - greenView[zoneIndex] = vf; - blueView[zoneIndex] = 1.0 - vf; - }); + axom::for_all(topoView.numberOfZones(), + [=] /*AXOM_LAMBDA*/ (axom::IndexType zoneIndex) { + const auto zone = deviceTopologyView.zone(zoneIndex); + // NOTE: node ordering shuffled because function takes different node ordering. + auto vf = + calculatePercentOverlapMonteCarlo(numSamples, + center, + circleRadius, + coordsetView[zone.getId(3)], + coordsetView[zone.getId(0)], + coordsetView[zone.getId(1)], + coordsetView[zone.getId(2)]); + greenView[zoneIndex] = vf; + blueView[zoneIndex] = 1.0 - vf; + }); // Figure out the material buffers from the volume fractions. std::vector material_ids, sizes, offsets, indices; diff --git a/src/axom/bump/docs/sphinx/bump_building_blueprint.rst b/src/axom/bump/docs/sphinx/bump_building_blueprint.rst index 5d76e81dc1..b2e3b6a345 100644 --- a/src/axom/bump/docs/sphinx/bump_building_blueprint.rst +++ b/src/axom/bump/docs/sphinx/bump_building_blueprint.rst @@ -11,12 +11,11 @@ Building Blueprint Output While views are provided to help write algorithms that process existing Blueprint data, the views are primarily meant to be read-only. Blueprint output from algorithms is built in the usual Conduit way by adding new key:value data into paths within the Conduit node -hierarchy. Axom provides a ``ConduitAllocateThroughAxom`` object to help allocate Conduit's -bulk data through Axom's memory allocation routines. Since data processing algorithms in -Axom are often templated on an execution space, the ConduitAllocateThroughAxom object is -also templated on execution space, which enables it to install various allocators for -Conduit. To make Conduit allocate data through Axom, set a Conduit node's allocator -to the allocator returned by ``ConduitAllocateThroughAxom::getConduitAllocatorID()``. +hierarchy. Axom provides ``axom::sidre::ConduitMemory::axomAllocIdToConduit()`` to help +allocate Conduit's bulk data through Axom's memory allocation routines. Since data +processing algorithms in Axom are often templated on an execution space, pass an +Axom allocator suitable for the execution space to the function. + After setting the allocator, the node's memory can be allocated by calling the ``Node::set()`` method and passing a ``conduit::DataType`` object that encodes the data type and size. After allocating data in the Conduit node, wrap the data in an ``axom::ArrayView`` using @@ -31,8 +30,10 @@ to pass ArrayViews and not the Conduit nodes to device kernels. { namespace utils = axom::bump::utilities; - // This object registers Axom's allocation functions with Conduit. - utils::ConduitAllocateThroughAxom c2a; + // Get a Conduit allocator that allocates through Axom. + const auto conduitAllocatorId = + axom::sidre::ConduitMemory::axomAllocIdToConduit( + axom::execution_space::allocatorID()); // Make the new field normally by adding members to the n_mesh Conduit node. conduit::Node &n_field = n_mesh["fields/newField"]; @@ -42,7 +43,7 @@ to pass ArrayViews and not the Conduit nodes to device kernels. // Set the allocator so Axom will be used to allocate the node's memory. // This is key when working on GPU platforms. - n_values.set_allocator(c2a.getConduitAllocatorID()); + n_values.set_allocator(conduitAllocatorId); // Allocate memory in the right memory space for ExecSpace. // The cpp2conduit template gets the Conduit data type id for supported C++ types. diff --git a/src/axom/bump/docs/sphinx/bump_utilities.rst b/src/axom/bump/docs/sphinx/bump_utilities.rst index 121e6b00e8..4a86196c85 100644 --- a/src/axom/bump/docs/sphinx/bump_utilities.rst +++ b/src/axom/bump/docs/sphinx/bump_utilities.rst @@ -53,27 +53,6 @@ as the ``conduit::Node::dtype()`` method. // device->host axom::bump::utilities::copy(hostMesh2, deviceMesh); -############################ -ConduitAllocateThroughAxom -############################ - -When writing algorithms that construct Blueprint data, it is helpful to force Conduit -to allocate its memory through Axom's allocation routines and then make an ``axom::ArrayView`` -of the data in the Conduit node. This prevents data from having to be copied from an Axom -data structure into a Conduit node since it can be constructed from the start inside the -Conduit node. The size of the array must be known. - -The ``axom::bump::utilities::ConduitAllocateThroughAxom`` -class is a template class that takes an execution space as a template argument. The class -installs an allocation routine in Conduit that can be used to allocate data through -Axom. The Conduit allocator is set on each ``conduit::Node`` before setting data into -the object. - -.. literalinclude:: ../../extraction/TableBasedExtractor.hpp - :start-after: _bump_utilities_c2a_begin - :end-before: _bump_utilities_c2a_end - :language: C++ - ########## ClipField ########## diff --git a/src/axom/bump/docs/sphinx/bump_views.rst b/src/axom/bump/docs/sphinx/bump_views.rst index 8dcd9d6db4..9bd68f515d 100644 --- a/src/axom/bump/docs/sphinx/bump_views.rst +++ b/src/axom/bump/docs/sphinx/bump_views.rst @@ -22,7 +22,7 @@ Axom provides ``axom::ArrayView`` to wrap data in a non-owning data structure th kernels. The BUMP component provides the ``axom::bump::utilities::make_array_view()`` function to help wrap arrays stored in ``conduit::Node`` to ``axom::ArrayView``. To use the ``make_array_view`` function, one must know the type held within the Conduit node. If that is -not the case, then consider using one of the dispatch ''Node_to_ArrayView'' functions. +not the case, then consider using one of the dispatch ''nodeToArrayView'' functions. .. code-block:: cpp @@ -193,7 +193,7 @@ Blueprint data can readily be wrapped in ``axom::ArrayView`` using the ``axom::b function. There are dispatch functions for ``conduit::Node`` data arrays that automate the wrapping to ``axom::ArrayView`` and passing the views to a user-supplied lambda. -To generically wrap any type of datatype supported by Conduit, the ``axom::bump::views::Node_to_ArrayView()`` +To generically wrap any type of datatype supported by Conduit, the ``axom::bump::views::nodeToArrayView()`` function can be used. This template function takes a variable number of ``conduit::Node`` arguments and a generic lambda function that accepts the view arguments. The lambda gets instantiated for every supported Conduit data type. @@ -201,22 +201,22 @@ instantiated for every supported Conduit data type. .. code-block:: cpp conduit::Node n; // Assume it contains data values - axom::bump::views::Node_to_ArrayView(n["foo"], n["bar"], [&](auto fooView, auto barView) + axom::bump::views::nodeToArrayView(n["foo"], n["bar"], [&](auto fooView, auto barView) { // Use fooView and barView axom::ArrayView objects to access data. // They can have different types. }); -Using ``axom::bump::views::Node_to_ArrayView`` with multiple data values can instantiate +Using ``axom::bump::views::nodeToArrayView`` with multiple data values can instantiate the supplied lambda many times so be careful. It is more common when wrapping multiple -nodes that they are the same type. The ``axom::bump::views::Node_to_ArrayView_same`` function +nodes that they are the same type. The ``axom::bump::views::nodeToArrayViewSame`` function ensures that the lambdas get instantiated with views that wrap the Conduit nodes in array views that of the same type. .. code-block:: cpp conduit::Node n; // Assume it contains data values - axom::bump::views::Node_to_ArrayView_same(n["foo"], n["bar"], [&](auto fooView, auto barView) + axom::bump::views::nodeToArrayViewSame(n["foo"], n["bar"], [&](auto fooView, auto barView) { // Use fooView and barView axom::ArrayView objects to access data. // They have the same types. @@ -226,10 +226,10 @@ When dealing with mesh data structures, it is common to have data that are using types or only floating-point types. Axom provides functions that limit the lambda instantiation to only those selected types using the following functions: - * ``axom::bump::views::IndexNode_to_ArrayView()`` - * ``axom::bump::views::IndexNode_to_ArrayView_same()`` - * ``axom::bump::views::FloatNode_to_ArrayView()`` - * ``axom::bump::views::FloatNode_to_ArrayView_same()`` + * ``axom::bump::views::indexNodeToArrayView()`` + * ``axom::bump::views::indexNodeToArrayViewSame()`` + * ``axom::bump::views::floatNodeToArrayView()`` + * ``axom::bump::views::floatNodeToArrayViewSame()`` The "Index" functions limit lambda instantiation to common index types signed/unsigned 32/64-bit integers. The "Float" functions instantiate lambdas with float32 and float64 types. diff --git a/src/axom/bump/extraction/BlendGroupBuilder.hpp b/src/axom/bump/extraction/BlendGroupBuilder.hpp index a29fe5d7da..f953ede43f 100644 --- a/src/axom/bump/extraction/BlendGroupBuilder.hpp +++ b/src/axom/bump/extraction/BlendGroupBuilder.hpp @@ -7,6 +7,7 @@ #define AXOM_BUMP_BLEND_GROUP_BUILDER_HPP_ #include "axom/core.hpp" +#include "axom/slic.hpp" #include "axom/bump/utilities/utilities.hpp" #include "axom/bump/BlendData.hpp" @@ -30,6 +31,29 @@ class BlendGroupBuilder public: using KeyType = typename NamingPolicyView::KeyType; + BlendGroupBuilder() : m_state(), m_allocator_id(axom::execution_space::allocatorID()) + { } + + /*! + * \brief Set the allocator id to use when allocating memory. + * + * \param allocator_id The allocator id to use when allocating memory. + */ + void setAllocatorID(int allocator_id) + { + SLIC_ERROR_IF(!axom::isValidAllocatorID(allocator_id), "Invalid allocator id."); + SLIC_ERROR_IF(!axom::execution_space::usesAllocId(allocator_id), + "Allocator id is not compatible with execution space."); + m_allocator_id = allocator_id; + } + + /*! + * \brief Get the allocator id to use when allocating memory. + * + * \return The allocator id to use when allocating memory. + */ + int getAllocatorID() const { return m_allocator_id; } + /*! * \brief This struct holds the views that represent data for blend groups. */ @@ -433,10 +457,11 @@ class BlendGroupBuilder if(nIndices > 0) { - const int allocatorID = axom::execution_space::allocatorID(); + using MaskType = typename axom::bump::utilities::mask_traits::type; + const int allocatorID = getAllocatorID(); // Make a mask of selected indices have more than one id in their blend group. - axom::Array mask(nIndices, nIndices, allocatorID); + axom::Array mask(nIndices, nIndices, allocatorID); auto maskView = mask.view(); axom::ReduceSum mask_reduce(0); State deviceState(m_state); @@ -445,7 +470,7 @@ class BlendGroupBuilder AXOM_LAMBDA(axom::IndexType index) { const auto uniqueIndex = deviceState.m_blendUniqueIndicesView[index]; const int m = (deviceState.m_blendGroupSizesView[uniqueIndex] > 1) ? 1 : 0; - maskView[index] = m; + maskView[index] = static_cast(m); mask_reduce += m; }); // If we need to filter, do it. @@ -503,6 +528,7 @@ class BlendGroupBuilder private: State m_state; + int m_allocator_id; }; } // end namespace extraction diff --git a/src/axom/bump/extraction/ClipTableManager.cpp b/src/axom/bump/extraction/ClipTableManager.cpp index a5c55a98bc..f20e664b6a 100644 --- a/src/axom/bump/extraction/ClipTableManager.cpp +++ b/src/axom/bump/extraction/ClipTableManager.cpp @@ -27,7 +27,7 @@ void ClipTableManager::loadShape(size_t shape) startClipShapesTri, clipShapesTri, clipShapesTriSize, - m_allocatorID); + m_allocator_id); } else if(shape == ST_QUA) { @@ -36,7 +36,7 @@ void ClipTableManager::loadShape(size_t shape) startClipShapesQua, clipShapesQua, clipShapesQuaSize, - m_allocatorID); + m_allocator_id); } else if(shape == ST_POLY5) { @@ -45,7 +45,7 @@ void ClipTableManager::loadShape(size_t shape) startClipShapesPoly5, clipShapesPoly5, clipShapesPoly5Size, - m_allocatorID); + m_allocator_id); } else if(shape == ST_POLY6) { @@ -54,7 +54,7 @@ void ClipTableManager::loadShape(size_t shape) startClipShapesPoly6, clipShapesPoly6, clipShapesPoly6Size, - m_allocatorID); + m_allocator_id); } else if(shape == ST_POLY7) { @@ -63,7 +63,7 @@ void ClipTableManager::loadShape(size_t shape) startClipShapesPoly7, clipShapesPoly7, clipShapesPoly7Size, - m_allocatorID); + m_allocator_id); } else if(shape == ST_POLY8) { @@ -72,7 +72,7 @@ void ClipTableManager::loadShape(size_t shape) startClipShapesPoly8, clipShapesPoly8, clipShapesPoly8Size, - m_allocatorID); + m_allocator_id); } else if(shape == ST_TET) { @@ -81,7 +81,7 @@ void ClipTableManager::loadShape(size_t shape) startClipShapesTet, clipShapesTet, clipShapesTetSize, - m_allocatorID); + m_allocator_id); } else if(shape == ST_PYR) { @@ -90,7 +90,7 @@ void ClipTableManager::loadShape(size_t shape) startClipShapesPyr, clipShapesPyr, clipShapesPyrSize, - m_allocatorID); + m_allocator_id); } else if(shape == ST_WDG) { @@ -99,7 +99,7 @@ void ClipTableManager::loadShape(size_t shape) startClipShapesWdg, clipShapesWdg, clipShapesWdgSize, - m_allocatorID); + m_allocator_id); } else if(shape == ST_HEX) { @@ -108,7 +108,7 @@ void ClipTableManager::loadShape(size_t shape) startClipShapesHex, clipShapesHex, clipShapesHexSize, - m_allocatorID); + m_allocator_id); } } } diff --git a/src/axom/bump/extraction/ClipTableManager.hpp b/src/axom/bump/extraction/ClipTableManager.hpp index cb9560f268..9a703cdc99 100644 --- a/src/axom/bump/extraction/ClipTableManager.hpp +++ b/src/axom/bump/extraction/ClipTableManager.hpp @@ -24,7 +24,7 @@ class ClipTableManager : public TableManager { public: /// Return true since the tables can generate ST_PNT points. - static constexpr bool generates_points() { return true; } + AXOM_HOST_DEVICE static constexpr bool generates_points() { return true; } protected: /*! diff --git a/src/axom/bump/extraction/CutTableManager.cpp b/src/axom/bump/extraction/CutTableManager.cpp index cd13bf6cc4..86c12322a2 100644 --- a/src/axom/bump/extraction/CutTableManager.cpp +++ b/src/axom/bump/extraction/CutTableManager.cpp @@ -27,7 +27,7 @@ void CutTableManager::loadShape(size_t shape) startCutShapesTri, cutShapesTri, cutShapesTriSize, - m_allocatorID); + m_allocator_id); } else if(shape == ST_QUA) { @@ -36,7 +36,7 @@ void CutTableManager::loadShape(size_t shape) startCutShapesQua, cutShapesQua, cutShapesQuaSize, - m_allocatorID); + m_allocator_id); } else if(shape == ST_POLY5) { @@ -45,7 +45,7 @@ void CutTableManager::loadShape(size_t shape) startCutShapesPoly5, cutShapesPoly5, cutShapesPoly5Size, - m_allocatorID); + m_allocator_id); } else if(shape == ST_POLY6) { @@ -54,7 +54,7 @@ void CutTableManager::loadShape(size_t shape) startCutShapesPoly6, cutShapesPoly6, cutShapesPoly6Size, - m_allocatorID); + m_allocator_id); } else if(shape == ST_POLY7) { @@ -63,7 +63,7 @@ void CutTableManager::loadShape(size_t shape) startCutShapesPoly7, cutShapesPoly7, cutShapesPoly7Size, - m_allocatorID); + m_allocator_id); } else if(shape == ST_POLY8) { @@ -72,7 +72,7 @@ void CutTableManager::loadShape(size_t shape) startCutShapesPoly8, cutShapesPoly8, cutShapesPoly8Size, - m_allocatorID); + m_allocator_id); } else if(shape == ST_TET) { @@ -81,7 +81,7 @@ void CutTableManager::loadShape(size_t shape) startCutShapesTet, cutShapesTet, cutShapesTetSize, - m_allocatorID); + m_allocator_id); } else if(shape == ST_PYR) { @@ -90,7 +90,7 @@ void CutTableManager::loadShape(size_t shape) startCutShapesPyr, cutShapesPyr, cutShapesPyrSize, - m_allocatorID); + m_allocator_id); } else if(shape == ST_WDG) { @@ -99,7 +99,7 @@ void CutTableManager::loadShape(size_t shape) startCutShapesWdg, cutShapesWdg, cutShapesWdgSize, - m_allocatorID); + m_allocator_id); } else if(shape == ST_HEX) { @@ -108,7 +108,7 @@ void CutTableManager::loadShape(size_t shape) startCutShapesHex, cutShapesHex, cutShapesHexSize, - m_allocatorID); + m_allocator_id); } } } diff --git a/src/axom/bump/extraction/CutTableManager.hpp b/src/axom/bump/extraction/CutTableManager.hpp index c0b854a2e4..18beaaa82e 100644 --- a/src/axom/bump/extraction/CutTableManager.hpp +++ b/src/axom/bump/extraction/CutTableManager.hpp @@ -24,7 +24,7 @@ class CutTableManager : public TableManager { public: /// Return false since the tables cannot generate ST_PNT points. - static constexpr bool generates_points() { return false; } + AXOM_HOST_DEVICE static constexpr bool generates_points() { return false; } protected: /*! diff --git a/src/axom/bump/extraction/FieldIntersector.hpp b/src/axom/bump/extraction/FieldIntersector.hpp index ad7f8d3ef8..0404a4cb08 100644 --- a/src/axom/bump/extraction/FieldIntersector.hpp +++ b/src/axom/bump/extraction/FieldIntersector.hpp @@ -36,6 +36,28 @@ class FieldIntersector using ConnectivityType = typename TopologyView::ConnectivityType; using ConnectivityView = axom::ArrayView; + FieldIntersector() : m_allocator_id(axom::execution_space::allocatorID()) { } + + /*! + * \brief Set the allocator id to use when allocating memory. + * + * \param allocator_id The allocator id to use when allocating memory. + */ + void setAllocatorID(int allocator_id) + { + SLIC_ERROR_IF(!axom::isValidAllocatorID(allocator_id), "Invalid allocator id."); + SLIC_ERROR_IF(!axom::execution_space::usesAllocId(allocator_id), + "Allocator id is not compatible with execution space."); + m_allocator_id = allocator_id; + } + + /*! + * \brief Get the allocator id to use when allocating memory. + * + * \return The allocator id to use when allocating memory. + */ + int getAllocatorID() const { return m_allocator_id; } + /*! * \brief This is a view class for FieldIntersector that can be used in device code. */ @@ -46,21 +68,21 @@ class FieldIntersector * the appropriate table case, taking into account the field and * value. * - * \param zoneIndex The zone index. - * \param nodeIds A view containing node ids for the zone. + * \param zone_index The zone index. + * \param node_ids A view containing node ids for the zone. */ AXOM_HOST_DEVICE - axom::IndexType determineTableCase(axom::IndexType AXOM_UNUSED_PARAM(zoneIndex), - const ConnectivityView &nodeIds) const + axom::IndexType determineTableCase(axom::IndexType AXOM_UNUSED_PARAM(zone_index), + const ConnectivityView &node_ids) const { - axom::IndexType caseNumber = 0, numIds = nodeIds.size(); - for(IndexType i = 0; i < numIds; i++) + axom::IndexType case_number = 0, num_ids = node_ids.size(); + for(IndexType i = 0; i < num_ids; i++) { - const auto id = nodeIds[i]; + const auto id = node_ids[i]; const auto distance = m_fieldView[id] - m_fieldValue; - caseNumber |= (distance > 0) ? (1 << i) : 0; + case_number |= (distance > 0) ? (1 << i) : 0; } - return caseNumber; + return case_number; } /*! @@ -72,7 +94,7 @@ class FieldIntersector * \return A parametric position t [0,1] where we locate \a clipValues in [d0,d1]. */ AXOM_HOST_DEVICE - FieldType computeWeight(axom::IndexType AXOM_UNUSED_PARAM(zoneIndex), + FieldType computeWeight(axom::IndexType AXOM_UNUSED_PARAM(zone_index), ConnectivityType id0, ConnectivityType id1) const { @@ -102,7 +124,7 @@ class FieldIntersector const conduit::Node &n_fields) { namespace utils = axom::bump::utilities; - const int allocatorID = axom::execution_space::allocatorID(); + const int allocator_id = getAllocatorID(); // Get the field name and value. FieldOptions opts(n_options); @@ -122,10 +144,10 @@ class FieldIntersector { // Convert to FieldType. const IndexType n = static_cast(n_field_values.dtype().number_of_elements()); - m_fieldData = axom::Array(n, n, allocatorID); + m_fieldData = axom::Array(n, n, allocator_id); m_view.m_fieldView = m_fieldData.view(); - views::Node_to_ArrayView(n_field_values, - [&](auto clipFieldViewSrc) { copyValues(clipFieldViewSrc); }); + views::nodeToArrayView(n_field_values, + [&](auto clip_field_view_src) { copyValues(clip_field_view_src); }); } } @@ -158,21 +180,22 @@ class FieldIntersector /*! * \brief Copy values from srcView into m_fieldData. * - * \param srcView The source data view. + * \param src_view The source data view. */ template - void copyValues(DataView srcView) + void copyValues(DataView src_view) { - auto clipFieldView = m_fieldData.view(); + auto clip_field_view = m_fieldData.view(); axom::for_all( - srcView.size(), + src_view.size(), AXOM_LAMBDA(axom::IndexType index) { - clipFieldView[index] = static_cast(srcView[index]); + clip_field_view[index] = static_cast(src_view[index]); }); } axom::Array m_fieldData {}; View m_view {}; + int m_allocator_id; }; } // end namespace extraction diff --git a/src/axom/bump/extraction/PlaneIntersector.hpp b/src/axom/bump/extraction/PlaneIntersector.hpp index 34b5b6e638..125535f3b6 100644 --- a/src/axom/bump/extraction/PlaneIntersector.hpp +++ b/src/axom/bump/extraction/PlaneIntersector.hpp @@ -110,6 +110,9 @@ class PlaneIntersector * \brief Initialize the object from options. * \param n_options The node that contains the options. * \param n_fields The node that contains fields. + * + * \note This is a host-side initialization, though some array data in the n_options + * node may be on-device already. */ void initialize(const TopologyView &AXOM_UNUSED_PARAM(topologyView), const CoordsetView &coordsetView, @@ -121,14 +124,16 @@ class PlaneIntersector // Make a plane from the options. SLIC_ASSERT(n_options.has_child("origin")); SLIC_ASSERT(n_options.has_child("normal")); - const auto origin = n_options["origin"].as_double_accessor(); - const auto normal = n_options["normal"].as_double_accessor(); + + // Get origin, normal from the options. value_type planeOrigin[NDIMS], planeNormal[NDIMS]; + getArrayValues(n_options["origin"], planeOrigin); + getArrayValues(n_options["normal"], planeNormal); + for(int i = 0; i < NDIMS; i++) { - planeOrigin[i] = static_cast(origin[i]); // Reverse the normal so generated surface's normals go in same direction as the normal. - planeNormal[i] = -static_cast(normal[i]); + planeNormal[i] = -planeNormal[i]; } // Set the plane in the view. @@ -162,6 +167,29 @@ class PlaneIntersector private: #endif + /*! + * \brief Get fixed number of floating point array values from a Conduit node in a + * way that should not matter whether the data are in host or device memory. + * + * \param n The Conduit node with the data. + * \param[out] values An output array of the data on the host, converted to value_type. + */ + void getArrayValues(const conduit::Node &n, value_type values[NDIMS]) const + { + SLIC_ERROR_IF(n.dtype().number_of_elements() != NDIMS, "Incompatible sizes."); + + // Make sure the data are on the host. + conduit::Node hostNode; + axom::bump::utilities::copy(hostNode, n); + + // Copy the values into output values + const auto hostAccessor = hostNode.as_double_accessor(); + for(int i = 0; i < NDIMS; i++) + { + values[i] = static_cast(hostAccessor[i]); + } + } + View m_view {}; }; diff --git a/src/axom/bump/extraction/TableBasedExtractor.hpp b/src/axom/bump/extraction/TableBasedExtractor.hpp index d0cab17ac6..e453064291 100644 --- a/src/axom/bump/extraction/TableBasedExtractor.hpp +++ b/src/axom/bump/extraction/TableBasedExtractor.hpp @@ -20,9 +20,11 @@ #include "axom/bump/HashNaming.hpp" #include "axom/bump/SelectedZones.hpp" #include "axom/bump/Unique.hpp" +#include "axom/bump/utilities/utilities.hpp" #include "axom/bump/views/Shapes.hpp" #include "axom/bump/views/view_traits.hpp" #include "axom/slic.hpp" +#include "axom/sidre/core/ConduitMemory.hpp" #include #include @@ -62,7 +64,7 @@ namespace detail * \return The ShapeID value that matches the st_index, or 0 if there is no match. */ template -AXOM_HOST_DEVICE inline constexpr IntegerType ST_Index_to_ShapeID(IntegerType st_index) +AXOM_HOST_DEVICE inline constexpr IntegerType stIndexToShapeID(IntegerType st_index) { IntegerType shapeID = 0; switch(st_index) @@ -276,7 +278,7 @@ struct FragmentOperations } const auto nIdsThisFragment = fragmentSize - 2; size = nIdsThisFragment; - shape = detail::ST_Index_to_ShapeID(fragmentShape); + shape = detail::stIndexToShapeID(fragmentShape); color = fragment[1] - COLOR0; return true; } @@ -294,6 +296,7 @@ struct FragmentOperations * \param[inout] offsetsView The view that wraps offsets (can change on output). * \param[inout] shapesView The view that wraps shapes (can change on output). * \param[inout] colorView The view that wraps colors (can change on output). + * \param allocator_id The allocator to use. */ static void filterZeroSizes(FragmentData &AXOM_UNUSED_PARAM(fragmentData), conduit::Node &AXOM_UNUSED_PARAM(n_sizes), @@ -303,7 +306,8 @@ struct FragmentOperations axom::ArrayView &AXOM_UNUSED_PARAM(sizesView), axom::ArrayView &AXOM_UNUSED_PARAM(offsetsView), axom::ArrayView &AXOM_UNUSED_PARAM(shapesView), - axom::ArrayView &AXOM_UNUSED_PARAM(colorView)) + axom::ArrayView &AXOM_UNUSED_PARAM(colorView), + int AXOM_UNUSED_PARAM(allocator_id)) { } /*! @@ -331,6 +335,7 @@ struct FragmentOperations * * \tparam ExecSpace The execution space. * \tparam DataView The type of data view that is operated on. + * \tparam MaskType The typed used to store mask data. * * \param n_src The Conduit node that contains the data. * \param srcView A view that wraps the input Conduit data. @@ -338,19 +343,18 @@ struct FragmentOperations * \param maskView The mask for valid data elements. * \param maskOffsetsView The offsets view to indicate where to write the new data. */ -template +template DataView filter(conduit::Node &n_src, DataView srcView, axom::IndexType newSize, - axom::ArrayView maskView, - axom::ArrayView maskOffsetsView) + axom::ArrayView maskView, + axom::ArrayView maskOffsetsView, + int allocator_id = axom::execution_space::allocatorID()) { using value_type = typename DataView::value_type; namespace utils = axom::bump::utilities; - // Get the ID of a Conduit allocator that will allocate through Axom with device allocator allocatorID. - utils::ConduitAllocateThroughAxom c2a; - const int conduitAllocatorID = c2a.getConduitAllocatorID(); + const auto conduitAllocatorID = axom::sidre::ConduitMemory::axomAllocIdToConduit(allocator_id); conduit::Node n_values; n_values.set_allocator(conduitAllocatorID); @@ -430,7 +434,7 @@ struct FragmentOperations<2, ExecSpace, ConnectivityType> } // Determine the shape from the number of ids we admitted. - shape = detail::ST_Index_to_ShapeID(fragmentShape); + shape = detail::stIndexToShapeID(fragmentShape); shape = (nIdsThisFragment == 3) ? static_cast(views::Tri_ShapeID) : shape; shape = (nIdsThisFragment == 4) ? static_cast(views::Quad_ShapeID) : shape; shape = (nIdsThisFragment > 4) ? static_cast(views::Polygon_ShapeID) : shape; @@ -462,6 +466,7 @@ struct FragmentOperations<2, ExecSpace, ConnectivityType> * \param[inout] offsetsView The view that wraps offsets (can change on output). * \param[inout] shapesView The view that wraps shapes (can change on output). * \param[inout] colorView The view that wraps colors (can change on output). + * \param allocator_id The allocator to use. */ static void filterZeroSizes(FragmentData &fragmentData, conduit::Node &n_sizes, @@ -471,9 +476,11 @@ struct FragmentOperations<2, ExecSpace, ConnectivityType> axom::ArrayView &sizesView, axom::ArrayView &offsetsView, axom::ArrayView &shapesView, - axom::ArrayView &colorView) + axom::ArrayView &colorView, + int allocator_id) { AXOM_ANNOTATE_SCOPE("filterZeroSizes"); + using MaskType = typename axom::bump::utilities::mask_traits::type; // There were degenerates so the expected number of fragments per zone (m_fragmentsView) // was adjusted down. That means redoing the offsets. These need to be up @@ -482,8 +489,8 @@ struct FragmentOperations<2, ExecSpace, ConnectivityType> // Use sizesView to make a mask that has 1's where size > 0. axom::IndexType nz = fragmentData.m_finalNumZones; - axom::Array mask(nz, nz, axom::execution_space::allocatorID()); - axom::Array maskOffsets(nz, nz, axom::execution_space::allocatorID()); + axom::Array mask(nz, nz, allocator_id); + axom::Array maskOffsets(nz, nz, allocator_id); auto maskView = mask.view(); auto maskOffsetsView = maskOffsets.view(); axom::ReduceSum mask_reduce(0); @@ -492,7 +499,7 @@ struct FragmentOperations<2, ExecSpace, ConnectivityType> nz, AXOM_LAMBDA(axom::IndexType index) { const int ival = (deviceSizesView[index] > 0) ? 1 : 0; - maskView[index] = ival; + maskView[index] = static_cast(ival); mask_reduce += ival; }); const axom::IndexType filteredZoneCount = mask_reduce.get(); @@ -505,22 +512,26 @@ struct FragmentOperations<2, ExecSpace, ConnectivityType> sizesView, filteredZoneCount, maskView, - maskOffsetsView); + maskOffsetsView, + allocator_id); offsetsView = filter>(n_offsets, offsetsView, filteredZoneCount, maskView, - maskOffsetsView); + maskOffsetsView, + allocator_id); shapesView = filter>(n_shapes, shapesView, filteredZoneCount, maskView, - maskOffsetsView); + maskOffsetsView, + allocator_id); colorView = filter>(n_color, colorView, filteredZoneCount, maskView, - maskOffsetsView); + maskOffsetsView, + allocator_id); // Record the filtered size. fragmentData.m_finalNumZones = filteredZoneCount; @@ -611,10 +622,12 @@ struct StridedStructuredFields * \param n_field The field being sliced. * \param n_newField The node that will contain the new field. */ - static bool sliceElementField(const TopologyView &AXOM_UNUSED_PARAM(topologyView), - const axom::bump::SliceData &AXOM_UNUSED_PARAM(slice), - const conduit::Node &AXOM_UNUSED_PARAM(n_field), - conduit::Node &AXOM_UNUSED_PARAM(n_newField)) + static bool sliceElementField( + const TopologyView &AXOM_UNUSED_PARAM(topologyView), + const axom::bump::SliceData &AXOM_UNUSED_PARAM(slice), + const conduit::Node &AXOM_UNUSED_PARAM(n_field), + conduit::Node &AXOM_UNUSED_PARAM(n_newField), + int AXOM_UNUSED_PARAM(allocator_id) = axom::execution_space::allocatorID()) { return false; } @@ -627,10 +640,12 @@ struct StridedStructuredFields * \param n_field The field being sliced. * \param n_newField The node that will contain the new field. */ - static bool blendVertexField(const TopologyView &AXOM_UNUSED_PARAM(topologyView), - const axom::bump::BlendData &AXOM_UNUSED_PARAM(blend), - const conduit::Node &AXOM_UNUSED_PARAM(n_field), - conduit::Node &AXOM_UNUSED_PARAM(n_newField)) + static bool blendVertexField( + const TopologyView &AXOM_UNUSED_PARAM(topologyView), + const axom::bump::BlendData &AXOM_UNUSED_PARAM(blend), + const conduit::Node &AXOM_UNUSED_PARAM(n_field), + conduit::Node &AXOM_UNUSED_PARAM(n_newField), + int AXOM_UNUSED_PARAM(allocator_id) = axom::execution_space::allocatorID()) { return false; } @@ -660,7 +675,8 @@ struct StridedStructuredFields static bool sliceElementField(const TopologyView &topologyView, const axom::bump::SliceData &slice, const conduit::Node &n_field, - conduit::Node &n_newField) + conduit::Node &n_newField, + int allocator_id = axom::execution_space::allocatorID()) { bool handled = false; if(n_field.has_path("offsets") && n_field.has_path("strides")) @@ -672,6 +688,7 @@ struct StridedStructuredFields indexing.update(n_field); axom::bump::FieldSlicer s(indexing); + s.setAllocatorID(allocator_id); s.execute(slice, n_field, n_newField); handled = true; } @@ -689,7 +706,8 @@ struct StridedStructuredFields static bool blendVertexField(const TopologyView &topologyView, const axom::bump::BlendData &blend, const conduit::Node &n_field, - conduit::Node &n_newField) + conduit::Node &n_newField, + int allocator_id = axom::execution_space::allocatorID()) { bool handled = false; if(n_field.has_path("offsets") && n_field.has_path("strides")) @@ -711,6 +729,7 @@ struct StridedStructuredFields // Blend the field. axom::bump::FieldBlender b( indexing); + b.setAllocatorID(allocator_id); b.execute(blend, n_field, n_newField); handled = true; } @@ -776,10 +795,32 @@ class TableBasedExtractor , m_intersector(intersector) , m_tableManager() , m_naming() + , m_allocator_id(axom::execution_space::allocatorID()) + { + m_tableManager.setAllocatorID(m_allocator_id); + } + + /*! + * \brief Set the allocator id to use when allocating memory. + * + * \param allocator_id The allocator id to use when allocating memory. + */ + void setAllocatorID(int allocator_id) { - m_tableManager.setAllocatorID(axom::execution_space::allocatorID()); + SLIC_ERROR_IF(!axom::isValidAllocatorID(allocator_id), "Invalid allocator id."); + SLIC_ERROR_IF(!axom::execution_space::usesAllocId(allocator_id), + "Allocator id is not compatible with execution space."); + m_allocator_id = allocator_id; + m_tableManager.setAllocatorID(allocator_id); } + /*! + * \brief Get the allocator id to use when allocating memory. + * + * \return The allocator id to use when allocating memory. + */ + int getAllocatorID() const { return m_allocator_id; } + /*! * \brief Allow the user to pass in a NamingPolicy to use when making blend group names. * @@ -831,7 +872,7 @@ class TableBasedExtractor conduit::Node &n_newFields) { namespace utils = axom::bump::utilities; - const auto allocatorID = axom::execution_space::allocatorID(); + const auto allocatorID = getAllocatorID(); AXOM_ANNOTATE_SCOPE("TableBasedExtractor"); const std::string newTopologyName = n_newTopo.name(); @@ -842,7 +883,7 @@ class TableBasedExtractor // Make the selected zones and get the size. ExtractorOptions opts(n_options); - SelectedZones selectedZones(m_topologyView.numberOfZones(), n_options); + SelectedZones selectedZones(m_topologyView.numberOfZones(), n_options, "selectedZones", allocatorID); const auto nzones = selectedZones.view().size(); // Give the intersector a chance to further initialize. @@ -858,9 +899,12 @@ class TableBasedExtractor // Allocate some memory and store views in ZoneData, FragmentData. AXOM_ANNOTATE_BEGIN("allocation"); - axom::Array caseNumbers(nzones, nzones, + axom::Array caseNumbers(axom::ArrayOptions::Uninitialized(), + nzones, + nzones, allocatorID); // The table case for a zone. axom::Array pointsUsed( + axom::ArrayOptions::Uninitialized(), nzones, nzones, allocatorID); // Which points are used over all selected fragments in a zone @@ -872,21 +916,29 @@ class TableBasedExtractor NodeData nodeData; #if defined(AXOM_REDUCE_BLEND_GROUPS) const auto nnodes = m_coordsetView.numberOfNodes(); - axom::Array nodeUsed(nnodes, nnodes, allocatorID); + axom::Array nodeUsed(axom::ArrayOptions::Uninitialized(), nnodes, nnodes, allocatorID); nodeData.m_nodeUsedView = nodeUsed.view(); #endif // Allocate some memory and store views in FragmentData. axom::Array fragments( + axom::ArrayOptions::Uninitialized(), nzones, nzones, allocatorID); // The number of fragments (child zones) produced for a zone. axom::Array fragmentsSize( + axom::ArrayOptions::Uninitialized(), nzones, nzones, allocatorID); // The connectivity size for all selected fragments in a zone. - axom::Array fragmentOffsets(nzones, nzones, allocatorID); - axom::Array fragmentSizeOffsets(nzones, nzones, allocatorID); + axom::Array fragmentOffsets(axom::ArrayOptions::Uninitialized(), + nzones, + nzones, + allocatorID); + axom::Array fragmentSizeOffsets(axom::ArrayOptions::Uninitialized(), + nzones, + nzones, + allocatorID); FragmentData fragmentData; fragmentData.m_fragmentsView = fragments.view(); @@ -894,16 +946,20 @@ class TableBasedExtractor fragmentData.m_fragmentOffsetsView = fragmentOffsets.view(); fragmentData.m_fragmentSizeOffsetsView = fragmentSizeOffsets.view(); - axom::Array blendGroups(nzones, + axom::Array blendGroups(axom::ArrayOptions::Uninitialized(), + nzones, nzones, allocatorID); // Number of blend groups in a zone. - axom::Array blendGroupsLen(nzones, + axom::Array blendGroupsLen(axom::ArrayOptions::Uninitialized(), + nzones, nzones, allocatorID); // Length of the blend groups in a zone. - axom::Array blendOffset(nzones, + axom::Array blendOffset(axom::ArrayOptions::Uninitialized(), + nzones, nzones, allocatorID); // Start of zone's blend group indices axom::Array blendGroupOffsets( + axom::ArrayOptions::Uninitialized(), nzones, nzones, allocatorID); // Start of zone's blend group offsets in definitions. @@ -914,13 +970,14 @@ class TableBasedExtractor // Make an object to help manage building the blend groups. BlendGroupBuilderType builder; + builder.setAllocatorID(allocatorID); builder.setNamingPolicy(m_naming.view()); builder.setBlendGroupSizes(blendGroups.view(), blendGroupsLen.view()); // Compute sizes and offsets computeSizes(tableViews, builder, zoneData, nodeData, fragmentData, opts, selectedZones); - computeFragmentSizes(fragmentData, selectedZones); computeFragmentOffsets(fragmentData); + computeFragmentSizes(fragmentData, selectedZones); // Compute original node count that we're preserving, make node maps. #if defined(AXOM_REDUCE_BLEND_GROUPS) @@ -932,7 +989,7 @@ class TableBasedExtractor createNodeMaps(nodeData); nodeUsed.clear(); - nodeData.m_nodeUsedView = axom::ArrayView(); + nodeData.m_nodeUsedView = axom::ArrayView(); #endif // Further initialize the blend group builder. @@ -967,7 +1024,28 @@ class TableBasedExtractor #endif { AXOM_ANNOTATE_SCOPE("unique"); - axom::bump::Unique::execute(builder.blendNames(), uNames, uIndices); +#if defined(AXOM_RUNTIME_POLICY_USE_OPENMP) + if constexpr(std::is_same_v) + { + // The serial version Unique specialization is faster + axom::bump::Unique::execute(builder.blendNames(), + uNames, + uIndices, + allocatorID); + } + else + { + axom::bump::Unique::execute(builder.blendNames(), + uNames, + uIndices, + allocatorID); + } +#else + axom::bump::Unique::execute(builder.blendNames(), + uNames, + uIndices, + allocatorID); +#endif builder.setUniqueNames(uNames.view(), uIndices.view()); #if defined(AXOM_REDUCE_BLEND_GROUPS) @@ -1041,9 +1119,10 @@ class TableBasedExtractor if(numElementFields > 0) { AXOM_ANNOTATE_SCOPE("sliceIndices"); - sliceIndices = axom::Array(fragmentData.m_finalNumZones, - fragmentData.m_finalNumZones, - allocatorID); + sliceIndices = axom::Array( // zero-filled + fragmentData.m_finalNumZones, + fragmentData.m_finalNumZones, + allocatorID); auto sliceIndicesView = sliceIndices.view(); // Fill in sliceIndicesView. @@ -1053,7 +1132,8 @@ class TableBasedExtractor AXOM_LAMBDA(axom::IndexType index) { const auto zoneIndex = selectedZonesView[index]; const auto start = fragmentData.m_fragmentOffsetsView[index]; - for(int i = 0; i < fragmentData.m_fragmentsView[index]; i++) + const int n = fragmentData.m_fragmentsView[index]; + for(int i = 0; i < n; i++) { sliceIndicesView[start + i] = zoneIndex; } @@ -1073,6 +1153,7 @@ class TableBasedExtractor private: #endif using FragmentData = detail::FragmentData; + using MaskType = typename axom::bump::utilities::mask_traits::type; /*! * \brief Contains some per-zone data that we want to hold onto between methods. @@ -1088,7 +1169,7 @@ class TableBasedExtractor */ struct NodeData { - axom::ArrayView m_nodeUsedView {}; + axom::ArrayView m_nodeUsedView {}; axom::ArrayView m_oldNodeToNewNodeView {}; axom::ArrayView m_originalIdsView {}; }; @@ -1162,7 +1243,7 @@ class TableBasedExtractor // Initialize nodeUsed data for nodes. axom::for_all( nodeData.m_nodeUsedView.size(), - AXOM_LAMBDA(axom::IndexType index) { nodeData.m_nodeUsedView[index] = 0; }); + AXOM_LAMBDA(axom::IndexType index) { nodeData.m_nodeUsedView[index] = MaskType {0}; }); const auto deviceIntersector = m_intersector.view(); @@ -1263,7 +1344,7 @@ class TableBasedExtractor const auto nodeId = zone.getId(pid); // NOTE: Multiple threads may write to this node but they all write the same value. - nodeData.m_nodeUsedView[nodeId] = 1; + nodeData.m_nodeUsedView[nodeId] = MaskType {1}; } } #else @@ -1307,33 +1388,6 @@ class TableBasedExtractor #endif } - /*! - * \brief Compute the total number of fragments and their size. - * - * \param[inout] fragmentData The object that contains data about the zone fragments. - */ - void computeFragmentSizes(FragmentData &fragmentData, const SelectedZones &selectedZones) const - { - AXOM_ANNOTATE_SCOPE("computeFragmentSizes"); - const auto nzones = selectedZones.view().size(); - - // Sum the number of fragments. - axom::ReduceSum fragment_sum(0); - const auto fragmentsView = fragmentData.m_fragmentsView; - axom::for_all( - nzones, - AXOM_LAMBDA(axom::IndexType szIndex) { fragment_sum += fragmentsView[szIndex]; }); - fragmentData.m_finalNumZones = fragment_sum.get(); - - // Sum the fragment connectivity sizes. - axom::ReduceSum fragment_nids_sum(0); - const auto fragmentsSizeView = fragmentData.m_fragmentsSizeView; - axom::for_all( - nzones, - AXOM_LAMBDA(axom::IndexType szIndex) { fragment_nids_sum += fragmentsSizeView[szIndex]; }); - fragmentData.m_finalConnSize = fragment_nids_sum.get(); - } - /*! * \brief Compute fragment offsets. * @@ -1360,6 +1414,42 @@ class TableBasedExtractor #endif } + /*! + * \brief Compute the total number of fragments and their size. + * + * \param[inout] fragmentData The object that contains data about the zone fragments. + */ + void computeFragmentSizes(FragmentData &fragmentData, const SelectedZones &selectedZones) const + { + AXOM_ANNOTATE_SCOPE("computeFragmentSizes"); + const auto nzones = selectedZones.view().size(); + if constexpr(axom::execution_space::onDevice()) + { + // Sum the number of fragments as well as the fragment connectivity sizes. + axom::ReduceSum fragment_sum(0); + axom::ReduceSum fragment_nids_sum(0); + const auto fragmentsView = fragmentData.m_fragmentsView; + const auto fragmentsSizeView = fragmentData.m_fragmentsSizeView; + axom::for_all( + nzones, + AXOM_LAMBDA(axom::IndexType szIndex) { + fragment_sum += fragmentsView[szIndex]; + fragment_nids_sum += fragmentsSizeView[szIndex]; + }); + + fragmentData.m_finalNumZones = fragment_sum.get(); + fragmentData.m_finalConnSize = fragment_nids_sum.get(); + } + else + { + // Use results of computeFragmentOffsets to compute the final sizes so we can skip reductions. + fragmentData.m_finalNumZones = + fragmentData.m_fragmentOffsetsView[nzones - 1] + fragmentData.m_fragmentsView[nzones - 1]; + fragmentData.m_finalConnSize = fragmentData.m_fragmentSizeOffsetsView[nzones - 1] + + fragmentData.m_fragmentsSizeView[nzones - 1]; + } + } + #if defined(AXOM_REDUCE_BLEND_GROUPS) /*! * \brief Counts the number of original nodes used by the selected fragments. @@ -1375,7 +1465,7 @@ class TableBasedExtractor const auto nodeUsedView = nodeData.m_nodeUsedView; axom::for_all( nodeUsedView.size(), - AXOM_LAMBDA(axom::IndexType index) { nUsed_reducer += nodeUsedView[index]; }); + AXOM_LAMBDA(axom::IndexType index) { nUsed_reducer += static_cast(nodeUsedView[index]); }); return nUsed_reducer.get(); } @@ -1387,11 +1477,14 @@ class TableBasedExtractor void createNodeMaps(NodeData nodeData) const { AXOM_ANNOTATE_SCOPE("createNodeMaps"); - const int allocatorID = axom::execution_space::allocatorID(); + const int allocatorID = getAllocatorID(); // Make offsets into a compact array. const auto nnodes = nodeData.m_nodeUsedView.size(); - axom::Array nodeOffsets(nnodes, nnodes, allocatorID); + axom::Array nodeOffsets(axom::ArrayOptions::Uninitialized(), + nnodes, + nnodes, + allocatorID); auto nodeOffsetsView = nodeOffsets.view(); axom::exclusive_scan(nodeData.m_nodeUsedView, nodeOffsetsView); @@ -1615,19 +1708,16 @@ class TableBasedExtractor n_newTopo["type"] = "unstructured"; n_newTopo["coordset"] = n_newCoordset.name(); - // Get the ID of a Conduit allocator that will allocate through Axom with device allocator allocatorID. - // _bump_utilities_c2a_begin namespace utils = axom::bump::utilities; constexpr auto connTypeID = utils::cpp2conduit::id; - utils::ConduitAllocateThroughAxom c2a; - const int conduitAllocatorID = c2a.getConduitAllocatorID(); + const auto conduitAllocatorID = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); // Allocate connectivity. conduit::Node &n_conn = n_newTopo["elements/connectivity"]; n_conn.set_allocator(conduitAllocatorID); n_conn.set(conduit::DataType(connTypeID, fragmentData.m_finalConnSize)); auto connView = utils::make_array_view(n_conn); - // _bump_utilities_c2a_end // Allocate shapes. conduit::Node &n_shapes = n_newTopo["elements/shapes"]; @@ -1869,7 +1959,8 @@ class TableBasedExtractor sizesView, offsetsView, shapesView, - colorView); + colorView, + getAllocatorID()); } #endif @@ -1975,7 +2066,7 @@ class TableBasedExtractor AXOM_ANNOTATE_SCOPE("makeCoordset"); // _bump_utilities_coordsetblender_begin axom::bump::CoordsetBlender cb; - cb.execute(blend, m_coordsetView, n_coordset, n_newCoordset); + cb.execute(blend, m_coordsetView, n_coordset, n_newCoordset, getAllocatorID()); // _bump_utilities_coordsetblender_end } @@ -1997,50 +2088,137 @@ class TableBasedExtractor conduit::Node &n_out_fields) const { AXOM_ANNOTATE_SCOPE("makeFields"); + bool handled = false; +#if defined(AXOM_RUNTIME_POLICY_USE_OPENMP) + if constexpr(std::is_same_v) + { + AXOM_ANNOTATE_SCOPE("makeFieldsInParallel"); + constexpr axom::IndexType SIZE_CUTOFF = 4000000; + const auto size = + axom::utilities::max(axom::bump::numberOfValues(blend), axom::bump::numberOfValues(slice)); + if(size < SIZE_CUTOFF) + { + // Make the fields at the same time using axom::SEQ_EXEC kernels to copy data. + makeFieldsInParallel(blend, slice, topologyName, fieldMap, n_fields, n_out_fields); + handled = true; + } + } +#endif + if(!handled) + { + // Make the fields one at a time using ExecSpace kernels to copy data. + for(auto it = fieldMap.begin(); it != fieldMap.end(); it++) + { + const conduit::Node &n_field = n_fields.fetch_existing(it->first); + conduit::Node &n_out_field = n_out_fields[it->second]; + makeSingleField(blend, slice, topologyName, n_field, n_out_field); + } + } + } + + /*! + * \brief Make a single new field for the output topology. + * + * \tparam FieldExecSpace the execution space used to copy data. + * + * \param blend The BlendData that we need to construct the new vertex fields. + * \param slice The SliceData we need to construct new element fields. + * \param topologyName The name of the new field's topology. + * \param n_field The source field. + * \param[out] n_out_field The node that will contain the new field. + */ + template + void makeSingleField(const BlendData &blend, + const SliceData &slice, + const std::string &topologyName, + const conduit::Node &n_field, + conduit::Node &n_out_field) const + { constexpr bool ss = axom::bump::views::view_traits::supports_strided_structured(); + const std::string association = n_field["association"].as_string(); - for(auto it = fieldMap.begin(); it != fieldMap.end(); it++) + if(association == "element") { - const conduit::Node &n_field = n_fields.fetch_existing(it->first); - const std::string association = n_field["association"].as_string(); - if(association == "element") - { - // Conditionally support strided-structured. - bool handled = - detail::StridedStructuredFields::sliceElementField( - m_topologyView, - slice, - n_field, - n_out_fields[it->second]); - - if(!handled) - { - axom::bump::FieldSlicer s; - s.execute(slice, n_field, n_out_fields[it->second]); - } + // Conditionally support strided-structured. + bool handled = + detail::StridedStructuredFields::sliceElementField( + m_topologyView, + slice, + n_field, + n_out_field, + getAllocatorID()); - n_out_fields[it->second]["topology"] = topologyName; - } - else if(association == "vertex") + if(!handled) { - // Conditionally support strided-structured. - bool handled = detail::StridedStructuredFields::blendVertexField( + axom::bump::FieldSlicer s; + s.setAllocatorID(getAllocatorID()); + s.execute(slice, n_field, n_out_field); + } + + n_out_field["topology"] = topologyName; + } + else if(association == "vertex") + { + // Conditionally support strided-structured. + bool handled = + detail::StridedStructuredFields::blendVertexField( m_topologyView, blend, n_field, - n_out_fields[it->second]); + n_out_field, + getAllocatorID()); - if(!handled) - { - // Blend the field normally. - axom::bump::FieldBlender b; - b.execute(blend, n_field, n_out_fields[it->second]); - } + if(!handled) + { + // Blend the field normally. + axom::bump::FieldBlender b; + b.setAllocatorID(getAllocatorID()); + b.execute(blend, n_field, n_out_field); + } + + n_out_field["topology"] = topologyName; + } + } - n_out_fields[it->second]["topology"] = topologyName; +#if defined(AXOM_RUNTIME_POLICY_USE_OPENMP) + /*! + * \brief Make new fields for the output topology. + * + * \param blend The BlendData that we need to construct the new vertex fields. + * \param slice The SliceData we need to construct new element fields. + * \param topologyName The name of the new field's topology. + * \param fieldMap A map containing the names of the fields that we'll operate on. + * \param n_fields The source fields. + * \param[out] n_out_fields The node that will contain the new fields. + */ + void makeFieldsInParallel(const BlendData &blend, + const SliceData &slice, + const std::string &topologyName, + const std::map &fieldMap, + const conduit::Node &n_fields, + conduit::Node &n_out_fields) const + { + // Set up output fields. + int numFields = static_cast(fieldMap.size()); + if(numFields > 0) + { + axom::Array inFields(numFields, numFields); + axom::Array outFields(numFields, numFields); + axom::IndexType i = 0; + for(auto it = fieldMap.begin(); it != fieldMap.end(); it++, i++) + { + inFields[i] = n_fields.fetch_ptr(it->first); + // Make output field. + outFields[i] = n_out_fields.fetch_ptr(it->second); } + + // Try and make fields in parallel. + axom::for_all(inFields.size(), [&](axom::IndexType index) { + makeSingleField(blend, slice, topologyName, *inFields[index], *outFields[index]); + }); } } +#endif /*! * \brief Make an originalElements field so we can know each output zone's original zone number in the input mesh. @@ -2065,8 +2243,8 @@ class TableBasedExtractor namespace utils = axom::bump::utilities; constexpr auto connTypeID = utils::cpp2conduit::id; - utils::ConduitAllocateThroughAxom c2a; - const int conduitAllocatorID = c2a.getConduitAllocatorID(); + const auto conduitAllocatorID = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); const auto selectedZonesView = selectedZones.view(); const auto nzones = selectedZonesView.size(); @@ -2077,7 +2255,7 @@ class TableBasedExtractor // originalElements already exists. We need to map it forward. const conduit::Node &n_orig = n_fields[originalElements]; const conduit::Node &n_orig_values = n_orig["values"]; - views::IndexNode_to_ArrayView(n_orig_values, [&](auto origValuesView) { + views::indexNodeToArrayView(n_orig_values, [&](auto origValuesView) { using value_type = typename decltype(origValuesView)::value_type; conduit::Node &n_origElem = n_newFields[originalElements]; n_origElem["association"] = "element"; @@ -2230,13 +2408,13 @@ class TableBasedExtractor else { // Make the field for the first time. - // Allocate Conduit data through Axom. - utils::ConduitAllocateThroughAxom c2a; + const auto conduitAllocatorId = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); conduit::Node &n_new_nodes = n_newFields[newNodes]; n_new_nodes["topology"] = topoName; n_new_nodes["association"] = "vertex"; conduit::Node &n_new_nodes_values = n_new_nodes["values"]; - n_new_nodes_values.set_allocator(c2a.getConduitAllocatorID()); + n_new_nodes_values.set_allocator(conduitAllocatorId); n_new_nodes_values.set(conduit::DataType(utils::cpp2conduit::id, outputSize)); auto valuesView = utils::make_array_view(n_new_nodes_values); @@ -2258,6 +2436,7 @@ class TableBasedExtractor Intersector m_intersector {}; TableManagerType m_tableManager {}; NamingPolicy m_naming {}; + int m_allocator_id {}; }; } // end namespace extraction diff --git a/src/axom/bump/extraction/TableManager.cpp b/src/axom/bump/extraction/TableManager.cpp index c0b160baa5..0e93e9c8df 100644 --- a/src/axom/bump/extraction/TableManager.cpp +++ b/src/axom/bump/extraction/TableManager.cpp @@ -12,9 +12,9 @@ namespace bump namespace extraction { -TableManager::TableManager() { m_allocatorID = axom::getDefaultAllocatorID(); } +TableManager::TableManager() { m_allocator_id = axom::getDefaultAllocatorID(); } -void TableManager::setAllocatorID(int allocatorID) { m_allocatorID = allocatorID; } +void TableManager::setAllocatorID(int allocatorID) { m_allocator_id = allocatorID; } Table &TableManager::operator[](size_t shape) { diff --git a/src/axom/bump/extraction/TableManager.hpp b/src/axom/bump/extraction/TableManager.hpp index f2e718f631..b10c56fd2b 100644 --- a/src/axom/bump/extraction/TableManager.hpp +++ b/src/axom/bump/extraction/TableManager.hpp @@ -25,7 +25,7 @@ namespace extraction class TableManager { public: - static constexpr int NumberOfTables = ST_MAX - ST_MIN; + static constexpr int NUMBER_OF_TABLES = ST_MAX - ST_MIN; TableManager(); @@ -73,8 +73,8 @@ class TableManager virtual void loadShape(size_t shape) = 0; protected: - axom::StackArray m_tables {}; - int m_allocatorID {}; + axom::StackArray m_tables {}; + int m_allocator_id {}; }; } // end namespace extraction diff --git a/src/axom/bump/extraction/tables/split/convert_clip_cases.py b/src/axom/bump/extraction/tables/split/convert_clip_cases.py index 609ce367f9..5fa84a910d 100644 --- a/src/axom/bump/extraction/tables/split/convert_clip_cases.py +++ b/src/axom/bump/extraction/tables/split/convert_clip_cases.py @@ -7,44 +7,47 @@ # clipping algorithms to produce fewer zones and fewer artificially # introduced mesh lines. -This script converts the polygonal clipping tables in this directory + +# This script converts the polygonal clipping tables in this directory def read_array_cc(filename, name, convert): - lines = open(filename, "rt").readlines() - reading = False - arr = [] - for line in lines: - if not reading: - if line.find(name) != -1: - reading = True - else: - if line.find(";") != -1: - reading = False - break - elif line.find("//") == 1: - # Skip the line. - continue - else: - s = 0 - e = line.find("//") - if e == -1: - e = len(line) - 1 - if convert: - numbers = eval("[" + line[s:e] + "]") - arr = arr + list(numbers) - else: - tokens1 = [x.replace(' ', '') for x in line[s:e].split(",")] - tokens = [x for x in tokens1 if x != ''] - arr = arr + list(tokens) - return arr - + lines = open(filename, "rt").readlines() + reading = False + arr = [] + for line in lines: + if not reading: + if line.find(name) != -1: + reading = True + else: + if line.find(";") != -1: + reading = False + break + elif line.find("//") == 1: + # Skip the line. + continue + else: + s = 0 + e = line.find("//") + if e == -1: + e = len(line) - 1 + if convert: + numbers = eval("[" + line[s:e] + "]") + arr = arr + list(numbers) + else: + tokens1 = [x.replace(' ', '') for x in line[s:e].split(",")] + tokens = [x for x in tokens1 if x != ''] + arr = arr + list(tokens) + return arr + + def find_shared_edge(poly1, poly2): - edges1 = set((poly1[i], poly1[(i+1)%len(poly1)]) for i in range(len(poly1))) - edges2 = set((poly2[i], poly2[(i+1)%len(poly2)]) for i in range(len(poly2))) + edges1 = set((poly1[i], poly1[(i + 1) % len(poly1)]) for i in range(len(poly1))) + edges2 = set((poly2[i], poly2[(i + 1) % len(poly2)]) for i in range(len(poly2))) for e1 in edges1: if e1 in edges2 or (e1[1], e1[0]) in edges2: return e1 return None + def merge_polygons(poly1, poly2, shared_edge): # Find indexes of shared edge in both polygons i1 = poly1.index(shared_edge[0]) @@ -62,7 +65,7 @@ def merge_polygons(poly1, poly2, shared_edge): poly2_order = poly2[::-1] # Remove shared edge from poly2 idx = poly2_order.index(shared_edge[0]) - merged = poly1_order + poly2_order[idx+2:] + poly2_order[:idx] + merged = poly1_order + poly2_order[idx + 2:] + poly2_order[:idx] # Remove duplicate vertices at the join result = [] for v in merged: @@ -70,6 +73,7 @@ def merge_polygons(poly1, poly2, shared_edge): result.append(v) return tuple(result) + def combine_polygons(polygons, max_edges=8): polygons = [tuple(p) for p in polygons] changed = True @@ -103,122 +107,125 @@ def combine_polygons(polygons, max_edges=8): polygons = new_polygons return polygons + def example(): # Example usage: - polygons = [ - ('A', 'B', 'C', 'D'), - ('C', 'D', 'E', 'F'), - ('E', 'F', 'G', 'H'), - ('X', 'Y', 'Z') - ] + polygons = [('A', 'B', 'C', 'D'), ('C', 'D', 'E', 'F'), ('E', 'F', 'G', 'H'), ('X', 'Y', 'Z')] result = combine_polygons(polygons, max_edges=8) print(result) + def sorted_point_order(numPoints): order = {} for i in range(numPoints): - p = f"P{i}" - e = f"E{chr(ord('A')+i)}" - order[p] = 2*i - order[e] = 2*i + 1 + p = f"P{i}" + e = f"E{chr(ord('A')+i)}" + order[p] = 2 * i + order[e] = 2 * i + 1 return order + def sort_points(pts, maxPoints): order = sorted_point_order(maxPoints) sp = {} for p in pts: - sp[order[p]] = p + sp[order[p]] = p sk = sorted(sp.keys()) out = [] for k in sk: - out.append(sp[k]) + out.append(sp[k]) return out + def advanceTable(): - return {"ST_LIN" : 2 + 2, - "ST_TRI": 2 + 3, - "ST_QUA": 2 + 4, - "ST_POLY5": 2 + 5, - "ST_POLY6": 2 + 6, - "ST_POLY7": 2 + 7, - "ST_POLY8": 2 + 8, - # fictional sizes to help for line conversion - "ST_POLY9": 2 + 9, - "ST_POLY10": 2 + 10, - "ST_POLY11": 2 + 11, - "ST_POLY12": 2 + 12, - } + return { + "ST_LIN": 2 + 2, + "ST_TRI": 2 + 3, + "ST_QUA": 2 + 4, + "ST_POLY5": 2 + 5, + "ST_POLY6": 2 + 6, + "ST_POLY7": 2 + 7, + "ST_POLY8": 2 + 8, + # fictional sizes to help for line conversion + "ST_POLY9": 2 + 9, + "ST_POLY10": 2 + 10, + "ST_POLY11": 2 + 11, + "ST_POLY12": 2 + 12, + } + def shapeSize(name): - return advanceTable()[name] - -def convert_clip_cases(filename, name, npts, max_edges = 8): - advance = advanceTable() - nptsToShapeName = {} - for k in advance: - nptsToShapeName[advance[k] - 2] = k - - sizes = read_array_cc(filename, f"numClipShapes{name}", True) - #print(sizes) - - offsets = read_array_cc(filename, f"startClipShapes{name}", True) - #print(offsets) - - shapes = read_array_cc(filename, f"clipShapes{name}", False) - #print(shapes) - - numCases = len(sizes) - - outSizes = [0]*numCases - outOffsets = [0]*numCases - outShapes = [] - outOffset = 0 - - for ci in range(numCases): - offset = offsets[ci] - #print(f"// Case {ci}") - color0 = [] - color1 = [] - for si in range(sizes[ci]): - shapeTag = shapes[offset] - colorTag = shapes[offset + 1] - - shapeSize = advance[shapeTag] - shapeTokens = shapes[offset:offset+shapeSize] - if colorTag == "COLOR0": - color0.append(shapeTokens[2:]) - else: - color1.append(shapeTokens[2:]) - #print(" ", shapeTokens) - offset = offset + shapeSize - - outOffsets[ci] = outOffset - if len(color0) > 0: - c0 = combine_polygons(color0, max_edges=max_edges) - #print("COLOR0", c0) - for c in c0: - sc = sort_points(c, npts) - outShapes.append(nptsToShapeName[len(sc)]) - outShapes.append("COLOR0") - for p in sc: - outShapes.append(p) - outOffset = outOffset + 2 + len(sc) - outSizes[ci] = outSizes[ci] + len(c0) - - if len(color1) > 0: - c1 = combine_polygons(color1, max_edges=max_edges) - #print("COLOR1", c1) - for c in c1: - sc = sort_points(c, npts) - outShapes.append(nptsToShapeName[len(sc)]) - outShapes.append("COLOR1") - for p in sc: - outShapes.append(p) - outOffset = outOffset + 2 + len(sc) - outSizes[ci] = outSizes[ci] + len(c1) - - return (outSizes, outOffsets, outShapes) + return advanceTable()[name] + + +def convert_clip_cases(filename, name, npts, max_edges=8): + advance = advanceTable() + nptsToShapeName = {} + for k in advance: + nptsToShapeName[advance[k] - 2] = k + + sizes = read_array_cc(filename, f"numClipShapes{name}", True) + #print(sizes) + + offsets = read_array_cc(filename, f"startClipShapes{name}", True) + #print(offsets) + + shapes = read_array_cc(filename, f"clipShapes{name}", False) + #print(shapes) + + numCases = len(sizes) + + outSizes = [0] * numCases + outOffsets = [0] * numCases + outShapes = [] + outOffset = 0 + + for ci in range(numCases): + offset = offsets[ci] + #print(f"// Case {ci}") + color0 = [] + color1 = [] + for si in range(sizes[ci]): + shapeTag = shapes[offset] + colorTag = shapes[offset + 1] + + shapeSize = advance[shapeTag] + shapeTokens = shapes[offset:offset + shapeSize] + if colorTag == "COLOR0": + color0.append(shapeTokens[2:]) + else: + color1.append(shapeTokens[2:]) + #print(" ", shapeTokens) + offset = offset + shapeSize + + outOffsets[ci] = outOffset + if len(color0) > 0: + c0 = combine_polygons(color0, max_edges=max_edges) + #print("COLOR0", c0) + for c in c0: + sc = sort_points(c, npts) + outShapes.append(nptsToShapeName[len(sc)]) + outShapes.append("COLOR0") + for p in sc: + outShapes.append(p) + outOffset = outOffset + 2 + len(sc) + outSizes[ci] = outSizes[ci] + len(c0) + + if len(color1) > 0: + c1 = combine_polygons(color1, max_edges=max_edges) + #print("COLOR1", c1) + for c in c1: + sc = sort_points(c, npts) + outShapes.append(nptsToShapeName[len(sc)]) + outShapes.append("COLOR1") + for p in sc: + outShapes.append(p) + outOffset = outOffset + 2 + len(sc) + outSizes[ci] = outSizes[ci] + len(c1) + + return (outSizes, outOffsets, outShapes) + def write_new_tables(filename, name, tableNames, sizes, offsets, shapes): @@ -242,13 +249,13 @@ def write_new_tables(filename, name, tableNames, sizes, offsets, shapes): f.write(f"namespace {clipping}") f.write(" {\n\n") f.write(f"int num{Clip}Cases{name} = {len(sizes)};") - f.write("\n\n") + f.write("\n\n") f.write(f"int num{Clip}Shapes{name}[] = ") f.write("{\n") f.write(" " + str(sizes)[1:-1]) f.write("\n};\n\n") - + f.write(f"int start{Clip}Shapes{name}[] = ") f.write("{\n") f.write(" " + str(offsets)[1:-1]) @@ -265,20 +272,22 @@ def write_new_tables(filename, name, tableNames, sizes, offsets, shapes): for si in range(sizes[ci]): shapeTag = shapes[offset] ss = shapeSize(shapeTag) - toks = shapes[offset:offset+ss] + toks = shapes[offset:offset + ss] #print(toks) toks_str = str(toks)[1:-1].replace("'", "") if ci < numCases - 1: - toks_str = toks_str + "," + toks_str = toks_str + "," else: - if si < sizes[ci] - 1: - toks_str = toks_str + "," + if si < sizes[ci] - 1: + toks_str = toks_str + "," f.write(" " + toks_str + "\n") offset = offset + ss f.write("};\n") f.write("// clang-format on\n\n") - f.write(f"const size_t {clip}Shapes{name}Size = sizeof({clip}Shapes{name}) / sizeof(unsigned char);\n\n") + f.write( + f"const size_t {clip}Shapes{name}Size = sizeof({clip}Shapes{name}) / sizeof(unsigned char);\n\n" + ) f.write("}") f.write(f" // namespace {clipping}\n") f.write("} // namespace tables\n") @@ -287,6 +296,7 @@ def write_new_tables(filename, name, tableNames, sizes, offsets, shapes): f.write("} // namespace axom\n") f.close() + def make_cut_cases(sizes, offsets, shapes): cutSizes = [] cutOffsets = [] @@ -300,15 +310,15 @@ def make_cut_cases(sizes, offsets, shapes): for si in range(sizes[ci]): shapeTag = shapes[offset] ss = shapeSize(shapeTag) - toks = shapes[offset:offset+ss] + toks = shapes[offset:offset + ss] for i in range(len(toks)): - e0 = toks[i] - e1 = toks[(i+1)%len(toks)] - if e0[0] == 'E' and e1[0] == 'E': - name = e0 + e1 - if name not in edges: - edges.append(name) + e0 = toks[i] + e1 = toks[(i + 1) % len(toks)] + if e0[0] == 'E' and e1[0] == 'E': + name = e0 + e1 + if name not in edges: + edges.append(name) offset = offset + ss @@ -321,52 +331,73 @@ def make_cut_cases(sizes, offsets, shapes): cutShapes.append(e1) cutSizes.append(len(edges)) cutOffsets.append(newOffset) - newOffset = newOffset + len(edges) * 4 + newOffset = newOffset + len(edges) * 4 return cutSizes, cutOffsets, cutShapes -def make_polygonal_clip_tables(): - tableNames = ["Clip", "clip", "clipping"] - outSizes, outOffsets, outShapes = convert_clip_cases("ClipCasesQua.cpp", "Qua", 4, max_points=4) - write_new_tables("../clipping/ClipCasesQua.cpp", "Qua", tableNames, outSizes, outOffsets, outShapes) +# yapf: disable +def make_polygonal_clip_tables(): + tableNames = ["Clip", "clip", "clipping"] - outSizes, outOffsets, outShapes = convert_clip_cases("ClipCasesPoly5.cpp", "Poly5", 5, max_points=5) - write_new_tables("../clipping/ClipCasesPoly5.cpp", "Poly5", tableNames, outSizes, outOffsets, outShapes) + outSizes, outOffsets, outShapes = convert_clip_cases("ClipCasesQua.cpp", "Qua", 4, max_points=4) + write_new_tables("../clipping/ClipCasesQua.cpp", "Qua", tableNames, outSizes, outOffsets, outShapes) - outSizes, outOffsets, outShapes = convert_clip_cases("ClipCasesPoly6.cpp", "Poly6", 6, max_points=6) - write_new_tables("../clipping/ClipCasesPoly6.cpp", "Poly6", tableNames, outSizes, outOffsets, outShapes) + outSizes, outOffsets, outShapes = convert_clip_cases("ClipCasesPoly5.cpp", "Poly5", 5, max_points=5) + write_new_tables("../clipping/ClipCasesPoly5.cpp", "Poly5", tableNames, outSizes, outOffsets, outShapes) - outSizes, outOffsets, outShapes = convert_clip_cases("ClipCasesPoly7.cpp", "Poly7", 7, max_points=7) - write_new_tables("../clipping/ClipCasesPoly7.cpp", "Poly7", tableNames, outSizes, outOffsets, outShapes) + outSizes, outOffsets, outShapes = convert_clip_cases("ClipCasesPoly6.cpp", "Poly6", 6, max_points=6) + write_new_tables("../clipping/ClipCasesPoly6.cpp", "Poly6", tableNames, outSizes, outOffsets, outShapes) - outSizes, outOffsets, outShapes = convert_clip_cases("ClipCasesPoly8.cpp", "Poly8", 8, max_points=8) - write_new_tables("../clipping/ClipCasesPoly8.cpp", "Poly8", tableNames, outSizes, outOffsets, outShapes) + outSizes, outOffsets, outShapes = convert_clip_cases("ClipCasesPoly7.cpp", "Poly7", 7, max_points=7) + write_new_tables("../clipping/ClipCasesPoly7.cpp", "Poly7", tableNames, outSizes, outOffsets, outShapes) -def make_polygonal_cut_tables(): - tableNames = ["Cut", "cut", "cutting"] + outSizes, outOffsets, outShapes = convert_clip_cases("ClipCasesPoly8.cpp", "Poly8", 8, max_points=8) + write_new_tables("../clipping/ClipCasesPoly8.cpp", "Poly8", tableNames, outSizes, outOffsets, outShapes) +# yapf: enable - outSizes, outOffsets, outShapes = convert_clip_cases("ClipCasesPoly5.cpp", "Poly5", 5, max_edges=20) - outSizes, outOffsets, outShapes = make_cut_cases(outSizes, outOffsets, outShapes) - write_new_tables("../cutting/CutCasesPoly5.cpp", "Poly5", tableNames, outSizes, outOffsets, outShapes) - outSizes, outOffsets, outShapes = convert_clip_cases("ClipCasesPoly6.cpp", "Poly6", 6, max_edges=20) - outSizes, outOffsets, outShapes = make_cut_cases(outSizes, outOffsets, outShapes) - write_new_tables("../cutting/CutCasesPoly6.cpp", "Poly6", tableNames, outSizes, outOffsets, outShapes) - - outSizes, outOffsets, outShapes = convert_clip_cases("ClipCasesPoly7.cpp", "Poly7", 7, max_edges=20) - outSizes, outOffsets, outShapes = make_cut_cases(outSizes, outOffsets, outShapes) - write_new_tables("../cutting/CutCasesPoly7.cpp", "Poly7", tableNames, outSizes, outOffsets, outShapes) +def make_polygonal_cut_tables(): + tableNames = ["Cut", "cut", "cutting"] + + outSizes, outOffsets, outShapes = convert_clip_cases("ClipCasesPoly5.cpp", + "Poly5", + 5, + max_edges=20) + outSizes, outOffsets, outShapes = make_cut_cases(outSizes, outOffsets, outShapes) + write_new_tables("../cutting/CutCasesPoly5.cpp", "Poly5", tableNames, outSizes, outOffsets, + outShapes) + + outSizes, outOffsets, outShapes = convert_clip_cases("ClipCasesPoly6.cpp", + "Poly6", + 6, + max_edges=20) + outSizes, outOffsets, outShapes = make_cut_cases(outSizes, outOffsets, outShapes) + write_new_tables("../cutting/CutCasesPoly6.cpp", "Poly6", tableNames, outSizes, outOffsets, + outShapes) + + outSizes, outOffsets, outShapes = convert_clip_cases("ClipCasesPoly7.cpp", + "Poly7", + 7, + max_edges=20) + outSizes, outOffsets, outShapes = make_cut_cases(outSizes, outOffsets, outShapes) + write_new_tables("../cutting/CutCasesPoly7.cpp", "Poly7", tableNames, outSizes, outOffsets, + outShapes) + + outSizes, outOffsets, outShapes = convert_clip_cases("ClipCasesPoly8.cpp", + "Poly8", + 8, + max_edges=20) + outSizes, outOffsets, outShapes = make_cut_cases(outSizes, outOffsets, outShapes) + write_new_tables("../cutting/CutCasesPoly8.cpp", "Poly8", tableNames, outSizes, outOffsets, + outShapes) - outSizes, outOffsets, outShapes = convert_clip_cases("ClipCasesPoly8.cpp", "Poly8", 8, max_edges=20) - outSizes, outOffsets, outShapes = make_cut_cases(outSizes, outOffsets, outShapes) - write_new_tables("../cutting/CutCasesPoly8.cpp", "Poly8", tableNames, outSizes, outOffsets, outShapes) def main(): - if "-clip" in sys.argv: - make_polygonal_clip_tables() - else: - make_polygonal_cut_tables() + if "-clip" in sys.argv: + make_polygonal_clip_tables() + else: + make_polygonal_cut_tables() + main() - diff --git a/src/axom/bump/tests/CMakeLists.txt b/src/axom/bump/tests/CMakeLists.txt index 0f0f7113d1..a79c77dda4 100644 --- a/src/axom/bump/tests/CMakeLists.txt +++ b/src/axom/bump/tests/CMakeLists.txt @@ -48,3 +48,7 @@ foreach(test ${gtest_bump_tests}) COMMAND ${test_name}_test ) endforeach() +if(ENABLE_HIP) + # Work around an issue with this test using HIP in Debug builds. + axom_force_release_for_target(bump_topology_mapper_test) +endif() diff --git a/src/axom/bump/tests/blueprint_testing_helpers.hpp b/src/axom/bump/tests/blueprint_testing_helpers.hpp index dd72968b0b..d23903a8af 100644 --- a/src/axom/bump/tests/blueprint_testing_helpers.hpp +++ b/src/axom/bump/tests/blueprint_testing_helpers.hpp @@ -12,8 +12,11 @@ #include #include #include +#include #include #include +#include +#include //------------------------------------------------------------------------------ // clang-format off @@ -448,16 +451,166 @@ void saveBaseline(const std::vector &baselinePaths, } } -bool loadBaseline(const std::string &filename, conduit::Node &n) +#if !defined(_WIN32) +/*! + * \brief This routine converts a YAML file to a JSON file. Ordinarily, we could + * use Conduit for this but this works around a case where Conduit is + * failing to read certain YAML baselines. + * + * \param The YAML filename to convert. + * \param The output JSON filename. + * + * \return True on success; False otherwise. + */ +bool convert_yaml_json(const std::string &yaml_filename, const std::string &json_filename) +{ + const std::string script_path = "convert_yaml_json.py"; + + // 1. Write the Python converter script to ./convert_yaml_json.py + { + std::ofstream script(script_path, std::ios::trunc); + if(!script) + { + return false; + } + + script << + R"(#!/usr/bin/env python3 +import sys +import json + +try: + import yaml +except ImportError: + sys.stderr.write("PyYAML is required (pip install pyyaml)\n") + sys.exit(1) + +def main(): + if len(sys.argv) != 3: + sys.stderr.write(f"Usage: {sys.argv[0]} input.yaml output.json\n") + sys.exit(1) + + in_path, out_path = sys.argv[1], sys.argv[2] + + print(f"in_path: {in_path}") + print(f"out_path: {out_path}") + with open(in_path, "rt") as f: + data = yaml.safe_load(f) + + with open(out_path, "wt") as f: + json.dump(data, f, indent=2) + +if __name__ == "__main__": + main() +)"; + + script.flush(); + if(!script) + { + return false; + } + } + + // 2. Build the command to call Python + // TODO: Use Axom's Python interpreter. + const auto cmd = + axom::fmt::format("python3 {} \"{}\" \"{}\"", script_path, yaml_filename, json_filename); + int ret = std::system(cmd.c_str()); + + if(axom::utilities::filesystem::pathExists(script_path)) + { + axom::utilities::filesystem::removeFile(script_path); + } + + return ret == 0; +} +#endif + +bool loadBaseline(const std::string &filename, const std::string &protocol, conduit::Node &n) { bool loaded = false; - std::string file_with_ext(filename + ".yaml"); + std::string file_with_ext(filename + "." + protocol); //SLIC_INFO(axom::fmt::format("Load baseline {}", file_with_ext)); - if(axom::utilities::filesystem::pathExists(file_with_ext)) + const int MAX_ATTEMPTS = 3; + for(int attempt = 0; attempt < MAX_ATTEMPTS && !loaded; attempt++) + { + if(axom::utilities::filesystem::pathExists(file_with_ext)) + { + try + { + n.reset(); + conduit::relay::io::load(file_with_ext, protocol, n); + loaded = true; + } + catch(conduit::Error &e) + { + if(attempt == MAX_ATTEMPTS - 1) + { + throw e; + } + else + { + SLIC_INFO(axom::fmt::format("Could not load {}! Retrying. {}", file_with_ext, e.message())); + } + } + catch(...) + { + if(attempt == MAX_ATTEMPTS - 1) + { + throw; + } + else + { + SLIC_INFO(axom::fmt::format("Could not load {}!", file_with_ext)); + } + } + } + if(!loaded) + { + std::this_thread::sleep_for(std::chrono::milliseconds(250)); + } + } + return loaded; +} + +bool loadBaseline(const std::string &filename, conduit::Node &n) +{ + bool loaded = false; +#if defined(_WIN32) + loaded = loadBaseline(filename, "yaml", n); +#else + try + { + loaded = loadBaseline(filename, "yaml", n); + } + catch(conduit::Error &e) { - conduit::relay::io::load(file_with_ext, "yaml", n); - loaded = true; + SLIC_INFO(axom::fmt::format("Could not load {}! {}", filename, e.message())); } + catch(...) + { + SLIC_INFO(axom::fmt::format("Could not load {}!", filename)); + } + // Try another format. + if(!loaded) + { + const std::string yaml_filename = axom::fmt::format("{}.yaml", filename); + if(axom::utilities::filesystem::pathExists(yaml_filename)) + { + const std::string json_filename = axom::fmt::format("{}.json", filename); + // Try converting the baseline on the fly to JSON and using that converted file. + SLIC_INFO(axom::fmt::format("Attempting to convert YAML baseline to JSON {}.", json_filename)); + if(convert_yaml_json(yaml_filename, json_filename)) + { + loaded = loadBaseline(filename, "json", n); + if(axom::utilities::filesystem::pathExists(json_filename)) + { + axom::utilities::filesystem::removeFile(json_filename); + } + } + } + } +#endif return loaded; } diff --git a/src/axom/bump/tests/bump_topology_mapper.cpp b/src/axom/bump/tests/bump_topology_mapper.cpp index ac68c12a87..8b31df39b5 100644 --- a/src/axom/bump/tests/bump_topology_mapper.cpp +++ b/src/axom/bump/tests/bump_topology_mapper.cpp @@ -362,6 +362,7 @@ class test_TopologyMapper axom::Array shapeValues, shapeIds; const conduit::Node &n_srcTopo = n_dev["topologies/postmir"]; auto shapeMap = views::buildShapeMap(n_srcTopo, shapeValues, shapeIds, allocatorID); + axom::synchronize(); SrcTopologyView srcTopo( utils::make_array_view(n_srcTopo["elements/connectivity"]), utils::make_array_view(n_srcTopo["elements/shapes"]), @@ -421,6 +422,7 @@ class test_TopologyMapper const conduit::Node &n_srcTopo = n_dev["topologies/postmir"]; const int allocatorID = axom::execution_space::allocatorID(); auto shapeMap = views::buildShapeMap(n_srcTopo, shapeValues, shapeIds, allocatorID); + axom::synchronize(); SrcTopologyView srcTopo( utils::make_array_view(n_srcTopo["elements/connectivity"]), utils::make_array_view(n_srcTopo["elements/shapes"]), @@ -470,6 +472,7 @@ class test_TopologyMapper const int allocatorID = axom::execution_space::allocatorID(); auto shapeMap = views::buildShapeMap(n_srcTopo, shapeValues, shapeIds, allocatorID); + axom::synchronize(); const auto srcConnView = utils::make_array_view(n_srcTopo["elements/connectivity"]); const auto srcShapesView = @@ -518,6 +521,7 @@ class test_TopologyMapper const conduit::Node &n_srcTopo = n_dev["topologies/epm"]; const int allocatorID = axom::execution_space::allocatorID(); auto shapeMap = views::buildShapeMap(n_srcTopo, shapeValues, shapeIds, allocatorID); + axom::synchronize(); SrcTopologyView srcTopo( utils::make_array_view(n_srcTopo["elements/connectivity"]), utils::make_array_view(n_srcTopo["elements/shapes"]), diff --git a/src/axom/bump/tests/bump_utilities.cpp b/src/axom/bump/tests/bump_utilities.cpp index 2bca55762d..d1d5e912c1 100644 --- a/src/axom/bump/tests/bump_utilities.cpp +++ b/src/axom/bump/tests/bump_utilities.cpp @@ -25,12 +25,14 @@ struct test_conduit_allocate { static void test() { - utils::ConduitAllocateThroughAxom c2a; - EXPECT_TRUE(c2a.getConduitAllocatorID() > 0); + const auto conduitAllocatorId = axom::sidre::ConduitMemory::axomAllocIdToConduit( + axom::execution_space::allocatorID()); + + EXPECT_TRUE(conduitAllocatorId > 0); constexpr int nValues = 100; conduit::Node n; - n.set_allocator(c2a.getConduitAllocatorID()); + n.set_allocator(conduitAllocatorId); n.set(conduit::DataType::int32(nValues)); // Make sure we can store some values into the data that were allocated. @@ -51,23 +53,55 @@ struct test_conduit_allocate // Check zero allocation. n.reset(); - n.set_allocator(c2a.getConduitAllocatorID()); + n.set_allocator(conduitAllocatorId); n.set(conduit::DataType::int32(0)); EXPECT_EQ(n.dtype().number_of_elements(), 0); } }; -TEST(bump_blueprint_utilities, allocate_seq) { test_conduit_allocate::test(); } +TEST(bump_utilities, allocate_seq) { test_conduit_allocate::test(); } #if defined(AXOM_RUNTIME_POLICY_USE_OPENMP) -TEST(bump_blueprint_utilities, allocate_omp) { test_conduit_allocate::test(); } +TEST(bump_utilities, allocate_omp) { test_conduit_allocate::test(); } #endif #if defined(AXOM_RUNTIME_POLICY_USE_CUDA) -TEST(bump_blueprint_utilities, allocate_cuda) { test_conduit_allocate::test(); } +TEST(bump_utilities, allocate_cuda) { test_conduit_allocate::test(); } #endif #if defined(AXOM_RUNTIME_POLICY_USE_HIP) -TEST(bump_blueprint_utilities, allocate_hip) { test_conduit_allocate::test(); } +TEST(bump_utilities, allocate_hip) { test_conduit_allocate::test(); } #endif +//------------------------------------------------------------------------------ +AXOM_CUDA_TEST(bump_utilities, make_array_view_interleaved_seq) +{ + constexpr conduit::index_t n = 4; + axom::Array interleaved {{-1., 10., -2., 20., -3., 30., -4., 40., -5.}}; + conduit::Node n_data; + n_data.set_external(conduit::DataType(conduit::DataType::FLOAT64_ID, + n, + sizeof(double), + 2 * sizeof(double), + sizeof(double), + conduit::Endianness::DEFAULT_ID), + interleaved.data()); + + auto view = utils::make_array_view(n_data); + EXPECT_EQ(view.size(), n); + + axom::for_all( + n, + AXOM_LAMBDA(axom::IndexType index) { view[index] = static_cast((index + 1) * 100); }); + + EXPECT_EQ(interleaved[0], -1.); + EXPECT_EQ(interleaved[1], 100.); + EXPECT_EQ(interleaved[2], -2.); + EXPECT_EQ(interleaved[3], 200.); + EXPECT_EQ(interleaved[4], -3.); + EXPECT_EQ(interleaved[5], 300.); + EXPECT_EQ(interleaved[6], -4.); + EXPECT_EQ(interleaved[7], 400.); + EXPECT_EQ(interleaved[8], -5.); +} + //------------------------------------------------------------------------------ template struct test_copy_braid @@ -119,16 +153,16 @@ struct test_copy_braid } }; -TEST(bump_blueprint_utilities, copy_seq) { test_copy_braid::test(); } +TEST(bump_utilities, copy_seq) { test_copy_braid::test(); } #if defined(AXOM_RUNTIME_POLICY_USE_OPENMP) -TEST(bump_blueprint_utilities, copy_omp) { test_copy_braid::test(); } +TEST(bump_utilities, copy_omp) { test_copy_braid::test(); } #endif #if defined(AXOM_RUNTIME_POLICY_USE_CUDA) -TEST(bump_blueprint_utilities, copy_cuda) { test_copy_braid::test(); } +TEST(bump_utilities, copy_cuda) { test_copy_braid::test(); } #endif #if defined(AXOM_RUNTIME_POLICY_USE_HIP) -TEST(bump_blueprint_utilities, copy_hip) { test_copy_braid::test(); } +TEST(bump_utilities, copy_hip) { test_copy_braid::test(); } #endif //------------------------------------------------------------------------------ diff --git a/src/axom/bump/tests/bump_views.cpp b/src/axom/bump/tests/bump_views.cpp index 4170950a03..21f5b43978 100644 --- a/src/axom/bump/tests/bump_views.cpp +++ b/src/axom/bump/tests/bump_views.cpp @@ -289,18 +289,20 @@ struct test_node_to_arrayview conduit::DataType::FLOAT32_ID, conduit::DataType::FLOAT64_ID}; constexpr int n = 16; - utils::ConduitAllocateThroughAxom c2a; + + const auto conduitAllocatorId = axom::sidre::ConduitMemory::axomAllocIdToConduit( + axom::execution_space::allocatorID()); + for(int dtype : dtypes) { // Make a node and fill it with data. conduit::Node n_data; - n_data.set_allocator(c2a.getConduitAllocatorID()); + n_data.set_allocator(conduitAllocatorId); n_data.set(conduit::DataType(dtype, n)); int sumValues = 0; - axom::bump::views::Node_to_ArrayView(n_data, [&](auto dataView) { - sumValues = testBody(dataView, n); - }); + axom::bump::views::nodeToArrayView(n_data, + [&](auto dataView) { sumValues = testBody(dataView, n); }); EXPECT_EQ(sumValues, sum(n)); } @@ -338,6 +340,48 @@ TEST(bump_views, node_to_arrayview_cuda) { test_node_to_arrayview::te TEST(bump_views, node_to_arrayview_hip) { test_node_to_arrayview::test(); } #endif +//------------------------------------------------------------------------------ +TEST(bump_views, node_to_arrayview_interleaved_seq) +{ + constexpr conduit::index_t n = 4; + axom::Array interleaved {{-1., 10., -2., 20., -3., 30., -4., 40., -5.}}; + conduit::Node n_data; + n_data.set_external(conduit::DataType(conduit::DataType::FLOAT64_ID, + n, + sizeof(double), + 2 * sizeof(double), + sizeof(double), + conduit::Endianness::DEFAULT_ID), + interleaved.data()); + + int sumValues = 0; + axom::bump::views::nodeToArrayView(n_data, [&](auto dataView) { + EXPECT_EQ(dataView.size(), n); + axom::for_all( + n, + AXOM_HOST_LAMBDA(axom::IndexType index) { + dataView[index] = static_cast((index + 1) * 100); + }); + + axom::ReduceSum sumValuesReduce(0.); + axom::for_all( + n, + AXOM_HOST_LAMBDA(axom::IndexType index) { sumValuesReduce += dataView[index]; }); + sumValues = static_cast(sumValuesReduce.get()); + }); + + EXPECT_EQ(sumValues, 1000); + EXPECT_EQ(interleaved[0], -1.); + EXPECT_EQ(interleaved[1], 100.); + EXPECT_EQ(interleaved[2], -2.); + EXPECT_EQ(interleaved[3], 200.); + EXPECT_EQ(interleaved[4], -3.); + EXPECT_EQ(interleaved[5], 300.); + EXPECT_EQ(interleaved[6], -4.); + EXPECT_EQ(interleaved[7], 400.); + EXPECT_EQ(interleaved[8], -5.); +} + //------------------------------------------------------------------------------ TEST(bump_views, explicit_coordsetview) { @@ -498,8 +542,8 @@ struct test_strided_structured actualNodesView[zoneIndex * 4 + i] = ids[i]; // Get the logical local id for the id. - const auto index = nodeIndexing.GlobalToLocal(ids[i]); - const auto logical = nodeIndexing.IndexToLogicalIndex(index); + const auto index = nodeIndexing.globalToLocal(ids[i]); + const auto logical = nodeIndexing.indexToLogicalIndex(index); logicalNodesView[(zoneIndex * 4 + i) * 2 + 0] = logical[0]; logicalNodesView[(zoneIndex * 4 + i) * 2 + 1] = logical[1]; } @@ -661,20 +705,20 @@ struct test_braid2d_mat } // Test iterators. - test_matsetview_iterators(matsetView, allocatorID); + test_matsetview_iterators(nzones, matsetView, allocatorID); } template - static void test_matsetview_iterators(MatsetView matsetView, int allocatorID) + static void test_matsetview_iterators(axom::IndexType nzones, MatsetView matsetView, int allocatorID) { using ZoneIndex = typename MatsetView::ZoneIndex; // Allocate results array on device. - const int nResults = matsetView.numberOfZones(); + const auto nResults = nzones; axom::Array resultsArrayDevice(nResults, nResults, allocatorID); auto resultsView = resultsArrayDevice.view(); axom::for_all( - matsetView.numberOfZones(), + nzones, AXOM_LAMBDA(axom::IndexType index) { typename MatsetView::IDList ids {}; typename MatsetView::VFList vfs {}; diff --git a/src/axom/bump/tests/bump_views_indexing.cpp b/src/axom/bump/tests/bump_views_indexing.cpp index 63efcc9e23..c1f18853db 100644 --- a/src/axom/bump/tests/bump_views_indexing.cpp +++ b/src/axom/bump/tests/bump_views_indexing.cpp @@ -44,12 +44,12 @@ TEST(bump_views_indexing, strided_structured_indexing_2d) for(int i = 0; i < dims[0]; i++) { LogicalIndex logical {i, j}; - const auto flat = indexing.LogicalIndexToIndex(logical); - const auto logical2 = indexing.IndexToLogicalIndex(flat); + const auto flat = indexing.logicalIndexToIndex(logical); + const auto logical2 = indexing.indexToLogicalIndex(flat); EXPECT_EQ(logical, logical2); - EXPECT_EQ(logical, indexing.GlobalToLocal(indexing.LocalToGlobal(logical))); - EXPECT_EQ(flat, indexing.GlobalToLocal(indexing.LocalToGlobal(flat))); + EXPECT_EQ(logical, indexing.globalToLocal(indexing.localToGlobal(logical))); + EXPECT_EQ(flat, indexing.globalToLocal(indexing.localToGlobal(flat))); } } @@ -60,26 +60,26 @@ TEST(bump_views_indexing, strided_structured_indexing_2d) for(int i = 0; i < stride[1]; i++, index++) { LogicalIndex logical {i, j}; - const auto flat = indexing.GlobalToGlobal(logical); + const auto flat = indexing.globalToGlobal(logical); // flat should start at 0 and increase EXPECT_EQ(flat, index); // Global flat back to logical. - LogicalIndex logical2 = indexing.GlobalToGlobal(flat); + LogicalIndex logical2 = indexing.globalToGlobal(flat); EXPECT_EQ(logical, logical2); // If we're in a valid region for the local window, try some other things. if(i >= origin[0] && i < origin[0] + dims[0] && j >= origin[1] && j < origin[1] + dims[1]) { - const auto logicalLocal = indexing.GlobalToLocal(logical); - const auto flatLocal = indexing.GlobalToLocal(flat); + const auto logicalLocal = indexing.globalToLocal(logical); + const auto flatLocal = indexing.globalToLocal(flat); // Flat local back to flat global - EXPECT_EQ(flat, indexing.LocalToGlobal(flatLocal)); + EXPECT_EQ(flat, indexing.localToGlobal(flatLocal)); // Logical local back to logical global - EXPECT_EQ(logical, indexing.LocalToGlobal(logicalLocal)); + EXPECT_EQ(logical, indexing.localToGlobal(logicalLocal)); } } } @@ -105,14 +105,14 @@ TEST(bump_views_indexing, strided_structured_indexing_3d) EXPECT_EQ(indexing.size(), dims[0] * dims[1] * dims[2]); const LogicalIndex logical0_0_0 {0, 0, 0}; - const auto index0_0_0 = indexing.LogicalIndexToIndex(logical0_0_0); + const auto index0_0_0 = indexing.logicalIndexToIndex(logical0_0_0); EXPECT_EQ(index0_0_0, 0); const LogicalIndex logical2_2_2 {2, 2, 2}; - const auto index2_2_2 = indexing.LogicalIndexToIndex(logical2_2_2); + const auto index2_2_2 = indexing.logicalIndexToIndex(logical2_2_2); EXPECT_EQ(index2_2_2, 2 + 2 * dims[0] + 2 * dims[0] * dims[1]); - LogicalIndex logical = indexing.IndexToLogicalIndex(index2_2_2); + LogicalIndex logical = indexing.indexToLogicalIndex(index2_2_2); EXPECT_TRUE(logical == logical2_2_2); for(int k = 0; k < dims[2]; k++) @@ -122,8 +122,8 @@ TEST(bump_views_indexing, strided_structured_indexing_3d) for(int i = 0; i < dims[0]; i++) { LogicalIndex logical {i, j, k}; - const auto flat = indexing.LogicalIndexToIndex(logical); - const auto logical2 = indexing.IndexToLogicalIndex(flat); + const auto flat = indexing.logicalIndexToIndex(logical); + const auto logical2 = indexing.indexToLogicalIndex(flat); EXPECT_EQ(logical, logical2); } } diff --git a/src/axom/bump/utilities/conduit_array_view.hpp b/src/axom/bump/utilities/conduit_array_view.hpp new file mode 100644 index 0000000000..6ea360a48c --- /dev/null +++ b/src/axom/bump/utilities/conduit_array_view.hpp @@ -0,0 +1,80 @@ +// Copyright (c) Lawrence Livermore National Security, LLC and other +// Axom Project Contributors. See top-level LICENSE and COPYRIGHT +// files for dates and other details. +// +// SPDX-License-Identifier: (BSD-3-Clause) + +#ifndef AXOM_BUMP_CONDUIT_ARRAY_VIEW_HPP_ +#define AXOM_BUMP_CONDUIT_ARRAY_VIEW_HPP_ + +#include "axom/bump/utilities/conduit_traits.hpp" +#include "axom/core/ArrayView.hpp" +#include "axom/slic.hpp" + +#include + +namespace axom +{ +namespace bump +{ +namespace utilities +{ +namespace detail +{ + +/*! + * \brief Make a 1D axom::ArrayView from a typed Conduit node. + * + * \note This helper honors Conduit offset and stride metadata, so it supports + * regular interleaved layouts in addition to dense arrays. + */ +template +inline axom::ArrayView make_conduit_array_view(conduit::Node &n) +{ + SLIC_ASSERT_MSG(cpp2conduit::id == n.dtype().id(), + "Cannot create ArrayView with a type that does not match the Conduit node."); + + const auto stride_bytes = n.dtype().stride(); + const auto element_bytes = n.dtype().element_bytes(); + SLIC_ERROR_IF(element_bytes != static_cast(sizeof(T)), + "Conduit element size does not match the selected node type."); + SLIC_ERROR_IF(stride_bytes % static_cast(sizeof(T)) != 0, + "Conduit stride is not compatible with the selected node type."); + + auto *data = static_cast(n.element_ptr(0)); + const auto stride = stride_bytes / static_cast(sizeof(T)); + return axom::ArrayView( + data, + axom::StackArray { + {static_cast(n.dtype().number_of_elements())}}, + axom::StackArray {{static_cast(stride)}}); +} + +template +inline axom::ArrayView make_conduit_array_view(const conduit::Node &n) +{ + SLIC_ASSERT_MSG(cpp2conduit::id == n.dtype().id(), + "Cannot create ArrayView with a type that does not match the Conduit node."); + + const auto stride_bytes = n.dtype().stride(); + const auto element_bytes = n.dtype().element_bytes(); + SLIC_ERROR_IF(element_bytes != static_cast(sizeof(T)), + "Conduit element size does not match the selected node type."); + SLIC_ERROR_IF(stride_bytes % static_cast(sizeof(T)) != 0, + "Conduit stride is not compatible with the selected node type."); + + auto *data = const_cast(static_cast(n.element_ptr(0))); + const auto stride = stride_bytes / static_cast(sizeof(T)); + return axom::ArrayView( + data, + axom::StackArray { + {static_cast(n.dtype().number_of_elements())}}, + axom::StackArray {{static_cast(stride)}}); +} + +} // namespace detail +} // namespace utilities +} // namespace bump +} // namespace axom + +#endif diff --git a/src/axom/bump/utilities/conduit_memory.cpp b/src/axom/bump/utilities/conduit_memory.cpp new file mode 100644 index 0000000000..a79b662170 --- /dev/null +++ b/src/axom/bump/utilities/conduit_memory.cpp @@ -0,0 +1,22 @@ +// Copyright (c) Lawrence Livermore National Security, LLC and other +// Axom Project Contributors. See top-level LICENSE and COPYRIGHT +// files for dates and other details. +// +// SPDX-License-Identifier: (BSD-3-Clause) +#include "axom/core.hpp" +#include "axom/bump/utilities/conduit_memory.hpp" + +namespace axom::bump::utilities +{ + +bool isDeviceAllocated(const conduit::Node &n) +{ +#if defined(AXOM_USE_UMPIRE) + return isDeviceAllocator(axom::getAllocatorIDFromPointer(n.data_ptr())); +#else + AXOM_UNUSED_VAR(n); + return false; +#endif +} + +} // end namespace axom::bump::utilities diff --git a/src/axom/bump/utilities/conduit_memory.hpp b/src/axom/bump/utilities/conduit_memory.hpp index 64833af320..03099b19f4 100644 --- a/src/axom/bump/utilities/conduit_memory.hpp +++ b/src/axom/bump/utilities/conduit_memory.hpp @@ -7,12 +7,15 @@ #ifndef AXOM_BUMP_CONDUIT_MEMORY_HPP_ #define AXOM_BUMP_CONDUIT_MEMORY_HPP_ +#include "axom/bump/utilities/conduit_array_view.hpp" #include "axom/bump/utilities/conduit_traits.hpp" #include "axom/core/Array.hpp" #include "axom/core/ArrayView.hpp" #include "axom/core/memory_management.hpp" #include "axom/core/NumericLimits.hpp" +#include "axom/core/execution/synchronize.hpp" #include "axom/slic.hpp" +#include "axom/sidre/core/ConduitMemory.hpp" #include "axom/export/bump.h" #include @@ -40,93 +43,30 @@ namespace utilities template inline axom::ArrayView make_array_view(conduit::Node &n) { - SLIC_ASSERT_MSG(cpp2conduit::id == n.dtype().id(), - axom::fmt::format("Cannot create ArrayView<{}> for Conduit {} data.", - cpp2conduit::name, - n.dtype().name())); - return axom::ArrayView(static_cast(n.data_ptr()), n.dtype().number_of_elements()); + return detail::make_conduit_array_view(n); } template inline axom::ArrayView make_array_view(const conduit::Node &n) { - SLIC_ASSERT_MSG(cpp2conduit::id == n.dtype().id(), - axom::fmt::format("Cannot create ArrayView<{}> for Conduit {} data.", - cpp2conduit::name, - n.dtype().name())); - return axom::ArrayView(static_cast(const_cast(n.data_ptr())), - n.dtype().number_of_elements()); + return detail::make_conduit_array_view(n); } /// @} //------------------------------------------------------------------------------ /*! - * \brief This class registers a Conduit allocator that can make Conduit allocate - * through Axom's allocate/deallocate functions using a specific allocator. - * This permits Conduit to allocate through Axom's UMPIRE logic. + * \brief Returns whether the data pointer in the Conduit node appears to be + * allocated on a device. * - * \tparam ExecSpace The execution space. + * \param n The node whose data we're checking for device allocation. + * + * \return True if the data looks device-allocated; false otherwise. */ -template -class ConduitAllocateThroughAxom -{ -public: - /*! - * \brief Get the Conduit allocator ID for this ExecSpace. - * - * \return The Conduit allocator ID for this ExecSpace. - */ - static conduit::index_t getConduitAllocatorID() - { - constexpr conduit::index_t NoAllocator = -1; - static conduit::index_t conduitAllocatorID = NoAllocator; - if(conduitAllocatorID == NoAllocator) - { - conduitAllocatorID = conduit::utils::register_allocator(internal_allocate, internal_free); - } - return conduitAllocatorID; - } - -private: - /*! - * \brief A function we register with Conduit to allocate memory. - * - * \param items The number of items to allocate. - * \param item_size The size of each item in bytes. - * - * \brief A block of newly allocated memory large enough for the requested items. - */ - static void *internal_allocate(size_t items, size_t item_size) - { - int axomAllocatorID; -#if defined(AXOM_USE_UMPIRE) && defined(AXOM_USE_GPU) - constexpr bool on_device = axom::execution_space::onDevice(); - - axomAllocatorID = on_device ? axom::getUmpireResourceAllocatorID(umpire::resource::Unified) - : axom::execution_space::allocatorID(); -#else - axomAllocatorID = axom::execution_space::allocatorID(); -#endif - - void *ptr = static_cast(axom::allocate(items * item_size, axomAllocatorID)); - //std::cout << axom::execution_space::name() - // << ": Allocated for Conduit via axom: items=" << items - // << ", item_size=" << item_size << ", ptr=" << ptr << std::endl; - return ptr; - } - - /*! - * \brief A deallocation function we register with Conduit. - */ - static void internal_free(void *ptr) - { - //std::cout << axom::execution_space::name() - // << ": Dellocating for Conduit via axom: ptr=" << ptr << std::endl; - axom::deallocate(ptr); - } -}; +bool isDeviceAllocated(const conduit::Node &n); //------------------------------------------------------------------------------ +namespace internal +{ /*! * \brief Copies a Conduit tree in the \a src node to a new Conduit \a dest node, * making sure to allocate array data in the appropriate memory space for @@ -136,29 +76,38 @@ class ConduitAllocateThroughAxom * * \param dest The conduit node that will receive the copied data. * \param src The source data to be copied. + * \param destAllocatorID The allocator for the destination. It defaults to the allocator for ExecSpace. */ template -void copy(conduit::Node &dest, const conduit::Node &src) +void copyImpl(conduit::Node &dest, + const conduit::Node &src, + int destAllocatorID, + bool destAllocatorForDevice) { - ConduitAllocateThroughAxom c2a; dest.reset(); if(src.number_of_children() > 0) { for(conduit::index_t i = 0; i < src.number_of_children(); i++) { - copy(dest[src[i].name()], src[i]); + copyImpl(dest[src[i].name()], src[i], destAllocatorID, destAllocatorForDevice); } } else { - const int allocatorID = axom::getAllocatorIDFromPointer(src.data_ptr()); - bool deviceAllocated = - (allocatorID == INVALID_ALLOCATOR_ID) ? false : isDeviceAllocator(allocatorID); - if(deviceAllocated || (!src.dtype().is_string() && src.dtype().number_of_elements() > 1)) + const int srcAllocatorID = axom::getAllocatorIDFromPointer(src.data_ptr()); + const bool srcDataOnDevice = + (srcAllocatorID == INVALID_ALLOCATOR_ID) ? false : isDeviceAllocator(srcAllocatorID); + const bool deviceInvolved = srcDataOnDevice || destAllocatorForDevice; + const bool isArray = (!src.dtype().is_string() && src.dtype().number_of_elements() > 1); + if(deviceInvolved || isArray) { // Allocate the node's memory in the right place. dest.reset(); - dest.set_allocator(c2a.getConduitAllocatorID()); + if(isArray) + { + // Just set the allocator for array data. Otherwise not setting makes it in host memory. + dest.set_allocator(axom::sidre::ConduitMemory::axomAllocIdToConduit(destAllocatorID)); + } dest.set(conduit::DataType(src.dtype().id(), src.dtype().number_of_elements())); // Copy the data to the destination node. Axom uses Umpire to manage that. @@ -171,6 +120,7 @@ void copy(conduit::Node &dest, const conduit::Node &src) src.compact_to(tmp); axom::copy(dest.data_ptr(), tmp.data_ptr(), tmp.dtype().bytes_compact()); } + axom::synchronize(); } else { @@ -180,6 +130,28 @@ void copy(conduit::Node &dest, const conduit::Node &src) } } +} // end namespace internal + +/*! + * \brief Copies a Conduit tree in the \a src node to a new Conduit \a dest node, + * making sure to allocate array data in the appropriate memory space for + * the execution space. + * + * \tparam ExecSpace The destination execution space (e.g. axom::SEQ_EXEC). + * + * \param dest The conduit node that will receive the copied data. + * \param src The source data to be copied. + * \param destAllocatorID The allocator for the destination. It defaults to the allocator for ExecSpace. + */ +template +void copy(conduit::Node &dest, + const conduit::Node &src, + int destAllocatorID = axom::execution_space::allocatorID()) +{ + const bool destAllocatorForDevice = isDeviceAllocator(destAllocatorID); + internal::copyImpl(dest, src, destAllocatorID, destAllocatorForDevice); +} + //------------------------------------------------------------------------------ /*! * \brief Fill an array with int values from a Conduit node. diff --git a/src/axom/bump/utilities/utilities.hpp b/src/axom/bump/utilities/utilities.hpp index a4501fa332..795057a9fc 100644 --- a/src/axom/bump/utilities/utilities.hpp +++ b/src/axom/bump/utilities/utilities.hpp @@ -11,6 +11,7 @@ #include "axom/slic.hpp" #include +#include namespace axom { @@ -18,6 +19,30 @@ namespace bump { namespace utilities { +//------------------------------------------------------------------------------ +/*! + * \brief Determines best mask type to use for an ExecSpace. + * + * \tparam ExecSpace The execution space. + * \tparam DefaultMaskType The default mask type to use if we cannot use char. + */ +template +struct mask_traits +{ + static constexpr bool is_hip() + { +#if defined(AXOM_RUNTIME_POLICY_USE_HIP) + constexpr int BLOCK_SIZE = 256; // The size here does not matter. + return std::string_view(axom::execution_space::name()) == + std::string_view(axom::execution_space>::name()); +#else + return false; +#endif + } + + using type = typename std::conditional::type; +}; + //------------------------------------------------------------------------------ /*! * \brief This class and its specializations provide a type trait that lets us diff --git a/src/axom/bump/views/BasicIndexing.hpp b/src/axom/bump/views/BasicIndexing.hpp index 80ef96981d..bce2534787 100644 --- a/src/axom/bump/views/BasicIndexing.hpp +++ b/src/axom/bump/views/BasicIndexing.hpp @@ -41,22 +41,22 @@ class BasicIndexing /// No-effect indexing transforms - AXOM_HOST_DEVICE inline axom::IndexType LocalToLocal(axom::IndexType index) const + AXOM_HOST_DEVICE inline axom::IndexType localToLocal(axom::IndexType index) const { return index; } - AXOM_HOST_DEVICE inline axom::IndexType LocalToGlobal(axom::IndexType index) const + AXOM_HOST_DEVICE inline axom::IndexType localToGlobal(axom::IndexType index) const { return index; } - AXOM_HOST_DEVICE inline axom::IndexType GlobalToLocal(axom::IndexType index) const + AXOM_HOST_DEVICE inline axom::IndexType globalToLocal(axom::IndexType index) const { return index; } - AXOM_HOST_DEVICE inline axom::IndexType GlobalToGlobal(axom::IndexType index) const + AXOM_HOST_DEVICE inline axom::IndexType globalToGlobal(axom::IndexType index) const { return index; } diff --git a/src/axom/bump/views/MaterialView.hpp b/src/axom/bump/views/MaterialView.hpp index 6050edc0a6..00f72ba2da 100644 --- a/src/axom/bump/views/MaterialView.hpp +++ b/src/axom/bump/views/MaterialView.hpp @@ -30,8 +30,8 @@ namespace views */ struct Material { - int number {}; - std::string name {}; + int m_number {}; + std::string m_name {}; }; using MaterialInformation = std::vector; diff --git a/src/axom/bump/views/NodeArrayView.hpp b/src/axom/bump/views/NodeArrayView.hpp index 05af7081ae..e0d76be8a6 100644 --- a/src/axom/bump/views/NodeArrayView.hpp +++ b/src/axom/bump/views/NodeArrayView.hpp @@ -7,10 +7,13 @@ #ifndef AXOM_BUMP_VIEWS_NODE_ARRAY_VIEW_HPP_ #define AXOM_BUMP_VIEWS_NODE_ARRAY_VIEW_HPP_ +#include "axom/bump/utilities/conduit_array_view.hpp" #include "axom/slic/interface/slic.hpp" #include -#include + +#include +#include namespace axom { @@ -27,7 +30,6 @@ struct Delimiter constexpr Delimiter ArgumentDelimiter; #if __cplusplus >= 201703L -// C++17 and later. template constexpr int encode_types(Args... args) { @@ -76,764 +78,135 @@ constexpr int select_float_types() return select_types(conduit::DataType::FLOAT32_ID, conduit::DataType::FLOAT64_ID); } -//------------------------------------------------------------------------------ -// General Node to ArrayView. Handle all types. -//------------------------------------------------------------------------------ -/// NOTE: Some of these functions use const_cast to get data into the ArrayView. -/// Is there a better way that does not let const bleed all over? -/// -/// TODO: Handle strided data from the Conduit node. - -template -std::enable_if_t Node_to_ArrayView_single_int8(const conduit::Node &n, FuncType &&func) -{ - const auto size = n.dtype().number_of_elements(); - axom::ArrayView view(const_cast(n.as_int8_ptr()), size); - func(view); -} - -template -std::enable_if_t Node_to_ArrayView_single_int8(const conduit::Node &AXOM_UNUSED_PARAM(n), - FuncType &&AXOM_UNUSED_PARAM(func)) -{ - SLIC_WARNING("Unsupported int8 node."); -} - -template -std::enable_if_t Node_to_ArrayView_single_int8(conduit::Node &n, FuncType &&func) -{ - const auto size = n.dtype().number_of_elements(); - axom::ArrayView view(n.as_int8_ptr(), size); - func(view); -} - -template -std::enable_if_t Node_to_ArrayView_single_int8(conduit::Node &AXOM_UNUSED_PARAM(n), - FuncType &&AXOM_UNUSED_PARAM(func)) -{ - SLIC_WARNING("Unsupported int8 node."); -} - -template -std::enable_if_t Node_to_ArrayView_single_int16(const conduit::Node &n, FuncType &&func) -{ - const auto size = n.dtype().number_of_elements(); - axom::ArrayView view(const_cast(n.as_int16_ptr()), size); - func(view); -} - -template -std::enable_if_t Node_to_ArrayView_single_int16( - const conduit::Node &AXOM_UNUSED_PARAM(n), - FuncType &&AXOM_UNUSED_PARAM(func)) -{ - SLIC_WARNING("Unsupported int16 node."); -} - -template -std::enable_if_t Node_to_ArrayView_single_int16(conduit::Node &n, FuncType &&func) -{ - const auto size = n.dtype().number_of_elements(); - axom::ArrayView view(n.as_int16_ptr(), size); - func(view); -} - -template -std::enable_if_t Node_to_ArrayView_single_int16(conduit::Node &AXOM_UNUSED_PARAM(n), - FuncType &&AXOM_UNUSED_PARAM(func)) -{ - SLIC_WARNING("Unsupported int16 node."); -} - -template -std::enable_if_t Node_to_ArrayView_single_int32(const conduit::Node &n, FuncType &&func) -{ - const auto size = n.dtype().number_of_elements(); - axom::ArrayView view(const_cast(n.as_int32_ptr()), size); - func(view); -} - -template -std::enable_if_t Node_to_ArrayView_single_int32( - const conduit::Node &AXOM_UNUSED_PARAM(n), - FuncType &&AXOM_UNUSED_PARAM(func)) -{ - SLIC_WARNING("Unsupported int32 node."); -} - -template -std::enable_if_t Node_to_ArrayView_single_int32(conduit::Node &n, FuncType &&func) -{ - const auto size = n.dtype().number_of_elements(); - axom::ArrayView view(n.as_int32_ptr(), size); - func(view); -} - -template -std::enable_if_t Node_to_ArrayView_single_int32(conduit::Node &AXOM_UNUSED_PARAM(n), - FuncType &&AXOM_UNUSED_PARAM(func)) -{ - SLIC_WARNING("Unsupported int32 node."); -} - -template -std::enable_if_t Node_to_ArrayView_single_int64(const conduit::Node &n, FuncType &&func) -{ - const auto size = n.dtype().number_of_elements(); - axom::ArrayView view(const_cast(n.as_int64_ptr()), size); - func(view); -} - -template -std::enable_if_t Node_to_ArrayView_single_int64( - const conduit::Node &AXOM_UNUSED_PARAM(n), - FuncType &&AXOM_UNUSED_PARAM(func)) -{ - SLIC_WARNING("Unsupported int64 node."); -} - -template -std::enable_if_t Node_to_ArrayView_single_int64(conduit::Node &n, FuncType &&func) -{ - const auto size = n.dtype().number_of_elements(); - axom::ArrayView view(n.as_int64_ptr(), size); - func(view); -} - -template -std::enable_if_t Node_to_ArrayView_single_int64(conduit::Node &AXOM_UNUSED_PARAM(n), - FuncType &&AXOM_UNUSED_PARAM(func)) -{ - SLIC_WARNING("Unsupported int64 node."); -} - -template -std::enable_if_t Node_to_ArrayView_single_uint8(const conduit::Node &n, FuncType &&func) -{ - const auto size = n.dtype().number_of_elements(); - axom::ArrayView view(const_cast(n.as_uint8_ptr()), size); - func(view); -} - -template -std::enable_if_t Node_to_ArrayView_single_uint8( - const conduit::Node &AXOM_UNUSED_PARAM(n), - FuncType &&AXOM_UNUSED_PARAM(func)) -{ - SLIC_WARNING("Unsupported uint8 node."); -} - -template -std::enable_if_t Node_to_ArrayView_single_uint8(conduit::Node &n, FuncType &&func) -{ - const auto size = n.dtype().number_of_elements(); - axom::ArrayView view(n.as_uint8_ptr(), size); - func(view); -} - -template -std::enable_if_t Node_to_ArrayView_single_uint8(conduit::Node &AXOM_UNUSED_PARAM(n), - FuncType &&AXOM_UNUSED_PARAM(func)) -{ - SLIC_WARNING("Unsupported uint8 node."); -} - -template -std::enable_if_t Node_to_ArrayView_single_uint16(const conduit::Node &n, - FuncType &&func) -{ - const auto size = n.dtype().number_of_elements(); - axom::ArrayView view(const_cast(n.as_uint16_ptr()), size); - func(view); -} - -template -std::enable_if_t Node_to_ArrayView_single_uint16( - const conduit::Node &AXOM_UNUSED_PARAM(n), - FuncType &&AXOM_UNUSED_PARAM(func)) -{ - SLIC_WARNING("Unsupported uint16 node."); -} - -template -std::enable_if_t Node_to_ArrayView_single_uint16(conduit::Node &n, FuncType &&func) -{ - const auto size = n.dtype().number_of_elements(); - axom::ArrayView view(n.as_uint16_ptr(), size); - func(view); -} +// NOTE: Const Conduit nodes still expose mutable ArrayViews for compatibility. -template -std::enable_if_t Node_to_ArrayView_single_uint16(conduit::Node &AXOM_UNUSED_PARAM(n), - FuncType &&AXOM_UNUSED_PARAM(func)) -{ - SLIC_WARNING("Unsupported uint16 node."); -} - -template -std::enable_if_t Node_to_ArrayView_single_uint32(const conduit::Node &n, - FuncType &&func) -{ - const auto size = n.dtype().number_of_elements(); - axom::ArrayView view(const_cast(n.as_uint32_ptr()), size); - func(view); -} +#define AXOM_BUMP_NODE_ARRAY_VIEW_TYPES(MACRO) \ + MACRO(conduit::int8, INT8_ID, is_int8, as_int8_ptr, "int8") \ + MACRO(conduit::int16, INT16_ID, is_int16, as_int16_ptr, "int16") \ + MACRO(conduit::int32, INT32_ID, is_int32, as_int32_ptr, "int32") \ + MACRO(conduit::int64, INT64_ID, is_int64, as_int64_ptr, "int64") \ + MACRO(conduit::uint8, UINT8_ID, is_uint8, as_uint8_ptr, "uint8") \ + MACRO(conduit::uint16, UINT16_ID, is_uint16, as_uint16_ptr, "uint16") \ + MACRO(conduit::uint32, UINT32_ID, is_uint32, as_uint32_ptr, "uint32") \ + MACRO(conduit::uint64, UINT64_ID, is_uint64, as_uint64_ptr, "uint64") \ + MACRO(conduit::float32, FLOAT32_ID, is_float32, as_float32_ptr, "float32") \ + MACRO(conduit::float64, FLOAT64_ID, is_float64, as_float64_ptr, "float64") -template -std::enable_if_t Node_to_ArrayView_single_uint32( - const conduit::Node &AXOM_UNUSED_PARAM(n), - FuncType &&AXOM_UNUSED_PARAM(func)) -{ - SLIC_WARNING("Unsupported uint32 node."); -} - -template -std::enable_if_t Node_to_ArrayView_single_uint32(conduit::Node &n, FuncType &&func) -{ - const auto size = n.dtype().number_of_elements(); - axom::ArrayView view(n.as_uint32_ptr(), size); - func(view); -} - -template -std::enable_if_t Node_to_ArrayView_single_uint32(conduit::Node &AXOM_UNUSED_PARAM(n), - FuncType &&AXOM_UNUSED_PARAM(func)) -{ - SLIC_WARNING("Unsupported uint32 node."); -} - -template -std::enable_if_t Node_to_ArrayView_single_uint64(const conduit::Node &n, - FuncType &&func) -{ - const auto size = n.dtype().number_of_elements(); - axom::ArrayView view(const_cast(n.as_uint64_ptr()), size); - func(view); -} - -template -std::enable_if_t Node_to_ArrayView_single_uint64( - const conduit::Node &AXOM_UNUSED_PARAM(n), - FuncType &&AXOM_UNUSED_PARAM(func)) -{ - SLIC_WARNING("Unsupported uint64 node."); -} - -template -std::enable_if_t Node_to_ArrayView_single_uint64(conduit::Node &n, FuncType &&func) -{ - const auto size = n.dtype().number_of_elements(); - axom::ArrayView view(n.as_uint64_ptr(), size); - func(view); -} - -template -std::enable_if_t Node_to_ArrayView_single_uint64(conduit::Node &AXOM_UNUSED_PARAM(n), - FuncType &&AXOM_UNUSED_PARAM(func)) -{ - SLIC_WARNING("Unsupported uint64 node."); -} +template +struct NodeTypeTraits; -template -std::enable_if_t Node_to_ArrayView_single_float32(const conduit::Node &n, - FuncType &&func) -{ - const auto size = n.dtype().number_of_elements(); - axom::ArrayView view(const_cast(n.as_float32_ptr()), size); - func(view); -} +#define AXOM_BUMP_DECLARE_NODE_TYPE_TRAITS(CppType, DTypeID, IsMethod, PtrMethod, Label) \ + template <> \ + struct NodeTypeTraits \ + { \ + static bool matches(const conduit::Node &n) { return n.dtype().IsMethod(); } \ + static CppType *data(conduit::Node &n) { return n.PtrMethod(); } \ + static CppType *data(const conduit::Node &n) { return const_cast(n.PtrMethod()); } \ + static const char *label() { return Label; } \ + static int dtypeId() { return conduit::DataType::DTypeID; } \ + }; -template -std::enable_if_t Node_to_ArrayView_single_float32( - const conduit::Node &AXOM_UNUSED_PARAM(n), - FuncType &&AXOM_UNUSED_PARAM(func)) -{ - SLIC_WARNING("Unsupported float32 node."); -} +AXOM_BUMP_NODE_ARRAY_VIEW_TYPES(AXOM_BUMP_DECLARE_NODE_TYPE_TRAITS) -template -std::enable_if_t Node_to_ArrayView_single_float32(conduit::Node &n, FuncType &&func) -{ - const auto size = n.dtype().number_of_elements(); - axom::ArrayView view(n.as_float32_ptr(), size); - func(view); -} +#undef AXOM_BUMP_DECLARE_NODE_TYPE_TRAITS -template -std::enable_if_t Node_to_ArrayView_single_float32(conduit::Node &AXOM_UNUSED_PARAM(n), - FuncType &&AXOM_UNUSED_PARAM(func)) +template +std::enable_if_t invoke_single_array_view(NodeType &n, FuncType &&func) { - SLIC_WARNING("Unsupported float32 node."); + func(axom::bump::utilities::detail::make_conduit_array_view(n)); } -template -std::enable_if_t Node_to_ArrayView_single_float64(const conduit::Node &n, - FuncType &&func) +template +std::enable_if_t invoke_single_array_view(NodeType &AXOM_UNUSED_PARAM(n), + FuncType &&AXOM_UNUSED_PARAM(func)) { - const auto size = n.dtype().number_of_elements(); - axom::ArrayView view(const_cast(n.as_float64_ptr()), size); - func(view); + SLIC_WARNING("Unsupported " << NodeTypeTraits::label() << " node."); } -template -std::enable_if_t Node_to_ArrayView_single_float64( - const conduit::Node &AXOM_UNUSED_PARAM(n), - FuncType &&AXOM_UNUSED_PARAM(func)) +template +std::enable_if_t invoke_same_array_views(FuncType &&func, NodeTypes &&...nodes) { - SLIC_WARNING("Unsupported float64 node."); + func(axom::bump::utilities::detail::make_conduit_array_view(nodes)...); } -template -std::enable_if_t Node_to_ArrayView_single_float64(conduit::Node &n, FuncType &&func) -{ - const auto size = n.dtype().number_of_elements(); - axom::ArrayView view(n.as_float64_ptr(), size); - func(view); -} +template +std::enable_if_t invoke_same_array_views(FuncType &&AXOM_UNUSED_PARAM(func), + NodeTypes &&...AXOM_UNUSED_PARAM(nodes)) +{ } -template -std::enable_if_t Node_to_ArrayView_single_float64(conduit::Node &AXOM_UNUSED_PARAM(n), - FuncType &&AXOM_UNUSED_PARAM(func)) +template +void dispatch_single_array_view(NodeType &n, FuncType &&func) { - SLIC_WARNING("Unsupported float64 node."); -} - -template -void Node_to_ArrayView_single(const conduit::Node &n, FuncType &&func) -{ - /* Later, with C++17, we can do this instead of using all of the SFINAE functions above: - if constexpr (type_selected(Types, conduit::DataType::INT8_ID)) - { - if(n.dtype().is_int8()) - { - axom::ArrayView view(n.as_int8_ptr(), size); - func(view); - } - } - */ - - if(n.dtype().is_int8()) - { - Node_to_ArrayView_single_int8(n, func); - } - else if(n.dtype().is_int16()) - { - Node_to_ArrayView_single_int16(n, func); - } - else if(n.dtype().is_int32()) - { - Node_to_ArrayView_single_int32(n, func); - } - else if(n.dtype().is_int64()) - { - Node_to_ArrayView_single_int64(n, func); - } - else if(n.dtype().is_uint8()) - { - Node_to_ArrayView_single_uint8(n, func); - } - else if(n.dtype().is_uint16()) - { - Node_to_ArrayView_single_uint16(n, func); - } - else if(n.dtype().is_uint32()) - { - Node_to_ArrayView_single_uint32(n, func); - } - else if(n.dtype().is_uint64()) - { - Node_to_ArrayView_single_uint64(n, func); - } - else if(n.dtype().is_float32()) - { - Node_to_ArrayView_single_float32(n, func); - } - else if(n.dtype().is_float64()) - { - Node_to_ArrayView_single_float64(n, func); - } +#define AXOM_BUMP_DISPATCH_SINGLE(CppType, DTypeID, IsMethod, PtrMethod, Label) \ + if(NodeTypeTraits::matches(n)) \ + { \ + invoke_single_array_view( \ + n, \ + std::forward(func)); \ + } \ else + + AXOM_BUMP_NODE_ARRAY_VIEW_TYPES(AXOM_BUMP_DISPATCH_SINGLE) { SLIC_ERROR("Unsupported data type " << n.dtype().name() << " on node " << n.path()); } + +#undef AXOM_BUMP_DISPATCH_SINGLE } -template -void Node_to_ArrayView_single(conduit::Node &n, FuncType &&func) +template +void dispatch_same_array_views(FirstNodeType &first, FuncType &&func, NodeTypes &&...nodes) { - if(n.dtype().is_int8()) - { - Node_to_ArrayView_single_int8(n, func); - } - else if(n.dtype().is_int16()) - { - Node_to_ArrayView_single_int16(n, func); - } - else if(n.dtype().is_int32()) - { - Node_to_ArrayView_single_int32(n, func); - } - else if(n.dtype().is_int64()) - { - Node_to_ArrayView_single_int64(n, func); - } - else if(n.dtype().is_uint8()) - { - Node_to_ArrayView_single_uint8(n, func); - } - else if(n.dtype().is_uint16()) - { - Node_to_ArrayView_single_uint16(n, func); - } - else if(n.dtype().is_uint32()) - { - Node_to_ArrayView_single_uint32(n, func); - } - else if(n.dtype().is_uint64()) - { - Node_to_ArrayView_single_uint64(n, func); - } - else if(n.dtype().is_float32()) - { - Node_to_ArrayView_single_float32(n, func); - } - else if(n.dtype().is_float64()) - { - Node_to_ArrayView_single_float64(n, func); - } +#define AXOM_BUMP_DISPATCH_SAME(CppType, DTypeID, IsMethod, PtrMethod, Label) \ + if(NodeTypeTraits::matches(first)) \ + { \ + invoke_same_array_views( \ + std::forward(func), \ + std::forward(nodes)...); \ + } \ else + + AXOM_BUMP_NODE_ARRAY_VIEW_TYPES(AXOM_BUMP_DISPATCH_SAME) { - SLIC_ERROR("Unsupported data type " << n.dtype().name() << " on node " << n.path()); + SLIC_ERROR("Unsupported data type " << first.dtype().name() << " on node " << first.path()); } -} -template -void Node_to_ArrayView_internal(FuncType &&func, Delimiter, View &...views) -{ - func(views...); +#undef AXOM_BUMP_DISPATCH_SAME } -template -void Node_to_ArrayView_internal(const conduit::Node &first, Args &&...args) +template +void nodeToArrayViewInternal(FuncType &&func, Delimiter, ViewTypes... views) { - Node_to_ArrayView_single(first, [&](auto view) { - Node_to_ArrayView_internal(args..., view); - }); + func(views...); } -template -void Node_to_ArrayView_internal(conduit::Node &first, Args &&...args) +template +void nodeToArrayViewInternal(NodeType &first, Args &&...args) { - Node_to_ArrayView_single(first, [&](auto view) { - Node_to_ArrayView_internal(args..., view); + dispatch_single_array_view(first, [&](auto view) { + nodeToArrayViewInternal(std::forward(args)..., view); }); } -//------------------------------------------------------------------------------ -/// NOTE: handle const conduit::Node& better. For now, const_cast. - -template -std::enable_if_t Node_to_ArrayView_same_internal_int8(FuncType &&func, Args &&...args) -{ - func(axom::ArrayView(const_cast(args.as_int8_ptr()), - args.dtype().number_of_elements())...); -} - -template -std::enable_if_t Node_to_ArrayView_same_internal_int8( - FuncType &&AXOM_UNUSED_PARAM(func), - Args &&...AXOM_UNUSED_PARAM(args)) -{ } - -template -std::enable_if_t Node_to_ArrayView_same_internal_int16(FuncType &&func, Args &&...args) -{ - func(axom::ArrayView(const_cast(args.as_int16_ptr()), - args.dtype().number_of_elements())...); -} - -template -std::enable_if_t Node_to_ArrayView_same_internal_int16( - FuncType &&AXOM_UNUSED_PARAM(func), - Args &&...AXOM_UNUSED_PARAM(args)) -{ } - -template -std::enable_if_t Node_to_ArrayView_same_internal_int32(FuncType &&func, Args &&...args) +template +void nodeToArrayViewSameInternal(FuncType &&func, Delimiter, FirstNode &first, Args &&...args) { - func(axom::ArrayView(const_cast(args.as_int32_ptr()), - args.dtype().number_of_elements())...); + dispatch_same_array_views(first, + std::forward(func), + first, + std::forward(args)...); } -template -std::enable_if_t Node_to_ArrayView_same_internal_int32( - FuncType &&AXOM_UNUSED_PARAM(func), - Args &&...AXOM_UNUSED_PARAM(args)) -{ } - -template -std::enable_if_t Node_to_ArrayView_same_internal_int64(FuncType &&func, Args &&...args) +template +void nodeToArrayViewSameInternal(FirstNode &first, Args &&...args) { - func(axom::ArrayView(const_cast(args.as_int64_ptr()), - args.dtype().number_of_elements())...); + nodeToArrayViewSameInternal(std::forward(args)..., first); } -template -std::enable_if_t Node_to_ArrayView_same_internal_int64( - FuncType &&AXOM_UNUSED_PARAM(func), - Args &&...AXOM_UNUSED_PARAM(args)) -{ } - -template -std::enable_if_t Node_to_ArrayView_same_internal_uint8(FuncType &&func, Args &&...args) -{ - func(axom::ArrayView(const_cast(args.as_uint8_ptr()), - args.dtype().number_of_elements())...); -} - -template -std::enable_if_t Node_to_ArrayView_same_internal_uint8( - FuncType &&AXOM_UNUSED_PARAM(func), - Args &&...AXOM_UNUSED_PARAM(args)) -{ } - -template -std::enable_if_t Node_to_ArrayView_same_internal_uint16(FuncType &&func, Args &&...args) -{ - func(axom::ArrayView(const_cast(args.as_uint16_ptr()), - args.dtype().number_of_elements())...); -} - -template -std::enable_if_t Node_to_ArrayView_same_internal_uint16( - FuncType &&AXOM_UNUSED_PARAM(func), - Args &&...AXOM_UNUSED_PARAM(args)) -{ } - -template -std::enable_if_t Node_to_ArrayView_same_internal_uint32(FuncType &&func, Args &&...args) -{ - func(axom::ArrayView(const_cast(args.as_uint32_ptr()), - args.dtype().number_of_elements())...); -} - -template -std::enable_if_t Node_to_ArrayView_same_internal_uint32( - FuncType &&AXOM_UNUSED_PARAM(func), - Args &&...AXOM_UNUSED_PARAM(args)) -{ } - -template -std::enable_if_t Node_to_ArrayView_same_internal_uint64(FuncType &&func, Args &&...args) -{ - func(axom::ArrayView(const_cast(args.as_uint64_ptr()), - args.dtype().number_of_elements())...); -} - -template -std::enable_if_t Node_to_ArrayView_same_internal_uint64( - FuncType &&AXOM_UNUSED_PARAM(func), - Args &&...AXOM_UNUSED_PARAM(args)) -{ } - -template -std::enable_if_t Node_to_ArrayView_same_internal_float32(FuncType &&func, - Args &&...args) -{ - func(axom::ArrayView(const_cast(args.as_float32_ptr()), - args.dtype().number_of_elements())...); -} - -template -std::enable_if_t Node_to_ArrayView_same_internal_float32( - FuncType &&AXOM_UNUSED_PARAM(func), - Args &&...AXOM_UNUSED_PARAM(args)) -{ } - -template -std::enable_if_t Node_to_ArrayView_same_internal_float64(FuncType &&func, - Args &&...args) -{ - func(axom::ArrayView(const_cast(args.as_float64_ptr()), - args.dtype().number_of_elements())...); -} - -template -std::enable_if_t Node_to_ArrayView_same_internal_float64( - FuncType &&AXOM_UNUSED_PARAM(func), - Args &&...AXOM_UNUSED_PARAM(args)) -{ } - -template -void Node_to_ArrayView_same_internal(FuncType &&func, - Delimiter, - const conduit::Node &first, - Args &&...args) -{ - if(first.dtype().is_int8()) - { - Node_to_ArrayView_same_internal_int8(func, - first, - args...); - } - else if(first.dtype().is_int16()) - { - Node_to_ArrayView_same_internal_int16(func, - first, - args...); - } - else if(first.dtype().is_int32()) - { - Node_to_ArrayView_same_internal_int32(func, - first, - args...); - } - else if(first.dtype().is_int64()) - { - Node_to_ArrayView_same_internal_int64(func, - first, - args...); - } - else if(first.dtype().is_uint8()) - { - Node_to_ArrayView_same_internal_uint8(func, - first, - args...); - } - else if(first.dtype().is_uint16()) - { - Node_to_ArrayView_same_internal_uint16( - func, - first, - args...); - } - else if(first.dtype().is_uint32()) - { - Node_to_ArrayView_same_internal_uint32( - func, - first, - args...); - } - else if(first.dtype().is_uint64()) - { - Node_to_ArrayView_same_internal_uint64( - func, - first, - args...); - } - else if(first.dtype().is_float32()) - { - Node_to_ArrayView_same_internal_float32( - func, - first, - args...); - } - else if(first.dtype().is_float64()) - { - Node_to_ArrayView_same_internal_float64( - func, - first, - args...); - } - else - { - SLIC_ERROR("Unsupported data type " << first.dtype().name() << " on node " << first.path()); - } -} - -template -void Node_to_ArrayView_same_internal(FuncType &&func, Delimiter, conduit::Node &first, Args &&...args) -{ - if(first.dtype().is_int8()) - { - Node_to_ArrayView_same_internal_int8(func, - first, - args...); - } - else if(first.dtype().is_int16()) - { - Node_to_ArrayView_same_internal_int16(func, - first, - args...); - } - else if(first.dtype().is_int32()) - { - Node_to_ArrayView_same_internal_int32(func, - first, - args...); - } - else if(first.dtype().is_int64()) - { - Node_to_ArrayView_same_internal_int64(func, - first, - args...); - } - else if(first.dtype().is_uint8()) - { - Node_to_ArrayView_same_internal_uint8(func, - first, - args...); - } - else if(first.dtype().is_uint16()) - { - Node_to_ArrayView_same_internal_uint16( - func, - first, - args...); - } - else if(first.dtype().is_uint32()) - { - Node_to_ArrayView_same_internal_uint32( - func, - first, - args...); - } - else if(first.dtype().is_uint64()) - { - Node_to_ArrayView_same_internal_uint64( - func, - first, - args...); - } - else if(first.dtype().is_float32()) - { - Node_to_ArrayView_same_internal_float32( - func, - first, - args...); - } - else if(first.dtype().is_float64()) - { - Node_to_ArrayView_same_internal_float64( - func, - first, - args...); - } - else - { - SLIC_ERROR("Unsupported data type " << first.dtype().name() << " on node " << first.path()); - } -} - -/// Reorder args -template -void Node_to_ArrayView_same_internal(const conduit::Node &first, Args &&...args) -{ - Node_to_ArrayView_same_internal(args..., first); -} - -template -void Node_to_ArrayView_same_internal(conduit::Node &first, Args &&...args) -{ - Node_to_ArrayView_same_internal(args..., first); -} +#undef AXOM_BUMP_NODE_ARRAY_VIEW_TYPES } // namespace detail -//------------------------------------------------------------------------------ -// Node to ArrayView. Handle all types. -//------------------------------------------------------------------------------ - /*! * \brief Convert a series of Conduit nodes to axom::ArrayView and pass the concrete * views to a lambda function passed as the last argument. @@ -845,19 +218,18 @@ void Node_to_ArrayView_same_internal(conduit::Node &first, Args &&...args) * \param args A sequence of Conduit nodes, followed by a lambda that can accept * the same number of views of any type. * - * Node_to_ArrayView(node1, node2, [](auto &view1, auto &view2) { }); - * + * nodeToArrayView(node1, node2, [](auto &view1, auto &view2) { }); */ template -void Node_to_ArrayView(const conduit::Node &first, Args &&...args) +void nodeToArrayView(const conduit::Node &first, Args &&...args) { - detail::Node_to_ArrayView_internal(first, args..., detail::ArgumentDelimiter); + detail::nodeToArrayViewInternal(first, std::forward(args)..., detail::ArgumentDelimiter); } template -void Node_to_ArrayView(conduit::Node &first, Args &&...args) +void nodeToArrayView(conduit::Node &first, Args &&...args) { - detail::Node_to_ArrayView_internal(first, args..., detail::ArgumentDelimiter); + detail::nodeToArrayViewInternal(first, std::forward(args)..., detail::ArgumentDelimiter); } /*! @@ -872,90 +244,82 @@ void Node_to_ArrayView(conduit::Node &first, Args &&...args) * \param args A sequence of Conduit nodes, followed by a lambda that can accept * the same number of views of any type. * - * Node_to_ArrayView_same(node1, node2, [](auto &view1, auto &view2) { }); - * + * nodeToArrayViewSame(node1, node2, [](auto &view1, auto &view2) { }); */ template -void Node_to_ArrayView_same(const conduit::Node &first, Args &&...args) +void nodeToArrayViewSame(const conduit::Node &first, Args &&...args) { - detail::Node_to_ArrayView_same_internal(first, args..., detail::ArgumentDelimiter); + detail::nodeToArrayViewSameInternal(first, std::forward(args)..., detail::ArgumentDelimiter); } template -void Node_to_ArrayView_same(conduit::Node &first, Args &&...args) +void nodeToArrayViewSame(conduit::Node &first, Args &&...args) { - detail::Node_to_ArrayView_same_internal(first, args..., detail::ArgumentDelimiter); + detail::nodeToArrayViewSameInternal(first, std::forward(args)..., detail::ArgumentDelimiter); } -//------------------------------------------------------------------------------ -// Index Node to ArrayView. Handle types used for indexing. -//------------------------------------------------------------------------------ - template -void IndexNode_to_ArrayView(const conduit::Node &first, Args &&...args) +void indexNodeToArrayView(const conduit::Node &first, Args &&...args) { - detail::Node_to_ArrayView_internal(first, - args..., - detail::ArgumentDelimiter); + detail::nodeToArrayViewInternal(first, + std::forward(args)..., + detail::ArgumentDelimiter); } template -void IndexNode_to_ArrayView(conduit::Node &first, Args &&...args) +void indexNodeToArrayView(conduit::Node &first, Args &&...args) { - detail::Node_to_ArrayView_internal(first, - args..., - detail::ArgumentDelimiter); + detail::nodeToArrayViewInternal(first, + std::forward(args)..., + detail::ArgumentDelimiter); } template -void IndexNode_to_ArrayView_same(const conduit::Node &first, Args &&...args) +void indexNodeToArrayViewSame(const conduit::Node &first, Args &&...args) { - detail::Node_to_ArrayView_same_internal(first, - args..., - detail::ArgumentDelimiter); + detail::nodeToArrayViewSameInternal(first, + std::forward(args)..., + detail::ArgumentDelimiter); } template -void IndexNode_to_ArrayView_same(conduit::Node &first, Args &&...args) +void indexNodeToArrayViewSame(conduit::Node &first, Args &&...args) { - detail::Node_to_ArrayView_same_internal(first, - args..., - detail::ArgumentDelimiter); + detail::nodeToArrayViewSameInternal(first, + std::forward(args)..., + detail::ArgumentDelimiter); } -//------------------------------------------------------------------------------ -// Float Node to ArrayView. Handle float types. -//------------------------------------------------------------------------------ template -void FloatNode_to_ArrayView(const conduit::Node &first, Args &&...args) +void floatNodeToArrayView(const conduit::Node &first, Args &&...args) { - detail::Node_to_ArrayView_internal(first, - args..., - detail::ArgumentDelimiter); + detail::nodeToArrayViewInternal(first, + std::forward(args)..., + detail::ArgumentDelimiter); } template -void FloatNode_to_ArrayView(conduit::Node &first, Args &&...args) +void floatNodeToArrayView(conduit::Node &first, Args &&...args) { - detail::Node_to_ArrayView_internal(first, - args..., - detail::ArgumentDelimiter); + detail::nodeToArrayViewInternal(first, + std::forward(args)..., + detail::ArgumentDelimiter); } template -void FloatNode_to_ArrayView_same(const conduit::Node &first, Args &&...args) +void floatNodeToArrayViewSame(const conduit::Node &first, Args &&...args) { - detail::Node_to_ArrayView_same_internal(first, - args..., - detail::ArgumentDelimiter); + detail::nodeToArrayViewSameInternal(first, + std::forward(args)..., + detail::ArgumentDelimiter); } template -void FloatNode_to_ArrayView_same(conduit::Node &first, Args &&...args) +void floatNodeToArrayViewSame(conduit::Node &first, Args &&...args) { - detail::Node_to_ArrayView_same_internal(first, - args..., - detail::ArgumentDelimiter); + detail::nodeToArrayViewSameInternal(first, + std::forward(args)..., + detail::ArgumentDelimiter); } } // namespace views diff --git a/src/axom/bump/views/RectilinearCoordsetView.hpp b/src/axom/bump/views/RectilinearCoordsetView.hpp index 99b4f3a8ed..b6d42a5ee9 100644 --- a/src/axom/bump/views/RectilinearCoordsetView.hpp +++ b/src/axom/bump/views/RectilinearCoordsetView.hpp @@ -111,7 +111,7 @@ class RectilinearCoordsetView2 AXOM_HOST_DEVICE PointType getPoint(IndexType vertex_index) const { - return getPoint(m_indexing.IndexToLogicalIndex(vertex_index)); + return getPoint(m_indexing.indexToLogicalIndex(vertex_index)); } /*! @@ -134,7 +134,7 @@ class RectilinearCoordsetView2 AXOM_HOST_DEVICE PointType operator[](IndexType vertex_index) const { - return getPoint(m_indexing.IndexToLogicalIndex(vertex_index)); + return getPoint(m_indexing.indexToLogicalIndex(vertex_index)); } private: @@ -238,7 +238,7 @@ class RectilinearCoordsetView3 AXOM_HOST_DEVICE PointType getPoint(IndexType vertex_index) const { - return getPoint(m_indexing.IndexToLogicalIndex(vertex_index)); + return getPoint(m_indexing.indexToLogicalIndex(vertex_index)); } /*! @@ -261,7 +261,7 @@ class RectilinearCoordsetView3 AXOM_HOST_DEVICE PointType operator[](IndexType vertex_index) const { - return getPoint(m_indexing.IndexToLogicalIndex(vertex_index)); + return getPoint(m_indexing.indexToLogicalIndex(vertex_index)); } private: diff --git a/src/axom/bump/views/Shapes.hpp b/src/axom/bump/views/Shapes.hpp index dd36d5f093..aa41c74b69 100644 --- a/src/axom/bump/views/Shapes.hpp +++ b/src/axom/bump/views/Shapes.hpp @@ -41,6 +41,19 @@ enum Invalid_ShapeID = 20 }; +/*! + * \brief Determine whether a value is a valid ShapeID. + * + * \param shapeID The value to test for validity. + * + * \return True if the value is a valid ShapeID; False otherwise. + */ +template +AXOM_HOST_DEVICE constexpr bool isValidShapeID(T shapeID) +{ + return shapeID >= static_cast(Point_ShapeID) && shapeID <= static_cast(Mixed_ShapeID); +} + /// prototype AXOM_HOST_DEVICE constexpr IndexType shapeDimension(int shapeId); @@ -548,8 +561,8 @@ struct PolygonShape : public PolygonTraits using ConnectivityType = ConnType; using ConnectivityView = axom::ArrayView; using ConnectivityStorage = ConnectivityType; - using ConnectivityStorageRef = ConnectivityType &; - using ConnectivityStorageConstRef = const ConnectivityType &; + using ConnectivityStorageRef = ConnectivityView &; + using ConnectivityStorageConstRef = const ConnectivityView &; /*! * \brief Construct a shape. @@ -831,7 +844,7 @@ struct VariableShape AXOM_HOST_DEVICE VariableShape(int shapeId, ConnectivityStorageConstRef ids) : m_shapeId(shapeId), m_ids(ids) { - SLIC_ASSERT(shapeId >= Point_ShapeID && shapeId <= Hex_ShapeID); + SLIC_ASSERT(isValidShapeID(shapeId)); } /*! @@ -1091,6 +1104,20 @@ struct VariableShape AXOM_HOST_DEVICE constexpr static const char *name() { return "mixed"; } + /*! + * \brief Get the storage for the ids that make up this shape. + * + * \return The container for the ids that make up this shape. + */ + AXOM_HOST_DEVICE ConnectivityStorageRef getIdsStorage() { return m_ids; } + + /*! + * \brief Get the storage for the ids that make up this shape. + * + * \return The container for the ids that make up this shape. + */ + AXOM_HOST_DEVICE ConnectivityStorageConstRef getIdsStorage() const { return m_ids; } + private: int m_shapeId; ConnectivityStorage m_ids; @@ -1131,19 +1158,6 @@ inline int shapeNameToID(const std::string &name) return id; } -/*! - * \brief Determine whether a value is a valid ShapeID. - * - * \param shapeID The value to test for validity. - * - * \return True if the value is a valid ShapeID; False otherwise. - */ -template -AXOM_HOST_DEVICE constexpr bool isValidShapeID(T shapeID) -{ - return shapeID >= static_cast(Point_ShapeID) && shapeID <= static_cast(Mixed_ShapeID); -} - /*! * \brief Return the dimension for the specified shape id. * diff --git a/src/axom/bump/views/StridedStructuredIndexing.hpp b/src/axom/bump/views/StridedStructuredIndexing.hpp index 574f6e2478..91fc40c333 100644 --- a/src/axom/bump/views/StridedStructuredIndexing.hpp +++ b/src/axom/bump/views/StridedStructuredIndexing.hpp @@ -144,7 +144,7 @@ struct StridedStructuredIndexing * \return The global index. */ AXOM_HOST_DEVICE - IndexType GlobalToGlobal(const LogicalIndex &global) const + IndexType globalToGlobal(const LogicalIndex &global) const { IndexType gl {}; for(int i = 0; i < NDIMS; i++) @@ -163,16 +163,16 @@ struct StridedStructuredIndexing */ /// @{ template - AXOM_HOST_DEVICE typename std::enable_if<_ndims == 1, LogicalIndex>::type GlobalToGlobal( + AXOM_HOST_DEVICE typename std::enable_if<_ndims == 1, LogicalIndex>::type globalToGlobal( IndexType global) const { LogicalIndex gl; gl[0] = global; - return global; + return gl; } template - AXOM_HOST_DEVICE typename std::enable_if<_ndims == 2, LogicalIndex>::type GlobalToGlobal( + AXOM_HOST_DEVICE typename std::enable_if<_ndims == 2, LogicalIndex>::type globalToGlobal( IndexType global) const { LogicalIndex gl; @@ -182,7 +182,7 @@ struct StridedStructuredIndexing } template - AXOM_HOST_DEVICE typename std::enable_if<_ndims == 3, LogicalIndex>::type GlobalToGlobal( + AXOM_HOST_DEVICE typename std::enable_if<_ndims == 3, LogicalIndex>::type globalToGlobal( IndexType global) const { LogicalIndex gl; @@ -191,6 +191,7 @@ struct StridedStructuredIndexing gl[2] = global / m_strides[2]; return gl; } + /// @} /*! @@ -199,7 +200,7 @@ struct StridedStructuredIndexing * \return local logical index. */ AXOM_HOST_DEVICE - LogicalIndex GlobalToLocal(const LogicalIndex &global) const + LogicalIndex globalToLocal(const LogicalIndex &global) const { LogicalIndex local(global); for(int i = 0; i < NDIMS; i++) @@ -217,9 +218,9 @@ struct StridedStructuredIndexing * \return The local index that corresponds to the \a local. */ AXOM_HOST_DEVICE - IndexType GlobalToLocal(IndexType global) const + IndexType globalToLocal(IndexType global) const { - return LogicalIndexToIndex(GlobalToLocal(GlobalToGlobal(global))); + return logicalIndexToIndex(globalToLocal(globalToGlobal(global))); } /*! @@ -228,7 +229,7 @@ struct StridedStructuredIndexing * \return global logical index. */ AXOM_HOST_DEVICE - LogicalIndex LocalToGlobal(const LogicalIndex &local) const + LogicalIndex localToGlobal(const LogicalIndex &local) const { LogicalIndex global(local); for(int i = 0; i < NDIMS; i++) @@ -244,9 +245,9 @@ struct StridedStructuredIndexing * \return local logical index. */ AXOM_HOST_DEVICE - IndexType LocalToGlobal(IndexType local) const + IndexType localToGlobal(IndexType local) const { - return GlobalToGlobal(LocalToGlobal(IndexToLogicalIndex(local))); + return globalToGlobal(localToGlobal(indexToLogicalIndex(local))); } /*! @@ -259,7 +260,7 @@ struct StridedStructuredIndexing /// @{ template - AXOM_HOST_DEVICE typename std::enable_if<_ndims == 1, LogicalIndex>::type IndexToLogicalIndex( + AXOM_HOST_DEVICE typename std::enable_if<_ndims == 1, LogicalIndex>::type indexToLogicalIndex( IndexType index) const { LogicalIndex logical; @@ -268,7 +269,7 @@ struct StridedStructuredIndexing } template - AXOM_HOST_DEVICE typename std::enable_if<_ndims == 2, LogicalIndex>::type IndexToLogicalIndex( + AXOM_HOST_DEVICE typename std::enable_if<_ndims == 2, LogicalIndex>::type indexToLogicalIndex( IndexType index) const { LogicalIndex logical; @@ -279,7 +280,7 @@ struct StridedStructuredIndexing } template - AXOM_HOST_DEVICE typename std::enable_if<_ndims == 3, LogicalIndex>::type IndexToLogicalIndex( + AXOM_HOST_DEVICE typename std::enable_if<_ndims == 3, LogicalIndex>::type indexToLogicalIndex( IndexType index) const { LogicalIndex logical; @@ -290,6 +291,7 @@ struct StridedStructuredIndexing logical[2] = index / nxy; return logical; } + /// @} /*! @@ -300,7 +302,7 @@ struct StridedStructuredIndexing * \return The index that corresponds to the \a logical index. */ AXOM_HOST_DEVICE - IndexType LogicalIndexToIndex(const LogicalIndex &logical) const + IndexType logicalIndexToIndex(const LogicalIndex &logical) const { IndexType index {}; IndexType stride {1}; @@ -338,7 +340,7 @@ struct StridedStructuredIndexing * \return True if the index is within the index, false otherwise. */ AXOM_HOST_DEVICE - bool contains(IndexType index) const { return contains(IndexToLogicalIndex(index)); } + bool contains(IndexType index) const { return contains(indexToLogicalIndex(index)); } /*! * \brief Expand the current StridedStructuredIndexing by one in each dimension. @@ -405,7 +407,7 @@ struct StridedStructuredIndexing IndexType clamp(IndexType index) const { - return LogicalIndexToIndex(clamp(IndexToLogicalIndex(index))); + return logicalIndexToIndex(clamp(indexToLogicalIndex(index))); } /// @} diff --git a/src/axom/bump/views/StructuredIndexing.hpp b/src/axom/bump/views/StructuredIndexing.hpp index 2a38eee67b..541088fc6f 100644 --- a/src/axom/bump/views/StructuredIndexing.hpp +++ b/src/axom/bump/views/StructuredIndexing.hpp @@ -116,9 +116,9 @@ class StructuredIndexing * \return The global index. */ AXOM_HOST_DEVICE - inline IndexType GlobalToGlobal(const LogicalIndex &global) const + inline IndexType globalToGlobal(const LogicalIndex &global) const { - return LogicalIndexToIndex(global); + return logicalIndexToIndex(global); } /*! @@ -127,7 +127,7 @@ class StructuredIndexing * \return The global logical index. */ AXOM_HOST_DEVICE - inline LogicalIndex GlobalToGlobal(IndexType global) const { return IndexToLogicalIndex(global); } + inline LogicalIndex globalToGlobal(IndexType global) const { return indexToLogicalIndex(global); } /*! * \brief Turn global logical index to local logical index. no-op. @@ -135,7 +135,7 @@ class StructuredIndexing * \return Same as the input in this case. */ AXOM_HOST_DEVICE - inline LogicalIndex GlobalToLocal(const LogicalIndex &index) const { return index; } + inline LogicalIndex globalToLocal(const LogicalIndex &index) const { return index; } /*! * \brief Turn global index to local index. no-op. @@ -143,7 +143,7 @@ class StructuredIndexing * \return Same as the input in this case. */ AXOM_HOST_DEVICE - inline IndexType GlobalToLocal(IndexType index) const { return index; } + inline IndexType globalToLocal(IndexType index) const { return index; } /*! * \brief Turn local logical index to global logical index. no-op. @@ -151,7 +151,7 @@ class StructuredIndexing * \return Same as the input in this case. */ AXOM_HOST_DEVICE - inline LogicalIndex LocalToGlobal(const LogicalIndex &index) const { return index; } + inline LogicalIndex localToGlobal(const LogicalIndex &index) const { return index; } /*! * \brief Turn local index to global index. no-op. @@ -159,7 +159,7 @@ class StructuredIndexing * \return Same as the input in this case. */ AXOM_HOST_DEVICE - inline IndexType LocalToGlobal(IndexType index) const { return index; } + inline IndexType localToGlobal(IndexType index) const { return index; } /*! * \brief Turn an index into a logical index. @@ -171,7 +171,7 @@ class StructuredIndexing /// @{ template - AXOM_HOST_DEVICE typename std::enable_if<_ndims == 1, LogicalIndex>::type IndexToLogicalIndex( + AXOM_HOST_DEVICE typename std::enable_if<_ndims == 1, LogicalIndex>::type indexToLogicalIndex( IndexType index) const { LogicalIndex logical; @@ -180,7 +180,7 @@ class StructuredIndexing } template - AXOM_HOST_DEVICE typename std::enable_if<_ndims == 2, LogicalIndex>::type IndexToLogicalIndex( + AXOM_HOST_DEVICE typename std::enable_if<_ndims == 2, LogicalIndex>::type indexToLogicalIndex( IndexType index) const { LogicalIndex logical; @@ -191,7 +191,7 @@ class StructuredIndexing } template - AXOM_HOST_DEVICE typename std::enable_if<_ndims == 3, LogicalIndex>::type IndexToLogicalIndex( + AXOM_HOST_DEVICE typename std::enable_if<_ndims == 3, LogicalIndex>::type indexToLogicalIndex( IndexType index) const { LogicalIndex logical; @@ -214,21 +214,21 @@ class StructuredIndexing */ /// @{ template - AXOM_HOST_DEVICE typename std::enable_if<_ndims == 1, IndexType>::type LogicalIndexToIndex( + AXOM_HOST_DEVICE typename std::enable_if<_ndims == 1, IndexType>::type logicalIndexToIndex( const LogicalIndex &logical) const { return logical[0]; } template - AXOM_HOST_DEVICE typename std::enable_if<_ndims == 2, IndexType>::type LogicalIndexToIndex( + AXOM_HOST_DEVICE typename std::enable_if<_ndims == 2, IndexType>::type logicalIndexToIndex( const LogicalIndex &logical) const { return logical[1] * m_dimensions[0] + logical[0]; } template - AXOM_HOST_DEVICE typename std::enable_if<_ndims == 3, IndexType>::type LogicalIndexToIndex( + AXOM_HOST_DEVICE typename std::enable_if<_ndims == 3, IndexType>::type logicalIndexToIndex( const LogicalIndex &logical) const { return (logical[2] * m_dimensions[1] * m_dimensions[0]) + (logical[1] * m_dimensions[0]) + @@ -263,7 +263,7 @@ class StructuredIndexing * \return True if the index is within the index, false otherwise. */ AXOM_HOST_DEVICE - bool contains(IndexType index) const { return contains(IndexToLogicalIndex(index)); } + bool contains(IndexType index) const { return contains(indexToLogicalIndex(index)); } /*! * \brief Expand the current StructuredIndexing by one in each dimension. @@ -306,7 +306,7 @@ class StructuredIndexing IndexType clamp(IndexType index) const { - return LogicalIndexToIndex(clamp(IndexToLogicalIndex(index))); + return logicalIndexToIndex(clamp(indexToLogicalIndex(index))); } /// @} diff --git a/src/axom/bump/views/StructuredTopologyView.hpp b/src/axom/bump/views/StructuredTopologyView.hpp index 9c036e95dd..83ed122820 100644 --- a/src/axom/bump/views/StructuredTopologyView.hpp +++ b/src/axom/bump/views/StructuredTopologyView.hpp @@ -129,13 +129,13 @@ class StructuredTopologyView { SLIC_ASSERT(zoneIndex < numberOfZones()); - const auto localLogical = m_zoneIndexing.IndexToLogicalIndex(zoneIndex); + const auto localLogical = m_zoneIndexing.indexToLogicalIndex(zoneIndex); const auto jp = m_nodeIndexing.jStride(); const auto kp = m_nodeIndexing.kStride(); Shape3D shape; auto &data = shape.getIdsStorage(); - data[0] = m_nodeIndexing.GlobalToGlobal(m_nodeIndexing.LocalToGlobal(localLogical)); + data[0] = m_nodeIndexing.globalToGlobal(m_nodeIndexing.localToGlobal(localLogical)); data[1] = data[0] + 1; data[2] = data[1] + jp; data[3] = data[2] - 1; @@ -161,12 +161,12 @@ class StructuredTopologyView { SLIC_ASSERT(zoneIndex < numberOfZones()); - const auto localLogical = m_zoneIndexing.IndexToLogicalIndex(zoneIndex); + const auto localLogical = m_zoneIndexing.indexToLogicalIndex(zoneIndex); const auto jp = m_nodeIndexing.jStride(); Shape2D shape; auto &data = shape.getIdsStorage(); - data[0] = m_nodeIndexing.GlobalToGlobal(m_nodeIndexing.LocalToGlobal(localLogical)); + data[0] = m_nodeIndexing.globalToGlobal(m_nodeIndexing.localToGlobal(localLogical)); data[1] = data[0] + 1; data[2] = data[1] + jp; data[3] = data[2] - 1; @@ -188,11 +188,11 @@ class StructuredTopologyView { SLIC_ASSERT(zoneIndex < numberOfZones()); - const auto localLogical = m_zoneIndexing.IndexToLogicalIndex(zoneIndex); + const auto localLogical = m_zoneIndexing.indexToLogicalIndex(zoneIndex); Shape1D shape; auto &data = shape.getIdsStorage(); - data[0] = m_nodeIndexing.GlobalToGlobal(m_nodeIndexing.LocalToGlobal(localLogical)); + data[0] = m_nodeIndexing.globalToGlobal(m_nodeIndexing.localToGlobal(localLogical)); data[1] = data[0] + 1; return shape; diff --git a/src/axom/bump/views/UniformCoordsetView.hpp b/src/axom/bump/views/UniformCoordsetView.hpp index f5b28ee82d..422ff71c33 100644 --- a/src/axom/bump/views/UniformCoordsetView.hpp +++ b/src/axom/bump/views/UniformCoordsetView.hpp @@ -128,7 +128,7 @@ class UniformCoordsetView AXOM_HOST_DEVICE PointType operator[](IndexType vertex_index) const { - return getPoint(m_indexing.IndexToLogicalIndex(vertex_index)); + return getPoint(m_indexing.indexToLogicalIndex(vertex_index)); } StructuredIndexing m_indexing; diff --git a/src/axom/bump/views/UnstructuredTopologySingleShapeView.hpp b/src/axom/bump/views/UnstructuredTopologySingleShapeView.hpp index 5d3877501a..f1389e9fbf 100644 --- a/src/axom/bump/views/UnstructuredTopologySingleShapeView.hpp +++ b/src/axom/bump/views/UnstructuredTopologySingleShapeView.hpp @@ -138,18 +138,14 @@ class UnstructuredTopologySingleShapeView { SLIC_ASSERT(zoneIndex < numberOfZones()); - ConnectivityView shapeIdsView {}; if(m_sizesView.empty()) { - shapeIdsView = ConnectivityView(m_connectivityView.data() + ShapeType::zoneOffset(zoneIndex), - ShapeType::numberOfNodes()); + return ShapeType(ConnectivityView(m_connectivityView.data() + ShapeType::zoneOffset(zoneIndex), + ShapeType::numberOfNodes())); } - else - { - shapeIdsView = ConnectivityView(m_connectivityView.data() + m_offsetsView[zoneIndex], - m_sizesView[zoneIndex]); - } - return ShapeType(shapeIdsView); + + return ShapeType(ConnectivityView(m_connectivityView.data() + m_offsetsView[zoneIndex], + m_sizesView[zoneIndex])); } /// @} diff --git a/src/axom/bump/views/dispatch_coordset.hpp b/src/axom/bump/views/dispatch_coordset.hpp index c06f8cdce7..a08fdce653 100644 --- a/src/axom/bump/views/dispatch_coordset.hpp +++ b/src/axom/bump/views/dispatch_coordset.hpp @@ -196,14 +196,14 @@ void dispatch_rectilinear_coordset(const conduit::Node &coordset, FuncType &&fun const conduit::Node &values = coordset["values"]; if(values.number_of_children() == 2) { - axom::bump::views::FloatNode_to_ArrayView_same(values[0], values[1], [&](auto xView, auto yView) { + axom::bump::views::floatNodeToArrayViewSame(values[0], values[1], [&](auto xView, auto yView) { RectilinearCoordsetView2 coordView(xView, yView); func(coordView); }); } else if(values.number_of_children() == 3) { - axom::bump::views::FloatNode_to_ArrayView_same( + axom::bump::views::floatNodeToArrayViewSame( values[0], values[1], values[2], @@ -294,14 +294,14 @@ void dispatch_explicit_coordset(const conduit::Node &coordset, FuncType &&func) const conduit::Node &values = coordset["values"]; if(values.number_of_children() == 2) { - axom::bump::views::FloatNode_to_ArrayView_same(values[0], values[1], [&](auto xView, auto yView) { + axom::bump::views::floatNodeToArrayViewSame(values[0], values[1], [&](auto xView, auto yView) { ExplicitCoordsetView coordView(xView, yView); func(coordView); }); } else if(values.number_of_children() == 3) { - axom::bump::views::FloatNode_to_ArrayView_same( + axom::bump::views::floatNodeToArrayViewSame( values[0], values[1], values[2], diff --git a/src/axom/bump/views/dispatch_material.hpp b/src/axom/bump/views/dispatch_material.hpp index 9cdba9b20a..8db64e49f9 100644 --- a/src/axom/bump/views/dispatch_material.hpp +++ b/src/axom/bump/views/dispatch_material.hpp @@ -64,13 +64,13 @@ bool dispatch_material_unibuffer(const conduit::Node &matset, FuncType &&func) verify(matset, "matset"); if(conduit::blueprint::mesh::matset::is_uni_buffer(matset)) { - IndexNode_to_ArrayView_same( + indexNodeToArrayViewSame( matset["material_ids"], matset["sizes"], matset["offsets"], matset["indices"], [&](auto material_ids, auto sizes, auto offsets, auto indices) { - FloatNode_to_ArrayView(matset["volume_fractions"], [&](auto volume_fractions) { + floatNodeToArrayView(matset["volume_fractions"], [&](auto volume_fractions) { using IndexType = typename decltype(material_ids)::value_type; using FloatType = typename decltype(volume_fractions)::value_type; @@ -130,8 +130,8 @@ bool dispatch_material_multibuffer(const conduit::Node &matset, FuncType &&func) { const conduit::Node &n_firstValues = volume_fractions[0].fetch_existing("values"); const conduit::Node &n_firstIndices = volume_fractions[0].fetch_existing("indices"); - IndexNode_to_ArrayView(n_firstIndices, [&](auto firstIndices) { - FloatNode_to_ArrayView(n_firstValues, [&](auto firstValues) { + indexNodeToArrayView(n_firstIndices, [&](auto firstIndices) { + floatNodeToArrayView(n_firstValues, [&](auto firstValues) { using IntElement = typename std::remove_const::type; using FloatElement = @@ -190,7 +190,7 @@ bool dispatch_material_element_dominant(const conduit::Node &matset, FuncType && if(volume_fractions.number_of_children() > 0) { const conduit::Node &n_firstValues = volume_fractions[0]; - FloatNode_to_ArrayView(n_firstValues, [&](auto firstValues) { + floatNodeToArrayView(n_firstValues, [&](auto firstValues) { using FloatElement = typename std::remove_const::type; using FloatView = axom::ArrayView; @@ -243,8 +243,8 @@ bool dispatch_material_material_dominant(const conduit::Node &matset, FuncType & const conduit::Node &n_firstValues = volume_fractions[0]; const conduit::Node &n_firstIndices = element_ids[0]; - IndexNode_to_ArrayView(n_firstIndices, [&](auto firstIndices) { - FloatNode_to_ArrayView(n_firstValues, [&](auto firstValues) { + indexNodeToArrayView(n_firstIndices, [&](auto firstIndices) { + floatNodeToArrayView(n_firstValues, [&](auto firstValues) { using FloatElement = typename std::remove_const::type; using IntElement = diff --git a/src/axom/bump/views/dispatch_unstructured_topology.hpp b/src/axom/bump/views/dispatch_unstructured_topology.hpp index f2a4a23e1f..a9c5610748 100644 --- a/src/axom/bump/views/dispatch_unstructured_topology.hpp +++ b/src/axom/bump/views/dispatch_unstructured_topology.hpp @@ -133,7 +133,7 @@ void dispatch_unstructured_polyhedral_topology(const conduit::Node &topo, FuncTy const std::string shape = topo["elements/shape"].as_string(); if(shape == "polyhedral") { - IndexNode_to_ArrayView_same( // + indexNodeToArrayViewSame( // topo["subelements/connectivity"], topo["subelements/sizes"], topo["subelements/offsets"], @@ -192,30 +192,29 @@ void dispatch_unstructured_mixed_topology(const conduit::Node &topo, FuncType && const std::string shape = topo["elements/shape"].as_string(); if(shape == "mixed") { - IndexNode_to_ArrayView_same( - topo["elements/connectivity"], - topo["elements/shapes"], - topo["elements/sizes"], - topo["elements/offsets"], - [&](auto connView, auto shapesView, auto sizesView, auto offsetsView) { - using ConnType = typename decltype(connView)::value_type; - - // Get the allocator that allocated the connectivity. The shape map data - // need to go into the same memory space. - const int allocatorID = - axom::getAllocatorIDFromPointer(topo["elements/connectivity"].data_ptr()); - - // Make the shape map. - axom::Array values, ids; - auto shapeMap = buildShapeMap(topo, values, ids, allocatorID); - - UnstructuredTopologyMixedShapeView ugView(connView, - shapesView, - sizesView, - offsetsView, - shapeMap); - func(shape, ugView); - }); + indexNodeToArrayViewSame(topo["elements/connectivity"], + topo["elements/shapes"], + topo["elements/sizes"], + topo["elements/offsets"], + [&](auto connView, auto shapesView, auto sizesView, auto offsetsView) { + using ConnType = typename decltype(connView)::value_type; + + // Get the allocator that allocated the connectivity. The shape map data + // need to go into the same memory space. + const int allocatorID = axom::getAllocatorIDFromPointer( + topo["elements/connectivity"].data_ptr()); + + // Make the shape map. + axom::Array values, ids; + auto shapeMap = buildShapeMap(topo, values, ids, allocatorID); + + UnstructuredTopologyMixedShapeView ugView(connView, + shapesView, + sizesView, + offsetsView, + shapeMap); + func(shape, ugView); + }); } } @@ -599,7 +598,7 @@ template void dispatch_unstructured_topology(const conduit::Node &topo, FuncType &&func) { verify(topo, "topology"); - IndexNode_to_ArrayView(topo["elements/connectivity"], [&](auto connView) { + indexNodeToArrayView(topo["elements/connectivity"], [&](auto connView) { using ConnType = typename decltype(connView)::value_type; typed_dispatch_unstructured_topology(topo, func); }); diff --git a/src/axom/bump/views/dispatch_utilities.cpp b/src/axom/bump/views/dispatch_utilities.cpp index e3215a103b..eaa58b4d1f 100644 --- a/src/axom/bump/views/dispatch_utilities.cpp +++ b/src/axom/bump/views/dispatch_utilities.cpp @@ -6,6 +6,8 @@ #include "axom/slic.hpp" #include "axom/bump/views/dispatch_utilities.hpp" +#include "axom/bump/utilities/conduit_memory.hpp" + #include namespace axom @@ -15,13 +17,39 @@ namespace bump namespace views { +static bool needToPerformCheck(const conduit::Node &obj, const std::string &protocol) +{ + bool performCheck = true; + + // NOTE: Some verification functions in conduit::blueprint::mesh::verify access + // array data. We need to skip verification for such things for now when + // data are on the GPU. + + if(protocol == "topology") + { + const conduit::Node &n_topo = obj; + if(n_topo["type"].as_string() == "unstructured" && n_topo.has_path("elements/shape")) + { + if(n_topo["elements/shape"].as_string() == "mixed" && n_topo.has_path("elements/shapes")) + { + performCheck = !axom::bump::utilities::isDeviceAllocated(n_topo["elements/shapes"]); + } + } + } + + return performCheck; +} + void verify(const conduit::Node &obj, const std::string &protocol) { conduit::Node info; + + const bool performCheck = needToPerformCheck(obj, protocol); + if(protocol.empty()) { // Check the mesh - if(!conduit::blueprint::mesh::verify(obj, info)) + if(performCheck && !conduit::blueprint::mesh::verify(obj, info)) { SLIC_ERROR(info.to_summary_string()); } @@ -29,7 +57,7 @@ void verify(const conduit::Node &obj, const std::string &protocol) else { // Protocol is not empty so check a specific thing in the mesh. - if(!conduit::blueprint::mesh::verify(protocol, obj, info)) + if(performCheck && !conduit::blueprint::mesh::verify(protocol, obj, info)) { SLIC_ERROR(info.to_summary_string()); } diff --git a/src/axom/core/Array.hpp b/src/axom/core/Array.hpp index 984bed185e..3ad3d54b14 100644 --- a/src/axom/core/Array.hpp +++ b/src/axom/core/Array.hpp @@ -1428,7 +1428,7 @@ Array::insert(Array: template inline void Array::insert(IndexType pos, IndexType n, const T* values) { - assert(values != nullptr); + assert(n == 0 || values != nullptr); reserveForInsert(n, pos); m_arrayOps.fill_range(m_data, pos, n, values, MemorySpace::Dynamic); } diff --git a/src/axom/core/ArrayBase.hpp b/src/axom/core/ArrayBase.hpp index 40a6d65134..d15c5fb46a 100644 --- a/src/axom/core/ArrayBase.hpp +++ b/src/axom/core/ArrayBase.hpp @@ -731,7 +731,11 @@ inline std::ostream& print(std::ostream& os, const ArrayBase& os << "[ "; for(IndexType i = 0; i < static_cast(array).size(); i++) { - os << data[i] << " "; + if(i > 0) + { + os << ", "; + } + os << data[i]; } os << " ]"; diff --git a/src/axom/core/ArrayView.hpp b/src/axom/core/ArrayView.hpp index f15d5fbc0f..f27eb91ba8 100644 --- a/src/axom/core/ArrayView.hpp +++ b/src/axom/core/ArrayView.hpp @@ -52,11 +52,8 @@ class ArrayView : public ArrayBase> using ArrayViewIterator = ArrayIteratorBase, T>; /// \brief Default constructor - AXOM_HOST_DEVICE ArrayView() -#ifndef AXOM_DEVICE_CODE - : m_allocator_id(axom::detail::getAllocatorID()) -#endif - { } + /// \note m_allocator_id is set to INVALID_ALLOCATOR_ID for now and will be set as needed later. + AXOM_HOST_DEVICE ArrayView() : m_allocator_id(INVALID_ALLOCATOR_ID) { } /*! * \brief Generic constructor for an ArrayView of arbitrary dimension with external data @@ -156,7 +153,13 @@ class ArrayView : public ArrayBase> /*! * \brief Get the ID for the umpire allocator */ - AXOM_HOST_DEVICE int getAllocatorID() const { return m_allocator_id; } + AXOM_HOST_DEVICE int getAllocatorID() const + { +#if !defined(AXOM_DEVICE_CODE) + determineAllocator(); +#endif + return m_allocator_id; + } /*! * \brief Returns an ArrayView that is a subspan of the original range of @@ -211,7 +214,6 @@ class ArrayView : public ArrayBase> */ AXOM_HOST_DEVICE ArrayView subspan(const StackArray& offsets, const StackArray& counts); - /*! * \brief Fill the ArrayView with a value. * @@ -280,13 +282,25 @@ class ArrayView : public ArrayBase> */ void assign(std::initializer_list elems); +private: + /*! + * \brief Determine the allocator if it has not been set before. We use the SPACE + * or try and determine the allocator for the data pointer when Umpire is + * available. + * + * \note This method is const so it can be called from getAllocatorId() but it + * may set the mutable m_allocator_id. + */ + void determineAllocator() const; + private: T* m_data = nullptr; /// \brief The full number of elements in the array /// i.e., 3 for a 1D Array of size 3, 9 for a 3x3 2D array, etc IndexType m_num_elements = 0; - /// \brief The allocator ID for the memory space in which m_data was allocated - int m_allocator_id; + /// \brief The allocator ID for the memory space in which m_data was allocated. + /// This is initialized to INVALID_ALLOCATOR_ID and updated later as needed. + mutable int m_allocator_id; }; /// \brief Helper alias for multi-component arrays @@ -313,9 +327,7 @@ AXOM_HOST_DEVICE ArrayView::ArrayView(T* data, IndexType min_stride) : ArrayBase>(shape, min_stride) , m_data(data) -#ifndef AXOM_DEVICE_CODE - , m_allocator_id(axom::detail::getAllocatorID()) -#endif + , m_allocator_id(INVALID_ALLOCATOR_ID) { #if defined(AXOM_DEVICE_CODE) && defined(AXOM_USE_UMPIRE) static_assert((SPACE != MemorySpace::Constant) || std::is_const::value, @@ -330,28 +342,6 @@ AXOM_HOST_DEVICE ArrayView::ArrayView(T* data, { m_num_elements = 0; } - -#if !defined(AXOM_DEVICE_CODE) && defined(AXOM_USE_UMPIRE) - // If we have Umpire, we can try and see what space the pointer is allocated in - // Probably not worth checking this if SPACE != Dynamic, we *could* error out - // if e.g., the user gives a host pointer to ArrayView, but even - // Thrust doesn't guard against this. - - // FIXME: Is it worth trying to get rid of this at compile time? - // (using a workaround since we don't have "if constexpr") - if(SPACE == MemorySpace::Dynamic) - { - auto& rm = umpire::ResourceManager::getInstance(); - - using NonConstT = typename std::remove_const::type; - // TODO: There's no reason these Umpire methods should take a non-const pointer. - if(rm.hasAllocator(const_cast(data))) - { - auto alloc = rm.getAllocator(const_cast(data)); - m_allocator_id = alloc.getId(); - } - } -#endif } //------------------------------------------------------------------------------ @@ -361,9 +351,7 @@ AXOM_HOST_DEVICE ArrayView::ArrayView(T* data, const StackArray& stride) : ArrayBase>(shape, stride) , m_data(data) -#ifndef AXOM_DEVICE_CODE - , m_allocator_id(axom::detail::getAllocatorID()) -#endif + , m_allocator_id(INVALID_ALLOCATOR_ID) { #if defined(AXOM_DEVICE_CODE) && defined(AXOM_USE_UMPIRE) static_assert((SPACE != MemorySpace::Constant) || std::is_const::value, @@ -378,28 +366,6 @@ AXOM_HOST_DEVICE ArrayView::ArrayView(T* data, { m_num_elements = 0; } - -#if !defined(AXOM_DEVICE_CODE) && defined(AXOM_USE_UMPIRE) - // If we have Umpire, we can try and see what space the pointer is allocated in - // Probably not worth checking this if SPACE != Dynamic, we *could* error out - // if e.g., the user gives a host pointer to ArrayView, but even - // Thrust doesn't guard against this. - - // FIXME: Is it worth trying to get rid of this at compile time? - // (using a workaround since we don't have "if constexpr") - if(SPACE == MemorySpace::Dynamic) - { - auto& rm = umpire::ResourceManager::getInstance(); - - using NonConstT = typename std::remove_const::type; - // TODO: There's no reason these Umpire methods should take a non-const pointer. - if(rm.hasAllocator(const_cast(data))) - { - auto alloc = rm.getAllocator(const_cast(data)); - m_allocator_id = alloc.getId(); - } - } -#endif } //------------------------------------------------------------------------------ @@ -488,11 +454,52 @@ AXOM_HOST_DEVICE ArrayView ArrayView::subspan( return slice; } +//------------------------------------------------------------------------------ +template +void ArrayView::determineAllocator() const +{ +#if !defined(AXOM_DEVICE_CODE) + if(m_allocator_id == INVALID_ALLOCATOR_ID) + { + #if defined(AXOM_USE_UMPIRE) + // If we have Umpire, we can try and see what space the pointer is allocated in + // Probably not worth checking this if SPACE != Dynamic, we *could* error out + // if e.g., the user gives a host pointer to ArrayView, but even + // Thrust doesn't guard against this. + + if constexpr(SPACE == MemorySpace::Dynamic) + { + auto& rm = umpire::ResourceManager::getInstance(); + + using NonConstT = typename std::remove_const::type; + // TODO: There's no reason these Umpire methods should take a non-const pointer. + if(m_data != nullptr && rm.hasAllocator(const_cast(m_data))) + { + auto alloc = rm.getAllocator(const_cast(m_data)); + m_allocator_id = alloc.getId(); + } + else + { + m_allocator_id = axom::detail::getAllocatorID(); + } + } + else + { + m_allocator_id = axom::detail::getAllocatorID(); + } + #else + m_allocator_id = axom::detail::getAllocatorID(); + #endif + } +#endif +} + //------------------------------------------------------------------------------ template void ArrayView::fill(const T& value) { using OpHelper = detail::ArrayOps; + determineAllocator(); const bool executeOnGPU = axom::isDeviceAllocator(m_allocator_id); OpHelper {m_allocator_id, executeOnGPU}.destroy(m_data, 0, m_num_elements); OpHelper {m_allocator_id, executeOnGPU}.fill(m_data, 0, m_num_elements, value); @@ -506,6 +513,7 @@ void ArrayView::fill(const T& value, IndexType n, IndexType pos) assert(pos + n <= m_num_elements); using OpHelper = detail::ArrayOps; + determineAllocator(); const bool executeOnGPU = axom::isDeviceAllocator(m_allocator_id); OpHelper {m_allocator_id, executeOnGPU}.destroy(m_data, pos, n); OpHelper {m_allocator_id, executeOnGPU}.fill(m_data, pos, n, value); @@ -519,6 +527,7 @@ void ArrayView::set(const T* elements, IndexType n, IndexType pos assert(pos + n <= m_num_elements); using OpHelper = detail::ArrayOps; + determineAllocator(); const bool executeOnGPU = axom::isDeviceAllocator(m_allocator_id); OpHelper {m_allocator_id, executeOnGPU}.destroy(m_data, pos, n); OpHelper {m_allocator_id, executeOnGPU}.fill_range(m_data, pos, n, elements, MemorySpace::Dynamic); @@ -531,6 +540,7 @@ void ArrayView::assign(axom::IndexType count, const T& value) assert(count >= 0); using OpHelper = detail::ArrayOps; + determineAllocator(); const bool executeOnGPU = axom::isDeviceAllocator(m_allocator_id); OpHelper {m_allocator_id, executeOnGPU}.destroy(m_data, 0, m_num_elements); OpHelper {m_allocator_id, executeOnGPU}.fill(m_data, 0, count, value); @@ -543,6 +553,7 @@ template void ArrayView::assign(InputIt first, InputIt last) { using OpHelper = detail::ArrayOps; + determineAllocator(); const bool executeOnGPU = axom::isDeviceAllocator(m_allocator_id); OpHelper {m_allocator_id, executeOnGPU}.destroy(m_data, 0, m_num_elements); m_num_elements = 0; diff --git a/src/axom/core/CMakeLists.txt b/src/axom/core/CMakeLists.txt index b7ab3f21df..fd2832829d 100644 --- a/src/axom/core/CMakeLists.txt +++ b/src/axom/core/CMakeLists.txt @@ -91,6 +91,7 @@ set(core_headers execution/scans.hpp execution/sorts.hpp execution/synchronize.hpp + execution/timed_for_all.hpp execution/internal/seq_exec.hpp execution/internal/omp_exec.hpp diff --git a/src/axom/core/FlatMapView.hpp b/src/axom/core/FlatMapView.hpp index 62beb3a72e..4d7ea5730f 100644 --- a/src/axom/core/FlatMapView.hpp +++ b/src/axom/core/FlatMapView.hpp @@ -46,7 +46,8 @@ class FlatMapView : detail::flat_map::SequentialLookupPolicy, FlatMap>; - AXOM_HOST_DEVICE FlatMapView() = default; + // NOTE: Defaulted constructors do not need to be marked AXOM_HOST_DEVICE + FlatMapView() = default; FlatMapView(FlatMapType& other) : m_numGroups2(other.m_numGroups2) @@ -207,7 +208,8 @@ class FlatMapView::IteratorImpl using reference = DataType&; public: - AXOM_HOST_DEVICE IteratorImpl() = default; + // NOTE: Defaulted constructors do not need to be marked AXOM_HOST_DEVICE + IteratorImpl() = default; AXOM_HOST_DEVICE IteratorImpl(const MapType& map, IndexType internalIdx) : m_map(map) diff --git a/src/axom/core/StaticArray.hpp b/src/axom/core/StaticArray.hpp index e9ce8a7317..303bd6f10d 100644 --- a/src/axom/core/StaticArray.hpp +++ b/src/axom/core/StaticArray.hpp @@ -36,7 +36,7 @@ class StaticArray : public StackArray AXOM_HOST_DEVICE StaticArray() : StackArray(), m_size(0) { #if defined(AXOM_DEBUG) - for(axom::IndexType i = 0; i < m_size; i++) + for(axom::IndexType i = 0; i < N; i++) { StackArray::m_data[i] = T {}; } @@ -64,8 +64,13 @@ class StaticArray : public StackArray * \brief Copy assignment operator. * \param obj The object to be copied. */ - AXOM_HOST_DEVICE StaticArray operator=(const StaticArray &obj) + AXOM_HOST_DEVICE StaticArray &operator=(const StaticArray &obj) { + if(this == &obj) + { + return *this; + } + for(axom::IndexType i = 0; i < obj.m_size; i++) { StackArray::m_data[i] = obj.StackArray::m_data[i]; diff --git a/src/axom/core/execution/scans.hpp b/src/axom/core/execution/scans.hpp index 6dfcd97405..442677be98 100644 --- a/src/axom/core/execution/scans.hpp +++ b/src/axom/core/execution/scans.hpp @@ -61,6 +61,8 @@ template inline void exclusive_scan(const Container1 &input, Container2 &&output) { assert(input.size() == output.size()); + using OutContainer = std::remove_reference_t; + using OutValue = std::remove_cv_t; #if defined(AXOM_USE_RAJA) #if defined(AXOM_USE_OPENMP) && defined(__INTEL_LLVM_COMPILER) @@ -73,18 +75,20 @@ inline void exclusive_scan(const Container1 &input, Container2 &&output) using exec_space = ExecSpace; #endif using loop_policy = typename axom::execution_space::loop_policy; + RAJA::exclusive_scan(RAJA::make_span(input.data(), input.size()), - RAJA::make_span(output.data(), output.size())); + RAJA::make_span(output.data(), output.size()), + RAJA::operators::plus {}); #else constexpr bool is_serial = std::is_same::value; AXOM_STATIC_ASSERT(is_serial); - typename std::remove_const::type total {0}; + OutValue total {0}; for(IndexType i = 0; i < input.size(); ++i) { output[i] = total; - total += input[i]; + total += static_cast(input[i]); } #endif } @@ -114,7 +118,10 @@ inline void exclusive_scan_inplace(Container &&input) constexpr bool is_serial = std::is_same::value; AXOM_STATIC_ASSERT(is_serial); - typename std::remove_const::type total {0}; + using OutContainer = std::remove_reference_t; + using OutValue = std::remove_cv_t; + + OutValue total {0}; for(IndexType i = 0; i < input.size(); ++i) { const auto tmp = input[i]; @@ -160,20 +167,23 @@ template inline void inclusive_scan(const Container1 &input, Container2 &&output) { assert(input.size() == output.size()); + using OutContainer = std::remove_reference_t; + using OutValue = std::remove_cv_t; #if defined(AXOM_USE_RAJA) using loop_policy = typename axom::execution_space::loop_policy; RAJA::inclusive_scan(RAJA::make_span(input.data(), input.size()), - RAJA::make_span(output.data(), output.size())); + RAJA::make_span(output.data(), output.size()), + RAJA::operators::plus {}); #else constexpr bool is_serial = std::is_same::value; AXOM_STATIC_ASSERT(is_serial); - typename std::remove_const::type total {0}; + OutValue total {0}; for(IndexType i = 0; i < input.size(); ++i) { - total += input[i]; + total += static_cast(input[i]); output[i] = total; } #endif @@ -204,7 +214,10 @@ inline void inclusive_scan_inplace(Container &&input) constexpr bool is_serial = std::is_same::value; AXOM_STATIC_ASSERT(is_serial); - typename std::remove_const::type total {0}; + using OutContainer = std::remove_reference_t; + using OutValue = std::remove_cv_t; + + OutValue total {0}; for(IndexType i = 0; i < input.size(); ++i) { total += input[i]; diff --git a/src/axom/core/execution/timed_for_all.hpp b/src/axom/core/execution/timed_for_all.hpp new file mode 100644 index 0000000000..0ea013264e --- /dev/null +++ b/src/axom/core/execution/timed_for_all.hpp @@ -0,0 +1,133 @@ +// Copyright (c) Lawrence Livermore National Security, LLC and other +// Axom Project Contributors. See top-level LICENSE and COPYRIGHT +// files for dates and other details. +// +// SPDX-License-Identifier: (BSD-3-Clause) + +#ifndef AXOM_CORE_EXECUTION_TIMED_FOR_ALL_HPP_ +#define AXOM_CORE_EXECUTION_TIMED_FOR_ALL_HPP_ + +#include "axom/config.hpp" +#include "axom/core/execution/for_all.hpp" +#include "axom/core/AnnotationMacros.hpp" + +#if defined(AXOM_USE_RAJA) && defined(AXOM_USE_OPENMP) + #include "axom/core/Array.hpp" + #include + #include + #include +#endif + +namespace axom +{ +/// \name Generic Timed Loop Traversal Functions +/// @{ + +namespace detail +{ +/*! + * \brief Default implementation for timing axom::for_all. + */ +template +struct TimedForAll +{ + /*! + * \brief Execute the for_all. + * + * \param name The name of the loop being timed. + * \param n The number it items in the loop. + * \param kernel The kernel to execute. + */ + static void execute([[maybe_unused]] const std::string &name, axom::IndexType n, KernelType &&kernel) + { + AXOM_ANNOTATE_SCOPE(name); + axom::for_all(n, std::forward(kernel)); + } +}; + +#if defined(AXOM_USE_RAJA) && defined(AXOM_USE_OPENMP) +/*! + * \brief A specialization for OpenMP that times each thread and prints the start/end times. + */ +template +struct TimedForAll +{ + using ExecSpace = axom::OMP_EXEC; + + /*! + * \brief Execute the for_all using OpenMP. + * + * \param name The name of the loop being timed. + * \param n The number it items in the loop. + * \param kernel The kernel to execute. + */ + static void execute(const std::string &name, axom::IndexType n, KernelType &&kernel) + { + AXOM_ANNOTATE_BEGIN(name); + const auto now1 = + std::chrono::duration(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); + const int allocatorID = axom::execution_space::allocatorID(); + const int nthreads = omp_get_max_threads() + 1; // make an extra slot. + axom::Array ompStart(nthreads, nthreads, allocatorID); + axom::Array ompEnd(nthreads, nthreads, allocatorID); + auto ompStartView = ompStart.view(); + auto ompEndView = ompEnd.view(); + + ompStart.fill(-1.); + // Save the start time as the last element in the array. + ompStart[nthreads - 1] = now1; + + auto outer = [&](axom::IndexType i) { + // Save the start time. + double &start = ompStartView[omp_get_thread_num()]; + if(start < 0.) + { + start = + std::chrono::duration(std::chrono::high_resolution_clock::now().time_since_epoch()) + .count(); + } + + kernel(i); + + // Save the end time. + ompEndView[omp_get_thread_num()] = + std::chrono::duration(std::chrono::high_resolution_clock::now().time_since_epoch()) + .count(); + }; + + // Run the outer kernel to gather timings and run the kernel. + axom::for_all(n, outer); + + // Save the end time as the last element in the array. + ompEnd[nthreads - 1] = + std::chrono::duration(std::chrono::high_resolution_clock::now().time_since_epoch()).count(); + AXOM_ANNOTATE_END(name); + + std::cout << name << ":\n"; + std::cout << "\tn: " << n << "\n"; + std::cout << "\tnthreads: " << (nthreads - 1) << "\n"; + std::cout << std::setprecision(20) << "\tstart=" << ompStart << std::endl; + std::cout << "\tend=" << ompEnd << std::endl; + } +}; +#endif +} // end namespace detail + +/*! + * \brief Execute axom::for_all and add a caliper timer (if enabled). Certain ExecSpace types may output additional timing information. + * + * \param name The name of the loop being timed. + * \param n The number it items in the loop. + * \param kernel The kernel to execute. + */ +template +void timed_for_all(const std::string &name, axom::IndexType n, KernelType &&kernel) +{ + detail::TimedForAll::execute(name, n, std::forward(kernel)); +} + +/// @} + +} // namespace axom + +#endif // AXOM_CORE_EXECUTION_TIMED_FOR_ALL_HPP_ diff --git a/src/axom/core/memory_management.cpp b/src/axom/core/memory_management.cpp index 108fef54a3..9aa818b449 100644 --- a/src/axom/core/memory_management.cpp +++ b/src/axom/core/memory_management.cpp @@ -76,6 +76,8 @@ int getSharedMemoryAllocatorID(std::size_t minSegmentSize) } allocator_id = alloc.getId(); } +#else + AXOM_UNUSED_VAR(minSegmentSize); #endif return allocator_id; } diff --git a/src/axom/core/memory_management.hpp b/src/axom/core/memory_management.hpp index b64822712a..155e9c7375 100644 --- a/src/axom/core/memory_management.hpp +++ b/src/axom/core/memory_management.hpp @@ -36,6 +36,31 @@ namespace axom constexpr int INVALID_ALLOCATOR_ID = -1; //!< Place holder for no/unknown allocator constexpr int MALLOC_ALLOCATOR_ID = -3; //!< Refers to MemorySpace::Malloc +/*! + * \brief Returns whether \a allocatorId is a valid Axom allocator id. + * + * \note When built without Umpire, the only valid allocator id is + * \c axom::MALLOC_ALLOCATOR_ID. + */ +inline bool isValidAllocatorID(int allocatorId) noexcept +{ + if(allocatorId == INVALID_ALLOCATOR_ID) + { + return false; + } + +#if defined(AXOM_USE_UMPIRE) + if(allocatorId == MALLOC_ALLOCATOR_ID) + { + return true; + } + + return umpire::ResourceManager::getInstance().isAllocator(allocatorId); +#else + return allocatorId == MALLOC_ALLOCATOR_ID; +#endif +} + // _memory_space_start /*! * \brief Memory spaces supported by Array-like types diff --git a/src/axom/core/numerics/quadrature.cpp b/src/axom/core/numerics/quadrature.cpp index 7646e6f37b..7cc0367514 100644 --- a/src/axom/core/numerics/quadrature.cpp +++ b/src/axom/core/numerics/quadrature.cpp @@ -14,12 +14,29 @@ #include "axom/config.hpp" #include +#include namespace axom { namespace numerics { +namespace +{ +struct GaussLegendreRuleStorage +{ + axom::Array nodes; + axom::Array weights; +}; + +std::uint64_t make_gauss_legendre_key(int npts, int allocatorID) +{ + const auto n = static_cast(static_cast(npts)); + const auto a = static_cast(static_cast(allocatorID)); + return (a << 32) | n; +} +} // namespace + /*! * \brief Computes a 1D quadrature rule of Gauss-Legendre points * @@ -149,20 +166,18 @@ QuadratureRule get_gauss_legendre(int npts, int allocatorID) { assert("Quadrature rules must have >= 1 point" && (npts >= 1)); - // Define a static map that stores the GL quadrature rule for a given order - static std::map, std::pair, axom::Array>> rule_library; + // Store cached rules keyed by (npts, allocatorID). This cache is not thread-safe. + static axom::FlatMap rule_library(64); - const std::pair key = std::make_pair(npts, allocatorID); + const std::uint64_t key = make_gauss_legendre_key(npts, allocatorID); - auto value_it = rule_library.find(key); - if(value_it == rule_library.end()) + auto [it, inserted] = rule_library.try_emplace(key); + if(inserted) { - auto& vals = rule_library[key]; - compute_gauss_legendre_data(npts, vals.first, vals.second, allocatorID); - value_it = rule_library.find(key); + compute_gauss_legendre_data(npts, it->second.nodes, it->second.weights, allocatorID); } - return QuadratureRule {value_it->second.first.view(), value_it->second.second.view()}; + return QuadratureRule {it->second.nodes.view(), it->second.weights.view()}; } } /* end namespace numerics */ diff --git a/src/axom/core/numerics/quadrature.hpp b/src/axom/core/numerics/quadrature.hpp index 1cb693da63..b8db612e11 100644 --- a/src/axom/core/numerics/quadrature.hpp +++ b/src/axom/core/numerics/quadrature.hpp @@ -32,6 +32,14 @@ class QuadratureRule friend QuadratureRule get_gauss_legendre(int, int); public: + //! \brief Accessor for the full array of quadrature nodes + AXOM_HOST_DEVICE + axom::ArrayView nodes() const { return axom::ArrayView(m_nodes); } + + //! \brief Accessor for the full array of quadrature weights + AXOM_HOST_DEVICE + axom::ArrayView weights() const { return axom::ArrayView(m_weights); } + //! \brief Accessor for quadrature nodes AXOM_HOST_DEVICE double node(size_t idx) const { return m_nodes[idx]; }; diff --git a/src/axom/core/tests/CMakeLists.txt b/src/axom/core/tests/CMakeLists.txt index d23dbf5cf6..662f0fee06 100644 --- a/src/axom/core/tests/CMakeLists.txt +++ b/src/axom/core/tests/CMakeLists.txt @@ -24,6 +24,7 @@ set(core_serial_tests core_bit_utilities.hpp core_device_hash.hpp core_execution_for_all.hpp + core_execution_scans.hpp core_execution_space.hpp core_map.hpp core_flatmap.hpp diff --git a/src/axom/core/tests/core_array.hpp b/src/axom/core/tests/core_array.hpp index f0ea4f4838..1a1350151f 100644 --- a/src/axom/core/tests/core_array.hpp +++ b/src/axom/core/tests/core_array.hpp @@ -1145,6 +1145,17 @@ TEST(core_array, checkResize) } } +//------------------------------------------------------------------------------ +TEST(core_array, insertZeroCountNullptrDoesNotAssert) +{ + axom::Array v(0, 1); + v.push_back(10); + // This should not assert + v.insert(1, 0, static_cast(nullptr)); + EXPECT_EQ(v.size(), 1); + EXPECT_EQ(v[0], 10); +} + //------------------------------------------------------------------------------ TEST(core_array_DeathTest, checkResize) { diff --git a/src/axom/core/tests/core_execution_scans.hpp b/src/axom/core/tests/core_execution_scans.hpp new file mode 100644 index 0000000000..c2c941e799 --- /dev/null +++ b/src/axom/core/tests/core_execution_scans.hpp @@ -0,0 +1,636 @@ +// Copyright (c) Lawrence Livermore National Security, LLC and other +// Axom Project Contributors. See top-level LICENSE and COPYRIGHT +// files for dates and other details. +// +// SPDX-License-Identifier: (BSD-3-Clause) + +#include "axom/core/execution/scans.hpp" +#include "axom/core/execution/execution_space.hpp" +#include "axom/core/Array.hpp" +#include "axom/core/memory_management.hpp" +#include "axom/core/Types.hpp" + +#include "gtest/gtest.h" + +#include +#include + +using axom::IndexType; + +// ----------------------------------------------------------------------------- +// Reference helpers on host +// ----------------------------------------------------------------------------- + +template +std::vector reference_exclusive_scan(const InContainer &input) +{ + std::vector result(input.size()); + OutValue total = 0; + for(IndexType i = 0; i < static_cast(input.size()); ++i) + { + result[i] = total; + total += static_cast(input[i]); + } + return result; +} + +template +std::vector reference_inclusive_scan(const InContainer &input) +{ + std::vector result(input.size()); + OutValue total = 0; + for(IndexType i = 0; i < static_cast(input.size()); ++i) + { + total += static_cast(input[i]); + result[i] = total; + } + return result; +} + +// ----------------------------------------------------------------------------- +// Data generation on host +// ----------------------------------------------------------------------------- + +// Fill a mask vector with 0/1 in the input type. +// alternating = true -> 0,1,0,1, ... +// alternating = false -> 1 every "stride" elements. +template +std::vector make_mask(IndexType n, bool alternating, int stride = 1) +{ + std::vector mask(n); + for(IndexType i = 0; i < n; ++i) + { + int val; + if(alternating) + { + val = (i % 2 == 0) ? 0 : 1; + } + else + { + val = ((i % stride) == 0) ? 1 : 0; + } + mask[i] = static_cast(val); + } + return mask; +} + +// ----------------------------------------------------------------------------- +// Common utilities for device/exec-space arrays +// ----------------------------------------------------------------------------- + +// Create an axom::Array in the allocator for ExecSpace and fill it from host +template +axom::Array create_exec_array_from_host(const std::vector &hostData) +{ + const IndexType n = static_cast(hostData.size()); + const int allocatorID = axom::execution_space::allocatorID(); + + axom::Array arr(n, n, allocatorID); + + if(n > 0) + { + axom::copy(arr.data(), hostData.data(), n * sizeof(T)); + } + + return arr; +} + +// Copy an axom::Array in exec-space back to a host std::vector +template +std::vector copy_exec_array_to_host(const axom::Array &arr) +{ + const IndexType n = arr.size(); + std::vector hostData(n); + + if(n > 0) + { + axom::copy(hostData.data(), arr.data(), n * sizeof(T)); + } + + return hostData; +} + +// ----------------------------------------------------------------------------- +// Generic test runners: host <-> exec arrays, all type combinations +// ----------------------------------------------------------------------------- + +// exclusive_scan: InType host mask, OutType host result; using ExecSpace +template +void run_exclusive_scan_test(IndexType n, bool alternating_pattern, int stride = 1) +{ + // 1. Host input + auto hostMask = make_mask(n, alternating_pattern, stride); + + // 2. Exec-space Arrays (input + output) + axom::Array devInput = create_exec_array_from_host(hostMask); + + const int allocatorID = axom::execution_space::allocatorID(); + axom::Array devOutput(n, n, allocatorID); + + // 3. Run Axom scan in ExecSpace + axom::exclusive_scan(devInput, devOutput); + + // 4. Copy output back to host and compute reference + auto hostOutput = copy_exec_array_to_host(devOutput); + auto hostRef = reference_exclusive_scan, OutType>(hostMask); + + ASSERT_EQ(hostOutput.size(), hostRef.size()); + for(IndexType i = 0; i < n; ++i) + { + EXPECT_EQ(hostOutput[i], hostRef[i]) << "Mismatch at index " << i; + } + + // 5. Check total sum is positive (since pattern is 0/1 and n > 0 for main tests) + if(n > 0) + { + OutType total_axom; + if(n == 1) + { + total_axom = static_cast(hostMask[0]); + } + else + { + total_axom = hostOutput.back() + static_cast(hostMask.back()); + } + + OutType total_ref = 0; + for(auto v : hostMask) + { + total_ref += static_cast(v); + } + EXPECT_EQ(total_axom, total_ref); + EXPECT_GT(total_axom, static_cast(0)); + } +} + +// inclusive_scan: InType host mask, OutType host result; using ExecSpace +template +void run_inclusive_scan_test(IndexType n, bool alternating_pattern, int stride = 1) +{ + auto hostMask = make_mask(n, alternating_pattern, stride); + + axom::Array devInput = create_exec_array_from_host(hostMask); + + const int allocatorID = axom::execution_space::allocatorID(); + axom::Array devOutput(n, n, allocatorID); + + axom::inclusive_scan(devInput, devOutput); + + auto hostOutput = copy_exec_array_to_host(devOutput); + auto hostRef = reference_inclusive_scan, OutType>(hostMask); + + ASSERT_EQ(hostOutput.size(), hostRef.size()); + for(IndexType i = 0; i < n; ++i) + { + EXPECT_EQ(hostOutput[i], hostRef[i]) << "Mismatch at index " << i; + } + + if(n > 0) + { + OutType total_axom = hostOutput.back(); + OutType total_ref = 0; + for(auto v : hostMask) + { + total_ref += static_cast(v); + } + EXPECT_EQ(total_axom, total_ref); + EXPECT_GT(total_axom, static_cast(0)); + } +} + +// exclusive_scan_inplace: InType host mask, OutType buffer in exec-space +// initialized from mask. +template +void run_exclusive_scan_inplace_test(IndexType n, bool alternating_pattern, int stride = 1) +{ + auto hostMask = make_mask(n, alternating_pattern, stride); + + // Host buffer cast to OutType + std::vector hostBuf(n); + for(IndexType i = 0; i < n; ++i) + { + hostBuf[i] = static_cast(hostMask[i]); + } + + axom::Array devBuf = create_exec_array_from_host(hostBuf); + + axom::exclusive_scan_inplace(devBuf); + + auto hostOutput = copy_exec_array_to_host(devBuf); + auto hostRef = reference_exclusive_scan, OutType>(hostMask); + + ASSERT_EQ(hostOutput.size(), hostRef.size()); + for(IndexType i = 0; i < n; ++i) + { + EXPECT_EQ(hostOutput[i], hostRef[i]) << "Mismatch at index " << i; + } + + if(n > 0) + { + OutType total_axom; + if(n == 1) + { + total_axom = static_cast(hostMask[0]); + } + else + { + total_axom = hostOutput.back() + static_cast(hostMask.back()); + } + + OutType total_ref = 0; + for(auto v : hostMask) + { + total_ref += static_cast(v); + } + EXPECT_EQ(total_axom, total_ref); + EXPECT_GT(total_axom, static_cast(0)); + } +} + +// inclusive_scan_inplace: InType host mask, OutType buffer in exec-space +// initialized from mask. +template +void run_inclusive_scan_inplace_test(IndexType n, bool alternating_pattern, int stride = 1) +{ + auto hostMask = make_mask(n, alternating_pattern, stride); + + std::vector hostBuf(n); + for(IndexType i = 0; i < n; ++i) + { + hostBuf[i] = static_cast(hostMask[i]); + } + + axom::Array devBuf = create_exec_array_from_host(hostBuf); + + axom::inclusive_scan_inplace(devBuf); + + auto hostOutput = copy_exec_array_to_host(devBuf); + auto hostRef = reference_inclusive_scan, OutType>(hostMask); + + ASSERT_EQ(hostOutput.size(), hostRef.size()); + for(IndexType i = 0; i < n; ++i) + { + EXPECT_EQ(hostOutput[i], hostRef[i]) << "Mismatch at index " << i; + } + + if(n > 0) + { + OutType total_axom = hostOutput.back(); + OutType total_ref = 0; + for(auto v : hostMask) + { + total_ref += static_cast(v); + } + EXPECT_EQ(total_axom, total_ref); + EXPECT_GT(total_axom, static_cast(0)); + } +} + +// ----------------------------------------------------------------------------- +// Type lists and execution space lists +// ----------------------------------------------------------------------------- + +// Input/output scalar types to test +using ScalarTypes = ::testing::Types; + +// Execution spaces to test (conditional on build) +using ExecSpaceTypes = ::testing::Types +#endif +#if defined(AXOM_RUNTIME_POLICY_USE_HIP) + , + axom::HIP_EXEC<256> +#endif + >; + +// A small helper struct to bundle ExecSpace and one scalar type +template +struct ExecScalarPair +{ + using exec_space = ExecSpace; + using scalar_type = Scalar; +}; + +// Build a combined list of (ExecSpace, Scalar) so we can iterate over +// scalar type combinations inside each test. +template +struct ExecScalarList +{ + using type = ::testing::Types, + ExecScalarPair, + ExecScalarPair>; +}; + +// However, gtest does not directly support nested type lists nicely, so we +// instead parameterize only on ExecSpace and loop over scalar type combinations +// explicitly in each test. + +// ----------------------------------------------------------------------------- +// Test fixture parameterized by ExecSpace only +// ----------------------------------------------------------------------------- + +template +class ExecutionScanAllTypes : public ::testing::Test +{ }; + +TYPED_TEST_SUITE(ExecutionScanAllTypes, ExecSpaceTypes); + +// ----------------------------------------------------------------------------- +// Tests: for each ExecSpace, loop over all InType/OutType combinations +// among char, int, IndexType, and run all four scan variants. +// ----------------------------------------------------------------------------- + +TYPED_TEST(ExecutionScanAllTypes, ExclusiveScan_AllTypeCombos_128_Alternating) +{ + using ExecSpace = TypeParam; + const IndexType N = 128; + + using InChar = char; + using InInt = int; + using InIdx = axom::IndexType; + + using OutChar = char; + using OutInt = int; + using OutIdx = axom::IndexType; + + // 3 x 3 input/output combinations + run_exclusive_scan_test(N, true); + run_exclusive_scan_test(N, true); + run_exclusive_scan_test(N, true); + + run_exclusive_scan_test(N, true); + run_exclusive_scan_test(N, true); + run_exclusive_scan_test(N, true); + + run_exclusive_scan_test(N, true); + run_exclusive_scan_test(N, true); + run_exclusive_scan_test(N, true); +} + +TYPED_TEST(ExecutionScanAllTypes, InclusiveScan_AllTypeCombos_128_Alternating) +{ + using ExecSpace = TypeParam; + const IndexType N = 128; + + using InChar = char; + using InInt = int; + using InIdx = axom::IndexType; + + using OutChar = char; + using OutInt = int; + using OutIdx = axom::IndexType; + + run_inclusive_scan_test(N, true); + run_inclusive_scan_test(N, true); + run_inclusive_scan_test(N, true); + + run_inclusive_scan_test(N, true); + run_inclusive_scan_test(N, true); + run_inclusive_scan_test(N, true); + + run_inclusive_scan_test(N, true); + run_inclusive_scan_test(N, true); + run_inclusive_scan_test(N, true); +} + +TYPED_TEST(ExecutionScanAllTypes, ExclusiveScanInplace_AllTypeCombos_128_Alternating) +{ + using ExecSpace = TypeParam; + const IndexType N = 128; + + using InChar = char; + using InInt = int; + using InIdx = axom::IndexType; + + using OutChar = char; + using OutInt = int; + using OutIdx = axom::IndexType; + + run_exclusive_scan_inplace_test(N, true); + run_exclusive_scan_inplace_test(N, true); + run_exclusive_scan_inplace_test(N, true); + + run_exclusive_scan_inplace_test(N, true); + run_exclusive_scan_inplace_test(N, true); + run_exclusive_scan_inplace_test(N, true); + + run_exclusive_scan_inplace_test(N, true); + run_exclusive_scan_inplace_test(N, true); + run_exclusive_scan_inplace_test(N, true); +} + +TYPED_TEST(ExecutionScanAllTypes, InclusiveScanInplace_AllTypeCombos_128_Alternating) +{ + using ExecSpace = TypeParam; + const IndexType N = 128; + + using InChar = char; + using InInt = int; + using InIdx = axom::IndexType; + + using OutChar = char; + using OutInt = int; + using OutIdx = axom::IndexType; + + run_inclusive_scan_inplace_test(N, true); + run_inclusive_scan_inplace_test(N, true); + run_inclusive_scan_inplace_test(N, true); + + run_inclusive_scan_inplace_test(N, true); + run_inclusive_scan_inplace_test(N, true); + run_inclusive_scan_inplace_test(N, true); + + run_inclusive_scan_inplace_test(N, true); + run_inclusive_scan_inplace_test(N, true); + run_inclusive_scan_inplace_test(N, true); +} + +// Sparse pattern, non power of two +TYPED_TEST(ExecutionScanAllTypes, ExclusiveScan_AllTypeCombos_257_Sparse) +{ + using ExecSpace = TypeParam; + const IndexType N = 257; + const int stride = 5; + + using InChar = char; + using InInt = int; + using InIdx = axom::IndexType; + + using OutChar = char; + using OutInt = int; + using OutIdx = axom::IndexType; + + run_exclusive_scan_test(N, false, stride); + run_exclusive_scan_test(N, false, stride); + run_exclusive_scan_test(N, false, stride); + + run_exclusive_scan_test(N, false, stride); + run_exclusive_scan_test(N, false, stride); + run_exclusive_scan_test(N, false, stride); + + run_exclusive_scan_test(N, false, stride); + run_exclusive_scan_test(N, false, stride); + run_exclusive_scan_test(N, false, stride); +} + +TYPED_TEST(ExecutionScanAllTypes, InclusiveScan_AllTypeCombos_257_Sparse) +{ + using ExecSpace = TypeParam; + const IndexType N = 257; + const int stride = 5; + + using InChar = char; + using InInt = int; + using InIdx = axom::IndexType; + + using OutChar = char; + using OutInt = int; + using OutIdx = axom::IndexType; + + run_inclusive_scan_test(N, false, stride); + run_inclusive_scan_test(N, false, stride); + run_inclusive_scan_test(N, false, stride); + + run_inclusive_scan_test(N, false, stride); + run_inclusive_scan_test(N, false, stride); + run_inclusive_scan_test(N, false, stride); + + run_inclusive_scan_test(N, false, stride); + run_inclusive_scan_test(N, false, stride); + run_inclusive_scan_test(N, false, stride); +} + +// Simple edge cases: empty and single element for one representative type combo +TYPED_TEST(ExecutionScanAllTypes, ExclusiveScan_Empty_IntToInt) +{ + using ExecSpace = TypeParam; + + std::vector hostMask; + axom::Array devInput = create_exec_array_from_host(hostMask); + + const int allocatorID = axom::execution_space::allocatorID(); + axom::Array devOutput(0, 0, allocatorID); + + axom::exclusive_scan(devInput, devOutput); + + auto hostOutput = copy_exec_array_to_host(devOutput); + + EXPECT_TRUE(hostMask.empty()); + EXPECT_TRUE(hostOutput.empty()); +} + +TYPED_TEST(ExecutionScanAllTypes, ExclusiveScan_SingleElement_CharToInt) +{ + using ExecSpace = TypeParam; + + std::vector hostMask(1, 1); + axom::Array devInput = create_exec_array_from_host(hostMask); + + const int allocatorID = axom::execution_space::allocatorID(); + axom::Array devOutput(1, 1, allocatorID); + + axom::exclusive_scan(devInput, devOutput); + + auto hostOutput = copy_exec_array_to_host(devOutput); + + ASSERT_EQ(hostOutput.size(), 1u); + EXPECT_EQ(hostOutput[0], 0); +} + +//------------------------------------------------------------------------------ +template +void test_exclusive_scan_char_int() +{ + // The HIP backend cannot pass this test currently. + const std::string name(axom::execution_space::name()); + if(name.find("HIP") != std::string::npos) + { + std::cout << "exclusive_scan for HIP will not successfully accumulate chars to int without " + "overflowing and making negative results.\n"; + return; + } + + // This data came from a failed test that showed exclusive_scan making negative offsets due to char overflow. + const char hostInput[] = { + 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0}; + const int hostOutput[] = { + 0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, + 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 16, 16, 16, 16, 17, 17, 17, 17, 18, + 18, 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, + 23, 23, 24, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27, 28, + 28, 28, 28, 29, 29, 29, 29, 30, 30, 31, 31, 31, 31, 32, 32, 32, 32, 33, 33, + 34, 34, 34, 34, 35, 35, 35, 35, 36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, + 38, 39, 39, 39, 39, 40, 40, 40, 40, 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, + 43, 43, 44, 44, 44, 44, 45, 45, 46, 46, 46, 46, 47, 47, 47, 47, 48, 48, 49, + 49, 49, 49, 50, 50, 50, 50, 51, 51, 51, 51, 52, 52, 52, 52, 53, 53, 53, 53, + 54, 54, 54, 54, 55, 55, 55, 55, 56, 56, 56, 56, 57, 57, 57, 57, 58, 58, 58, + 58, 59, 59, 59, 59, 60, 60, 61, 61, 61, 61, 62, 62, 62, 62, 63, 63, 64, 64, + 64, 64, 65, 65, 65, 65, 66, 66, 66, 66, 67, 67, 67, 67, 68, 68, 68, 68, 69, + 69, 69, 69, 70, 70, 70, 70, 71, 71, 71, 71, 72, 72, 72, 72, 73, 73, 73, 73, + 74, 74, 74, 74, 75, 75, 76, 76, 76, 76, 77, 77, 77, 77, 78, 78, 79, 79, 79, + 79, 80, 80, 80, 80, 81, 81, 81, 81, 82, 82, 82, 82, 83, 83, 83, 83, 84, 84, + 84, 84, 85, 85, 85, 85, 86, 86, 86, 86, 87, 87, 87, 87, 88, 88, 88, 88, 89, + 89, 89, 89, 90, 90, 91, 91, 91, 91, 92, 92, 92, 92, 93, 93, 94, 94, 94, 94, + 95, 95, 95, 95, 96, 96, 96, 96, 97, 97, 97, 97, 98, 98, 98, 98, 99, 99, 99, + 99, 100, 100, 100, 100, 101, 101, 101, 101, 102, 102, 102, 102, 103, 103, 103, 103, 104, 104, + 104, 104, 105, 105, 106, 106, 106, 106, 107, 107, 107, 107, 108, 108, 109, 109, 109, 109, 110, + 110, 110, 110, 111, 111, 111, 111, 112, 112, 112, 112, 113, 113, 113, 113, 114, 114, 114, 114, + 115, 115, 115, 115, 116, 116, 116, 116, 117, 117, 117, 117, 118, 118, 118, 118, 119, 119, 119, + 119, 120, 120, 121, 121, 121, 121, 122, 122, 122, 122, 123, 123, 124, 124, 124, 124, 125, 125, + 125, 125, 126, 126, 126, 126, 127, 127, 127, 127, 128, 128, 128, 128, 129, 129, 129, 129, 130, + 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132, 133, 133, 133, 133, 134, 134, 134, 134, + 135, 135, 136, 136, 136, 136, 137, 137, 137, 137, 138, 138, 139, 139, 139, 139, 140, 140, 140, + 140, 141, 141, 141, 141, 142, 142, 142, 142, 143, 143, 143, 143, 144, 144, 144, 144, 145, 145, + 145, 145, 146, 146, 146, 146, 147, 147, 147, 147, 148, 148, 148, 148, 149, 149, 149, 149, 150, + 150, 151, 151, 152, 152, 153, 154, 154, 155, 155, 156, 156, 157, 157, 158, 158, 159, 159, 160, + 160, 161, 161, 162, 162, 163, 163, 164, 164, 165, 166, 166, 167, 167, 167, 167, 168, 168, 168, + 168, 169, 169, 169, 169, 170, 170, 170, 170, 171, 171, 171, 171, 172, 172, 172, 172, 173, 173, + 173, 173, 174, 174, 174, 174, 175, 175, 175, 175, 176}; + const auto n = static_cast(sizeof(hostInput) / sizeof(char)); + + // host->device + axom::Array deviceMask(n, n, axom::execution_space::allocatorID()); + axom::copy(deviceMask.data(), hostInput, sizeof(char) * n); + + axom::Array deviceOffset(n, n, axom::execution_space::allocatorID()); + axom::exclusive_scan(deviceMask, deviceOffset); + + // device->host + axom::Array hostOffset(n, n); + axom::copy(hostOffset.data(), deviceOffset.data(), sizeof(int) * n); + + for(axom::IndexType i = 0; i < n; i++) + { + EXPECT_EQ(hostOffset[i], hostOutput[i]); + } +} + +TYPED_TEST(ExecutionScanAllTypes, ExclusiveScan_CharToInt) +{ + using ExecSpace = TypeParam; + test_exclusive_scan_char_int(); +} diff --git a/src/axom/core/tests/core_serial_main.cpp b/src/axom/core/tests/core_serial_main.cpp index daafe0df65..6b41b128c6 100644 --- a/src/axom/core/tests/core_serial_main.cpp +++ b/src/axom/core/tests/core_serial_main.cpp @@ -16,6 +16,7 @@ #include "core_bit_utilities.hpp" #include "core_device_hash.hpp" #include "core_execution_for_all.hpp" +#include "core_execution_scans.hpp" #include "core_execution_space.hpp" #include "core_map.hpp" #include "core_flatmap.hpp" diff --git a/src/axom/core/tests/core_static_array.hpp b/src/axom/core/tests/core_static_array.hpp index 93e26f8d49..1e4e7c042a 100644 --- a/src/axom/core/tests/core_static_array.hpp +++ b/src/axom/core/tests/core_static_array.hpp @@ -16,6 +16,28 @@ //------------------------------------------------------------------------------ namespace { +struct DevicePair +{ + int first; + int second; + + AXOM_HOST_DEVICE DevicePair() : first(0), second(0) { } + + AXOM_HOST_DEVICE explicit DevicePair(int value) : first(value), second(-value) { } + + AXOM_HOST_DEVICE DevicePair& operator=(const DevicePair& other) + { + first = other.first; + second = other.second; + return *this; + } + + AXOM_HOST_DEVICE bool operator==(const DevicePair& other) const + { + return first == other.first && second == other.second; + } +}; + template void check_static_array_policy() { @@ -68,6 +90,48 @@ void check_static_array_policy() } } +template +void check_static_array_nonpod_assignment_policy() +{ + constexpr int MAX_SIZE = 4; + using StaticArrayType = axom::StaticArray; + + const int host_allocator = axom::execution_space::allocatorID(); + const int kernel_allocator = axom::execution_space::allocatorID(); + + axom::Array arrays_device(1, 1, kernel_allocator); + auto arrays_view = arrays_device.view(); + + axom::for_all( + 1, + AXOM_LAMBDA(int i) { + AXOM_UNUSED_VAR(i); + + StaticArrayType source; + source.push_back(DevicePair(1)); + source.push_back(DevicePair(2)); + + StaticArrayType target; + target.push_back(DevicePair(-1)); + target = source; + target.push_back(DevicePair(3)); + + arrays_view[0] = target; + }); + + if(axom::execution_space::async()) + { + axom::synchronize(); + } + + axom::Array arrays_host(arrays_device, host_allocator); + + EXPECT_EQ(arrays_host[0].size(), 3); + EXPECT_EQ(arrays_host[0][0], DevicePair(1)); + EXPECT_EQ(arrays_host[0][1], DevicePair(2)); + EXPECT_EQ(arrays_host[0][2], DevicePair(3)); +} + } /* end anonymous namespace */ //------------------------------------------------------------------------------ @@ -77,8 +141,35 @@ void check_static_array_policy() //------------------------------------------------------------------------------ TEST(core_static_array, check_static_array_seq) { check_static_array_policy(); } +TEST(core_static_array, assignment_returns_reference) +{ + using StaticArrayType = axom::StaticArray; + + StaticArrayType source; + source.push_back(DevicePair(1)); + source.push_back(DevicePair(2)); + + StaticArrayType target; + (target = source).push_back(DevicePair(3)); + + EXPECT_EQ(target.size(), 3); + EXPECT_EQ(target[0], DevicePair(1)); + EXPECT_EQ(target[1], DevicePair(2)); + EXPECT_EQ(target[2], DevicePair(3)); +} + +TEST(core_static_array, check_static_array_nonpod_assignment_seq) +{ + check_static_array_nonpod_assignment_policy(); +} + #if defined(AXOM_USE_OPENMP) && defined(AXOM_USE_RAJA) TEST(core_static_array, check_static_array_omp) { check_static_array_policy(); } + +TEST(core_static_array, check_static_array_nonpod_assignment_omp) +{ + check_static_array_nonpod_assignment_policy(); +} #endif #if defined(AXOM_USE_CUDA) && defined(AXOM_USE_RAJA) && defined(AXOM_USE_UMPIRE) @@ -87,6 +178,12 @@ TEST(core_static_array, check_static_array_cuda) check_static_array_policy>(); check_static_array_policy>(); } + +TEST(core_static_array, check_static_array_nonpod_assignment_cuda) +{ + check_static_array_nonpod_assignment_policy>(); + check_static_array_nonpod_assignment_policy>(); +} #endif #if defined(AXOM_USE_HIP) && defined(AXOM_USE_RAJA) && defined(AXOM_USE_UMPIRE) @@ -95,4 +192,10 @@ TEST(core_static_array, check_static_array_hip) check_static_array_policy>(); check_static_array_policy>(); } + +TEST(core_static_array, check_static_array_nonpod_assignment_hip) +{ + check_static_array_nonpod_assignment_policy>(); + check_static_array_nonpod_assignment_policy>(); +} #endif diff --git a/src/axom/core/tests/numerics_determinants.hpp b/src/axom/core/tests/numerics_determinants.hpp index e18b7dac95..c57ace5704 100644 --- a/src/axom/core/tests/numerics_determinants.hpp +++ b/src/axom/core/tests/numerics_determinants.hpp @@ -9,6 +9,87 @@ #include "axom/core/numerics/Matrix.hpp" #include "axom/core/numerics/Determinants.hpp" +#include "axom/fmt.hpp" + +#include +#include +#include +#include +#include +#include + +namespace +{ + +/** + * \brief Returns the number of IEEE-754 double-precision representable values + * (ULPs) separating \p a and \p b. + * + * Computes the absolute difference in their ordered bit representations. + * Assumes IEEE-754 64-bit floats + * Returns max uint64_t if either argument is NaN; and 0 for equal params (e.g. +0 and -0). + */ +std::uint64_t ulps_apart(double a, double b) +{ + static_assert(sizeof(double) == sizeof(std::uint64_t), "unexpected double size"); + static_assert(std::numeric_limits::is_iec559, "requires IEEE-754"); + + if(std::isnan(a) || std::isnan(b)) + { + return std::numeric_limits::max(); + } + + // Treat +0 and -0 (and any equal values) as distance 0 + if(a == b) + { + return 0; + } + + // Order-preserving bit transform for ULP comparison. + auto to_ordered = [](double x) -> std::uint64_t { + std::uint64_t bits = 0; + std::memcpy(&bits, &x, sizeof(bits)); + constexpr std::uint64_t sign = std::uint64_t {1} << 63; + return (bits & sign) ? ~bits : (bits + sign); + }; + + const std::uint64_t oa = to_ordered(a); + const std::uint64_t ob = to_ordered(b); + return (oa > ob) ? (oa - ob) : (ob - oa); +} + +// "raw" implementation of 2x2 determinant for comparisons to axom::utilities::determinant +// uses `volatile` in an attempt to allide compiler optimization that internally use fma calculations +double det2_raw(double a00, double a01, double a10, double a11) +{ + volatile double p0 = a00 * a11; + volatile double p1 = a01 * a10; + return p0 - p1; +} + +// "raw" implementation of 3x3 determinant for comparisons to axom::utilities::determinant +// uses `volatile` in an attempt to allide compiler optimization that internally use fma calculations +double det3_raw(double a00, + double a01, + double a02, + double a10, + double a11, + double a12, + double a20, + double a21, + double a22) +{ + volatile double m01 = a11 * a22 - a12 * a21; + volatile double m02 = a10 * a22 - a12 * a20; + volatile double m12 = a10 * a21 - a11 * a20; + + volatile double t0 = a00 * m01; + volatile double t1 = a01 * m02; + volatile double t2 = a02 * m12; + return (t0 - t1) + t2; +} +} // namespace + TEST(numerics_determinants, determinant_of_In) { const int N = 25; @@ -27,34 +108,260 @@ TEST(numerics_determinants, determinant5x5) const int N = 5; const double EPS = 1e-11; + // clang-format off axom::numerics::Matrix A(N, N); - A(0, 0) = 1; - A(0, 1) = 2; - A(0, 2) = 4; - A(0, 3) = 3; - A(0, 4) = 0; - A(1, 0) = 2; - A(1, 1) = 1; - A(1, 2) = -1; - A(1, 3) = 1; - A(1, 4) = 3; - A(2, 0) = 4; - A(2, 1) = -1; - A(2, 2) = -2; - A(2, 3) = 5; - A(2, 4) = 1; - A(3, 0) = 7; - A(3, 1) = 3; - A(3, 2) = 6; - A(3, 3) = 2; - A(3, 4) = 1; - A(4, 0) = 1; - A(4, 1) = 0; - A(4, 2) = -1; - A(4, 3) = 1; - A(4, 4) = 1; + A(0, 0) = 1; A(0, 1) = 2; A(0, 2) = 4; A(0, 3) = 3; A(0, 4) = 0; + A(1, 0) = 2; A(1, 1) = 1; A(1, 2) = -1; A(1, 3) = 1; A(1, 4) = 3; + A(2, 0) = 4; A(2, 1) = -1; A(2, 2) = -2; A(2, 3) = 5; A(2, 4) = 1; + A(3, 0) = 7; A(3, 1) = 3; A(3, 2) = 6; A(3, 3) = 2; A(3, 4) = 1; + A(4, 0) = 1; A(4, 1) = 0; A(4, 2) = -1; A(4, 3) = 1; A(4, 4) = 1; + // clang-format on double computed_det = axom::numerics::determinant(A); double expected_det = -34.0; EXPECT_NEAR(expected_det, computed_det, EPS); } + +//------------------------------------------------------------------------------ +TEST(numerics_determinants, check_ulps_apart_function) +{ + constexpr auto zero = std::uint64_t {0}; + constexpr auto one = std::uint64_t {1}; + constexpr auto two = std::uint64_t {2}; + constexpr auto three = std::uint64_t {3}; + + // test identity/equality + { + EXPECT_EQ(ulps_apart(1., 1.), zero); + EXPECT_EQ(ulps_apart(-0., +0.), zero); + } + + // test values around 1 + { + const double x = 1.; + const double up = std::nextafter(x, x + 1.); // next ulp in positive direction + const double down = std::nextafter(x, x - 1.); // nex ulp in negative direction + EXPECT_EQ(ulps_apart(x, up), one); + EXPECT_EQ(ulps_apart(x, down), one); + EXPECT_EQ(ulps_apart(down, up), two); + + // check symmetric + EXPECT_EQ(ulps_apart(x, up), ulps_apart(up, x)); + + // check a few increasing values + double y = x; + for(int k = 1; k <= 10; ++k) + { + y = nextafter(y, y + 1.); + EXPECT_EQ(ulps_apart(x, y), static_cast(k)); + } + } + + // test values around zero + { + const double ms = std::numeric_limits::denorm_min(); + const double nms = -ms; + EXPECT_EQ(ulps_apart(nms, -0.0), one); + EXPECT_EQ(ulps_apart(+0.0, ms), one); + EXPECT_EQ(ulps_apart(nms, ms), three); // -0 to +0 still counts as one ulp + + const double up = std::nextafter(ms, 1.); + EXPECT_EQ(ulps_apart(ms, up), one); + + const double down = std::nextafter(nms, -1.); + EXPECT_EQ(ulps_apart(nms, down), one); + } + + // test inf + { + const double mx = std::numeric_limits::max(); + const double inf = std::numeric_limits::infinity(); + EXPECT_EQ(ulps_apart(mx, nextafter(mx, inf)), one); + EXPECT_EQ(nextafter(mx, inf), inf); + EXPECT_EQ(ulps_apart(mx, inf), one); + + const double ninf = -inf; + const double nmx = -mx; + EXPECT_EQ(nextafter(nmx, ninf), ninf); + EXPECT_EQ(ulps_apart(nmx, ninf), one); + } + + // test NaN + { + constexpr uint64_t UMAX = std::numeric_limits::max(); + const double qnan = std::numeric_limits::quiet_NaN(); + EXPECT_EQ(ulps_apart(qnan, 1.0), UMAX); + EXPECT_EQ(ulps_apart(1.0, qnan), UMAX); + EXPECT_EQ(ulps_apart(qnan, qnan), UMAX); + } +} + +//------------------------------------------------------------------------------ +TEST(numerics_determinants, determinant_fma_reduces_ulp_for_cancellation) +{ + // Choose values that are exactly representable in double, but whose products are not. + // This forces rounding in intermediate products, and the determinant computation is sensitive to cancellation. + // + // Let b=c=2^27, a=2^27+1, d=2^27-1. + // Exact det = a*d - b*c = (2^54 - 1) - 2^54 = -1. + const double base = std::ldexp(1.0, 27); + const double a = base + 1.0; + const double b = base; + const double c = base; + const double d = base - 1.0; + constexpr double expected = -1.0; + + { + const double det_fma = axom::numerics::determinant(a, b, c, d); + const double det_raw = det2_raw(a, b, c, d); + + const auto ulp_fma = ulps_apart(det_fma, expected); + const auto ulp_raw = ulps_apart(det_raw, expected); + axom::fmt::print( + "2x2 cancellation: expected={} det_fma={} det_raw={} (ulps from expected: fma={} raw={})\n", + expected, + det_fma, + det_raw, + ulp_fma, + ulp_raw); + + EXPECT_DOUBLE_EQ(expected, det_fma); + EXPECT_LE(ulp_fma, ulp_raw); + } + + // Embed the same 2x2 cancellation into a 3x3 determinant. + { + const double det_fma = axom::numerics::determinant(a, b, 0.0, c, d, 0.0, 0.0, 0.0, 1.0); + const double det_raw = det3_raw(a, b, 0.0, c, d, 0.0, 0.0, 0.0, 1.0); + + const auto ulp_fma = ulps_apart(det_fma, expected); + const auto ulp_raw = ulps_apart(det_raw, expected); + + axom::fmt::print( + "3x3 cancellation: expected={} det_fma={} det_raw={} (ulps from expected: fma={} raw={})\n", + expected, + det_fma, + det_raw, + ulp_fma, + ulp_raw); + + EXPECT_DOUBLE_EQ(expected, det_fma); + EXPECT_LE(ulp_fma, ulp_raw); + } +} + +//------------------------------------------------------------------------------ +TEST(numerics_determinants, determinant_fma_reduces_ulp_statistics_2x2) +{ +#if !defined(__SIZEOF_INT128__) + GTEST_SKIP() << "Test requires __int128 for an exact integer reference determinant."; +#else + // Use many near-cancellation 2x2 determinants with integer inputs. + // Compare the ULP error against the correctly-rounded double value of the exact integer determinant. + + constexpr std::int64_t base = (1LL << 27); // exactly representable as double + constexpr int SAMPLES = 5000; + + std::mt19937_64 rng(42ULL); + std::uniform_int_distribution delta_dist(-2048, 2048); + + long double sum_raw_ulp = 0.0L; + long double sum_fma_ulp = 0.0L; + long double sum_delta = 0.0L; + + std::uint64_t max_raw_ulp = 0; + std::uint64_t max_fma_ulp = 0; + int better = 0; + int worse = 0; + int tied = 0; + + for(int i = 0; i < SAMPLES; ++i) + { + // use some explicit test cases, or random numbers otherwise + std::int64_t da {}, dd {}; + switch(i) + { + case 0: + da = 1.; + dd = -1.; + break; + case 1: + da = 2048; + dd = -2048; + break; + case 2: + da = 2048; + dd = 2028; + break; + default: + da = delta_dist(rng); + dd = delta_dist(rng); + break; + } + + // actual determinant should be an integer: (a_i * d_i) - (b_i * c_i) + const std::int64_t a_i = base + da; + const std::int64_t b_i = base; + const std::int64_t c_i = base; + const std::int64_t d_i = base + dd; + + const __int128 exact = // + static_cast<__int128>(a_i) * static_cast<__int128>(d_i) - + static_cast<__int128>(b_i) * static_cast<__int128>(c_i); + const double ref = static_cast(exact); + + const double a = static_cast(a_i); + const double b = static_cast(b_i); + const double c = static_cast(c_i); + const double d = static_cast(d_i); + + const double det_fma = axom::numerics::determinant(a, b, c, d); + const double det_raw = det2_raw(a, b, c, d); + + const std::uint64_t ulp_fma = ulps_apart(det_fma, ref); + const std::uint64_t ulp_raw = ulps_apart(det_raw, ref); + + sum_fma_ulp += static_cast(ulp_fma); + sum_raw_ulp += static_cast(ulp_raw); + sum_delta += static_cast(ulp_raw) - static_cast(ulp_fma); + + max_fma_ulp = std::max(max_fma_ulp, ulp_fma); + max_raw_ulp = std::max(max_raw_ulp, ulp_raw); + + if(ulp_fma < ulp_raw) + { + ++better; + } + else if(ulp_fma > ulp_raw) + { + ++worse; + } + else + { + ++tied; + } + } + + const long double mean_fma = sum_fma_ulp / static_cast(SAMPLES); + const long double mean_raw = sum_raw_ulp / static_cast(SAMPLES); + const long double mean_delta = sum_delta / static_cast(SAMPLES); + + axom::fmt::print( + "2x2 ULP stats for {} samples\n" + "\t mean_fma={} mean_raw={} mean_delta(raw-fma)={}\n" + "\t max_fma={} max_raw={}\n" + "\t better={} worse={} tied={}\n", + SAMPLES, + static_cast(mean_fma), + static_cast(mean_raw), + static_cast(mean_delta), + max_fma_ulp, + max_raw_ulp, + better, + worse, + tied); + + EXPECT_GE(mean_delta, 0.0L); + EXPECT_GE(better, worse); +#endif +} diff --git a/src/axom/core/utilities/RAII.hpp b/src/axom/core/utilities/RAII.hpp index b3ce856c34..1ca509bc6d 100644 --- a/src/axom/core/utilities/RAII.hpp +++ b/src/axom/core/utilities/RAII.hpp @@ -90,7 +90,7 @@ class MPIWrapper private: int m_rank {0}; int m_numranks {1}; - bool m_should_finalize {false}; + [[maybe_unused]] bool m_should_finalize {false}; }; /** diff --git a/src/axom/core/utilities/Utilities.hpp b/src/axom/core/utilities/Utilities.hpp index 1e09740215..ab55497844 100644 --- a/src/axom/core/utilities/Utilities.hpp +++ b/src/axom/core/utilities/Utilities.hpp @@ -194,6 +194,26 @@ inline AXOM_HOST_DEVICE T clampLower(T val, T lower) return val < lower ? lower : val; } +/*! + * \brief Determine whether a value is in [0,upper). + * \param value The value to check in the range. + * \param upper The upper value for the range (non-inclusive). + * \return True if value is in [0,upper); False otherwise. + * \note For unsigned types value must be >= 0 so we do not compare against 0. + */ +template +inline constexpr AXOM_HOST_DEVICE bool inBounds_0_N(T value, T upper) +{ + if constexpr(std::is_integral_v && !std::is_signed_v) + { + return value < upper; + } + else + { + return value >= 0 && value < upper; + } +} + /*! * \brief Computes the binomial coefficient `n choose k` * diff --git a/src/axom/lumberjack/Combiner.hpp b/src/axom/lumberjack/Combiner.hpp index e4dd5a136e..81ca34e348 100644 --- a/src/axom/lumberjack/Combiner.hpp +++ b/src/axom/lumberjack/Combiner.hpp @@ -52,6 +52,17 @@ class Combiner */ virtual const std::string id() = 0; + /*! + ***************************************************************************** + * \brief Function used by Lumberjack to indicate whether a Message class + * should be considered for this combiner. Default is true in the base class. + * + * \param [in] The Message to be considered. Unused in the base class + * but likely used in derived classes. + ***************************************************************************** + */ + virtual bool isMessageCandidateForCombiner(const Message&) { return true; } + /*! ***************************************************************************** * \brief Function used by Lumberjack to indicate whether two Message classes diff --git a/src/axom/lumberjack/LineFileTagCombiner.hpp b/src/axom/lumberjack/LineFileTagCombiner.hpp index 439f5f0006..bf8a4e09e1 100644 --- a/src/axom/lumberjack/LineFileTagCombiner.hpp +++ b/src/axom/lumberjack/LineFileTagCombiner.hpp @@ -45,7 +45,7 @@ class LineFileTagCombiner : public axom::lumberjack::Combiner * Lumberjack to differentiate between other combiners. ***************************************************************************** */ - const std::string id() { return m_id; } + const std::string id() override { return m_id; } /*! ***************************************************************************** @@ -61,7 +61,7 @@ class LineFileTagCombiner : public axom::lumberjack::Combiner ***************************************************************************** */ bool shouldMessagesBeCombined(const axom::lumberjack::Message& leftMessage, - const axom::lumberjack::Message& rightMessage) + const axom::lumberjack::Message& rightMessage) override { return ((leftMessage.lineNumber() == rightMessage.lineNumber()) && leftMessage.fileName().compare(rightMessage.fileName()) == 0 && @@ -88,7 +88,7 @@ class LineFileTagCombiner : public axom::lumberjack::Combiner */ void combine(axom::lumberjack::Message& combined, const axom::lumberjack::Message& combinee, - const int ranksLimit) + const int ranksLimit) override { combined.addRanks(combinee.ranks(), combinee.count(), ranksLimit); if(combinee.creationTime() < combined.creationTime()) diff --git a/src/axom/lumberjack/Lumberjack.cpp b/src/axom/lumberjack/Lumberjack.cpp index 550cb7671e..be6c4960b7 100644 --- a/src/axom/lumberjack/Lumberjack.cpp +++ b/src/axom/lumberjack/Lumberjack.cpp @@ -234,29 +234,65 @@ bool Lumberjack::isCommunicatorOwned() { return m_isCommunicatorOwned; } void Lumberjack::combineMessages() { int messagesSize = (int)m_messages.size(); + + // Early exit if there is only one message if(messagesSize < 2) { return; } + // Holds messages that are candidates for any combiners std::vector finalMessages; + + // Holds messages that are not candidates for any combiners + std::vector uncombinableMessages; + std::vector indexesToBeDeleted; int combinersSize = (int)m_combiners.size(); + // Early exit if there are no combiners if(combinersSize == 0) { return; } bool combinedMessage = false; - finalMessages.push_back(m_messages[0]); - for(int allIndex = 1; allIndex < messagesSize; ++allIndex) + for(int allIndex = 0; allIndex < messagesSize; ++allIndex) { combinedMessage = false; + + // Determine the combiners our current message is a candidate for + std::vector candidateCombiners; + + for(int combinerIndex = 0; combinerIndex < combinersSize; ++combinerIndex) + { + if(m_combiners[combinerIndex]->isMessageCandidateForCombiner(*m_messages[allIndex])) + { + candidateCombiners.push_back(combinerIndex); + } + } + + // If our current message is not a candidate for any combiner, it can never be + // combined, so we can skip the expensive duplicate checking. + if(candidateCombiners.empty()) + { + uncombinableMessages.push_back(m_messages[allIndex]); + continue; + } + + // Find the first message that shares a combiner with our current message + // and the combiner says both messages should be combined. Combine messages. for(int finalIndex = 0; finalIndex < (int)finalMessages.size(); ++finalIndex) { - for(int combinerIndex = 0; combinerIndex < combinersSize; ++combinerIndex) + for(unsigned int candidateCombinerIndex = 0; candidateCombinerIndex < candidateCombiners.size(); + ++candidateCombinerIndex) { + int combinerIndex = candidateCombiners[candidateCombinerIndex]; + if(!m_combiners[combinerIndex]->isMessageCandidateForCombiner(*finalMessages[finalIndex])) + { + continue; + } + if(m_combiners[combinerIndex]->shouldMessagesBeCombined(*finalMessages[finalIndex], *m_messages[allIndex])) { @@ -273,12 +309,16 @@ void Lumberjack::combineMessages() break; } } + + // If current message was not combined, add it to pool of candidates. if(!combinedMessage) { finalMessages.push_back(m_messages[allIndex]); } } + // Set m_messages to the final list of combined and uncombinable messages + finalMessages.insert(finalMessages.end(), uncombinableMessages.begin(), uncombinableMessages.end()); for(int i = 0; i < (int)indexesToBeDeleted.size(); ++i) { delete m_messages[indexesToBeDeleted[i]]; diff --git a/src/axom/lumberjack/TextEqualityCombiner.hpp b/src/axom/lumberjack/TextEqualityCombiner.hpp index 9850ad54e4..1796709890 100644 --- a/src/axom/lumberjack/TextEqualityCombiner.hpp +++ b/src/axom/lumberjack/TextEqualityCombiner.hpp @@ -52,7 +52,7 @@ class TextEqualityCombiner : public Combiner * Lumberjack to differentiate between other combiners. ***************************************************************************** */ - const std::string id() { return m_id; } + const std::string id() override { return m_id; } /*! ***************************************************************************** @@ -66,7 +66,7 @@ class TextEqualityCombiner : public Combiner * \param [in] rightMessage One of the Messages to be compared. ***************************************************************************** */ - bool shouldMessagesBeCombined(const Message& leftMessage, const Message& rightMessage) + bool shouldMessagesBeCombined(const Message& leftMessage, const Message& rightMessage) override { return (leftMessage.text().compare(rightMessage.text()) == 0); } @@ -88,7 +88,7 @@ class TextEqualityCombiner : public Combiner * \pre shouldMessagesBeCombined(combined, combinee) must be true ***************************************************************************** */ - void combine(Message& combined, const Message& combinee, const int ranksLimit) + void combine(Message& combined, const Message& combinee, const int ranksLimit) override { combined.addRanks(combinee.ranks(), combinee.count(), ranksLimit); if(combinee.creationTime() < combined.creationTime()) diff --git a/src/axom/lumberjack/TextTagCombiner.hpp b/src/axom/lumberjack/TextTagCombiner.hpp index 0857924cea..50d11b36ce 100644 --- a/src/axom/lumberjack/TextTagCombiner.hpp +++ b/src/axom/lumberjack/TextTagCombiner.hpp @@ -50,7 +50,7 @@ class TextTagCombiner : public Combiner * Lumberjack to differentiate between other combiners. ***************************************************************************** */ - const std::string id() { return m_id; } + const std::string id() override { return m_id; } /*! ***************************************************************************** @@ -64,7 +64,7 @@ class TextTagCombiner : public Combiner * \param [in] rightMessage One of the Messages to be compared. ***************************************************************************** */ - bool shouldMessagesBeCombined(const Message& leftMessage, const Message& rightMessage) + bool shouldMessagesBeCombined(const Message& leftMessage, const Message& rightMessage) override { return (leftMessage.text().compare(rightMessage.text()) == 0 && leftMessage.tag().compare(rightMessage.tag()) == 0); @@ -87,7 +87,7 @@ class TextTagCombiner : public Combiner * \pre shouldMessagesBeCombined(combined, combinee) must be true ***************************************************************************** */ - void combine(Message& combined, const Message& combinee, const int ranksLimit) + void combine(Message& combined, const Message& combinee, const int ranksLimit) override { combined.addRanks(combinee.ranks(), combinee.count(), ranksLimit); if(combinee.creationTime() < combined.creationTime()) diff --git a/src/axom/lumberjack/docs/sphinx/combiner_class.rst b/src/axom/lumberjack/docs/sphinx/combiner_class.rst index 31685b8781..2901e0b470 100644 --- a/src/axom/lumberjack/docs/sphinx/combiner_class.rst +++ b/src/axom/lumberjack/docs/sphinx/combiner_class.rst @@ -5,20 +5,27 @@ Combiner Class The Combiner class is an abstract base class that defines the interface for all Combiner classes. Concrete instances need to inherit from this class and -implement these functions to be used when Message classes are combined by the -Lumberjack class. +must implement these functions (with the exception of isMessageCandidateForCombiner) +to be used when Message classes are combined by the Lumberjack class. Functions --------- -========================= =================== -Name Description -========================= =================== -id Returns the unique differentiating identifier for the class instance. -shouldMessagesBeCombined Indicates if two messages should be combined. -combine Combines the second message into the first. -========================= =================== +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Name + - Description + * - id + - Returns the unique differentiating identifier for the class instance. + * - shouldMessagesBeCombined + - Indicates if two messages should be combined. + * - combine + - Combines the second message into the first. + * - isMessageCandidateForCombiner + - Indicates if a single message should be considered by this combiner. Optional to implement, default is always True. Concrete Instances ------------------ diff --git a/src/axom/lumberjack/docs/sphinx/core_concepts.rst b/src/axom/lumberjack/docs/sphinx/core_concepts.rst index 3e1b15321f..b156202cbb 100644 --- a/src/axom/lumberjack/docs/sphinx/core_concepts.rst +++ b/src/axom/lumberjack/docs/sphinx/core_concepts.rst @@ -21,7 +21,7 @@ Combiners and register them with Lumberjack. The idea is that each Combiner wou its own criteria for whether a Message should be combined and how to combine that specific Message with another of the same type. -Combiner's have two main functions, shouldMessagesBeCombined and combine. +Combiners have three main functions: shouldMessagesBeCombined, combine, and optionally isMessageCandidateForCombiner. The function shouldMessagesBeCombined, returns True if the pair of messages satisfy the associated criteria. For example in the TextTagCombiner, if the Text strings and tag strings are exactly equal, it signals they should be combined. @@ -32,6 +32,11 @@ that happens is the second Message's ranks gets added to the first and the messa is increased. This is because the text strings were equal. This may not be the case for all Combiners that you write yourself. +The optional function isMessageCandidateForCombiner is used by Lumberjack as a pre-filter +to determine whether a single Message should be considered by a specific Combiner. +By default the function always returns True, but custom Combiners can override it to skip +Messages that can never match their criteria. If the function returns +False for a Message, Lumberjack will not attempt to combine that Message using that Combiner. .. _communication_label: diff --git a/src/axom/lumberjack/tests/CMakeLists.txt b/src/axom/lumberjack/tests/CMakeLists.txt index d6683795b2..8deb5fcbf1 100644 --- a/src/axom/lumberjack/tests/CMakeLists.txt +++ b/src/axom/lumberjack/tests/CMakeLists.txt @@ -85,3 +85,17 @@ axom_add_executable(NAME lumberjack_speed_test_no_combiners axom_add_test(NAME lumberjack_speedTestNoCombiners COMMAND lumberjack_speed_test_no_combiners NUM_MPI_TASKS 1) + +#------------------------------------------------------------------------------ +# Performance test with non-combinable messages +#------------------------------------------------------------------------------ +axom_add_executable(NAME lumberjack_speed_test_skip_noncombinable + SOURCES lumberjack_speedTestSkipNoncombinable.cpp + OUTPUT_DIR ${TEST_OUTPUT_DIRECTORY} + DEPENDS_ON lumberjack + FOLDER axom/lumberjack/tests ) + +axom_add_test(NAME lumberjack_speedTestSkipNoncombinable + COMMAND lumberjack_speed_test_skip_noncombinable + NUM_MPI_TASKS 1 + PASS_REGULAR_EXPRESSION "After combining, there are 10,?001 messages.") diff --git a/src/axom/lumberjack/tests/lumberjack_Lumberjack.hpp b/src/axom/lumberjack/tests/lumberjack_Lumberjack.hpp index e02cddd6ca..eb1ca1b33a 100644 --- a/src/axom/lumberjack/tests/lumberjack_Lumberjack.hpp +++ b/src/axom/lumberjack/tests/lumberjack_Lumberjack.hpp @@ -6,6 +6,8 @@ #include "gtest/gtest.h" +#include "axom/core/Macros.hpp" + #include "axom/lumberjack/Lumberjack.hpp" #include "axom/lumberjack/Communicator.hpp" @@ -58,6 +60,81 @@ class TestCommunicator : public axom::lumberjack::Communicator double m_startTime; }; +class TestCombiner : public axom::lumberjack::Combiner +{ +public: + const std::string id() override { return m_id; } + + bool shouldMessagesBeCombined(const axom::lumberjack::Message& leftMessage, + const axom::lumberjack::Message& rightMessage) override + { + return (leftMessage.text().compare("foo") == 0 && rightMessage.text().compare("bar") == 0) || + (leftMessage.text().compare("bar") == 0 && rightMessage.text().compare("foo") == 0); + } + + void combine(axom::lumberjack::Message& combined, + const axom::lumberjack::Message& combinee, + const int ranksLimit) override + { + combined.addRanks(combinee.ranks(), combinee.count(), ranksLimit); + combined.text("foobar"); + } + +private: + const std::string m_id = "TestCombiner"; +}; + +class TestCandidateCombinerA : public TestCombiner +{ +public: + const std::string id() override { return m_id; } + + bool isMessageCandidateForCombiner(const axom::lumberjack::Message& m) override + { + return m.text().compare("foo") == 0 || m.text().compare("bar") == 0; + } + + bool shouldMessagesBeCombined(const axom::lumberjack::Message& leftMessage, + const axom::lumberjack::Message& rightMessage) override + { + AXOM_UNUSED_VAR(leftMessage); + AXOM_UNUSED_VAR(rightMessage); + return true; + } + +private: + const std::string m_id = "TestCandidateCombinerA"; +}; + +class TestCandidateCombinerB : public axom::lumberjack::Combiner +{ + const std::string id() override { return m_id; } + + bool isMessageCandidateForCombiner(const axom::lumberjack::Message& m) override + { + return m.text().compare("fizz") == 0 || m.text().compare("buzz") == 0; + } + + bool shouldMessagesBeCombined(const axom::lumberjack::Message& leftMessage, + const axom::lumberjack::Message& rightMessage) override + { + AXOM_UNUSED_VAR(leftMessage); + AXOM_UNUSED_VAR(rightMessage); + return true; + } + + void combine(axom::lumberjack::Message& combined, + const axom::lumberjack::Message& combinee, + const int ranksLimit) override + { + combined.addRanks(combinee.ranks(), combinee.count(), ranksLimit); + combined.text("fizzbuzz"); + } + +private: + const std::string m_id = "TestCandidateCombinerB"; +}; + TEST(lumberjack_Lumberjack, combineMessagesNoCombiners) { int ranksLimit = 5; @@ -91,6 +168,93 @@ TEST(lumberjack_Lumberjack, combineMessagesNoCombiners) communicator.finalize(); } +TEST(lumberjack_Lumberjack, combineMessagesMultipleCombiners) +{ + int ranksLimit = 5; + TestCommunicator communicator; + communicator.initialize(MPI_COMM_NULL, ranksLimit); + axom::lumberjack::Lumberjack lumberjack; + lumberjack.initialize(&communicator, ranksLimit); + + lumberjack.addCombiner(new TestCombiner); + + lumberjack.queueMessage("bar"); + lumberjack.queueMessage("Should be combined."); + lumberjack.queueMessage("foo"); + lumberjack.queueMessage("Should be combined."); + lumberjack.queueMessage("Should be combined."); + lumberjack.queueMessage("foo"); + lumberjack.queueMessage("bar"); + lumberjack.queueMessage("Should be combined."); + + lumberjack.pushMessagesOnce(); + + std::vector messages = lumberjack.getMessages(); + + EXPECT_EQ((int)messages.size(), 3); + + EXPECT_EQ(messages[0]->text(), "foobar"); + EXPECT_EQ(messages[0]->count(), 2); + + EXPECT_EQ(messages[1]->text(), "Should be combined."); + EXPECT_EQ(messages[1]->count(), 4); + + EXPECT_EQ(messages[2]->text(), "foobar"); + EXPECT_EQ(messages[2]->count(), 2); + + lumberjack.finalize(); + communicator.finalize(); +} + +TEST(lumberjack_Lumberjack, combineMessagesMultipleCombinersWithCandidates) +{ + int ranksLimit = 5; + TestCommunicator communicator; + communicator.initialize(MPI_COMM_NULL, ranksLimit); + axom::lumberjack::Lumberjack lumberjack; + lumberjack.initialize(&communicator, ranksLimit); + + // Both test Combiners have shouldMessagesBeCombined return true for any messages. + // The isMessageCandidateForCombiner check filters candidates to the correct + // combiners and skips expensive combining check for unqualified candidates. + lumberjack.removeCombiner("TextTagCombiner"); + lumberjack.addCombiner(new TestCandidateCombinerA); + lumberjack.addCombiner(new TestCandidateCombinerB); + + // Messages that will skip the combine step + for(int i = 0; i < 10000; i++) + { + lumberjack.queueMessage("Should not be combined.", i); + } + + // Messages to be combined + lumberjack.queueMessage("foo", 10000); + lumberjack.queueMessage("bar", 10000); + lumberjack.queueMessage("buzz", 10001); + lumberjack.queueMessage("fizz", 10001); + + // Messages are sorted by creation time + lumberjack.pushMessagesOnce(); + + std::vector messages = lumberjack.getMessages(); + + EXPECT_EQ((int)messages.size(), 10002); + + EXPECT_EQ(messages[10000]->text(), "foobar"); + EXPECT_EQ(messages[10000]->count(), 2); + EXPECT_EQ(messages[10001]->text(), "fizzbuzz"); + EXPECT_EQ(messages[10001]->count(), 2); + + for(int i = 0; i < 10000; i++) + { + EXPECT_EQ(messages[i]->text(), "Should not be combined."); + EXPECT_EQ(messages[i]->count(), 1); + } + + lumberjack.finalize(); + communicator.finalize(); +} + TEST(lumberjack_Lumberjack, combineMessagesPushOnce01) { int ranksLimit = 5; diff --git a/src/axom/lumberjack/tests/lumberjack_speedTestNoCombiners.cpp b/src/axom/lumberjack/tests/lumberjack_speedTestNoCombiners.cpp index 561eb933c5..526a8c616f 100644 --- a/src/axom/lumberjack/tests/lumberjack_speedTestNoCombiners.cpp +++ b/src/axom/lumberjack/tests/lumberjack_speedTestNoCombiners.cpp @@ -60,7 +60,7 @@ int main() lumberjack.initialize(&communicator, ranksLimit); // Remove default combiner (no combiners now) - lumberjack.removeCombiner("TextTagCreationTimeCombiner"); + lumberjack.removeCombiner("TextTagCombiner"); for(int i = 0; i < 100000; i++) { diff --git a/src/axom/lumberjack/tests/lumberjack_speedTestSkipNoncombinable.cpp b/src/axom/lumberjack/tests/lumberjack_speedTestSkipNoncombinable.cpp new file mode 100644 index 0000000000..cadba410d4 --- /dev/null +++ b/src/axom/lumberjack/tests/lumberjack_speedTestSkipNoncombinable.cpp @@ -0,0 +1,110 @@ +// Copyright (c) Lawrence Livermore National Security, LLC and other +// Axom Project Contributors. See top-level LICENSE and COPYRIGHT +// files for dates and other details. +// +// SPDX-License-Identifier: (BSD-3-Clause) + +#include "axom/lumberjack/Lumberjack.hpp" + +#include +#include + +class DummyCommunicator : public axom::lumberjack::Communicator +{ +public: + void initialize(MPI_Comm comm, int ranksLimit) + { + m_mpiComm = comm; + m_ranksLimit = ranksLimit; + m_isOutputNode = true; + srand(time(nullptr)); + m_startTime = 0.0; + } + + void finalize() { } + + MPI_Comm comm() { return m_mpiComm; } + + int rank() { return 0; } + + void ranksLimit(int value) { m_ranksLimit = value; } + + int ranksLimit() { return m_ranksLimit; } + + int numPushesToFlush() { return 1; } + + void push(const char* /* packedMessagesToBeSent */, + std::vector& /* receivedPackedMessages */) + { } + + bool isOutputNode() { return m_isOutputNode; } + + void outputNode(bool value) { m_isOutputNode = value; } + + double startTime() { return m_startTime; } + +private: + MPI_Comm m_mpiComm; + int m_ranksLimit; + bool m_isOutputNode; + double m_startTime; +}; + +// Inherits from TextTagCombiner - only messages with tag "tagA" are candidates +class CombinerTagA : public axom::lumberjack::TextTagCombiner +{ +public: + const std::string id() { return m_id; } + + bool isMessageCandidateForCombiner(const axom::lumberjack::Message& m) + { + return m.tag() == "tagA"; + } + +private: + const std::string m_id = "TagACombiner"; +}; + +//------------------------------------------------------------------------------ +int main() +{ + int ranksLimit = 5; + DummyCommunicator communicator; + communicator.initialize(MPI_COMM_NULL, ranksLimit); + axom::lumberjack::Lumberjack lumberjack; + lumberjack.initialize(&communicator, ranksLimit); + + // Remove default combiner, use custom combiner + lumberjack.removeCombiner("TextTagCombiner"); + lumberjack.addCombiner(new CombinerTagA); + + // Combinable message + lumberjack.queueMessage("Should be combined.", "", 0, 0, 0.0, "tagA"); + + // Unique, uncombinable messages (different text) + for(int i = 0; i < 10000; i++) + { + lumberjack.queueMessage("Unique message " + std::to_string(i) + " is not combinable ", + "", + 0, + 0, + 1.0, + "ignoreTag"); + } + lumberjack.queueMessage("Should be combined.", "", 0, 0, 0.0, "tagA"); + + std::clock_t begin = clock(); + lumberjack.pushMessagesOnce(); + std::clock_t end = clock(); + + std::cout << "After combining, there are " << lumberjack.getMessages().size() << " messages." + << std::endl; + + lumberjack.finalize(); + communicator.finalize(); + + std::cout << "Elapsed time to push messages (ms): " + << ((double)(end - begin) * 1000) / CLOCKS_PER_SEC << std::endl; + + return 0; +} diff --git a/src/axom/mir/ElviraAlgorithm.hpp b/src/axom/mir/ElviraAlgorithm.hpp index 2305e3d4ff..13a9731086 100644 --- a/src/axom/mir/ElviraAlgorithm.hpp +++ b/src/axom/mir/ElviraAlgorithm.hpp @@ -122,11 +122,32 @@ class ElviraAlgorithm : public axom::mir::MIRAlgorithm , m_topologyView(topoView) , m_coordsetView(coordsetView) , m_matsetView(matsetView) + , m_allocator_id(axom::execution_space::allocatorID()) { } /// Destructor virtual ~ElviraAlgorithm() = default; + /*! + * \brief Set the allocator id to use when allocating memory. + * + * \param allocator_id The allocator id to use when allocating memory. + */ + void setAllocatorID(int allocator_id) + { + SLIC_ERROR_IF(!axom::isValidAllocatorID(allocator_id), "Invalid allocator id."); + SLIC_ERROR_IF(!axom::execution_space::usesAllocId(allocator_id), + "Allocator id is not compatible with execution space."); + m_allocator_id = allocator_id; + } + + /*! + * \brief Get the allocator id to use when allocating memory. + * + * \return The allocator id to use when allocating memory. + */ + int getAllocatorID() const { return m_allocator_id; } + // The following members are protected (unless using CUDA) #if !defined(__CUDACC__) protected: @@ -165,18 +186,22 @@ class ElviraAlgorithm : public axom::mir::MIRAlgorithm // Copy the options to make sure they are in the right memory space. conduit::Node n_options_copy; - utils::copy(n_options_copy, n_options); + utils::copy(n_options_copy, n_options, getAllocatorID()); n_options_copy["topology"] = n_topo.name(); // _bump_utilities_selectedzones_begin // Get selected zones from the options. - bump::SelectedZones selectedZones(m_topologyView.numberOfZones(), n_options_copy); + bump::SelectedZones selectedZones(m_topologyView.numberOfZones(), + n_options_copy, + "selectedZones", + getAllocatorID()); const auto selectedZonesView = selectedZones.view(); // _bump_utilities_selectedzones_end // Partition the selected zones into clean, mixed lists. axom::Array cleanZones, mixedZones; bump::ZoneListBuilder zlb(m_topologyView, m_matsetView); + zlb.setAllocatorID(getAllocatorID()); zlb.execute(selectedZonesView, cleanZones, mixedZones); SLIC_ASSERT((cleanZones.size() + mixedZones.size()) == selectedZonesView.size()); SLIC_INFO( @@ -341,14 +366,15 @@ class ElviraAlgorithm : public axom::mir::MIRAlgorithm // Merge clean and MIR output. std::vector inputs(2); inputs[0].m_input = &n_cleanOutput; - inputs[0].topologyName = topoName; + inputs[0].m_topologyName = topoName; inputs[1].m_input = &n_mirOutput; - inputs[1].topologyName = topoName; + inputs[1].m_topologyName = topoName; conduit::Node mmOpts; mmOpts["topologyName"] = topoName; MergeMeshes mm; + mm.setAllocatorID(getAllocatorID()); mm.execute(inputs, mmOpts, n_merged); } @@ -368,14 +394,15 @@ class ElviraAlgorithm : public axom::mir::MIRAlgorithm { AXOM_ANNOTATE_SCOPE("addOriginal"); namespace utils = axom::bump::utilities; - utils::ConduitAllocateThroughAxom c2a; + const auto conduitAllocatorID = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); const auto nvalues = selectedZonesView.size(); // Add a new field for the original ids. n_field["topology"] = topoName; n_field["association"] = association; - n_field["values"].set_allocator(c2a.getConduitAllocatorID()); + n_field["values"].set_allocator(conduitAllocatorID); n_field["values"].set(conduit::DataType(utils::cpp2conduit::id, nvalues)); auto view = utils::make_array_view(n_field["values"]); axom::for_all( @@ -417,6 +444,7 @@ class ElviraAlgorithm : public axom::mir::MIRAlgorithm // _bump_utilities_makepointmesh_begin // Make a point mesh of the selected zones. bump::MakePointMesh pm(m_topologyView, m_coordsetView); + pm.setAllocatorID(getAllocatorID()); pm.execute(cleanZones, n_topology, n_coordset, n_options, n_cleanOutput); // _bump_utilities_makepointmesh_end @@ -424,6 +452,7 @@ class ElviraAlgorithm : public axom::mir::MIRAlgorithm bump::MatsetSlicer mslicer(m_matsetView); bump::SliceData slice; slice.m_indicesView = cleanZones; + mslicer.setAllocatorID(getAllocatorID()); mslicer.execute(slice, n_matset, n_cleanOutput["matsets/" + opts.matsetName(n_matset.name())]); // Add an originalElements array. @@ -457,7 +486,8 @@ class ElviraAlgorithm : public axom::mir::MIRAlgorithm m_topologyView, m_coordsetView, m_matsetView, - n_cleanOutput); + n_cleanOutput, + getAllocatorID()); } #if defined(AXOM_ELVIRA_DEBUG) @@ -497,7 +527,6 @@ class ElviraAlgorithm : public axom::mir::MIRAlgorithm { AXOM_ANNOTATE_SCOPE("processMixedZones"); namespace utils = axom::bump::utilities; - const int allocatorID = axom::execution_space::allocatorID(); // Note: MSVC needs constexpr lambda capture to be marked `static` even though constexpr should suffice static constexpr int NDIMS = TopologyView::dimension(); @@ -545,8 +574,8 @@ class ElviraAlgorithm : public axom::mir::MIRAlgorithm AXOM_ANNOTATE_BEGIN("counting"); const auto nzones = mixedZonesView.size(); - axom::Array matCount(nzones, nzones, allocatorID); - axom::Array matZone(nzones, nzones, allocatorID); + axom::Array matCount(nzones, nzones, getAllocatorID()); + axom::Array matZone(nzones, nzones, getAllocatorID()); auto matCountView = matCount.view(); auto matZoneView = matZone.view(); @@ -602,7 +631,7 @@ class ElviraAlgorithm : public axom::mir::MIRAlgorithm //-------------------------------------------------------------------------- AXOM_ANNOTATE_BEGIN("offsets"); - axom::Array matOffset(nzones, nzones, allocatorID); + axom::Array matOffset(nzones, nzones, getAllocatorID()); auto matOffsetView = matOffset.view(); axom::exclusive_scan(matCountView, matOffsetView); #if defined(AXOM_ELVIRA_GATHER_INFO) @@ -623,6 +652,7 @@ class ElviraAlgorithm : public axom::mir::MIRAlgorithm // _bump_utilities_makezonecenters_begin bump::MakeZoneCenters zc(m_topologyView, m_coordsetView); conduit::Node n_zcfield; + zc.setAllocatorID(getAllocatorID()); zc.execute(n_topo, n_coordset, n_zcfield); // _bump_utilities_makezonecenters_end axom::ArrayView xview, yview, zview; @@ -648,24 +678,24 @@ class ElviraAlgorithm : public axom::mir::MIRAlgorithm AXOM_ANNOTATE_BEGIN("stencil"); const auto numFragmentsStencil = numFragments * StencilSize; - axom::Array fragmentVFStencil(numFragmentsStencil, numFragmentsStencil, allocatorID); + axom::Array fragmentVFStencil(numFragmentsStencil, numFragmentsStencil, getAllocatorID()); auto fragmentVFStencilView = fragmentVFStencil.view(); // Sorted material ids / vfs for each zone. axom::Array sortedMaterialIds(numFragments, numFragments, - allocatorID); + getAllocatorID()); axom::Array sortedMaterialVfs(numFragments, numFragments, - allocatorID); + getAllocatorID()); auto sortedMaterialIdsView = sortedMaterialIds.view(); auto sortedMaterialVfsView = sortedMaterialVfs.view(); // Coordinate stencil data for each zone. const auto nzonesStencil = nzones * StencilSize; - axom::Array xcStencil(nzonesStencil, nzonesStencil, allocatorID); - axom::Array ycStencil(nzonesStencil, nzonesStencil, allocatorID); - axom::Array zcStencil(nzonesStencil, nzonesStencil, allocatorID); + axom::Array xcStencil(nzonesStencil, nzonesStencil, getAllocatorID()); + axom::Array ycStencil(nzonesStencil, nzonesStencil, getAllocatorID()); + axom::Array zcStencil(nzonesStencil, nzonesStencil, getAllocatorID()); auto xcStencilView = xcStencil.view(); auto ycStencilView = ycStencil.view(); auto zcStencilView = zcStencil.view(); @@ -695,7 +725,7 @@ class ElviraAlgorithm : public axom::mir::MIRAlgorithm axom::utilities::reverse_sort_multiple(vfs.data(), ids.data(), matCount); // Retrieve the stencil data from neighbor zones. - auto logical = deviceTopologyView.indexing().IndexToLogicalIndex(zoneIndex); + auto logical = deviceTopologyView.indexing().indexToLogicalIndex(zoneIndex); for(int si = 0; si < StencilSize; si++) { // Stencil neighbor logical index. @@ -711,7 +741,7 @@ class ElviraAlgorithm : public axom::mir::MIRAlgorithm // Clamp the neighbor to a zone that is inside the indexing space. neighbor = deviceTopologyView.indexing().clamp(neighbor); const auto neighborIndex = static_cast( - deviceTopologyView.indexing().LogicalIndexToIndex(neighbor)); + deviceTopologyView.indexing().logicalIndexToIndex(neighbor)); const auto matNeighborIndex = static_cast(neighborIndex); // Copy material vfs into the stencil. @@ -747,7 +777,7 @@ class ElviraAlgorithm : public axom::mir::MIRAlgorithm //-------------------------------------------------------------------------- AXOM_ANNOTATE_BEGIN("vectors"); const auto vecSize = numFragments * numVectorComponents; - axom::Array fragmentVectors(vecSize, vecSize, allocatorID); + axom::Array fragmentVectors(vecSize, vecSize, getAllocatorID()); auto fragmentVectorsView = fragmentVectors.view(); #if defined(AXOM_ELVIRA_GATHER_INFO) @@ -838,7 +868,14 @@ class ElviraAlgorithm : public axom::mir::MIRAlgorithm // Make the builder that will set up the Blueprint output. Builder build; - build.allocate(numFragments, maxCuts, n_newCoordset, n_newTopo, n_newFields, n_newMatset, n_options); + build.allocate(numFragments, + maxCuts, + n_newCoordset, + n_newTopo, + n_newFields, + n_newMatset, + n_options, + getAllocatorID()); if(n_matset.has_path("material_map")) { n_newMatset["material_map"].set(n_matset["material_map"]); @@ -1092,6 +1129,7 @@ class ElviraAlgorithm : public axom::mir::MIRAlgorithm TopologyView m_topologyView; CoordsetView m_coordsetView; MatsetView m_matsetView; + int m_allocator_id; }; } // end namespace mir diff --git a/src/axom/mir/EquiZAlgorithm.hpp b/src/axom/mir/EquiZAlgorithm.hpp index f06f4f5ae7..f0ca1f7e9c 100644 --- a/src/axom/mir/EquiZAlgorithm.hpp +++ b/src/axom/mir/EquiZAlgorithm.hpp @@ -79,11 +79,32 @@ class EquiZAlgorithm : public axom::mir::MIRAlgorithm , m_coordsetView(coordsetView) , m_matsetView(matsetView) , m_selectionKey("selectedZones") + , m_allocator_id(axom::execution_space::allocatorID()) { } /// Destructor virtual ~EquiZAlgorithm() = default; + /*! + * \brief Set the allocator id to use when allocating memory. + * + * \param allocator_id The allocator id to use when allocating memory. + */ + void setAllocatorID(int allocator_id) + { + SLIC_ERROR_IF(!axom::isValidAllocatorID(allocator_id), "Invalid allocator id."); + SLIC_ERROR_IF(!axom::execution_space::usesAllocId(allocator_id), + "Allocator id is not compatible with execution space."); + m_allocator_id = allocator_id; + } + + /*! + * \brief Get the allocator id to use when allocating memory. + * + * \return The allocator id to use when allocating memory. + */ + int getAllocatorID() const { return m_allocator_id; } + // The following members are protected (unless using CUDA) #if !defined(__CUDACC__) protected: @@ -121,7 +142,7 @@ class EquiZAlgorithm : public axom::mir::MIRAlgorithm // Copy the options. conduit::Node n_options_copy; - utils::copy(n_options_copy, n_options); + utils::copy(n_options_copy, n_options, getAllocatorID()); n_options_copy["topology"] = n_topo.name(); #if defined(AXOM_EQUIZ_DEBUG) @@ -304,6 +325,7 @@ class EquiZAlgorithm : public axom::mir::MIRAlgorithm namespace utils = axom::bump::utilities; axom::bump::ZoneListBuilder zlb(m_topologyView, m_matsetView); + zlb.setAllocatorID(getAllocatorID()); [[maybe_unused]] axom::IndexType expectedSize = 0; if(n_options.has_child(m_selectionKey)) { @@ -364,6 +386,7 @@ class EquiZAlgorithm : public axom::mir::MIRAlgorithm conduit::Node mmOpts; mmOpts["topology"] = topoName; MergeMeshes mm; + mm.setAllocatorID(getAllocatorID()); mm.execute(inputs, mmOpts, n_merged); } @@ -386,12 +409,13 @@ class EquiZAlgorithm : public axom::mir::MIRAlgorithm { AXOM_ANNOTATE_SCOPE("addOriginal"); namespace utils = axom::bump::utilities; - utils::ConduitAllocateThroughAxom c2a; + const auto conduitAllocatorID = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); // Add a new field for the original ids. n_field["topology"] = topoName; n_field["association"] = association; - n_field["values"].set_allocator(c2a.getConduitAllocatorID()); + n_field["values"].set_allocator(conduitAllocatorID); n_field["values"].set(conduit::DataType(utils::cpp2conduit::id, nvalues)); auto view = utils::make_array_view(n_field["values"]); axom::for_all( @@ -439,6 +463,7 @@ class EquiZAlgorithm : public axom::mir::MIRAlgorithm n_ezopts[key].set(n_options[key]); } } + ez.setAllocatorID(getAllocatorID()); ez.execute(cleanZones, n_root, n_ezopts, n_cleanOutput); #if defined(AXOM_EQUIZ_DEBUG) AXOM_ANNOTATE_BEGIN("saveClean"); @@ -667,13 +692,13 @@ class EquiZAlgorithm : public axom::mir::MIRAlgorithm AXOM_ANNOTATE_SCOPE("cleanup"); for(const auto &mat : allMats) { - const std::string nodalMatName(nodalFieldName(mat.number)); + const std::string nodalMatName(nodalFieldName(mat.m_number)); if(n_newFields.has_child(nodalMatName)) { n_newFields.remove(nodalMatName); } #if defined(AXOM_EQUIZ_DEBUG) - const std::string zonalMatName(zonalFieldName(mat.number)); + const std::string zonalMatName(zonalFieldName(mat.m_number)); if(n_newFields.has_child(zonalMatName)) { n_newFields.remove(zonalMatName); @@ -786,13 +811,15 @@ class EquiZAlgorithm : public axom::mir::MIRAlgorithm { AXOM_ANNOTATE_SCOPE("relation"); axom::bump::NodeToZoneRelationBuilder rb; + rb.setAllocatorID(getAllocatorID()); rb.execute(n_topo, n_coordset, relation); //printNode(relation); //std::cout.flush(); } // Get the ID of a Conduit allocator that will allocate through Axom with device allocator allocatorID. - utils::ConduitAllocateThroughAxom c2a; + const auto conduitAllocatorID = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); // Make nodal VFs for each mixed material. const auto nzones = m_topologyView.numberOfZones(); @@ -801,12 +828,12 @@ class EquiZAlgorithm : public axom::mir::MIRAlgorithm AXOM_ANNOTATE_SCOPE("zonal"); for(const auto &mat : mixedMats) { - const int matNumber = mat.number; + const int matNumber = mat.m_number; const std::string zonalName = zonalFieldName(matNumber); conduit::Node &n_zonalField = n_fields[zonalName]; n_zonalField["topology"] = n_topo.name(); n_zonalField["association"] = "element"; - n_zonalField["values"].set_allocator(c2a.getConduitAllocatorID()); + n_zonalField["values"].set_allocator(conduitAllocatorID); n_zonalField["values"].set(conduit::DataType(utils::cpp2conduit::id, nzones)); auto zonalFieldView = utils::make_array_view(n_zonalField["values"]); @@ -826,7 +853,7 @@ class EquiZAlgorithm : public axom::mir::MIRAlgorithm AXOM_ANNOTATE_SCOPE("recenter"); for(const auto &mat : mixedMats) { - const int matNumber = mat.number; + const int matNumber = mat.m_number; const std::string zonalName = zonalFieldName(matNumber); conduit::Node &n_zonalField = n_fields[zonalName]; @@ -835,9 +862,10 @@ class EquiZAlgorithm : public axom::mir::MIRAlgorithm conduit::Node &n_nodalField = n_fields[nodalName]; n_nodalField["topology"] = n_topo.name(); n_nodalField["association"] = "vertex"; - n_nodalField["values"].set_allocator(c2a.getConduitAllocatorID()); + n_nodalField["values"].set_allocator(conduitAllocatorID); n_nodalField["values"].set(conduit::DataType(utils::cpp2conduit::id, nnodes)); axom::bump::RecenterField z2n; + z2n.setAllocatorID(getAllocatorID()); z2n.execute(n_zonalField, relation, n_nodalField); #if !defined(AXOM_EQUIZ_DEBUG) @@ -866,7 +894,8 @@ class EquiZAlgorithm : public axom::mir::MIRAlgorithm AXOM_ANNOTATE_SCOPE("makeWorkingFields"); // Get the ID of a Conduit allocator that will allocate through Axom with device allocator allocatorID. - utils::ConduitAllocateThroughAxom c2a; + const auto conduitAllocatorID = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); const auto nzones = m_topologyView.numberOfZones(); @@ -874,7 +903,7 @@ class EquiZAlgorithm : public axom::mir::MIRAlgorithm conduit::Node &n_zonalIDField = n_fields[zonalMaterialIDName()]; n_zonalIDField["topology"] = n_topo.name(); n_zonalIDField["association"] = "element"; - n_zonalIDField["values"].set_allocator(c2a.getConduitAllocatorID()); + n_zonalIDField["values"].set_allocator(conduitAllocatorID); n_zonalIDField["values"].set(conduit::DataType(utils::cpp2conduit::id, nzones)); auto zonalIDFieldView = utils::make_array_view(n_zonalIDField["values"]); @@ -888,7 +917,7 @@ class EquiZAlgorithm : public axom::mir::MIRAlgorithm MatsetView deviceMatsetView(m_matsetView); for(const auto &mat : cleanMats) { - const int matNumber = mat.number; + const int matNumber = mat.m_number; axom::for_all( nzones, AXOM_LAMBDA(axom::IndexType zoneIndex) { @@ -989,12 +1018,12 @@ class EquiZAlgorithm : public axom::mir::MIRAlgorithm for(int index = 0; index < nmats; index++) { // Add a matvf view to the intersector. - const std::string matFieldName = nodalFieldName(allMats[index].number); + const std::string matFieldName = nodalFieldName(allMats[index].m_number); auto matVFView = utils::make_array_view(n_fields.fetch_existing(matFieldName + "/values")); intersector.addMaterial(matVFView); - matNumber.push_back(allMats[index].number); + matNumber.push_back(allMats[index].m_number); matIndex.push_back(index); } // Sort indices by matNumber. @@ -1006,7 +1035,7 @@ class EquiZAlgorithm : public axom::mir::MIRAlgorithm int currentMatIndex = 0; for(axom::IndexType i = 0; i < matNumber.size(); i++) { - if(matNumber[i] == currentMat.number) + if(matNumber[i] == currentMat.m_number) { currentMatIndex = matIndex[i]; break; @@ -1020,7 +1049,7 @@ class EquiZAlgorithm : public axom::mir::MIRAlgorithm axom::copy(matIndexDevice.data(), matIndex.data(), sizeof(int) * nmats); intersector.setMaterialNumbers(matNumberDevice.view()); intersector.setMaterialIndices(matIndexDevice.view()); - intersector.setCurrentMaterial(currentMat.number, currentMatIndex); + intersector.setCurrentMaterial(currentMat.m_number, currentMatIndex); // Store the current zone material ids and current material number into the intersector. intersector.setZoneMaterialID(utils::make_array_view( @@ -1066,6 +1095,7 @@ class EquiZAlgorithm : public axom::mir::MIRAlgorithm ICoordsetView, IntersectorType>; ClipperType clipper(topoView, coordsetView, intersector); + clipper.setAllocatorID(getAllocatorID()); clipper.execute(n_topo, n_coordset, n_fields, options, n_newTopo, n_newCoordset, n_newFields); } @@ -1085,7 +1115,7 @@ class EquiZAlgorithm : public axom::mir::MIRAlgorithm conduit::Node &n_zonalMaterialID = n_newFields.fetch_existing(zonalMaterialIDName() + "/values"); auto zonalMaterialID = utils::make_array_view(n_zonalMaterialID); - const int currentMatNumber = currentMat.number; + const int currentMatNumber = currentMat.m_number; axom::for_all( nzonesNew, AXOM_LAMBDA(axom::IndexType zoneIndex) { @@ -1157,12 +1187,13 @@ class EquiZAlgorithm : public axom::mir::MIRAlgorithm conduit::Node &n_offsets = n_newMatset["offsets"]; conduit::Node &n_indices = n_newMatset["indices"]; - utils::ConduitAllocateThroughAxom c2a; - n_material_ids.set_allocator(c2a.getConduitAllocatorID()); - n_volume_fractions.set_allocator(c2a.getConduitAllocatorID()); - n_sizes.set_allocator(c2a.getConduitAllocatorID()); - n_offsets.set_allocator(c2a.getConduitAllocatorID()); - n_indices.set_allocator(c2a.getConduitAllocatorID()); + const auto conduitAllocatorID = + axom::sidre::ConduitMemory::axomAllocIdToConduit(getAllocatorID()); + n_material_ids.set_allocator(conduitAllocatorID); + n_volume_fractions.set_allocator(conduitAllocatorID); + n_sizes.set_allocator(conduitAllocatorID); + n_offsets.set_allocator(conduitAllocatorID); + n_indices.set_allocator(conduitAllocatorID); // We'll store the output matset in the same types as the input matset. using MIntType = typename MatsetView::IndexType; @@ -1196,6 +1227,7 @@ class EquiZAlgorithm : public axom::mir::MIRAlgorithm CoordsetView m_coordsetView; MatsetView m_matsetView; std::string m_selectionKey; + int m_allocator_id; }; } // end namespace mir diff --git a/src/axom/mir/detail/elvira_detail.hpp b/src/axom/mir/detail/elvira_detail.hpp index 86d2607203..3c31280ead 100644 --- a/src/axom/mir/detail/elvira_detail.hpp +++ b/src/axom/mir/detail/elvira_detail.hpp @@ -271,6 +271,7 @@ class TopologyBuilder::allocatorID()) { namespace utils = axom::bump::utilities; - utils::ConduitAllocateThroughAxom c2a; + const auto conduitAllocatorId = axom::sidre::ConduitMemory::axomAllocIdToConduit(allocator_id); // Handle options ELVIRAOptions opts(n_options); @@ -294,42 +296,52 @@ class TopologyBuilder::id, numCoordValues)); m_view.m_x = utils::make_array_view(n_coordset["values/x"]); - n_coordset["values/y"].set_allocator(c2a.getConduitAllocatorID()); + n_coordset["values/y"].set_allocator(conduitAllocatorId); n_coordset["values/y"].set(conduit::DataType(utils::cpp2conduit::id, numCoordValues)); m_view.m_y = utils::make_array_view(n_coordset["values/y"]); - m_view.m_x.fill(CoordType(0)); - m_view.m_y.fill(CoordType(0)); - // Set up connectivity and allocate data arrays. n_topology["type"] = "unstructured"; n_topology["elements/shape"] = m_view.m_makePointMesh ? "point" : "polygonal"; conduit::Node &n_conn = n_topology["elements/connectivity"]; - n_conn.set_allocator(c2a.getConduitAllocatorID()); + n_conn.set_allocator(conduitAllocatorId); n_conn.set(conduit::DataType(utils::cpp2conduit::id, numCoordValues)); m_view.m_connectivity = utils::make_array_view(n_conn); - m_view.m_connectivity.fill(ConnectivityType(0)); + + // Initialize the arrays + { + const auto dev_x = m_view.m_x; + const auto dev_y = m_view.m_y; + const auto dev_connectivity = m_view.m_connectivity; + axom::for_all( + numCoordValues, + AXOM_LAMBDA(axom::IndexType index) { + dev_x[index] = CoordType(0); + dev_y[index] = CoordType(0); + dev_connectivity[index] = ConnectivityType(0); + }); + } conduit::Node &n_sizes = n_topology["elements/sizes"]; - n_sizes.set_allocator(c2a.getConduitAllocatorID()); + n_sizes.set_allocator(conduitAllocatorId); n_sizes.set(conduit::DataType(utils::cpp2conduit::id, numFragments)); m_view.m_sizes = utils::make_array_view(n_sizes); conduit::Node &n_offsets = n_topology["elements/offsets"]; - n_offsets.set_allocator(c2a.getConduitAllocatorID()); + n_offsets.set_allocator(conduitAllocatorId); n_offsets.set(conduit::DataType(utils::cpp2conduit::id, numFragments)); m_view.m_offsets = utils::make_array_view(n_offsets); @@ -338,7 +350,7 @@ class TopologyBuilder::id, numFragments)); m_view.m_original_zones = utils::make_array_view(n_orig_elem_values); @@ -349,10 +361,10 @@ class TopologyBuilder::id, numFragments)); m_view.m_norm_x = utils::make_array_view(n_x); - n_y.set_allocator(c2a.getConduitAllocatorID()); + n_y.set_allocator(conduitAllocatorId); n_y.set(conduit::DataType(utils::cpp2conduit::id, numFragments)); m_view.m_norm_y = utils::make_array_view(n_y); @@ -360,7 +372,7 @@ class TopologyBuilder::id, numFragments)); m_view.m_plane_offset = utils::make_array_view(n_values); } @@ -368,28 +380,33 @@ class TopologyBuilder::id, numFragments)); m_view.m_volume_fractions = utils::make_array_view(n_volume_fractions); conduit::Node &n_material_ids = n_matset["material_ids"]; - n_material_ids.set_allocator(c2a.getConduitAllocatorID()); + n_material_ids.set_allocator(conduitAllocatorId); n_material_ids.set(conduit::DataType(utils::cpp2conduit::id, numFragments)); m_view.m_material_ids = utils::make_array_view(n_material_ids); conduit::Node &n_indices = n_matset["indices"]; - n_indices.set_allocator(c2a.getConduitAllocatorID()); + n_indices.set_allocator(conduitAllocatorId); n_indices.set(conduit::DataType(utils::cpp2conduit::id, numFragments)); m_view.m_mat_indices = utils::make_array_view(n_indices); conduit::Node &n_mat_sizes = n_matset["sizes"]; - n_mat_sizes.set_allocator(c2a.getConduitAllocatorID()); + n_mat_sizes.set_allocator(conduitAllocatorId); n_mat_sizes.set(conduit::DataType(utils::cpp2conduit::id, numFragments)); m_view.m_mat_sizes = utils::make_array_view(n_mat_sizes); - m_view.m_mat_sizes.fill(MaterialID(0)); + { + const auto dev_mat_sizes = m_view.m_mat_sizes; + axom::for_all( + numFragments, + AXOM_LAMBDA(axom::IndexType index) { dev_mat_sizes[index] = MaterialID(0); }); + } conduit::Node &n_mat_offsets = n_matset["offsets"]; - n_mat_offsets.set_allocator(c2a.getConduitAllocatorID()); + n_mat_offsets.set_allocator(conduitAllocatorId); n_mat_offsets.set(conduit::DataType(utils::cpp2conduit::id, numFragments)); m_view.m_mat_offsets = utils::make_array_view(n_mat_offsets); } @@ -420,7 +437,7 @@ class TopologyBuilder(connOffset + i); @@ -496,7 +513,7 @@ class TopologyBuilder::allocatorID()) { namespace utils = axom::bump::utilities; - utils::ConduitAllocateThroughAxom c2a; + const auto conduitAllocatorId = axom::sidre::ConduitMemory::axomAllocIdToConduit(allocator_id); // Handle options ELVIRAOptions opts(n_options); @@ -573,28 +592,37 @@ class TopologyBuilder::id, numCoordValues)); m_view.m_x = utils::make_array_view(n_coordset["values/x"]); - n_coordset["values/y"].set_allocator(c2a.getConduitAllocatorID()); + n_coordset["values/y"].set_allocator(conduitAllocatorId); n_coordset["values/y"].set(conduit::DataType(utils::cpp2conduit::id, numCoordValues)); m_view.m_y = utils::make_array_view(n_coordset["values/y"]); - n_coordset["values/z"].set_allocator(c2a.getConduitAllocatorID()); + n_coordset["values/z"].set_allocator(conduitAllocatorId); n_coordset["values/z"].set(conduit::DataType(utils::cpp2conduit::id, numCoordValues)); m_view.m_z = utils::make_array_view(n_coordset["values/z"]); - m_view.m_x.fill(CoordType(0)); - m_view.m_y.fill(CoordType(0)); - m_view.m_z.fill(CoordType(0)); + { + const auto dev_x = m_view.m_x; + const auto dev_y = m_view.m_y; + const auto dev_z = m_view.m_z; + axom::for_all( + numCoordValues, + AXOM_LAMBDA(axom::IndexType index) { + dev_x[index] = CoordType(0); + dev_y[index] = CoordType(0); + dev_z[index] = CoordType(0); + }); + } // elements (zone definitions) constexpr ConnectivityType UnusedValue = axom::numeric_limits::is_signed @@ -602,22 +630,26 @@ class TopologyBuilder::max(); { const auto numConnValues = - m_view.m_makePointMesh ? numFragments : (numFragments * m_view.m_MAX_FACES_PER_FRAGMENT); + m_view.m_makePointMesh ? numFragments : (numFragments * m_view.m_maxFacesPerFragment); n_topology["type"] = "unstructured"; n_topology["elements/shape"] = m_view.m_makePointMesh ? "point" : "polyhedral"; conduit::Node &n_conn = n_topology["elements/connectivity"]; - n_conn.set_allocator(c2a.getConduitAllocatorID()); + n_conn.set_allocator(conduitAllocatorId); n_conn.set(conduit::DataType(utils::cpp2conduit::id, numConnValues)); m_view.m_connectivity = utils::make_array_view(n_conn); - m_view.m_connectivity.fill(UnusedValue); - + { + const auto dev_connectivity = m_view.m_connectivity; + axom::for_all( + numConnValues, + AXOM_LAMBDA(axom::IndexType index) { dev_connectivity[index] = UnusedValue; }); + } conduit::Node &n_sizes = n_topology["elements/sizes"]; - n_sizes.set_allocator(c2a.getConduitAllocatorID()); + n_sizes.set_allocator(conduitAllocatorId); n_sizes.set(conduit::DataType(utils::cpp2conduit::id, numFragments)); m_view.m_sizes = utils::make_array_view(n_sizes); conduit::Node &n_offsets = n_topology["elements/offsets"]; - n_offsets.set_allocator(c2a.getConduitAllocatorID()); + n_offsets.set_allocator(conduitAllocatorId); n_offsets.set(conduit::DataType(utils::cpp2conduit::id, numFragments)); m_view.m_offsets = utils::make_array_view(n_offsets); } @@ -627,26 +659,38 @@ class TopologyBuilder::id, - numFragments * m_view.m_MAX_FACES_PER_FRAGMENT * m_view.m_MAX_POINTS_PER_FACE)); + n_se_conn.set_allocator(conduitAllocatorId); + const auto seConnSize = numFragments * m_view.m_maxFacesPerFragment * m_view.m_maxPointsPerFace; + n_se_conn.set(conduit::DataType(utils::cpp2conduit::id, seConnSize)); m_view.m_subelement_connectivity = utils::make_array_view(n_se_conn); - m_view.m_subelement_connectivity.fill(UnusedValue); - + { + const auto dev_subelement_connectivity = m_view.m_subelement_connectivity; + axom::for_all( + seConnSize, + AXOM_LAMBDA(axom::IndexType index) { dev_subelement_connectivity[index] = UnusedValue; }); + } conduit::Node &n_se_sizes = n_topology["subelements/sizes"]; - n_se_sizes.set_allocator(c2a.getConduitAllocatorID()); + n_se_sizes.set_allocator(conduitAllocatorId); n_se_sizes.set(conduit::DataType(utils::cpp2conduit::id, - numFragments * m_view.m_MAX_FACES_PER_FRAGMENT)); + numFragments * m_view.m_maxFacesPerFragment)); m_view.m_subelement_sizes = utils::make_array_view(n_se_sizes); - m_view.m_subelement_sizes.fill(ConnectivityType {0}); conduit::Node &n_se_offsets = n_topology["subelements/offsets"]; - n_se_offsets.set_allocator(c2a.getConduitAllocatorID()); + n_se_offsets.set_allocator(conduitAllocatorId); n_se_offsets.set(conduit::DataType(utils::cpp2conduit::id, - numFragments * m_view.m_MAX_FACES_PER_FRAGMENT)); + numFragments * m_view.m_maxFacesPerFragment)); m_view.m_subelement_offsets = utils::make_array_view(n_se_offsets); - m_view.m_subelement_offsets.fill(UnusedValue); + + { + const auto dev_subelement_sizes = m_view.m_subelement_sizes; + const auto dev_subelement_offsets = m_view.m_subelement_offsets; + axom::for_all( + numFragments * m_view.m_maxFacesPerFragment, + AXOM_LAMBDA(axom::IndexType index) { + dev_subelement_sizes[index] = ConnectivityType {0}; + dev_subelement_offsets[index] = UnusedValue; + }); + } } // Make new fields. @@ -654,7 +698,7 @@ class TopologyBuilder::id, numFragments)); m_view.m_original_zones = utils::make_array_view(n_orig_elem_values); @@ -666,13 +710,13 @@ class TopologyBuilder::id, numFragments)); m_view.m_norm_x = utils::make_array_view(n_x); - n_y.set_allocator(c2a.getConduitAllocatorID()); + n_y.set_allocator(conduitAllocatorId); n_y.set(conduit::DataType(utils::cpp2conduit::id, numFragments)); m_view.m_norm_y = utils::make_array_view(n_y); - n_z.set_allocator(c2a.getConduitAllocatorID()); + n_z.set_allocator(conduitAllocatorId); n_z.set(conduit::DataType(utils::cpp2conduit::id, numFragments)); m_view.m_norm_z = utils::make_array_view(n_z); @@ -680,7 +724,7 @@ class TopologyBuilder::id, numFragments)); m_view.m_plane_offset = utils::make_array_view(n_values); } @@ -688,28 +732,33 @@ class TopologyBuilder::id, numFragments)); m_view.m_volume_fractions = utils::make_array_view(n_volume_fractions); conduit::Node &n_material_ids = n_matset["material_ids"]; - n_material_ids.set_allocator(c2a.getConduitAllocatorID()); + n_material_ids.set_allocator(conduitAllocatorId); n_material_ids.set(conduit::DataType(utils::cpp2conduit::id, numFragments)); m_view.m_material_ids = utils::make_array_view(n_material_ids); conduit::Node &n_indices = n_matset["indices"]; - n_indices.set_allocator(c2a.getConduitAllocatorID()); + n_indices.set_allocator(conduitAllocatorId); n_indices.set(conduit::DataType(utils::cpp2conduit::id, numFragments)); m_view.m_mat_indices = utils::make_array_view(n_indices); conduit::Node &n_mat_sizes = n_matset["sizes"]; - n_mat_sizes.set_allocator(c2a.getConduitAllocatorID()); + n_mat_sizes.set_allocator(conduitAllocatorId); n_mat_sizes.set(conduit::DataType(utils::cpp2conduit::id, numFragments)); m_view.m_mat_sizes = utils::make_array_view(n_mat_sizes); - m_view.m_mat_sizes.fill(MaterialID(0)); + { + const auto dev_mat_sizes = m_view.m_mat_sizes; + axom::for_all( + numFragments, + AXOM_LAMBDA(axom::IndexType index) { dev_mat_sizes[index] = MaterialID(0); }); + } conduit::Node &n_mat_offsets = n_matset["offsets"]; - n_mat_offsets.set_allocator(c2a.getConduitAllocatorID()); + n_mat_offsets.set_allocator(conduitAllocatorId); n_mat_offsets.set(conduit::DataType(utils::cpp2conduit::id, numFragments)); m_view.m_mat_offsets = utils::make_array_view(n_mat_offsets); } @@ -740,7 +789,7 @@ class TopologyBuilder(connOffset + i); @@ -877,9 +926,9 @@ class TopologyBuilder &cleanZones, const conduit::Node &n_mesh, @@ -990,13 +1040,15 @@ struct MakeCleanZones const TopologyView &topologyView, const CoordsetView &coordsetView, const MatsetView &matsetView, - conduit::Node &n_cleanOutput) + conduit::Node &n_cleanOutput, + int allocator_id) { // Make the clean mesh. axom::bump::ExtractZonesAndMatset ez( topologyView, coordsetView, matsetView); + ez.setAllocatorID(allocator_id); ez.execute(cleanZones, n_mesh, n_options, n_cleanOutput); } }; @@ -1025,6 +1077,7 @@ struct MakeCleanZones * \param coordsetView The view that wraps the coordinates. * \param matsetView The view that wraps the matset. * \param[out] n_cleanOutput The node that will contain the new mesh. + * \param allocator_id The allocator to use. */ static void execute(const axom::ArrayView &cleanZones, const conduit::Node &n_mesh, @@ -1032,7 +1085,8 @@ struct MakeCleanZones const TopologyView &topologyView, const CoordsetView &coordsetView, const MatsetView &matsetView, - conduit::Node &n_cleanOutput) + conduit::Node &n_cleanOutput, + int allocator_id) { using IndexingPolicy = typename TopologyView::IndexingPolicy; @@ -1043,6 +1097,7 @@ struct MakeCleanZones topologyView, coordsetView, matsetView); + ez.setAllocatorID(allocator_id); ez.execute(cleanZones, n_mesh, n_options, n_cleanOutput); } }; diff --git a/src/axom/mir/detail/elvira_impl.hpp b/src/axom/mir/detail/elvira_impl.hpp index fae77ea5bd..8af899de79 100644 --- a/src/axom/mir/detail/elvira_impl.hpp +++ b/src/axom/mir/detail/elvira_impl.hpp @@ -48,7 +48,7 @@ struct Result2D * \param value The input value to convert to Difference. * \return The converted Difference value. */ -inline AXOM_HOST_DEVICE Difference IntToDifference(int value) +inline AXOM_HOST_DEVICE Difference intToDifference(int value) { return (value == 0) ? Difference::BACKWARD : ((value == 2) ? Difference::FORWARD : Difference::CENTRAL); @@ -59,7 +59,7 @@ inline AXOM_HOST_DEVICE Difference IntToDifference(int value) * \param value The input value to convert to int. * \return The converted int value. */ -inline AXOM_HOST_DEVICE int DifferenceToInt(Difference value) +inline AXOM_HOST_DEVICE int differenceToInt(Difference value) { return (value == Difference::BACKWARD) ? 0 : ((value == Difference::FORWARD) ? 2 : 1); } @@ -68,7 +68,7 @@ inline AXOM_HOST_DEVICE int DifferenceToInt(Difference value) * \param value The input value to reverse. * \return The reversed direction. */ -inline AXOM_HOST_DEVICE Difference Reverse(Difference value) +inline AXOM_HOST_DEVICE Difference reverseDifference(Difference value) { return (value == Difference::BACKWARD) ? Difference::FORWARD @@ -974,8 +974,8 @@ AXOM_HOST_DEVICE void pick_elv(Result2D elv2d[2], const FloatType *vf } // Record which differences were used. - elv2d[0].difference_used = IntToDifference(imin); - elv2d[1].difference_used = IntToDifference(jmin); + elv2d[0].difference_used = intToDifference(imin); + elv2d[1].difference_used = intToDifference(jmin); } /*! @@ -1322,8 +1322,8 @@ AXOM_HOST_DEVICE void correct1(Result2D elv2d[2], const int p2 = 3 - p0 - p1; FloatType n30[3]; - norm3d(elv2d[0].normal[DifferenceToInt(elv2d[0].difference_used)], - elv2d[1].normal[DifferenceToInt(elv2d[1].difference_used)], + norm3d(elv2d[0].normal[differenceToInt(elv2d[0].difference_used)], + elv2d[1].normal[differenceToInt(elv2d[1].difference_used)], n30); // Ensure correct order. @@ -1356,7 +1356,7 @@ AXOM_HOST_DEVICE void correct1(Result2D elv2d[2], { axom::utilities::swap(upcen[0], upcen[2]); - diff[0] = Reverse(diff[0]); // Forward <--> Backward + diff[0] = reverseDifference(diff[0]); // Forward <--> Backward axom::utilities::swap(upcol[0][0], upcol[0][2]); } @@ -1365,7 +1365,7 @@ AXOM_HOST_DEVICE void correct1(Result2D elv2d[2], FloatType n2a[2][2]; for(int i = 0; i < 2; i++) { - const FloatType *n2 = elv2d[i].normal[DifferenceToInt(elv2d[i].difference_used)]; + const FloatType *n2 = elv2d[i].normal[differenceToInt(elv2d[i].difference_used)]; for(int k = 0; k < 2; k++) { n2a[i][k] = axom::utilities::abs(n2[k]); diff --git a/src/axom/mir/detail/equiz_detail.hpp b/src/axom/mir/detail/equiz_detail.hpp index 474c1aea91..1d2e19e8ba 100644 --- a/src/axom/mir/detail/equiz_detail.hpp +++ b/src/axom/mir/detail/equiz_detail.hpp @@ -79,7 +79,7 @@ class MaterialIntersector { const auto nid = nodeIdsView[i]; SLIC_ASSERT_MSG( - nid >= 0 && nid < static_cast(m_matvfViews[0].size()), + axom::utilities::inBounds_0_N(nid, static_cast(m_matvfViews[0].size())), axom::fmt::format("Node id {} is not in range [0, {}).", nid, m_matvfViews[0].size())); // clang-format off @@ -107,10 +107,10 @@ class MaterialIntersector if(zoneMatID != NULL_MATERIAL) backgroundIndex = matNumberToIndex(zoneMatID); // Determine the matvf view index for the current material. SLIC_ASSERT_MSG( - id0 >= 0 && id0 < static_cast(m_matvfViews[0].size()), + axom::utilities::inBounds_0_N(id0, static_cast(m_matvfViews[0].size())), axom::fmt::format("Node id {} is not in range [0, {}).", id0, m_matvfViews[0].size())); SLIC_ASSERT_MSG( - id1 >= 0 && id1 < static_cast(m_matvfViews[0].size()), + axom::utilities::inBounds_0_N(id1, static_cast(m_matvfViews[0].size())), axom::fmt::format("Node id {} is not in range [0, {}).", id1, m_matvfViews[0].size())); // Get the volume fractions for mat1, mat2 at the edge endpoints id0, id1. diff --git a/src/axom/mir/examples/concentric_circles/MIRApplication.cpp b/src/axom/mir/examples/concentric_circles/MIRApplication.cpp index c4b7b9f7b6..0921c89809 100644 --- a/src/axom/mir/examples/concentric_circles/MIRApplication.cpp +++ b/src/axom/mir/examples/concentric_circles/MIRApplication.cpp @@ -187,27 +187,25 @@ int MIRApplication::runMIR() { retval = runMIR_seq(dimension, mesh, options, resultMesh); } -#if defined(AXOM_USE_RAJA) && defined(AXOM_USE_UMPIRE) - #if defined(AXOM_USE_OPENMP) +#if defined(AXOM_RUNTIME_POLICY_USE_OPENMP) else if(policy == RuntimePolicy::omp) { retval = runMIR_omp(dimension, mesh, options, resultMesh); } - #endif - #if defined(AXOM_USE_CUDA) +#endif +#if defined(AXOM_RUNTIME_POLICY_USE_CUDA) else if(policy == RuntimePolicy::cuda) { - constexpr int CUDA_BLOCK_SIZE = 256; - using cuda_exec = axom::CUDA_EXEC; + options["pool_size"] = estimateMemoryPoolSize(); retval = runMIR_cuda(dimension, mesh, options, resultMesh); } - #endif - #if defined(AXOM_USE_HIP) +#endif +#if defined(AXOM_RUNTIME_POLICY_USE_HIP) else if(policy == RuntimePolicy::hip) { + options["pool_size"] = estimateMemoryPoolSize(); retval = runMIR_hip(dimension, mesh, options, resultMesh); } - #endif #endif else { @@ -227,6 +225,26 @@ int MIRApplication::runMIR() return retval; } +//-------------------------------------------------------------------------------- +size_t MIRApplication::estimateMemoryPoolSize() const +{ + // Estimate the mesh size + using FloatType = float; + using ConnType = int; + const auto nzones = static_cast(pow(gridSize, dimension)); + const auto nnodes = static_cast(pow(gridSize + 1, dimension)); + const auto topoSizeBytes = + ((((dimension == 3) ? 8 : 4) * nzones) + (nzones * 2)) * sizeof(ConnType); + const auto coordSizeBytes = (dimension * nnodes) * sizeof(FloatType); + const auto mixFraction = 1.5; + const auto matsetSizeBytes = (((nzones * mixFraction) * 2) * sizeof(ConnType)) + + (((nzones * mixFraction) * 1) * sizeof(FloatType)) + ((nzones * 2) * sizeof(ConnType)); + const auto estMeshSizeBytes = topoSizeBytes + coordSizeBytes + matsetSizeBytes; + // Estimate pool size + const auto initialPoolSizeBytes = estMeshSizeBytes; + return initialPoolSizeBytes; +} + //-------------------------------------------------------------------------------- void MIRApplication::adjustMesh(conduit::Node &) { } diff --git a/src/axom/mir/examples/concentric_circles/MIRApplication.hpp b/src/axom/mir/examples/concentric_circles/MIRApplication.hpp index 5d938518f6..1ded039a0a 100644 --- a/src/axom/mir/examples/concentric_circles/MIRApplication.hpp +++ b/src/axom/mir/examples/concentric_circles/MIRApplication.hpp @@ -59,6 +59,13 @@ class MIRApplication */ virtual void saveMesh(const conduit::Node &n_mesh, const std::string &path); + /*! + * \brief Estimate memory needed to perform MIR operations. + * + * \return A size in bytes. + */ + size_t estimateMemoryPoolSize() const; + /*! * \brief A static error handler for Conduit. */ diff --git a/src/axom/mir/examples/concentric_circles/runMIR.hpp b/src/axom/mir/examples/concentric_circles/runMIR.hpp index fa37a6ff69..9ece5401f5 100644 --- a/src/axom/mir/examples/concentric_circles/runMIR.hpp +++ b/src/axom/mir/examples/concentric_circles/runMIR.hpp @@ -59,6 +59,34 @@ void test_matset_traversal(MatsetView matsetView) (axom::utilities::abs(vf1 - vf2) < eps) ? "pass" : "fail")); } +//-------------------------------------------------------------------------------- +template +int installAllocator([[maybe_unused]] size_t initialPoolSizeBytes) +{ + int allocator_id = axom::execution_space::allocatorID(); +#if defined(AXOM_USE_UMPIRE) + auto &rm = umpire::ResourceManager::getInstance(); + umpire::Allocator allocator = rm.getAllocator(allocator_id); + + const std::string newName = allocator.getName() + "_POOL"; + SLIC_INFO( + axom::fmt::format("Creating pool allocator {} with {} bytes.", newName, initialPoolSizeBytes)); + + // Create a pool on top of the allocator. + auto pooled = rm.makeAllocator( + newName, + allocator, + initialPoolSizeBytes, // first_minimum_pool_allocation_size + 1 << 20, // next_minimum_pool_allocation_size = 1 MiB chunks + 256 // alignment + ); + + allocator_id = pooled.getId(); +#endif + return allocator_id; +} + +//-------------------------------------------------------------------------------- template int runMIR(const conduit::Node &hostMesh, const conduit::Node &options, conduit::Node &hostResult) { @@ -96,10 +124,20 @@ int runMIR(const conduit::Node &hostMesh, const conduit::Node &options, conduit: return -4; } + // See whether we were directed to make a memory pool. + int allocator_id = axom::execution_space::allocatorID(); + if(options.has_path("pool_size")) + { + const auto pool_size = options["pool_size"].to_uint64(); + allocator_id = installAllocator(pool_size); + SLIC_INFO(axom::fmt::format("Using custom allocator {}", allocator_id)); + } + conduit::Node deviceMesh; { AXOM_ANNOTATE_SCOPE("host->device"); - utils::copy(deviceMesh, hostMesh); + // Pass allocator_id since it might be custom for device. + utils::copy(deviceMesh, hostMesh, allocator_id); } const conduit::Node &n_coordset = deviceMesh["coordsets/coords"]; @@ -126,6 +164,7 @@ int runMIR(const conduit::Node &hostMesh, const conduit::Node &options, conduit: using MIR = axom::mir::EquiZAlgorithm; MIR m(topologyView, coordsetView, matsetView); + m.setAllocatorID(allocator_id); m.execute(deviceMesh, options, deviceResult); // _equiz_mir_end } @@ -145,6 +184,7 @@ int runMIR(const conduit::Node &hostMesh, const conduit::Node &options, conduit: using MIR = axom::mir::ElviraAlgorithm; MIR m(topologyView, coordsetView, matsetView); + m.setAllocatorID(allocator_id); m.execute(deviceMesh, options, deviceResult); } else if(method == "traversal") @@ -164,6 +204,27 @@ int runMIR(const conduit::Node &hostMesh, const conduit::Node &options, conduit: utils::copy(hostResult, deviceResult); } + if(options.has_path("pool_size")) + { +#if defined(AXOM_USE_UMPIRE) + try + { + auto &rm = umpire::ResourceManager::getInstance(); + umpire::Allocator allocator = rm.getAllocator(allocator_id); + SLIC_INFO("Allocator Information:"); + SLIC_INFO(axom::fmt::format("\tname: {}", allocator.getName())); + SLIC_INFO(axom::fmt::format("\thighwatermark: {}", allocator.getHighWatermark())); + SLIC_INFO(axom::fmt::format("\tcurrentsize: {}", allocator.getCurrentSize())); + SLIC_INFO(axom::fmt::format("\tactualsize: {}", allocator.getActualSize())); + SLIC_INFO(axom::fmt::format("\tallocationcount: {}", allocator.getAllocationCount())); + } + catch(...) + { + SLIC_ERROR("Allocator information could not be retrieved."); + } +#endif + } + return 0; } diff --git a/src/axom/mir/examples/heavily_mixed/HMApplication.cpp b/src/axom/mir/examples/heavily_mixed/HMApplication.cpp index 3cdc2b56e7..d4d505b8b5 100644 --- a/src/axom/mir/examples/heavily_mixed/HMApplication.cpp +++ b/src/axom/mir/examples/heavily_mixed/HMApplication.cpp @@ -159,25 +159,23 @@ void heavily_mixed(conduit::Node &n_mesh, int dims[3], int refinement, int nmats conduit::Node n_field; n_field.set(conduit::DataType::int32(rdims[0] * rdims[1] * rdims[2])); conduit::int32 *destPtr = n_field.as_int32_ptr(); - axom::for_all( - rdims[2], - AXOM_LAMBDA(int k) { - const auto t = static_cast(k) / (dims[2] - 1); - // Interpolate the window - const conduit::float64 x0 = axom::utilities::lerp(x_min, x1_min, t); - const conduit::float64 x1 = axom::utilities::lerp(x_max, x1_max, t); - const conduit::float64 y0 = axom::utilities::lerp(y_min, y1_min, t); - const conduit::float64 y1 = axom::utilities::lerp(y_max, y1_max, t); - conduit::Node n_rmesh; - conduit::blueprint::mesh::examples::julia(rdims[0], rdims[1], x0, x1, y0, y1, c_re, c_im, n_rmesh); - const conduit::Node &n_src_field = n_rmesh["fields/iters/values"]; - const conduit::int32 *srcPtr = n_src_field.as_int32_ptr(); - conduit::int32 *currentDestPtr = destPtr + k * rdims[0] * rdims[1]; - axom::copy(currentDestPtr, srcPtr, rdims[0] * rdims[1] * sizeof(conduit::int32)); + axom::for_all(rdims[2], [&](int k) { + const auto t = static_cast(k) / (dims[2] - 1); + // Interpolate the window + const conduit::float64 x0 = axom::utilities::lerp(x_min, x1_min, t); + const conduit::float64 x1 = axom::utilities::lerp(x_max, x1_max, t); + const conduit::float64 y0 = axom::utilities::lerp(y_min, y1_min, t); + const conduit::float64 y1 = axom::utilities::lerp(y_max, y1_max, t); + conduit::Node n_rmesh; + conduit::blueprint::mesh::examples::julia(rdims[0], rdims[1], x0, x1, y0, y1, c_re, c_im, n_rmesh); + const conduit::Node &n_src_field = n_rmesh["fields/iters/values"]; + const conduit::int32 *srcPtr = n_src_field.as_int32_ptr(); + conduit::int32 *currentDestPtr = destPtr + k * rdims[0] * rdims[1]; + axom::copy(currentDestPtr, srcPtr, rdims[0] * rdims[1] * sizeof(conduit::int32)); #ifndef AXOM_DEVICE_CODE - SLIC_INFO(axom::fmt::format("Made slice {}/{}", k + 1, rdims[2])); + SLIC_INFO(axom::fmt::format("Made slice {}/{}", k + 1, rdims[2])); #endif - }); + }); // Make a matset based on the higher resolution julia field. heavily_mixed_matset("topo", dims, refinement, n_mesh, n_field, nmats); @@ -379,27 +377,25 @@ int HMApplication::runMIR() { retval = runMIR_seq(dimension, mesh, options, resultMesh); } -#if defined(AXOM_USE_RAJA) && defined(AXOM_USE_UMPIRE) - #if defined(AXOM_USE_OPENMP) +#if defined(AXOM_RUNTIME_POLICY_USE_OPENMP) else if(m_policy == RuntimePolicy::omp) { retval = runMIR_omp(dimension, mesh, options, resultMesh); } - #endif - #if defined(AXOM_USE_CUDA) +#endif +#if defined(AXOM_RUNTIME_POLICY_USE_CUDA) else if(m_policy == RuntimePolicy::cuda) { - constexpr int CUDA_BLOCK_SIZE = 256; - using cuda_exec = axom::CUDA_EXEC; + options["pool_size"] = estimateMemoryPoolSize(); retval = runMIR_cuda(dimension, mesh, options, resultMesh); } - #endif - #if defined(AXOM_USE_HIP) +#endif +#if defined(AXOM_RUNTIME_POLICY_USE_HIP) else if(m_policy == RuntimePolicy::hip) { + options["pool_size"] = estimateMemoryPoolSize(); retval = runMIR_hip(dimension, mesh, options, resultMesh); } - #endif #endif else { @@ -419,6 +415,26 @@ int HMApplication::runMIR() return retval; } +//-------------------------------------------------------------------------------- +size_t HMApplication::estimateMemoryPoolSize() const +{ + // Estimate the mesh size + using FloatType = conduit::float64; + const auto nzones = static_cast(m_dims[0] * m_dims[1] * m_dims[2]); + const auto nnodes = static_cast((m_dims[0] + 1) * (m_dims[1] + 1) * (m_dims[2] + 1)); + const auto topoSizeBytes = 0; + const auto coordSizeBytes = + static_cast((m_dims[0] + m_dims[1] + m_dims[2] + 3) * sizeof(FloatType)); + const auto mixFraction = 5.; + const auto matsetSizeBytes = (((nzones * mixFraction) * 2) * sizeof(int)) + + (((nzones * mixFraction) * 1) * sizeof(double)) + ((nzones * 2) * sizeof(int)); + const auto fieldsSizeBytes = static_cast((nzones * 2 + nnodes * 2) * sizeof(FloatType)); + const auto estMeshSizeBytes = topoSizeBytes + coordSizeBytes + matsetSizeBytes + fieldsSizeBytes; + // Estimate pool size + const auto initialPoolSizeBytes = estMeshSizeBytes; + return initialPoolSizeBytes; +} + //-------------------------------------------------------------------------------- void HMApplication::adjustMesh(conduit::Node &) { } diff --git a/src/axom/mir/examples/heavily_mixed/HMApplication.hpp b/src/axom/mir/examples/heavily_mixed/HMApplication.hpp index 1e45544970..f374a24f31 100644 --- a/src/axom/mir/examples/heavily_mixed/HMApplication.hpp +++ b/src/axom/mir/examples/heavily_mixed/HMApplication.hpp @@ -53,6 +53,13 @@ class HMApplication */ virtual void saveMesh(const conduit::Node &n_mesh, const std::string &path); + /*! + * \brief Estimate memory needed to perform MIR operations. + * + * \return A size in bytes. + */ + size_t estimateMemoryPoolSize() const; + /*! * \brief A static error handler for Conduit. */ diff --git a/src/axom/mir/examples/heavily_mixed/runMIR.hpp b/src/axom/mir/examples/heavily_mixed/runMIR.hpp index fdadc80077..74e64e0ba1 100644 --- a/src/axom/mir/examples/heavily_mixed/runMIR.hpp +++ b/src/axom/mir/examples/heavily_mixed/runMIR.hpp @@ -11,6 +11,34 @@ #include "axom/bump.hpp" #include "axom/mir.hpp" +//-------------------------------------------------------------------------------- +template +int installAllocator([[maybe_unused]] size_t initialPoolSizeBytes) +{ + int allocator_id = axom::execution_space::allocatorID(); +#if defined(AXOM_USE_UMPIRE) + auto &rm = umpire::ResourceManager::getInstance(); + umpire::Allocator allocator = rm.getAllocator(allocator_id); + + const std::string newName = allocator.getName() + "_POOL"; + SLIC_INFO( + axom::fmt::format("Creating pool allocator {} with {} bytes.", newName, initialPoolSizeBytes)); + + // Create a pool on top of the allocator. + auto pooled = rm.makeAllocator( + newName, + allocator, + initialPoolSizeBytes, // first_minimum_pool_allocation_size + 1 << 20, // next_minimum_pool_allocation_size = 1 MiB chunks + 256 // alignment + ); + + allocator_id = pooled.getId(); +#endif + return allocator_id; +} + +//-------------------------------------------------------------------------------- template int runMIR(const conduit::Node &hostMesh, const conduit::Node &options, conduit::Node &hostResult) { @@ -48,6 +76,15 @@ int runMIR(const conduit::Node &hostMesh, const conduit::Node &options, conduit: return -4; } + // See whether we were directed to make a memory pool. + int allocator_id = axom::execution_space::allocatorID(); + if(options.has_path("pool_size")) + { + const auto pool_size = options["pool_size"].to_uint64(); + allocator_id = installAllocator(pool_size); + SLIC_INFO(axom::fmt::format("Using custom allocator {}", allocator_id)); + } + conduit::Node deviceMesh; { AXOM_ANNOTATE_SCOPE("host->device"); @@ -97,6 +134,27 @@ int runMIR(const conduit::Node &hostMesh, const conduit::Node &options, conduit: utils::copy(hostResult, deviceResult); } + if(options.has_path("pool_size")) + { +#if defined(AXOM_USE_UMPIRE) + try + { + auto &rm = umpire::ResourceManager::getInstance(); + umpire::Allocator allocator = rm.getAllocator(allocator_id); + SLIC_INFO("Allocator Information:"); + SLIC_INFO(axom::fmt::format("\tname: {}", allocator.getName())); + SLIC_INFO(axom::fmt::format("\thighwatermark: {}", allocator.getHighWatermark())); + SLIC_INFO(axom::fmt::format("\tcurrentsize: {}", allocator.getCurrentSize())); + SLIC_INFO(axom::fmt::format("\tactualsize: {}", allocator.getActualSize())); + SLIC_INFO(axom::fmt::format("\tallocationcount: {}", allocator.getAllocationCount())); + } + catch(...) + { + SLIC_ERROR("Allocator information could not be retrieved."); + } +#endif + } + return 0; } diff --git a/src/axom/mir/tests/CMakeLists.txt b/src/axom/mir/tests/CMakeLists.txt index 291541e959..b40a7908dc 100644 --- a/src/axom/mir/tests/CMakeLists.txt +++ b/src/axom/mir/tests/CMakeLists.txt @@ -42,3 +42,8 @@ foreach(test ${gtest_mir_tests}) COMMAND ${test_name}_test ) endforeach() +if(ENABLE_HIP) + axom_force_release_for_target(mir_coupled_test) + axom_force_release_for_target(mir_elvira2d_test) + axom_force_release_for_target(mir_equiz2d_test) +endif() diff --git a/src/axom/mir/tests/mir_coupled.cpp b/src/axom/mir/tests/mir_coupled.cpp index 9b5473dcce..e23e69c546 100644 --- a/src/axom/mir/tests/mir_coupled.cpp +++ b/src/axom/mir/tests/mir_coupled.cpp @@ -410,87 +410,87 @@ class test_coupling }; //------------------------------------------------------------------------------ -TEST(mir_coupling, coupling_2D_sz0_ss0_seq) +TEST(mir_coupled, coupling_2D_sz0_ss0_seq) { AXOM_ANNOTATE_SCOPE("coupling_2D_sz0_ss0_seq"); test_coupling::test2D("coupling_2D_sz0_ss0", false, false); } -TEST(mir_coupling, coupling_2D_sz0_ss1_seq) +TEST(mir_coupled, coupling_2D_sz0_ss1_seq) { AXOM_ANNOTATE_SCOPE("coupling_2D_sz0_ss1_seq"); test_coupling::test2D("coupling_2D_sz0_ss1", false, true); } -TEST(mir_coupling, coupling_2D_sz1_ss0_seq) +TEST(mir_coupled, coupling_2D_sz1_ss0_seq) { AXOM_ANNOTATE_SCOPE("coupling_2D_sz1_ss0_seq"); test_coupling::test2D("coupling_2D_sz1_ss0", true, false); } -TEST(mir_coupling, coupling_2D_sz1_ss1_seq) +TEST(mir_coupled, coupling_2D_sz1_ss1_seq) { AXOM_ANNOTATE_SCOPE("coupling_2D_sz1_ss1_seq"); test_coupling::test2D("coupling_2D_sz1_ss1", true, true); } #if defined(AXOM_RUNTIME_POLICY_USE_OPENMP) -TEST(mir_coupling, coupling_2D_sz0_ss0_omp) +TEST(mir_coupled, coupling_2D_sz0_ss0_omp) { AXOM_ANNOTATE_SCOPE("coupling_2D_sz0_ss0_omp"); test_coupling::test2D("coupling_2D_sz0_ss0", false, false); } -TEST(mir_coupling, coupling_2D_sz0_ss1_omp) +TEST(mir_coupled, coupling_2D_sz0_ss1_omp) { AXOM_ANNOTATE_SCOPE("coupling_2D_sz0_ss1_omp"); test_coupling::test2D("coupling_2D_sz0_ss1", false, true); } -TEST(mir_coupling, coupling_2D_sz1_ss0_omp) +TEST(mir_coupled, coupling_2D_sz1_ss0_omp) { AXOM_ANNOTATE_SCOPE("coupling_2D_sz1_ss0_omp"); test_coupling::test2D("coupling_2D_sz1_ss0", true, false); } -TEST(mir_coupling, coupling_2D_sz1_ss1_omp) +TEST(mir_coupled, coupling_2D_sz1_ss1_omp) { AXOM_ANNOTATE_SCOPE("coupling_2D_sz1_ss1_omp"); test_coupling::test2D("coupling_2D_sz1_ss1", true, true); } #endif #if defined(AXOM_RUNTIME_POLICY_USE_CUDA) -TEST(mir_coupling, coupling_2D_sz0_ss0_cuda) +TEST(mir_coupled, coupling_2D_sz0_ss0_cuda) { AXOM_ANNOTATE_SCOPE("coupling_2D_sz0_ss0_cuda"); test_coupling::test2D("coupling_2D_sz0_ss0", false, false); } -TEST(mir_coupling, coupling_2D_sz0_ss1_cuda) +TEST(mir_coupled, coupling_2D_sz0_ss1_cuda) { AXOM_ANNOTATE_SCOPE("coupling_2D_sz0_ss1_cuda"); test_coupling::test2D("coupling_2D_sz0_ss1", false, true); } -TEST(mir_coupling, coupling_2D_sz1_ss0_cuda) +TEST(mir_coupled, coupling_2D_sz1_ss0_cuda) { AXOM_ANNOTATE_SCOPE("coupling_2D_sz1_ss0_cuda"); test_coupling::test2D("coupling_2D_sz1_ss0", true, false); } -TEST(mir_coupling, coupling_2D_sz1_ss1_cuda) +TEST(mir_coupled, coupling_2D_sz1_ss1_cuda) { AXOM_ANNOTATE_SCOPE("coupling_2D_sz1_ss1_cuda"); test_coupling::test2D("coupling_2D_sz1_ss1", true, true); } #endif #if defined(AXOM_RUNTIME_POLICY_USE_HIP) -TEST(mir_coupling, coupling_2D_sz0_ss0_hip) +TEST(mir_coupled, coupling_2D_sz0_ss0_hip) { AXOM_ANNOTATE_SCOPE("coupling_2D_sz0_ss0_hip"); test_coupling::test2D("coupling_2D_sz0_ss0", false, false); } -TEST(mir_coupling, coupling_2D_sz0_ss1_hip) +TEST(mir_coupled, coupling_2D_sz0_ss1_hip) { AXOM_ANNOTATE_SCOPE("coupling_2D_sz0_ss1_hip"); test_coupling::test2D("coupling_2D_sz0_ss1", false, true); } -TEST(mir_coupling, coupling_2D_sz1_ss0_hip) +TEST(mir_coupled, coupling_2D_sz1_ss0_hip) { AXOM_ANNOTATE_SCOPE("coupling_2D_sz1_ss0_hip"); test_coupling::test2D("coupling_2D_sz1_ss0", true, false); } -TEST(mir_coupling, coupling_2D_sz1_ss1_hip) +TEST(mir_coupled, coupling_2D_sz1_ss1_hip) { AXOM_ANNOTATE_SCOPE("coupling_2D_sz1_ss1_hip"); test_coupling::test2D("coupling_2D_sz1_ss1", true, true); diff --git a/src/axom/mir/tests/mir_elvira2d.cpp b/src/axom/mir/tests/mir_elvira2d.cpp index b7de7afa00..7441711f66 100644 --- a/src/axom/mir/tests/mir_elvira2d.cpp +++ b/src/axom/mir/tests/mir_elvira2d.cpp @@ -192,7 +192,7 @@ struct braid2d_mat_test }; //------------------------------------------------------------------------------ -TEST(mir_elvira, options) +TEST(mir_elvira2d, options) { conduit::Node n_options; @@ -208,7 +208,7 @@ TEST(mir_elvira, options) } //------------------------------------------------------------------------------ -TEST(mir_elvira, elvira_uniform_unibuffer_seq) +TEST(mir_elvira2d, elvira_uniform_unibuffer_seq) { AXOM_ANNOTATE_SCOPE("elvira_uniform_unibuffer_seq"); const bool selectZones = false; @@ -243,7 +243,7 @@ TEST(mir_elvira, elvira_uniform_unibuffer_seq) } } -TEST(mir_elvira, elvira_uniform_unibuffer_sel_seq) +TEST(mir_elvira2d, elvira_uniform_unibuffer_sel_seq) { AXOM_ANNOTATE_SCOPE("elvira_uniform_unibuffer_sel_seq"); const bool selectZones = true; @@ -266,7 +266,7 @@ TEST(mir_elvira, elvira_uniform_unibuffer_sel_seq) } } -TEST(mir_elvira, elvira_uniform_unibuffer_seq_pm) +TEST(mir_elvira2d, elvira_uniform_unibuffer_seq_pm) { AXOM_ANNOTATE_SCOPE("elvira_uniform_unibuffer_pm_seq"); const bool selectZones = false; @@ -278,7 +278,7 @@ TEST(mir_elvira, elvira_uniform_unibuffer_seq_pm) pointMesh); } -TEST(mir_elvira, elvira_uniform_unibuffer_sel_pm_seq) +TEST(mir_elvira2d, elvira_uniform_unibuffer_sel_pm_seq) { AXOM_ANNOTATE_SCOPE("elvira_uniform_unibuffer_sel_pm_seq"); const bool selectZones = true; @@ -291,7 +291,7 @@ TEST(mir_elvira, elvira_uniform_unibuffer_sel_pm_seq) } #if defined(AXOM_USE_OPENMP) -TEST(mir_elvira, elvira_uniform_unibuffer_omp) +TEST(mir_elvira2d, elvira_uniform_unibuffer_omp) { AXOM_ANNOTATE_SCOPE("elvira_uniform_unibuffer_omp"); const bool selectZones = false; @@ -325,7 +325,7 @@ TEST(mir_elvira, elvira_uniform_unibuffer_omp) } } -TEST(mir_elvira, elvira_uniform_unibuffer_sel_omp) +TEST(mir_elvira2d, elvira_uniform_unibuffer_sel_omp) { AXOM_ANNOTATE_SCOPE("elvira_uniform_unibuffer_sel_omp"); const bool selectZones = true; @@ -347,7 +347,7 @@ TEST(mir_elvira, elvira_uniform_unibuffer_sel_omp) } } -TEST(mir_elvira, elvira_uniform_unibuffer_pm_omp) +TEST(mir_elvira2d, elvira_uniform_unibuffer_pm_omp) { AXOM_ANNOTATE_SCOPE("elvira_uniform_unibuffer_pm_omp"); const bool selectZones = false; @@ -359,7 +359,7 @@ TEST(mir_elvira, elvira_uniform_unibuffer_pm_omp) pointMesh); } -TEST(mir_elvira, elvira_uniform_unibuffer_sel_pm_omp) +TEST(mir_elvira2d, elvira_uniform_unibuffer_sel_pm_omp) { AXOM_ANNOTATE_SCOPE("elvira_uniform_unibuffer_sel_pm_omp"); const bool selectZones = true; @@ -373,7 +373,7 @@ TEST(mir_elvira, elvira_uniform_unibuffer_sel_pm_omp) #endif #if defined(AXOM_USE_CUDA) -TEST(mir_elvira, elvira_uniform_unibuffer_cuda) +TEST(mir_elvira2d, elvira_uniform_unibuffer_cuda) { AXOM_ANNOTATE_SCOPE("elvira_uniform_unibuffer_cuda"); const bool selectZones = false; @@ -407,7 +407,7 @@ TEST(mir_elvira, elvira_uniform_unibuffer_cuda) } } -TEST(mir_elvira, elvira_uniform_unibuffer_sel_cuda) +TEST(mir_elvira2d, elvira_uniform_unibuffer_sel_cuda) { AXOM_ANNOTATE_SCOPE("elvira_uniform_unibuffer_sel_cuda"); const bool selectZones = true; @@ -430,7 +430,7 @@ TEST(mir_elvira, elvira_uniform_unibuffer_sel_cuda) } } -TEST(mir_elvira, elvira_uniform_unibuffer_pm_cuda) +TEST(mir_elvira2d, elvira_uniform_unibuffer_pm_cuda) { AXOM_ANNOTATE_SCOPE("elvira_uniform_unibuffer_pm_cuda"); const bool selectZones = false; @@ -442,7 +442,7 @@ TEST(mir_elvira, elvira_uniform_unibuffer_pm_cuda) pointMesh); } -TEST(mir_elvira, elvira_uniform_unibuffer_sel_pm_cuda) +TEST(mir_elvira2d, elvira_uniform_unibuffer_sel_pm_cuda) { AXOM_ANNOTATE_SCOPE("elvira_uniform_unibuffer_sel_pm_cuda"); const bool selectZones = true; @@ -456,7 +456,7 @@ TEST(mir_elvira, elvira_uniform_unibuffer_sel_pm_cuda) #endif #if defined(AXOM_USE_HIP) -TEST(mir_elvira, elvira_uniform_unibuffer_hip) +TEST(mir_elvira2d, elvira_uniform_unibuffer_hip) { AXOM_ANNOTATE_SCOPE("elvira_uniform_unibuffer_hip"); const bool selectZones = false; @@ -490,7 +490,7 @@ TEST(mir_elvira, elvira_uniform_unibuffer_hip) } } -TEST(mir_elvira, elvira_uniform_unibuffer_sel_hip) +TEST(mir_elvira2d, elvira_uniform_unibuffer_sel_hip) { AXOM_ANNOTATE_SCOPE("elvira_uniform_unibuffer_sel_hip"); const bool selectZones = true; @@ -512,7 +512,7 @@ TEST(mir_elvira, elvira_uniform_unibuffer_sel_hip) } } -TEST(mir_elvira, elvira_uniform_unibuffer_pm_hip) +TEST(mir_elvira2d, elvira_uniform_unibuffer_pm_hip) { AXOM_ANNOTATE_SCOPE("elvira_uniform_unibuffer_pm_hip"); const bool selectZones = false; @@ -524,7 +524,7 @@ TEST(mir_elvira, elvira_uniform_unibuffer_pm_hip) pointMesh); } -TEST(mir_elvira, elvira_uniform_unibuffer_sel_pm_hip) +TEST(mir_elvira2d, elvira_uniform_unibuffer_sel_pm_hip) { AXOM_ANNOTATE_SCOPE("elvira_uniform_unibuffer_sel_pm_hip"); const bool selectZones = true; diff --git a/src/axom/mir/tests/mir_elvira3d.cpp b/src/axom/mir/tests/mir_elvira3d.cpp index 9e9042d756..41eec8e8c0 100644 --- a/src/axom/mir/tests/mir_elvira3d.cpp +++ b/src/axom/mir/tests/mir_elvira3d.cpp @@ -287,7 +287,7 @@ struct test_Elvira3D int mi = 0; for(const auto &mat : matInfo) { - sortedIdsHost[mi++] = mat.number; + sortedIdsHost[mi++] = mat.m_number; } axom::utilities::Sorting::sort(sortedIdsHost.data(), sortedIdsHost.size()); axom::Array sortedIds(nmats, nmats, allocatorID); diff --git a/src/axom/mir/tests/mir_equiz2d.cpp b/src/axom/mir/tests/mir_equiz2d.cpp index bcb82726d0..1e759da3aa 100644 --- a/src/axom/mir/tests/mir_equiz2d.cpp +++ b/src/axom/mir/tests/mir_equiz2d.cpp @@ -40,14 +40,14 @@ TEST(mir_equiz, materialinformation) auto mi = axom::bump::views::materials(matset); EXPECT_EQ(mi.size(), 3); - EXPECT_EQ(mi[0].number, 1); - EXPECT_EQ(mi[0].name, "a"); + EXPECT_EQ(mi[0].m_number, 1); + EXPECT_EQ(mi[0].m_name, "a"); - EXPECT_EQ(mi[1].number, 2); - EXPECT_EQ(mi[1].name, "b"); + EXPECT_EQ(mi[1].m_number, 2); + EXPECT_EQ(mi[1].m_name, "b"); - EXPECT_EQ(mi[2].number, 0); - EXPECT_EQ(mi[2].name, "c"); + EXPECT_EQ(mi[2].m_number, 0); + EXPECT_EQ(mi[2].m_name, "c"); } //------------------------------------------------------------------------------ diff --git a/src/axom/multimat/multimat.cpp b/src/axom/multimat/multimat.cpp index 01ba2f0f5d..9cc6642923 100644 --- a/src/axom/multimat/multimat.cpp +++ b/src/axom/multimat/multimat.cpp @@ -1502,9 +1502,9 @@ axom::Array TransposeDenseImpl(const MultiMat::DenseField2D // Note: even though this is a dense field, we iterate over the relation set // in order to only copy over filled-in slots. - ExecLambdaForMemory( + // Note: Execute sequentially to avoid intermittent error with HIP + axom::for_all( relationSet->totalSize() * stride, - allocatorId, AXOM_LAMBDA(int index) { int flatIdx = index / stride; int comp = index % stride; diff --git a/src/axom/primal/CMakeLists.txt b/src/axom/primal/CMakeLists.txt index 1ecaaa4c90..ca3e591070 100644 --- a/src/axom/primal/CMakeLists.txt +++ b/src/axom/primal/CMakeLists.txt @@ -47,6 +47,8 @@ set( primal_headers geometry/Quadrilateral.hpp geometry/Vector.hpp geometry/construct.hpp + + geometry/detail/analytic_test_surfaces.hpp ## operators operators/clip.hpp diff --git a/src/axom/primal/geometry/BoundingBox.hpp b/src/axom/primal/geometry/BoundingBox.hpp index 1cbb9761b0..6a4f2b9e44 100644 --- a/src/axom/primal/geometry/BoundingBox.hpp +++ b/src/axom/primal/geometry/BoundingBox.hpp @@ -12,6 +12,7 @@ #include "axom/core/Macros.hpp" #include "axom/core/numerics/floating_point_limits.hpp" #include "axom/core/NumericLimits.hpp" +#include "axom/core/utilities/Utilities.hpp" #include "axom/primal/geometry/Point.hpp" #include "axom/primal/geometry/Vector.hpp" @@ -199,6 +200,7 @@ class BoundingBox * \note If the intersection is empty, the bounding box will be cleared * \return A reference to the bounding box after it has been intersected */ + AXOM_HOST_DEVICE BoundingBox& intersect(const BoundingBox& otherBox); /*! @@ -256,7 +258,7 @@ class BoundingBox * \note If \a otherBB is empty, we return true */ template - bool contains(const BoundingBox& otherBB) const; + AXOM_HOST_DEVICE bool contains(const BoundingBox& otherBB) const; /*! * \param [in] otherBB the bounding box that we are checking. @@ -287,6 +289,7 @@ class BoundingBox * \pre dimension >= -1 && dimension < NDIMS * \note if dimension==-1, the bounding box is split along its longest edge. */ + AXOM_HOST_DEVICE void bisect(BoxType& right, BoxType& left, int dimension = -1) const; /*! @@ -426,7 +429,7 @@ AXOM_HOST_DEVICE BoundingBox::BoundingBox(const PointType* pts, int n) //------------------------------------------------------------------------------ template template -bool BoundingBox::contains(const BoundingBox& otherBB) const +AXOM_HOST_DEVICE bool BoundingBox::contains(const BoundingBox& otherBB) const { return otherBB.isValid() ? this->contains(otherBB.getMin()) && this->contains(otherBB.getMax()) : true; @@ -609,12 +612,12 @@ std::ostream& BoundingBox::print(std::ostream& os) const //------------------------------------------------------------------------------ template -BoundingBox& BoundingBox::intersect(const BoundingBox& otherBox) +AXOM_HOST_DEVICE BoundingBox& BoundingBox::intersect(const BoundingBox& otherBox) { for(int i = 0; i < NDIMS; ++i) { - m_min[i] = std::max(m_min[i], otherBox.m_min[i]); - m_max[i] = std::min(m_max[i], otherBox.m_max[i]); + m_min[i] = axom::utilities::max(m_min[i], otherBox.m_min[i]); + m_max[i] = axom::utilities::min(m_max[i], otherBox.m_max[i]); } if(!isValid()) @@ -627,7 +630,7 @@ BoundingBox& BoundingBox::intersect(const BoundingBox& other //------------------------------------------------------------------------------ template -void BoundingBox::bisect(BoxType& right, BoxType& left, int dim) const +AXOM_HOST_DEVICE void BoundingBox::bisect(BoxType& right, BoxType& left, int dim) const { SLIC_ASSERT(this->isValid()); diff --git a/src/axom/primal/geometry/KnotVector.hpp b/src/axom/primal/geometry/KnotVector.hpp index c948f1c76a..035e4cc0cc 100644 --- a/src/axom/primal/geometry/KnotVector.hpp +++ b/src/axom/primal/geometry/KnotVector.hpp @@ -758,6 +758,286 @@ class KnotVector return ders; } + /*! + * \brief Scratch storage for \a derivativeBasisFunctionsBySpan(...) + * + * Stores intermediate tables from Algorithms A2.2/A2.3 ("The NURBS Book") + * in contiguous, row-major buffers to avoid per-call dynamic allocations. + * + * Typical usage is to keep one instance per thread (e.g. `thread_local`) and + * reuse it across evaluations. + */ + struct DerivativeBasisWorkspace + { + //! Derivative table of size `(n+1) x (p+1)` (row-major, derivative-order major) + axom::Array ders; + //! Basis-function triangle from Algorithm A2.2 of size `(p+1) x (p+1)` (row-major) + axom::Array ndu; + //! Alternating coefficient rows from Algorithm A2.3 of size `2 x (p+1)` (row-major) + axom::Array a; + //! Left/right distance buffers from Algorithm A2.2 of length `p+1` + axom::Array left; + axom::Array right; + + void ensure(int deg, int n) + { + const int p1 = deg + 1; + const int ndu_size = p1 * p1; + const int ders_size = (n + 1) * p1; + const int a_size = 2 * p1; + + if(ndu.size() < ndu_size) + { + ndu.resize(ndu_size); + } + if(ders.size() < ders_size) + { + ders.resize(ders_size); + } + if(a.size() < a_size) + { + a.resize(a_size); + } + if(left.size() < p1) + { + left.resize(p1); + } + if(right.size() < p1) + { + right.resize(p1); + } + } + }; + + class DerivativeBasisView + { + public: + struct RowProxy + { + const T* row {nullptr}; + + AXOM_HOST_DEVICE const T& operator[](int col) const { return row[col]; } + }; + + DerivativeBasisView(const T* data, int nrows, int ncols) + : m_data(data) + , m_nrows(nrows) + , m_ncols(ncols) + { } + + AXOM_HOST_DEVICE RowProxy operator[](int row) const + { + return RowProxy {m_data + row * m_ncols}; + } + + AXOM_HOST_DEVICE int getNumDerivatives() const { return m_nrows; } + AXOM_HOST_DEVICE int getNumBasisFunctions() const { return m_ncols; } + + private: + const T* m_data {nullptr}; + int m_nrows {0}; + int m_ncols {0}; + }; + + /*! + * \brief Evaluates the NURBS basis functions and derivatives using a caller-supplied workspace + * + * \note This overload avoids per-call dynamic allocations by reusing memory in \a workspace. + * \warning The returned views are only valid until \a workspace is reused. + */ + DerivativeBasisView derivativeBasisFunctionsBySpan(axom::IndexType span, + T t, + int n, + DerivativeBasisWorkspace& workspace) const + { + SLIC_ASSERT(isValidSpan(span, t)); + SLIC_ASSERT(n >= 0); + SLIC_ASSERT(n <= m_deg); + + const int p = m_deg; + const int p1 = p + 1; + workspace.ensure(p, n); + + T* ders = workspace.ders.data(); + T* ndu = workspace.ndu.data(); + T* left = workspace.left.data(); + T* right = workspace.right.data(); + + // Fast paths for the most common degrees in practice (especially in winding number use cases) + if(n == 1) + { + const auto& U = m_knots; + const T Ui = U[span]; + const T Ui1 = U[span + 1]; + + if(p == 1) + { + const T denom = Ui1 - Ui; + if(denom != static_cast(0)) + { + const T inv = static_cast(1) / denom; + ders[0] = (Ui1 - t) * inv; + ders[1] = (t - Ui) * inv; + ders[2] = -inv; + ders[3] = inv; + } + else + { + ders[0] = static_cast(0); + ders[1] = static_cast(0); + ders[2] = static_cast(0); + ders[3] = static_cast(0); + } + + return DerivativeBasisView(ders, 2, p1); + } + + if(p == 2) + { + // First compute the degree-1 basis functions on the current span: N_{i-1,1}, N_{i,1} + const T denom01 = Ui1 - Ui; + T N_im1_1 = static_cast(0); + T N_i_1 = static_cast(0); + if(denom01 != static_cast(0)) + { + const T inv = static_cast(1) / denom01; + N_im1_1 = (Ui1 - t) * inv; + N_i_1 = (t - Ui) * inv; + } + + // Denominators for degree-2 recurrence/derivatives + const T Uim1 = U[span - 1]; + const T Uip2 = U[span + 2]; + const T denomA = Ui1 - Uim1; // U[i+1] - U[i-1] + const T denomB = Uip2 - Ui; // U[i+2] - U[i] + + const T invA = + (denomA != static_cast(0)) ? (static_cast(1) / denomA) : static_cast(0); + const T invB = + (denomB != static_cast(0)) ? (static_cast(1) / denomB) : static_cast(0); + + // Basis values (row 0): N_{i-2,2}, N_{i-1,2}, N_{i,2} + ders[0] = (Ui1 - t) * invA * N_im1_1; + ders[1] = (t - Uim1) * invA * N_im1_1 + (Uip2 - t) * invB * N_i_1; + ders[2] = (t - Ui) * invB * N_i_1; + + // First derivatives (row 1): d/dt N_{j,2} = 2/(U[j+2]-U[j])*N_{j,1} - 2/(U[j+3]-U[j+1])*N_{j+1,1} + // On the current span, N_{i-2,1} and N_{i+1,1} are zero. + ders[3] = static_cast(-2) * invA * N_im1_1; + ders[4] = static_cast(2) * invA * N_im1_1 - static_cast(2) * invB * N_i_1; + ders[5] = static_cast(2) * invB * N_i_1; + + return DerivativeBasisView(ders, 2, p1); + } + } + + // ndu stores both the triangular basis function table and denominator terms + // from Algorithm A2.2. We store it in row-major order with stride p1. + ndu[0] = 1.; + for(int j = 1; j <= p; ++j) + { + left[j] = t - m_knots[span + 1 - j]; + right[j] = m_knots[span + j] - t; + T saved = 0.0; + + const auto ndu_j = ndu + j * p1; + for(int r = 0; r < j; ++r) + { + ndu_j[r] = right[r + 1] + left[j - r]; + const T temp = ndu[r * p1 + (j - 1)] / ndu_j[r]; + ndu[r * p1 + j] = saved + right[r + 1] * temp; + saved = left[j - r] * temp; + } + ndu_j[j] = saved; + } + + // ders row 0: basis function values + for(int j = 0; j <= p; ++j) + { + ders[j] = ndu[j * p1 + p]; + } + + if(n == 0) + { + return DerivativeBasisView(ders, 1, p1); + } + + // Fast path for the common case: first derivatives only. + // This simplifies Algorithm A2.3 since k is fixed to 1. + if(n == 1) + { + const auto denom_row = ndu + p * p1; + for(int r = 0; r <= p; ++r) + { + T d = 0.; + if(r >= 1) + { + d += ndu[(r - 1) * p1 + (p - 1)] / denom_row[r - 1]; + } + if(r <= p - 1) + { + d -= ndu[r * p1 + (p - 1)] / denom_row[r]; + } + ders[p1 + r] = d * static_cast(p); + } + + return DerivativeBasisView(ders, 2, p1); + } + + // General case (n >= 2): Algorithm A2.3, implemented with workspace buffers. + T* a = workspace.a.data(); + + auto ndu_at = [&](int row, int col) -> T& { return ndu[row * p1 + col]; }; + auto ders_at = [&](int row, int col) -> T& { return ders[row * p1 + col]; }; + auto a_at = [&](int row, int col) -> T& { return a[row * p1 + col]; }; + + for(int r = 0; r <= p; ++r) + { + int s1 = 0, s2 = 1; + a_at(0, 0) = 1.; + for(int k = 1; k <= n; ++k) + { + T d = 0.; + const int rk = r - k; + const int pk = p - k; + if(r >= k) + { + a_at(s2, 0) = a_at(s1, 0) / ndu_at(pk + 1, rk); + d = a_at(s2, 0) * ndu_at(rk, pk); + } + + const int j1 = (rk >= -1) ? 1 : -rk; + const int j2 = (r - 1 <= pk) ? (k - 1) : (p - r); + for(int j = j1; j <= j2; ++j) + { + a_at(s2, j) = (a_at(s1, j) - a_at(s1, j - 1)) / ndu_at(pk + 1, rk + j); + d += a_at(s2, j) * ndu_at(rk + j, pk); + } + + if(r <= pk) + { + a_at(s2, k) = -a_at(s1, k - 1) / ndu_at(pk + 1, r); + d += a_at(s2, k) * ndu_at(r, pk); + } + + ders_at(k, r) = d; + std::swap(s1, s2); + } + } + + T factor = static_cast(p); + for(int k = 1; k <= n; ++k) + { + for(int j = 0; j <= p; ++j) + { + ders_at(k, j) *= factor; + } + factor *= static_cast(p - k); + } + + return DerivativeBasisView(ders, n + 1, p1); + } + /*! * \brief Evaluates the NURBS basis functions and derivatives for parameter value t * diff --git a/src/axom/primal/geometry/NURBSCurve.hpp b/src/axom/primal/geometry/NURBSCurve.hpp index 9658692fe5..42f95b1eac 100644 --- a/src/axom/primal/geometry/NURBSCurve.hpp +++ b/src/axom/primal/geometry/NURBSCurve.hpp @@ -406,7 +406,7 @@ class NURBSCurve for(int idx = 0; idx < n_segments; ++idx) { T theta_start = theta_0 + pi23 * idx; - T theta_end = std::min(theta_start + pi23, theta_1); + T theta_end = axom::utilities::min(theta_start + pi23, theta_1); arc_curve[1 + 2 * idx + 1] = PointType({std::cos(theta_end), std::sin(theta_end)}); @@ -810,7 +810,7 @@ class NURBSCurve const auto span = m_knotvec.findSpan(t, s); // Fix the maximum multiplicity of the knot - int r = std::min(target_multiplicity - s, p - s); + int r = axom::utilities::min(target_multiplicity - s, p - s); if(r <= 0) { return span; // Early exit if no knots to add @@ -1079,9 +1079,10 @@ class NURBSCurve const bool isCurveRational = this->isRational(); - int du = std::min(d, p); + int du = axom::utilities::min(d, p); const auto span = m_knotvec.findSpan(t); - const auto N_evals = m_knotvec.derivativeBasisFunctionsBySpan(span, t, du); + thread_local typename KnotVector::DerivativeBasisWorkspace basis_workspace; + const auto N_evals = m_knotvec.derivativeBasisFunctionsBySpan(span, t, du, basis_workspace); // Store w(u) in Awders[NDIMS][0], w'(u) in Awders[NDIMS][1], ... axom::Array> Awders(d + 1); diff --git a/src/axom/primal/geometry/NURBSPatch.hpp b/src/axom/primal/geometry/NURBSPatch.hpp index 79006f5ccf..eed10b824d 100644 --- a/src/axom/primal/geometry/NURBSPatch.hpp +++ b/src/axom/primal/geometry/NURBSPatch.hpp @@ -1688,7 +1688,7 @@ class NURBSPatch { for(int j = 0; j < m; ++j) { - min_weight = std::min(min_weight, m_weights(i, j)); + min_weight = axom::utilities::min(min_weight, m_weights(i, j)); } } @@ -2170,16 +2170,30 @@ class NURBSPatch } /*! - * \brief Evaluate the NURBS patch geometry and the first \a d derivatives at parameter \a u, \a v + * \brief Evaluate the NURBS patch geometry derivatives up to order \a d at parameter \a u, \a v * * \param [in] u The parameter value on the first axis * \param [in] v The parameter value on the second axis - * \param [in] d The number of derivatives to evaluate + * \param [in] ord The maximum (or total) order of evaluated derivatives to evaluate * \param [out] ders A matrix of size d+1 x d+1 containing the derivatives + * \param [in] evalByTotalOrder If true, only evaluate derivatives up to total + * order d instead of maximum component order d. * * ders[i][j] is the derivative of S with respect to u i times and v j times. * For consistency, ders[0][0] contains the evaluation point stored as a vector - * + * + * If `evalByTotalOrder` is false (default behavior), then ders contains for d == 3 + * + * | eval , S_u , S_uu | + * ders = | S_v , S_uv , S_uuv | + * | S_vv , S_vvu , S_uuvv | + * + * If `evalByTotalOrder` is true, then ders[i][j] == 0 whenever i + j > d + * + * | eval , S_u , S_uu | + * ders = | S_v , S_uv , 0 | + * | S_vv , 0 , 0 | + * * Implementation adapted from Algorithm A3.6 on p. 111 of "The NURBS Book". * Rational derivatives from Algorithm A4.4 on p. 137 of "The NURBS Book". * @@ -2187,7 +2201,11 @@ class NURBSPatch * * \note If u/v is outside the knot span up this tolerance, it is clamped to the span */ - void evaluateDerivatives(T u, T v, int d, axom::Array& ders) const + void evaluateDerivatives(T u, + T v, + int d, + axom::Array& ders, + bool evalByTotalOrder = false) const { u = axom::utilities::clampVal(u, getMinKnot_u(), getMaxKnot_u()); v = axom::utilities::clampVal(v, getMinKnot_v(), getMaxKnot_v()); @@ -2198,6 +2216,11 @@ class NURBSPatch const int deg_v = getDegree_v(); const int dv = axom::utilities::min(d, deg_v); + // Basis-derivative workspaces are needed for both axes at the same time (u and v), + // so keep one per axis and reuse across calls to avoid per-call allocations. + thread_local typename KnotVectorType::DerivativeBasisWorkspace basis_workspace_u; + thread_local typename KnotVectorType::DerivativeBasisWorkspace basis_workspace_v; + // Matrix for derivatives ders.resize(d + 1, d + 1); ders.fill(VectorType(0.0)); @@ -2211,10 +2234,12 @@ class NURBSPatch // Find the span of the knot vectors and basis function derivatives const auto span_u = m_knotvec_u.findSpan(u); - const auto N_evals_u = m_knotvec_u.derivativeBasisFunctionsBySpan(span_u, u, du); + const auto N_evals_u = + m_knotvec_u.derivativeBasisFunctionsBySpan(span_u, u, du, basis_workspace_u); const auto span_v = m_knotvec_v.findSpan(v); - const auto N_evals_v = m_knotvec_v.derivativeBasisFunctionsBySpan(span_v, v, dv); + const auto N_evals_v = + m_knotvec_v.derivativeBasisFunctionsBySpan(span_v, v, dv, basis_workspace_v); for(int k = 0; k <= du; ++k) { @@ -2236,7 +2261,7 @@ class NURBSPatch } } - int dd = axom::utilities::min(d - k, dv); + const int dd = evalByTotalOrder ? axom::utilities::min(d - k, dv) : dv; for(int l = 0; l <= dd; ++l) { for(int s = 0; s <= deg_v; ++s) @@ -2252,16 +2277,17 @@ class NURBSPatch // Compute the derivatives of the homogeneous surface for(int k = 0; k <= d; ++k) { - for(int l = 0; l <= d - k; ++l) + const int dd = evalByTotalOrder ? d - k : d; + for(int l = 0; l <= dd; ++l) { - auto v = Awders[k][l]; + auto v1 = Awders[k][l]; for(int j = 0; j <= l; ++j) { auto bin = axom::utilities::binomialCoefficient(l, j); for(int n = 0; n < NDIMS; ++n) { - v[n] -= bin * Awders[0][j][NDIMS] * ders[k][l - j][n]; + v1[n] -= bin * Awders[0][j][NDIMS] * ders[k][l - j][n]; } } @@ -2270,7 +2296,7 @@ class NURBSPatch auto bin = axom::utilities::binomialCoefficient(k, i); for(int n = 0; n < NDIMS; ++n) { - v[n] -= bin * Awders[i][0][NDIMS] * ders[k - i][l][n]; + v1[n] -= bin * Awders[i][0][NDIMS] * ders[k - i][l][n]; } auto v2 = Point::zero(); @@ -2285,13 +2311,13 @@ class NURBSPatch for(int n = 0; n < NDIMS; ++n) { - v[n] -= bin * v2[n]; + v1[n] -= bin * v2[n]; } } for(int n = 0; n < NDIMS; ++n) { - ders[k][l][n] = v[n] / Awders[0][0][NDIMS]; + ders[k][l][n] = v1[n] / Awders[0][0][NDIMS]; } } } @@ -2306,16 +2332,122 @@ class NURBSPatch * \param [out] Du The vector value of S_u(u, v) * \param [out] Dv The vector value of S_v(u, v) * + * Uses a specialized formula that is faster than evaluateDerivatives, avoiding + * repeated dynamic allocations in the generic implementation. + * This is performance-critical for 3D winding-number evaluations + * * \pre We require evaluation of the patch at \a u and \a v between 0 and 1 */ void evaluateFirstDerivatives(T u, T v, PointType& eval, VectorType& Du, VectorType& Dv) const { - axom::Array ders; - evaluateDerivatives(u, v, 1, ders); + Du = VectorType(0.0); + Dv = VectorType(0.0); - eval = PointType(ders[0][0].array()); - Du = ders[1][0]; - Dv = ders[0][1]; + u = axom::utilities::clampVal(u, getMinKnot_u(), getMaxKnot_u()); + v = axom::utilities::clampVal(v, getMinKnot_v(), getMaxKnot_v()); + + const int deg_u = getDegree_u(); + const int du = axom::utilities::min(1, deg_u); + + const int deg_v = getDegree_v(); + const int dv = axom::utilities::min(1, deg_v); + + // Basis-derivative workspaces are needed for both axes at the same time (u and v), + // so keep one per axis and reuse across calls to avoid per-call allocations. + thread_local typename KnotVectorType::DerivativeBasisWorkspace basis_workspace_u; + thread_local typename KnotVectorType::DerivativeBasisWorkspace basis_workspace_v; + + const bool isRationalPatch = isRational(); + + const auto span_u = m_knotvec_u.findSpan(u); + const auto N_evals_u = + m_knotvec_u.derivativeBasisFunctionsBySpan(span_u, u, du, basis_workspace_u); + + const auto span_v = m_knotvec_v.findSpan(v); + const auto N_evals_v = + m_knotvec_v.derivativeBasisFunctionsBySpan(span_v, v, dv, basis_workspace_v); + + using HomogeneousPoint = Point; + + thread_local axom::Array temp0; + thread_local axom::Array temp1; + + const int nv = deg_v + 1; + if(temp0.size() < nv) + { + temp0.resize(nv); + temp1.resize(nv); + } + + for(int s = 0; s <= deg_v; ++s) + { + temp0[s] = HomogeneousPoint::zero(); + temp1[s] = HomogeneousPoint::zero(); + + for(int r = 0; r <= deg_u; ++r) + { + const auto iu = span_u - deg_u + r; + const auto iv = span_v - deg_v + s; + + const T weight = isRationalPatch ? m_weights(iu, iv) : static_cast(1); + const auto& pt = m_controlPoints(iu, iv); + + const T Nu0 = N_evals_u[0][r]; + const T Nu1 = (du == 1) ? N_evals_u[1][r] : static_cast(0); + + for(int n = 0; n < NDIMS; ++n) + { + const T wpt = weight * pt[n]; + temp0[s][n] += Nu0 * wpt; + temp1[s][n] += Nu1 * wpt; + } + + temp0[s][NDIMS] += Nu0 * weight; + temp1[s][NDIMS] += Nu1 * weight; + } + } + + HomogeneousPoint A00 = HomogeneousPoint::zero(); + HomogeneousPoint A10 = HomogeneousPoint::zero(); + HomogeneousPoint A01 = HomogeneousPoint::zero(); + + for(int s = 0; s <= deg_v; ++s) + { + const T Nv0 = N_evals_v[0][s]; + const T Nv1 = (dv == 1) ? N_evals_v[1][s] : static_cast(0); + + for(int n = 0; n <= NDIMS; ++n) + { + A00[n] += Nv0 * temp0[s][n]; + A10[n] += Nv0 * temp1[s][n]; + A01[n] += Nv1 * temp0[s][n]; + } + } + + const T w = isRationalPatch ? A00[NDIMS] : static_cast(1); + + for(int n = 0; n < NDIMS; ++n) + { + eval[n] = isRationalPatch ? (A00[n] / w) : A00[n]; + } + + if(du == 1) + { + const T w_u = isRationalPatch ? A10[NDIMS] : static_cast(0); + for(int n = 0; n < NDIMS; ++n) + { + Du[n] = isRationalPatch ? ((A10[n] - w_u * eval[n]) / w) : A10[n]; + } + } + + if(dv == 1) + { + const T w_v = isRationalPatch ? A01[NDIMS] : static_cast(0); + for(int n = 0; n < NDIMS; ++n) + { + Dv[n] = isRationalPatch ? ((A01[n] - w_v * eval[n]) / w) : A01[n]; + } + } } /*! @@ -2342,7 +2474,7 @@ class NURBSPatch axom::Array ders; evaluateDerivatives(u, v, 1, ders); - eval = PointType(ders[0][0]); + eval = PointType(ders[0][0].array()); Du = ders[1][0]; Dv = ders[0][1]; DuDv = ders[1][1]; @@ -2374,9 +2506,10 @@ class NURBSPatch VectorType& DuDv) const { axom::Array ders; - evaluateDerivatives(u, v, 2, ders); + constexpr bool evalByTotalOrder = true; // To skip evaluation of ders[1][2], etc. + evaluateDerivatives(u, v, 2, ders, evalByTotalOrder); - eval = PointType(ders[0][0]); + eval = PointType(ders[0][0].array()); Du = ders[1][0]; Dv = ders[0][1]; DuDu = ders[2][0]; @@ -2397,7 +2530,8 @@ class NURBSPatch VectorType du(T u, T v) const { axom::Array ders; - evaluateDerivatives(u, v, 1, ders); + constexpr bool evalByTotalOrder = true; // To skip evaluation of ders[1][1] + evaluateDerivatives(u, v, 1, ders, evalByTotalOrder); return ders[1][0]; } @@ -2415,7 +2549,8 @@ class NURBSPatch VectorType dv(T u, T v) const { axom::Array ders; - evaluateDerivatives(u, v, 1, ders); + constexpr bool evalByTotalOrder = true; // To skip evaluation of ders[1][1] + evaluateDerivatives(u, v, 1, ders, evalByTotalOrder); return ders[0][1]; } @@ -2433,7 +2568,8 @@ class NURBSPatch VectorType dudu(T u, T v) const { axom::Array ders; - evaluateDerivatives(u, v, 2, ders); + constexpr bool evalByTotalOrder = true; // To skip evaluation of ders[1][1], etc. + evaluateDerivatives(u, v, 2, ders, evalByTotalOrder); return ders[2][0]; } @@ -2451,7 +2587,8 @@ class NURBSPatch VectorType dvdv(T u, T v) const { axom::Array ders; - evaluateDerivatives(u, v, 2, ders); + constexpr bool evalByTotalOrder = true; // To skip evaluation of ders[1][1], etc. + evaluateDerivatives(u, v, 2, ders, evalByTotalOrder); return ders[0][2]; } @@ -2469,7 +2606,7 @@ class NURBSPatch VectorType dudv(T u, T v) const { axom::Array ders; - evaluateDerivatives(u, v, 2, ders); + evaluateDerivatives(u, v, 1, ders); return ders[1][1]; } @@ -4055,4 +4192,4 @@ template struct axom::fmt::formatter> : ostream_formatter { }; -#endif // AXOM_PRIMAL_NURBSPATCH_HPP_ +#endif // AXOM_PRIMAL_NURBSPATCH_HPP_ \ No newline at end of file diff --git a/src/axom/primal/geometry/Point.hpp b/src/axom/primal/geometry/Point.hpp index 290ffb938c..0cb6d40f0b 100644 --- a/src/axom/primal/geometry/Point.hpp +++ b/src/axom/primal/geometry/Point.hpp @@ -199,6 +199,27 @@ class Point AXOM_HOST_DEVICE friend inline bool operator!=(const Point& lhs, const Point& rhs) { return !(lhs == rhs); } + /*! + * \brief Equality comparison for points that checks that each component is + * compared within a tolerance. This is simpler test than distance, which + * requires multiplies. + * + * \param obj The point being compared to this object. + * \param tol The tolerance being used. + * + * \return True if the points are equal within the tolerance, false otherwise. + */ + AXOM_HOST_DEVICE + bool isNearlyEqual(const Point& obj, const T tol = 1.e-10) const + { + bool value = true; + for(int d = 0; d < NDIMS && value; d++) + { + value = value && axom::utilities::isNearlyEqual(m_components[d], obj.m_components[d], tol); + } + return value; + } + /*! * \brief Simple formatted print of a point instance * \param os The output stream to write to diff --git a/src/axom/primal/geometry/detail/analytic_test_surfaces.hpp b/src/axom/primal/geometry/detail/analytic_test_surfaces.hpp new file mode 100644 index 0000000000..eb409fadce --- /dev/null +++ b/src/axom/primal/geometry/detail/analytic_test_surfaces.hpp @@ -0,0 +1,325 @@ +// Copyright (c) Lawrence Livermore National Security, LLC and other +// Axom Project Contributors. See top-level LICENSE and COPYRIGHT +// files for dates and other details. +// +// SPDX-License-Identifier: (BSD-3-Clause) + +/*! + * \file analytic_test_surfaces.hpp + * + * \brief Consists of methods that generate arrays of NURBSPatch objects which depict + * objects whose containment decisions can be made analytically, primarily + * for the purpose of testing GWN containment methods + * + * \sa primal_solid_angle.cpp + */ + +#ifndef AXOM_PRIMAL_ANALYTIC_TEST_SURFACES_HPP +#define AXOM_PRIMAL_ANALYTIC_TEST_SURFACES_HPP + +#include "axom/config.hpp" +#include "axom/primal.hpp" + +namespace axom +{ +namespace primal +{ +namespace detail +{ + +/*! + * \brief Construct a unit sphere out of six rational, biquintic, untrimmed NURBS patches. + * + * Defines the nodes and weights for one of six rational, biquartic Bezier patches + * that compose the unit sphere. These will be rotated to form the other 5. + * Nodes and weights obtained from the technical report + * "Tiling the Sphere with Rational Bezier Patches", James E. Cobb, University of Utah, 1988 + * + * \return The array of NURBS patches + */ +axom::Array> make_unit_sphere_biquartic() +{ + using Point3D = primal::Point; + using NPatch = primal::NURBSPatch; + + double rt2 = sqrt(2), rt3 = sqrt(3), rt6 = sqrt(6); + + // clang-format off + axom::Array node_data = { + Point3D {4*(1-rt3), 4*(1-rt3), 4*(1-rt3)}, Point3D {rt2*(rt3-4), -rt2, rt2*(rt3-4)}, Point3D {4*(1-2*rt3)/3, 0, 4*(1-2*rt3)/3}, Point3D {rt2*(rt3-4), rt2, rt2*(rt3-4)}, Point3D {4*(1-rt3), 4*(rt3-1), 4*(1-rt3)}, + Point3D { -rt2, rt2*(rt3 - 4), rt2*(rt3 - 4)}, Point3D {(2-3*rt3)/2, (2-3*rt3)/2, -(rt3+6)/2}, Point3D {rt2*(2*rt3-7)/3, 0, -5*rt6/3}, Point3D {(2-3*rt3)/2, (3*rt3-2)/2, -(rt3+6)/2}, Point3D { -rt2, rt2*(4-rt3), rt2*(rt3-4)}, + Point3D { 0, 4*(1-2*rt3)/3, 4*(1-2*rt3)/3}, Point3D { 0, rt2*(2*rt3-7)/3, -5*rt6/3}, Point3D {0, 0, 4*(rt3-5)/3}, Point3D { 0, rt2*(7-2*rt3)/3, -5*rt6/3}, Point3D { 0, 4*(2*rt3-1)/3, 4*(1-2*rt3)/3}, + Point3D { rt2, rt2*(rt3 - 4), rt2*(rt3 - 4)}, Point3D {(3*rt3-2)/2, (2-3*rt3)/2, -(rt3+6)/2}, Point3D {rt2*(7-2*rt3)/3, 0, -5*rt6/3}, Point3D {(3*rt3-2)/2, (3*rt3-2)/2, -(rt3+6)/2}, Point3D { rt2, rt2*(4-rt3), rt2*(rt3-4)}, + Point3D {4*(rt3-1), 4*(1-rt3), 4*(1-rt3)}, Point3D {rt2*(4-rt3), -rt2, rt2*(rt3-4)}, Point3D {4*(2*rt3-1)/3, 0, 4*(1-2*rt3)/3}, Point3D {rt2*(4-rt3), rt2, rt2*(rt3-4)}, Point3D {4*(rt3-1), 4*(rt3-1), 4*(1-rt3)}}; + + axom::Array weight_data = { + 4*(3-rt3), rt2*(3*rt3-2), 4*(5-rt3)/3, rt2*(3*rt3-2), 4*(3-rt3), + rt2*(3*rt3-2), (rt3+6)/2, rt2*(rt3+6)/3, (rt3+6)/2, rt2*(3*rt3-2), + 4*(5-rt3)/3, rt2*(rt3+6)/3, 4*(5*rt3-1)/9, rt2*(rt3+6)/3, 4*(5-rt3)/3, + rt2*(3*rt3-2), (rt3+6)/2, rt2*(rt3+6)/3, (rt3+6)/2, rt2*(3*rt3-2), + 4*(3-rt3), rt2*(3*rt3-2), 4*(5-rt3)/3, rt2*(3*rt3-2), 4*(3-rt3)}; + // clang-format on + + axom::Array sphere_faces(6); + for(int n = 0; n < 6; ++n) + { + sphere_faces[n].setParameters(5, 5, 4, 4); + sphere_faces[n].makeRational(); + } + + for(int i = 0; i < 5; ++i) + { + for(int j = 0; j < 5; ++j) + { + const int idx = 5 * i + j; + for(int n = 0; n < 6; ++n) + { + sphere_faces[n].setWeight(i, j, weight_data[idx]); + } + + // Set up each face by rotating one of the patch faces + sphere_faces[0](i, j)[0] = node_data[idx][1]; + sphere_faces[0](i, j)[1] = node_data[idx][0]; + sphere_faces[0](i, j)[2] = node_data[idx][2]; + sphere_faces[0](i, j).array() /= weight_data[idx]; + + sphere_faces[1](i, j)[0] = -node_data[idx][0]; + sphere_faces[1](i, j)[1] = -node_data[idx][1]; + sphere_faces[1](i, j)[2] = -node_data[idx][2]; + sphere_faces[1](i, j).array() /= weight_data[idx]; + + sphere_faces[2](i, j)[0] = node_data[idx][2]; + sphere_faces[2](i, j)[1] = node_data[idx][1]; + sphere_faces[2](i, j)[2] = node_data[idx][0]; + sphere_faces[2](i, j).array() /= weight_data[idx]; + + sphere_faces[3](i, j)[0] = -node_data[idx][1]; + sphere_faces[3](i, j)[1] = -node_data[idx][2]; + sphere_faces[3](i, j)[2] = -node_data[idx][0]; + sphere_faces[3](i, j).array() /= weight_data[idx]; + + sphere_faces[4](i, j)[0] = node_data[idx][0]; + sphere_faces[4](i, j)[1] = node_data[idx][2]; + sphere_faces[4](i, j)[2] = node_data[idx][1]; + sphere_faces[4](i, j).array() /= weight_data[idx]; + + sphere_faces[5](i, j)[0] = -node_data[idx][2]; + sphere_faces[5](i, j)[1] = -node_data[idx][0]; + sphere_faces[5](i, j)[2] = -node_data[idx][1]; + sphere_faces[5](i, j).array() /= weight_data[idx]; + } + } + + return sphere_faces; +} + +/*! + * \brief Construct a unit sphere out of 8 rational, bicubic, untrimmed NURBS patches. + * + * Defines two BezierCurves which, when rotated around the z-axis, + * forms the top and bottom halves of a sphere. + * Note that the resulting surfaces each have degenerate edges at the poles of the sphere + * + * \return The array of NURBS patches + */ +axom::Array> make_unit_sphere_biquadratic() +{ + using Point2D = primal::Point; + using Point3D = primal::Point; + using BCurve = primal::BezierCurve; + using NPatch = primal::NURBSPatch; + + double rt2 = sqrt(2); + + BCurve top_curve(2), bottom_curve(2); + top_curve[0] = Point2D {0.0, 1.0}; + top_curve[1] = Point2D {1.0, 1.0}; + top_curve[2] = Point2D {1.0, 0.0}; + + bottom_curve[0] = Point2D {1.0, 0.0}; + bottom_curve[1] = Point2D {1.0, -1.0}; + bottom_curve[2] = Point2D {0.0, -1.0}; + + top_curve.makeRational(); + top_curve.setWeight(1, 1.0 / rt2); + + bottom_curve.makeRational(); + bottom_curve.setWeight(1, 1.0 / rt2); + + axom::Array sphere_faces(8); + for(int n = 0; n < 8; ++n) + { + sphere_faces[n].setParameters(3, 3, 2, 2); + sphere_faces[n].makeRational(); + } + + for(int n = 0; n < 2; ++n) + { + auto& curve = (n == 0) ? top_curve : bottom_curve; + + for(int i = 0; i <= 2; ++i) + { + // clang-format off + sphere_faces[4*n + 0](i, 0) = Point3D {curve[i][0], 0.0, curve[i][1]}; + sphere_faces[4*n + 0](i, 1) = Point3D {curve[i][0], curve[i][0], curve[i][1]}; + sphere_faces[4*n + 0](i, 2) = Point3D {0.0, curve[i][0], curve[i][1]}; + + sphere_faces[4*n + 1](i, 0) = Point3D {0.0, curve[i][0], curve[i][1]}; + sphere_faces[4*n + 1](i, 1) = Point3D {-curve[i][0], curve[i][0], curve[i][1]}; + sphere_faces[4*n + 1](i, 2) = Point3D {-curve[i][0], 0.0, curve[i][1]}; + + sphere_faces[4*n + 2](i, 0) = Point3D {-curve[i][0], 0.0, curve[i][1]}; + sphere_faces[4*n + 2](i, 1) = Point3D {-curve[i][0], -curve[i][0], curve[i][1]}; + sphere_faces[4*n + 2](i, 2) = Point3D {0.0, -curve[i][0], curve[i][1]}; + + sphere_faces[4*n + 3](i, 0) = Point3D {0.0, -curve[i][0], curve[i][1]}; + sphere_faces[4*n + 3](i, 1) = Point3D {curve[i][0], -curve[i][0], curve[i][1]}; + sphere_faces[4*n + 3](i, 2) = Point3D {curve[i][0], 0.0, curve[i][1]}; + + const double the_weight = curve.getWeight(i); + + sphere_faces[4*n + 0].setWeight(i, 0, the_weight); + sphere_faces[4*n + 1].setWeight(i, 0, the_weight); + sphere_faces[4*n + 2].setWeight(i, 0, the_weight); + sphere_faces[4*n + 3].setWeight(i, 0, the_weight); + + sphere_faces[4*n + 0].setWeight(i, 1, the_weight / rt2); + sphere_faces[4*n + 1].setWeight(i, 1, the_weight / rt2); + sphere_faces[4*n + 2].setWeight(i, 1, the_weight / rt2); + sphere_faces[4*n + 3].setWeight(i, 1, the_weight / rt2); + + sphere_faces[4*n + 0].setWeight(i, 2, the_weight); + sphere_faces[4*n + 1].setWeight(i, 2, the_weight); + sphere_faces[4*n + 2].setWeight(i, 2, the_weight); + sphere_faces[4*n + 3].setWeight(i, 2, the_weight); + // clang-format on + } + } + + return sphere_faces; +} + +/*! + * \brief Construct a "teardrop" sphere out of order (3, 3) and order (4, 3) NURBS patches. + * + * Defines two BezierCurves which, when rotated around the z-axis, form the shape. + * The bottom portion is a sphere with the same construction as `make_unit_sphere_biquadratic()`. + * The top "tip" portion is made from a polynomial cubic curve for which containment is defined by + * the equation y = 3sin(1/3 * asin(1-2x)) + x - 0.5 + * + * Note that the resulting surfaces each have degenerate edges at the poles of the sphere + * + * \return The array of NURBS patches + */ +axom::Array> make_teardrop() +{ + // Generate a teardrop shape using (degenerate) bicubic patches. + // The bottom portion is a bicubic sphere, + // The top portion is defined by the solid of revolution of a cubic Bezier curve + + using Point2D = primal::Point; + using Point3D = primal::Point; + using BCurve = primal::BezierCurve; + using NPatch = primal::NURBSPatch; + + double rt2 = sqrt(2); + + // Define BezierCurves which, when rotated around the z-axis, + // form the top and bottom halves of a sphere. + BCurve top_curve(3), bottom_curve(2); + top_curve[0] = Point2D {0.0, 1.0}; + top_curve[1] = Point2D {0.0, 0.0}; + top_curve[2] = Point2D {1.0, 0.0}; + top_curve[3] = Point2D {1.0, -1.0}; + + bottom_curve[0] = Point2D {1.0, -1.0}; + bottom_curve[1] = Point2D {1.0, -2.0}; + bottom_curve[2] = Point2D {0.0, -2.0}; + + bottom_curve.makeRational(); + bottom_curve.setWeight(1, 1.0 / rt2); + + axom::Array teardrop_faces(8); + for(int n = 0; n < 4; ++n) + { + teardrop_faces[n].setParameters(4, 3, 3, 2); + teardrop_faces[n].makeRational(); + + teardrop_faces[4 + n].setParameters(3, 3, 2, 2); + teardrop_faces[4 + n].makeRational(); + } + + // Top faces + for(int i = 0; i <= 3; ++i) + { + // clang-format off + teardrop_faces[0](i, 0) = Point3D {top_curve[i][0], 0.0, top_curve[i][1]}; + teardrop_faces[0](i, 1) = Point3D {top_curve[i][0], top_curve[i][0], top_curve[i][1]}; + teardrop_faces[0](i, 2) = Point3D {0.0, top_curve[i][0], top_curve[i][1]}; + + teardrop_faces[1](i, 0) = Point3D {0.0, top_curve[i][0], top_curve[i][1]}; + teardrop_faces[1](i, 1) = Point3D {-top_curve[i][0], top_curve[i][0], top_curve[i][1]}; + teardrop_faces[1](i, 2) = Point3D {-top_curve[i][0], 0.0, top_curve[i][1]}; + + teardrop_faces[2](i, 0) = Point3D {-top_curve[i][0], 0.0, top_curve[i][1]}; + teardrop_faces[2](i, 1) = Point3D {-top_curve[i][0], -top_curve[i][0], top_curve[i][1]}; + teardrop_faces[2](i, 2) = Point3D {0.0, -top_curve[i][0], top_curve[i][1]}; + + teardrop_faces[3](i, 0) = Point3D {0.0, -top_curve[i][0], top_curve[i][1]}; + teardrop_faces[3](i, 1) = Point3D {top_curve[i][0], -top_curve[i][0], top_curve[i][1]}; + teardrop_faces[3](i, 2) = Point3D {top_curve[i][0], 0.0, top_curve[i][1]}; + + teardrop_faces[0].setWeight(i, 1, 1.0 / rt2); + teardrop_faces[1].setWeight(i, 1, 1.0 / rt2); + teardrop_faces[2].setWeight(i, 1, 1.0 / rt2); + teardrop_faces[3].setWeight(i, 1, 1.0 / rt2); + // clang-format on + } + + // Bottom faces + for(int i = 0; i <= 2; ++i) + { + // clang-format off + teardrop_faces[4](i, 0) = Point3D {bottom_curve[i][0], 0.0, bottom_curve[i][1]}; + teardrop_faces[4](i, 1) = Point3D {bottom_curve[i][0], bottom_curve[i][0], bottom_curve[i][1]}; + teardrop_faces[4](i, 2) = Point3D {0.0, bottom_curve[i][0], bottom_curve[i][1]}; + + teardrop_faces[5](i, 0) = Point3D {0.0, bottom_curve[i][0], bottom_curve[i][1]}; + teardrop_faces[5](i, 1) = Point3D {-bottom_curve[i][0], bottom_curve[i][0], bottom_curve[i][1]}; + teardrop_faces[5](i, 2) = Point3D {-bottom_curve[i][0], 0.0, bottom_curve[i][1]}; + + teardrop_faces[6](i, 0) = Point3D {-bottom_curve[i][0], 0.0, bottom_curve[i][1]}; + teardrop_faces[6](i, 1) = Point3D {-bottom_curve[i][0], -bottom_curve[i][0], bottom_curve[i][1]}; + teardrop_faces[6](i, 2) = Point3D {0.0, -bottom_curve[i][0], bottom_curve[i][1]}; + + teardrop_faces[7](i, 0) = Point3D {0.0, -bottom_curve[i][0], bottom_curve[i][1]}; + teardrop_faces[7](i, 1) = Point3D {bottom_curve[i][0], -bottom_curve[i][0], bottom_curve[i][1]}; + teardrop_faces[7](i, 2) = Point3D {bottom_curve[i][0], 0.0, bottom_curve[i][1]}; + + const double the_weight = bottom_curve.getWeight(i); + + teardrop_faces[4].setWeight(i, 0, the_weight); + teardrop_faces[5].setWeight(i, 0, the_weight); + teardrop_faces[6].setWeight(i, 0, the_weight); + teardrop_faces[7].setWeight(i, 0, the_weight); + + teardrop_faces[4].setWeight(i, 1, the_weight / rt2); + teardrop_faces[5].setWeight(i, 1, the_weight / rt2); + teardrop_faces[6].setWeight(i, 1, the_weight / rt2); + teardrop_faces[7].setWeight(i, 1, the_weight / rt2); + + teardrop_faces[4].setWeight(i, 2, the_weight); + teardrop_faces[5].setWeight(i, 2, the_weight); + teardrop_faces[6].setWeight(i, 2, the_weight); + teardrop_faces[7].setWeight(i, 2, the_weight); + // clang-format on + } + + return teardrop_faces; +} + +} // namespace detail +} // namespace primal +} // namespace axom + +#endif // AXOM_PRIMAL_ANALYTIC_TEST_SURFACES_HPP diff --git a/src/axom/primal/operators/detail/clip_impl.hpp b/src/axom/primal/operators/detail/clip_impl.hpp index b0d6734c3d..4a1539cd7f 100644 --- a/src/axom/primal/operators/detail/clip_impl.hpp +++ b/src/axom/primal/operators/detail/clip_impl.hpp @@ -870,27 +870,58 @@ AXOM_HOST_DEVICE Polyhedron clipTetrahedron(const Tetrahedron +AXOM_HOST_DEVICE void clipPolygonAddVertex(PolygonType& polygon, const PointType& pt, T typed_eps) +{ + const auto nverts = polygon.numVertices(); + bool addVert = nverts == 0; + if(nverts > 1) + { + // Make sure the new point differs from the start/end points in the polygon. + addVert = + !pt.isNearlyEqual(polygon[0], typed_eps) && !pt.isNearlyEqual(polygon[nverts - 1], typed_eps); + } + else if(nverts > 0) + { + // Make sure the new point differs from the start point in the polygon. + addVert = !pt.isNearlyEqual(polygon[0], typed_eps); + } + if(addVert) + { + polygon.addVertex(pt); + } +} + +/*! + * \brief Clips a 2D subject polygon against a clipping plane in 2D, storing + * their geometric intersection in an output polygon. * * \param inputList The input polygon to be clipped. * \param plane The plane being used for clipping. * \param eps The tolerance used for intersection. - * - * \return A clipped polygon. + * \param outputList The clipped polygon. */ AXOM_SUPPRESS_HD_WARN template -AXOM_HOST_DEVICE PolygonType clipPolygonPlaneSimple(const PolygonType& inputList, - const PlaneType& plane, - double eps) +AXOM_HOST_DEVICE void clipPolygonPlaneSimple(const PolygonType& inputList, + const PlaneType& plane, + double eps, + PolygonType& outputList) { using T = typename PolygonType::PointType::CoordType; using SegmentType = Segment; using PointType = Point; - PolygonType outputList; + outputList.clear(); + const T typed_eps = static_cast(eps); const int numVertices = inputList.numVertices(); for(int iVert = 0; iVert < numVertices; iVert++) { @@ -898,45 +929,52 @@ AXOM_HOST_DEVICE PolygonType clipPolygonPlaneSimple(const PolygonType& inputList const PointType& current_point = inputList[iVert]; const PointType& prev_point = inputList[prevVert]; - T seg_param; - PointType intersecting_point; - SegmentType subject_edge(prev_point, current_point); - - const bool intersected = intersect(plane, subject_edge, seg_param, eps); - if(intersected) - { - intersecting_point = subject_edge.at(seg_param); - } - const int cur_p_orientation = plane.getOrientation(current_point, eps); const int prev_p_orientation = plane.getOrientation(prev_point, eps); - if(cur_p_orientation == ON_POSITIVE_SIDE) + const bool cur_in = cur_p_orientation == ON_POSITIVE_SIDE || cur_p_orientation == ON_BOUNDARY; + const bool prev_in = prev_p_orientation == ON_POSITIVE_SIDE || prev_p_orientation == ON_BOUNDARY; + + if(prev_in && cur_in) { - if(prev_p_orientation != ON_POSITIVE_SIDE) - { - outputList.addVertex(intersecting_point); - } - outputList.addVertex(current_point); + // Case 1: inside to inside + clipPolygonAddVertex(outputList, current_point, typed_eps); } - else if(prev_p_orientation == ON_POSITIVE_SIDE) + else if(prev_in && !cur_in) { - // In this branch, there has been a plane crossing from positive to negative. + // Case 2: inside to outside + T seg_param; + SegmentType subject_edge(prev_point, current_point); + const bool intersected = intersect(plane, subject_edge, seg_param, eps); if(intersected) { - outputList.addVertex(intersecting_point); + const auto intersecting_point = subject_edge.at(seg_param); + clipPolygonAddVertex(outputList, intersecting_point, typed_eps); } - else + } + else if(!prev_in && cur_in) + { + // Case 3: outside to inside + T seg_param; + SegmentType subject_edge(prev_point, current_point); + const bool intersected = intersect(plane, subject_edge, seg_param, eps); + if(intersected) { - // If there was not an intersection point then it was close but not - // within eps tolerance. It would have been really close to current_point. - // Since there was a plane crossing, add current_point. - outputList.addVertex(current_point); + const auto intersecting_point = subject_edge.at(seg_param); + clipPolygonAddVertex(outputList, intersecting_point, typed_eps); } + clipPolygonAddVertex(outputList, current_point, typed_eps); } + // Case 4: outside to outside + // emit nothing } - return outputList; + // If the intersection produced a point or line segment, clear the output + // "polygon" since we are not currently interested in those intersections. + if(outputList.numVertices() < 3) + { + outputList.clear(); + } } /*! @@ -949,13 +987,15 @@ AXOM_HOST_DEVICE PolygonType clipPolygonPlaneSimple(const PolygonType& inputList * ON_POSITIVE_SIDE, ON_BOUNDARY, ON_POSITIVE where point on the boundary * is added twice. * - * \return A new polygon that has unique points. + * \param uniqueList The filtered polygon that has unique points. */ AXOM_SUPPRESS_HD_WARN template -AXOM_HOST_DEVICE PolygonType makeUniquePoints(const PolygonType& poly, double eps) +AXOM_HOST_DEVICE void makeUniquePoints(const PolygonType& poly, double eps, PolygonType& uniqueList) { - PolygonType uniqueList; + using T = typename PolygonType::PointType::CoordType; + const T typed_eps = static_cast(eps); + uniqueList.clear(); const int numVertices = poly.numVertices(); for(int i = 0; i < numVertices; i++) { @@ -963,71 +1003,181 @@ AXOM_HOST_DEVICE PolygonType makeUniquePoints(const PolygonType& poly, double ep const auto& curPoint = poly[i]; const auto& prevPoint = poly[prevIndex]; // Check whether curPoint and prevPoint are far enough apart to be different. - // If so, add the point. NOTE: casts are needed to match eps when the polygon - // does not use double precision coordinates. - if(!axom::utilities::isNearlyEqual(static_cast(curPoint[0]), - static_cast(prevPoint[0]), - eps) || - !axom::utilities::isNearlyEqual(static_cast(curPoint[1]), - static_cast(prevPoint[1]), - eps)) + // If so, add the point. + if(!curPoint.isNearlyEqual(prevPoint, typed_eps)) { uniqueList.addVertex(poly[i]); } } - - return uniqueList; } /*! - * \brief Clips a 2D subject polygon against a clip polygon in 2D, returning - * their geometric intersection as a polygon. - * - * \sa axom::primal::clip() + * \brief Clips a 2D subject polygon against a clip polygon in 2D using the + * current contents of \a outputPolygon as the input polygon. */ AXOM_SUPPRESS_HD_WARN template -AXOM_HOST_DEVICE Polygon clipPolygonPolygon( - const Polygon& subjectPolygon, - const Polygon& clipPolygon, - double eps = 1.e-10, - bool tryFixOrientation = false) +AXOM_HOST_DEVICE void clipPolygonPolygonImpl(const Polygon& clipPolygon, + Polygon& outputPolygon, + Polygon& scratchPolygon, + double eps = 1.e-10) { - SLIC_ASSERT(ARRAY_TYPE == axom::primal::PolygonArray::Dynamic || - (ARRAY_TYPE == axom::primal::PolygonArray::Static && - MAX_VERTS >= (subjectPolygon.numVertices() + clipPolygon.numVertices()))); - using PlaneType = Plane; using PolygonType = Polygon; - PolygonType outputList = subjectPolygon; - PolygonType planePoints = clipPolygon; + SLIC_ASSERT(ARRAY_TYPE == axom::primal::PolygonArray::Dynamic || + (ARRAY_TYPE == axom::primal::PolygonArray::Static && + MAX_VERTS >= (outputPolygon.numVertices() + clipPolygon.numVertices()))); - if(tryFixOrientation) + scratchPolygon.clear(); + const int numClipEdges = clipPolygon.numVertices(); + PolygonType* currentPolygon = &outputPolygon; + PolygonType* nextPolygon = &scratchPolygon; + + // Iterate through edges of clip polygon, represented as planes + for(int iEdge = 0; iEdge < numClipEdges; iEdge++) { - if(outputList.signedArea() < 0) - { - outputList.reverseOrientation(); - } + PlaneType plane = make_plane(clipPolygon[iEdge], clipPolygon[(iEdge + 1) % numClipEdges]); - if(planePoints.signedArea() < 0) + clipPolygonPlaneSimple(*currentPolygon, plane, eps, *nextPolygon); + + if(nextPolygon->numVertices() == 0) { - planePoints.reverseOrientation(); + // No intersection because all points are gone. + outputPolygon.clear(); + return; } + + axom::utilities::swap(currentPolygon, nextPolygon); + } // end of iteration through edges of clip polygon + + // Remove duplicate points. + if(currentPolygon == &outputPolygon) + { + makeUniquePoints(*currentPolygon, eps, *nextPolygon); + outputPolygon = *nextPolygon; + } + else + { + makeUniquePoints(*currentPolygon, eps, outputPolygon); + } +} + +/*! + * \brief Clips a 2D subject polygon against a clip polygon in 2D without + * adjusting polygon orientation. + */ +AXOM_SUPPRESS_HD_WARN +template +AXOM_HOST_DEVICE void clipPolygonPolygonNoOrientation( + const Polygon& subjectPolygon, + const Polygon& clipPolygon, + Polygon& outputPolygon, + Polygon& scratchPolygon, + double eps = 1.e-10) +{ + outputPolygon = subjectPolygon; + clipPolygonPolygonImpl(clipPolygon, outputPolygon, scratchPolygon, eps); +} + +/*! + * \brief Clips a 2D subject polygon against a clip polygon in 2D, correcting + * orientation when requested. + */ +AXOM_SUPPRESS_HD_WARN +template +AXOM_HOST_DEVICE void clipPolygonPolygonWithOrientation( + const Polygon& subjectPolygon, + const Polygon& clipPolygon, + Polygon& outputPolygon, + Polygon& scratchPolygon, + double eps = 1.e-10) +{ + using PolygonType = Polygon; + + outputPolygon = subjectPolygon; + if(outputPolygon.signedArea() < 0) + { + outputPolygon.reverseOrientation(); + } + + if(clipPolygon.signedArea() < 0) + { + PolygonType orientedClipPolygon = clipPolygon; + orientedClipPolygon.reverseOrientation(); + clipPolygonPolygonImpl(orientedClipPolygon, outputPolygon, scratchPolygon, eps); + return; } - const int numClipEdges = planePoints.numVertices(); + clipPolygonPolygonImpl(clipPolygon, outputPolygon, scratchPolygon, eps); +} - // Iterate through edges of clip polygon, represented as planes - for(int iEdge = 0; iEdge < numClipEdges; iEdge++) +/*! + * \brief Clips a 2D subject polygon against a clip polygon in 2D, returning + * their geometric intersection as a polygon. + * + * \sa axom::primal::clip() + */ +AXOM_SUPPRESS_HD_WARN +template +AXOM_HOST_DEVICE void clipPolygonPolygon(const Polygon& subjectPolygon, + const Polygon& clipPolygon, + Polygon& outputPolygon, + Polygon& scratchPolygon, + double eps = 1.e-10, + bool tryFixOrientation = false) +{ + if(tryFixOrientation) { - PlaneType plane = make_plane(planePoints[iEdge], planePoints[(iEdge + 1) % numClipEdges]); + clipPolygonPolygonWithOrientation(subjectPolygon, clipPolygon, outputPolygon, scratchPolygon, eps); + return; + } - outputList = clipPolygonPlaneSimple(outputList, plane, eps); - } // end of iteration through edges of clip polygon + clipPolygonPolygonNoOrientation(subjectPolygon, clipPolygon, outputPolygon, scratchPolygon, eps); +} - // Remove duplicate points. - return makeUniquePoints(outputList, eps); +/*! + * \brief Clips a 2D subject polygon against a clip polygon in 2D, returning + * their geometric intersection as a polygon. + * + * \sa axom::primal::clip() + */ +AXOM_SUPPRESS_HD_WARN +template +AXOM_HOST_DEVICE Polygon clipPolygonPolygon( + const Polygon& subjectPolygon, + const Polygon& clipPolygon, + double eps = 1.e-10, + bool tryFixOrientation = false) +{ + using PolygonType = Polygon; + + PolygonType outputPolygon; + PolygonType scratchPolygon; + clipPolygonPolygon(subjectPolygon, clipPolygon, outputPolygon, scratchPolygon, eps, tryFixOrientation); + return outputPolygon; +} + +/*! + * \brief Clips a 2D subject polygon against a clip polygon in 2D and returns + * the area of the geometric intersection. + * + * \sa axom::primal::clip() + */ +AXOM_SUPPRESS_HD_WARN +template +AXOM_HOST_DEVICE double clipPolygonPolygonArea( + const Polygon& subjectPolygon, + const Polygon& clipPolygon, + double eps = 1.e-10, + bool tryFixOrientation = false) +{ + using PolygonType = Polygon; + + PolygonType outputPolygon; + PolygonType scratchPolygon; + clipPolygonPolygon(subjectPolygon, clipPolygon, outputPolygon, scratchPolygon, eps, tryFixOrientation); + return outputPolygon.area(); } /*! @@ -1046,6 +1196,7 @@ AXOM_HOST_DEVICE Polygon clipPolygonPlane( using PolygonType = Polygon; PolygonType outputList = subjectPolygon; + PolygonType clippedPolygon; if(tryFixOrientation) { if(outputList.signedArea() < 0) @@ -1055,7 +1206,8 @@ AXOM_HOST_DEVICE Polygon clipPolygonPlane( } // Clip the plane. - return makeUniquePoints(clipPolygonPlaneSimple(outputList, clipPlane, eps), eps); + clipPolygonPlaneSimple(outputList, clipPlane, eps, clippedPolygon); + return clippedPolygon; } } // namespace detail diff --git a/src/axom/primal/operators/detail/intersect_ray_impl.hpp b/src/axom/primal/operators/detail/intersect_ray_impl.hpp index 101b8191e6..fe1f1ed137 100644 --- a/src/axom/primal/operators/detail/intersect_ray_impl.hpp +++ b/src/axom/primal/operators/detail/intersect_ray_impl.hpp @@ -7,8 +7,9 @@ #ifndef AXOM_PRIMAL_INTERSECT_RAY_IMPL_HPP_ #define AXOM_PRIMAL_INTERSECT_RAY_IMPL_HPP_ -// numerics includes +// core includes #include "axom/core/numerics/floating_point_limits.hpp" +#include "axom/core/utilities/Utilities.hpp" // primal includes #include "axom/primal/geometry/Point.hpp" @@ -80,7 +81,7 @@ AXOM_HOST_DEVICE inline bool intersect_ray(const primal::Ray& R, const double t1 = col1[0] * ray_dir[0] + col1[1] * ray_dir[1]; const double t2 = t1 + seg_dir.dot(ray_dir); - if(std::min(t1, t2) > 0.0) + if(axom::utilities::min(t1, t2) > 0.0) { // The origin is outside the segment, // but the ray intersects diff --git a/src/axom/primal/operators/detail/winding_number_3d_impl.hpp b/src/axom/primal/operators/detail/winding_number_3d_impl.hpp index c1f6f714d6..9901e3964a 100644 --- a/src/axom/primal/operators/detail/winding_number_3d_impl.hpp +++ b/src/axom/primal/operators/detail/winding_number_3d_impl.hpp @@ -317,43 +317,98 @@ double stokes_gwn_component(const Point& query, const numerics::Matrix& rotator, const TrimmingCurveQuadratureData& trimming_curve_data) { - double this_quad = 0; + using VectorType = Vector; + + const int num_pts = trimming_curve_data.getNumPoints(); + const auto quad_points = trimming_curve_data.getQuadraturePoints(); + const auto quad_tangents = trimming_curve_data.getQuadratureTangents(); + const auto quad_weights = trimming_curve_data.getQuadratureWeights(); + + // Shared loop structure for the different discontinuity axes: + // - build node vector (quadrature point relative to query, optionally rotated) + // - build tangent vector (optionally rotated) + // - accumulate weight * numerator(node, dt) / (denom(node) * ||node||) + auto accumulate = [&](auto&& make_node, auto&& make_dt, auto&& numer_fn, auto&& denom_fn) -> double { + double this_quad = 0.0; + for(int q = 0; q < num_pts; ++q) + { + const auto& node = make_node(q); + const auto& node_dt = make_dt(q); + const double inv = 1.0 / (denom_fn(node) * node.norm()); + this_quad += quad_weights[q] * numer_fn(node, node_dt) * inv; + } + return this_quad; + }; - const bool is_rotated = (ax == DiscontinuityAxis::rotated); - for(int q = 0; q < trimming_curve_data.getNumPoints(); ++q) - { - const Vector node = is_rotated - ? rotate_point(rotator, query, trimming_curve_data.getQuadraturePoint(q)) - query - : trimming_curve_data.getQuadraturePoint(q) - query; + auto numer_x = [](const VectorType& node, const VectorType& dt) -> double { + return node[0] * (node[2] * dt[1] - node[1] * dt[2]); + }; + auto numer_y = [](const VectorType& node, const VectorType& dt) -> double { + return node[1] * (node[0] * dt[2] - node[2] * dt[0]); + }; + auto numer_z = [](const VectorType& node, const VectorType& dt) -> double { + return node[2] * (node[1] * dt[0] - node[0] * dt[1]); + }; + + auto denom_x = [](const VectorType& node) -> double { + return (node[1] * node[1]) + (node[2] * node[2]); + }; + auto denom_y = [](const VectorType& node) -> double { + return (node[0] * node[0]) + (node[2] * node[2]); + }; + auto denom_z = [](const VectorType& node) -> double { + return (node[0] * node[0]) + (node[1] * node[1]); + }; - const Vector node_dt = is_rotated - ? rotate_vector_origin(rotator, trimming_curve_data.getQuadratureTangent(q)) - : trimming_curve_data.getQuadratureTangent(q); + // Non-rotated paths share the same node/dt construction. + auto make_node_unrot = [&](int q) -> VectorType { return quad_points[q] - query; }; + auto make_dt_unrot = [&](int q) -> const VectorType& { return quad_tangents[q]; }; - const double node_norm = node.norm(); - const double quad_weight = trimming_curve_data.getQuadratureWeight(q); + // The axis is constant for the full loop; split into specialized loops to avoid + // per-iteration switching/branching overhead. + if(ax == DiscontinuityAxis::rotated) + { + // Rotate query-relative vectors directly; avoid the extra translate in + // rotate_point(..., query, P) - query. + const T* r = rotator.data(); + const double r00 = r[0], r01 = r[3], r02 = r[6]; + const double r10 = r[1], r11 = r[4], r12 = r[7]; + const double r20 = r[2], r21 = r[5], r22 = r[8]; + + auto make_node_rot = [&](int q) -> VectorType { + const auto& qp = quad_points[q]; + const double dx = qp[0] - query[0]; + const double dy = qp[1] - query[1]; + const double dz = qp[2] - query[2]; + + return VectorType {r00 * dx + r01 * dy + r02 * dz, + r10 * dx + r11 * dy + r12 * dz, + r20 * dx + r21 * dy + r22 * dz}; + }; + + auto make_dt_rot = [&](int q) -> VectorType { + const auto& qt = quad_tangents[q]; + + return VectorType {r00 * qt[0] + r01 * qt[1] + r02 * qt[2], + r10 * qt[0] + r11 * qt[1] + r12 * qt[2], + r20 * qt[0] + r21 * qt[1] + r22 * qt[2]}; + }; + + return accumulate(make_node_rot, make_dt_rot, numer_z, denom_z); + } - // Compute one of three vector field line integrals depending on - // the orientation of the original surface, indicated through ax. - switch(ax) - { - case(DiscontinuityAxis::x): - this_quad += quad_weight * (node[2] * node[0] * node_dt[1] - node[1] * node[0] * node_dt[2]) / - (node[1] * node[1] + node[2] * node[2]) / node_norm; - break; - case(DiscontinuityAxis::y): - this_quad += quad_weight * (node[0] * node[1] * node_dt[2] - node[2] * node[1] * node_dt[0]) / - (node[0] * node[0] + node[2] * node[2]) / node_norm; - break; - case(DiscontinuityAxis::z): - case(DiscontinuityAxis::rotated): - this_quad += quad_weight * (node[1] * node[2] * node_dt[0] - node[0] * node[2] * node_dt[1]) / - (node[0] * node[0] + node[1] * node[1]) / node_norm; - break; - } + if(ax == DiscontinuityAxis::x) + { + return accumulate(make_node_unrot, make_dt_unrot, numer_x, denom_x); + } + + if(ax == DiscontinuityAxis::y) + { + return accumulate(make_node_unrot, make_dt_unrot, numer_y, denom_y); } - return this_quad; + // Default: z-axis field. + return accumulate(make_node_unrot, make_dt_unrot, numer_z, denom_z); } /*! diff --git a/src/axom/primal/operators/detail/winding_number_3d_memoization.hpp b/src/axom/primal/operators/detail/winding_number_3d_memoization.hpp index f1dccf8195..c4486b81c4 100644 --- a/src/axom/primal/operators/detail/winding_number_3d_memoization.hpp +++ b/src/axom/primal/operators/detail/winding_number_3d_memoization.hpp @@ -30,6 +30,8 @@ #include #include +#include +#include #include #include "axom/fmt.hpp" @@ -72,7 +74,9 @@ struct TrimmingCurveQuadratureData : m_quad_npts(quad_npts) { // Generate the (cached) quadrature rules in parameter space - const numerics::QuadratureRule& gl_rule = numerics::get_gauss_legendre(quad_npts); + const numerics::QuadratureRule gl_rule = numerics::get_gauss_legendre(quad_npts); + const auto quad_nodes = gl_rule.nodes(); + const auto quad_weights = gl_rule.weights(); auto& the_curve = a_patch.getTrimmingCurve(a_curve_index); @@ -83,11 +87,14 @@ struct TrimmingCurveQuadratureData m_span_length = (curve_max_knot - curve_min_knot) / std::pow(2, a_refinementLevel); const T span_offset = m_span_length * a_refinementSection; + m_quadrature_scaled_weights.resize(m_quad_npts); m_quadrature_points.resize(m_quad_npts); m_quadrature_tangents.resize(m_quad_npts); for(int q = 0; q < m_quad_npts; ++q) { - const T quad_x = gl_rule.node(q) * m_span_length + curve_min_knot + span_offset; + m_quadrature_scaled_weights[q] = quad_weights[q] * m_span_length; + + const T quad_x = quad_nodes[q] * m_span_length + curve_min_knot + span_offset; Point c_eval; Vector c_Dt; @@ -104,18 +111,26 @@ struct TrimmingCurveQuadratureData const Point& getQuadraturePoint(size_t idx) const { return m_quadrature_points[idx]; } const Vector& getQuadratureTangent(size_t idx) const { return m_quadrature_tangents[idx]; } - double getQuadratureWeight(size_t idx) const + double getQuadratureWeight(size_t idx) const { return m_quadrature_scaled_weights[idx]; } + int getNumPoints() const { return m_quad_npts; } + + axom::ArrayView> getQuadraturePoints() const { - // Because the quadrature weights are identical for each trimming curve (up to a scaling factor), - // we query the static rule instead of storing redundant weights - const numerics::QuadratureRule& gl_rule = numerics::get_gauss_legendre(m_quad_npts); - return gl_rule.weight(idx) * m_span_length; + return m_quadrature_points.view(); + } + axom::ArrayView> getQuadratureTangents() const + { + return m_quadrature_tangents.view(); + } + axom::ArrayView getQuadratureWeights() const + { + return m_quadrature_scaled_weights.view(); } - int getNumPoints() const { return m_quad_npts; } private: axom::Array> m_quadrature_points; axom::Array> m_quadrature_tangents; + axom::Array m_quadrature_scaled_weights; T m_span_length; int m_quad_npts; }; @@ -233,19 +248,20 @@ class NURBSPatchGWNCache int refinementLevel, int refinementIndex) const { - // Check to see if we have already computed the quadrature data for this curve - const auto hash_key = std::make_pair(refinementLevel, refinementIndex); - - if(m_curveQuadratureMaps[curveIndex].find(hash_key) == m_curveQuadratureMaps[curveIndex].end()) - { - m_curveQuadratureMaps[curveIndex][hash_key] = TrimmingCurveQuadratureData(m_alteredPatch, - curveIndex, - quadNPts, - refinementLevel, - refinementIndex); - } - - return m_curveQuadratureMaps[curveIndex][hash_key]; + // Cache quadrature data per trimming curve keyed by (refinementLevel, refinementIndex). + // Note: `quadNPts` is fixed in the 3D winding-number implementation (currently 15). + const auto make_key = [](int level, int index) -> std::uint64_t { + return (static_cast(static_cast(level)) << 32) | + static_cast(static_cast(index)); + }; + + const std::uint64_t key = make_key(refinementLevel, refinementIndex); + auto& curve_map = m_curveQuadratureMaps[curveIndex]; + + // Single lookup for both hit and miss; avoids multiple tree traversals and operator[]. + auto [it, inserted] = + curve_map.try_emplace(key, m_alteredPatch, curveIndex, quadNPts, refinementLevel, refinementIndex); + return it->second; } private: @@ -260,7 +276,7 @@ class NURBSPatchGWNCache double m_pboxDiag; // Per trimming curve data, keyed by (whichRefinementLevel, whichRefinementIndex) - mutable axom::Array, TrimmingCurveQuadratureData>> m_curveQuadratureMaps; + mutable axom::Array>> m_curveQuadratureMaps; }; } // namespace detail diff --git a/src/axom/primal/operators/evaluate_integral.hpp b/src/axom/primal/operators/evaluate_integral.hpp index fd30649592..e059d17fe8 100644 --- a/src/axom/primal/operators/evaluate_integral.hpp +++ b/src/axom/primal/operators/evaluate_integral.hpp @@ -28,6 +28,7 @@ // Axom includes #include "axom/config.hpp" +#include "axom/core/utilities/Utilities.hpp" #include "axom/primal/geometry/CurvedPolygon.hpp" #include "axom/primal/operators/detail/evaluate_integral_impl.hpp" @@ -285,7 +286,7 @@ LambdaRetType evaluate_area_integral(const primal::CurvedPolygon& cpo { for(int j = 1; j < cpoly[i].getOrder() + 1; j++) { - lower_bound_y = std::min(lower_bound_y, cpoly[i][j][1]); + lower_bound_y = axom::utilities::min(lower_bound_y, cpoly[i][j][1]); } } @@ -351,7 +352,7 @@ LambdaRetType evaluate_area_integral(const axom::Array& carray, { for(int j = 1; j < carray[i].getNumControlPoints(); j++) { - lower_bound_y = std::min(lower_bound_y, carray[i][j][1]); + lower_bound_y = axom::utilities::min(lower_bound_y, carray[i][j][1]); } } @@ -376,4 +377,4 @@ LambdaRetType evaluate_area_integral(const axom::Array& carray, } // namespace primal } // end namespace axom -#endif \ No newline at end of file +#endif diff --git a/src/axom/primal/operators/winding_number.hpp b/src/axom/primal/operators/winding_number.hpp index bbdb1b8bcd..00faa15dcc 100644 --- a/src/axom/primal/operators/winding_number.hpp +++ b/src/axom/primal/operators/winding_number.hpp @@ -44,6 +44,17 @@ namespace axom { namespace primal { + +/// Struct containing tolerances shared across GWN values with sensible defaults +struct WindingTolerances +{ + double ls_tol {1e-6}; + double quad_tol {1e-6}; + double disk_size {0.01}; + double edge_tol {1e-8}; + double EPS {1e-8}; +}; + /*! * \brief Compute the GWN for a 2D point wrt a 2D line segment * diff --git a/src/axom/primal/tests/CMakeLists.txt b/src/axom/primal/tests/CMakeLists.txt index da1ef35bd6..9546c68d37 100644 --- a/src/axom/primal/tests/CMakeLists.txt +++ b/src/axom/primal/tests/CMakeLists.txt @@ -25,6 +25,7 @@ set( primal_tests primal_integral.cpp primal_intersect.cpp primal_intersect_impl.cpp + primal_intersection_volume.cpp primal_knot_vector.cpp primal_nurbs_curve.cpp primal_nurbs_patch.cpp diff --git a/src/axom/primal/tests/primal_clip.cpp b/src/axom/primal/tests/primal_clip.cpp index 39bf58abc3..7ca6f4adad 100644 --- a/src/axom/primal/tests/primal_clip.cpp +++ b/src/axom/primal/tests/primal_clip.cpp @@ -43,6 +43,21 @@ using PlaneType = axom::primal::Plane; using PolyhedronType = axom::primal::Polyhedron; } // namespace Primal3D +/// Compare two polygons with a tolerance. +template +bool polygonsEqual(const PolygonType& p1, const PolygonType& p2, T tol) +{ + bool eq = p1.numVertices() == p2.numVertices(); + if(eq) + { + for(int i = 0; i < p1.numVertices() && eq; i++) + { + eq &= p1[i].isNearlyEqual(p2[i], tol); + } + } + return eq; +} + TEST(primal_clip, simple_clip) { using namespace Primal3D; @@ -707,6 +722,182 @@ void check_polygon_polygon_clip(double EPS) EXPECT_EQ(output_polygon_host[0].numVertices(), 6); } +template +void check_polygon_polygon_clip_reassignment(double EPS) +{ + const int MAX_NUM_VERTS = 8; + + using PolygonStatic2D = + axom::primal::Polygon; + using Point2D = axom::primal::Point; + + const int host_allocator = axom::execution_space::allocatorID(); + const int kernel_allocator = axom::execution_space::allocatorID(); + + axom::Array outputs_device(3, 3, kernel_allocator); + auto outputs_view = outputs_device.view(); + + axom::for_all( + 1, + AXOM_LAMBDA(int i) { + AXOM_UNUSED_VAR(i); + + PolygonStatic2D working; + + const PolygonStatic2D subject_triangle( + {Point2D({0.0, 0.0}), Point2D({1.0, 0.0}), Point2D({0.5, 1.0})}); + const PolygonStatic2D clip_triangle( + {Point2D({0.0, 2.0 / 3.0}), Point2D({0.5, -1.0 / 3.0}), Point2D({1.0, 2.0 / 3.0})}); + + working = axom::primal::clip(subject_triangle, clip_triangle, EPS); + outputs_view[0] = working; + + const PolygonStatic2D disjoint_subject( + {Point2D({2.0, 2.0}), Point2D({3.0, 2.0}), Point2D({3.0, 3.0}), Point2D({2.0, 3.0})}); + const PolygonStatic2D disjoint_clip( + {Point2D({-1.0, -1.0}), Point2D({0.0, -1.0}), Point2D({0.0, 0.0}), Point2D({-1.0, 0.0})}); + + working = axom::primal::clip(disjoint_subject, disjoint_clip, EPS); + outputs_view[1] = working; + + const PolygonStatic2D subject_square( + {Point2D({0.0, 0.0}), Point2D({1.0, 0.0}), Point2D({1.0, 1.0}), Point2D({0.0, 1.0})}); + const PolygonStatic2D clip_rectangle( + {Point2D({0.5, 0.25}), Point2D({1.5, 0.25}), Point2D({1.5, 0.75}), Point2D({0.5, 0.75})}); + + working = axom::primal::clip(subject_square, clip_rectangle, EPS); + outputs_view[2] = working; + }); + + if(axom::execution_space::async()) + { + axom::synchronize(); + } + + axom::Array outputs_host(outputs_device, host_allocator); + + EXPECT_EQ(outputs_host[0].numVertices(), 6); + EXPECT_NEAR(outputs_host[0].signedArea(), 1.0 / 3.0, EPS); + + EXPECT_EQ(outputs_host[1].numVertices(), 0); + EXPECT_FALSE(outputs_host[1].isValid()); + + EXPECT_EQ(outputs_host[2].numVertices(), 4); + EXPECT_NEAR(outputs_host[2].signedArea(), 0.25, EPS); +} + +template +void check_polygon_polygon_clip_with_scratch(double EPS) +{ + const int MAX_NUM_VERTS = 8; + + using PolygonStatic2D = + axom::primal::Polygon; + using Point2D = axom::primal::Point; + + const int host_allocator = axom::execution_space::allocatorID(); + const int kernel_allocator = axom::execution_space::allocatorID(); + + axom::Array outputs_device(3, 3, kernel_allocator); + auto outputs_view = outputs_device.view(); + + axom::for_all( + 1, + AXOM_LAMBDA(int i) { + AXOM_UNUSED_VAR(i); + + PolygonStatic2D working; + PolygonStatic2D scratch; + + const PolygonStatic2D subject_triangle( + {Point2D({0.0, 0.0}), Point2D({1.0, 0.0}), Point2D({0.5, 1.0})}); + const PolygonStatic2D clip_triangle( + {Point2D({0.0, 2.0 / 3.0}), Point2D({0.5, -1.0 / 3.0}), Point2D({1.0, 2.0 / 3.0})}); + + axom::primal::detail::clipPolygonPolygon(subject_triangle, clip_triangle, working, scratch, EPS); + outputs_view[0] = working; + + const PolygonStatic2D disjoint_subject( + {Point2D({2.0, 2.0}), Point2D({3.0, 2.0}), Point2D({3.0, 3.0}), Point2D({2.0, 3.0})}); + const PolygonStatic2D disjoint_clip( + {Point2D({-1.0, -1.0}), Point2D({0.0, -1.0}), Point2D({0.0, 0.0}), Point2D({-1.0, 0.0})}); + + axom::primal::detail::clipPolygonPolygon(disjoint_subject, disjoint_clip, working, scratch, EPS); + outputs_view[1] = working; + + const PolygonStatic2D subject_square( + {Point2D({0.0, 0.0}), Point2D({1.0, 0.0}), Point2D({1.0, 1.0}), Point2D({0.0, 1.0})}); + const PolygonStatic2D clip_rectangle( + {Point2D({0.5, 0.25}), Point2D({1.5, 0.25}), Point2D({1.5, 0.75}), Point2D({0.5, 0.75})}); + + axom::primal::detail::clipPolygonPolygon(subject_square, clip_rectangle, working, scratch, EPS); + outputs_view[2] = working; + }); + + if(axom::execution_space::async()) + { + axom::synchronize(); + } + + axom::Array outputs_host(outputs_device, host_allocator); + + EXPECT_EQ(outputs_host[0].numVertices(), 6); + EXPECT_NEAR(outputs_host[0].signedArea(), 1.0 / 3.0, EPS); + + EXPECT_EQ(outputs_host[1].numVertices(), 0); + EXPECT_FALSE(outputs_host[1].isValid()); + + EXPECT_EQ(outputs_host[2].numVertices(), 4); + EXPECT_NEAR(outputs_host[2].signedArea(), 0.25, EPS); +} + +template +void check_polygon_polygon_clip_area(double EPS) +{ + constexpr bool CHECK_SIGN = true; + const int MAX_NUM_VERTS = 6; + + using PolygonStatic2D = + axom::primal::Polygon; + using Point2D = axom::primal::Point; + + const int host_allocator = axom::execution_space::allocatorID(); + const int kernel_allocator = axom::execution_space::allocatorID(); + + axom::Array areas_device(2, 2, kernel_allocator); + auto areas_view = areas_device.view(); + + axom::for_all( + 1, + AXOM_LAMBDA(int i) { + AXOM_UNUSED_VAR(i); + + const PolygonStatic2D subject({Point2D({0.0, 0.0}), Point2D({1.0, 0.0}), Point2D({0.5, 1.0})}); + const PolygonStatic2D clip( + {Point2D({0.0, 2.0 / 3.0}), Point2D({0.5, -1.0 / 3.0}), Point2D({1.0, 2.0 / 3.0})}); + + areas_view[0] = axom::primal::detail::clipPolygonPolygonArea(subject, clip, EPS); + + const PolygonStatic2D reversed_subject( + {Point2D({0.5, 1.0}), Point2D({1.0, 0.0}), Point2D({0.0, 0.0})}); + const PolygonStatic2D reversed_clip( + {Point2D({0.5, -1.0 / 3.0}), Point2D({0.0, 2.0 / 3.0}), Point2D({1.0, 2.0 / 3.0})}); + + areas_view[1] = + axom::primal::detail::clipPolygonPolygonArea(reversed_subject, reversed_clip, EPS, CHECK_SIGN); + }); + + if(axom::execution_space::async()) + { + axom::synchronize(); + } + + axom::Array areas_host(areas_device, host_allocator); + + EXPECT_NEAR(areas_host[0], 1.0 / 3.0, EPS); + EXPECT_NEAR(areas_host[1], 1.0 / 3.0, EPS); +} + TEST(primal_clip, unit_poly_clip_vertices_sequential) { unit_check_poly_clip(); } TEST(primal_clip, clip_hex_tet_sequential) @@ -733,6 +924,24 @@ TEST(primal_clip, clip_polygon_polygon_sequential) check_polygon_polygon_clip(EPS); } +TEST(primal_clip, clip_polygon_polygon_reassignment_sequential) +{ + constexpr double EPS = 1e-4; + check_polygon_polygon_clip_reassignment(EPS); +} + +TEST(primal_clip, clip_polygon_polygon_with_scratch_sequential) +{ + constexpr double EPS = 1e-4; + check_polygon_polygon_clip_with_scratch(EPS); +} + +TEST(primal_clip, clip_polygon_polygon_area_sequential) +{ + constexpr double EPS = 1e-4; + check_polygon_polygon_clip_area(EPS); +} + #ifdef AXOM_USE_OPENMP TEST(primal_clip, unit_poly_clip_vertices_omp) { unit_check_poly_clip(); } @@ -759,6 +968,24 @@ TEST(primal_clip, clip_polygon_polygon_omp) constexpr double EPS = 1e-4; check_polygon_polygon_clip(EPS); } + +TEST(primal_clip, clip_polygon_polygon_reassignment_omp) +{ + constexpr double EPS = 1e-4; + check_polygon_polygon_clip_reassignment(EPS); +} + +TEST(primal_clip, clip_polygon_polygon_with_scratch_omp) +{ + constexpr double EPS = 1e-4; + check_polygon_polygon_clip_with_scratch(EPS); +} + +TEST(primal_clip, clip_polygon_polygon_area_omp) +{ + constexpr double EPS = 1e-4; + check_polygon_polygon_clip_area(EPS); +} #endif /* AXOM_USE_OPENMP */ #if defined(AXOM_USE_CUDA) @@ -790,6 +1017,24 @@ TEST(primal_clip, clip_polygon_polygon_cuda) constexpr double EPS = 1e-4; check_polygon_polygon_clip>(EPS); } + +TEST(primal_clip, clip_polygon_polygon_reassignment_cuda) +{ + constexpr double EPS = 1e-4; + check_polygon_polygon_clip_reassignment>(EPS); +} + +TEST(primal_clip, clip_polygon_polygon_with_scratch_cuda) +{ + constexpr double EPS = 1e-4; + check_polygon_polygon_clip_with_scratch>(EPS); +} + +TEST(primal_clip, clip_polygon_polygon_area_cuda) +{ + constexpr double EPS = 1e-4; + check_polygon_polygon_clip_area>(EPS); +} #endif /* AXOM_USE_CUDA */ #if defined(AXOM_USE_HIP) @@ -818,6 +1063,24 @@ TEST(primal_clip, clip_polygon_polygon_hip) constexpr double EPS = 1e-4; check_polygon_polygon_clip>(EPS); } + +TEST(primal_clip, clip_polygon_polygon_reassignment_hip) +{ + constexpr double EPS = 1e-4; + check_polygon_polygon_clip_reassignment>(EPS); +} + +TEST(primal_clip, clip_polygon_polygon_with_scratch_hip) +{ + constexpr double EPS = 1e-4; + check_polygon_polygon_clip_with_scratch>(EPS); +} + +TEST(primal_clip, clip_polygon_polygon_area_hip) +{ + constexpr double EPS = 1e-4; + check_polygon_polygon_clip_area>(EPS); +} #endif /* AXOM_USE_HIP */ #endif /* AXOM_USE_RAJA && AXOM_USE_UMPIRE */ @@ -1815,7 +2078,7 @@ TEST(primal_clip, polygon_intersects_polygon) clipPolygon.addVertex(Point2D {0.0, 1.0}); Polygon2D poly = axom::primal::clip(subjectPolygon, clipPolygon, EPS); - + EXPECT_EQ(poly.isValid(), true); EXPECT_NEAR(poly.signedArea(), 0.25, EPS); EXPECT_EQ(poly.numVertices(), 3); } @@ -1881,38 +2144,41 @@ TEST(primal_clip, polygon_intersects_polygon) Polygon2D poly = axom::primal::clip(subjectPolygon, clipPolygon, EPS); EXPECT_NEAR(poly.signedArea(), 37083.3333333333, EPS); - EXPECT_EQ(poly.numVertices(), 10); + EXPECT_EQ(poly.numVertices(), 11); // Check vertices EXPECT_NEAR(poly[0][0], 100, EPS); - EXPECT_NEAR(poly[0][1], 116.6666666666, EPS); + EXPECT_NEAR(poly[0][1], 200, EPS); - EXPECT_NEAR(poly[1][0], 125, EPS); - EXPECT_NEAR(poly[1][1], 100, EPS); + EXPECT_NEAR(poly[1][0], 100, EPS); + EXPECT_NEAR(poly[1][1], 116.6666666666, EPS); - EXPECT_NEAR(poly[2][0], 275, EPS); + EXPECT_NEAR(poly[2][0], 125, EPS); EXPECT_NEAR(poly[2][1], 100, EPS); - EXPECT_NEAR(poly[3][0], 300, EPS); - EXPECT_NEAR(poly[3][1], 116.6666666666, EPS); + EXPECT_NEAR(poly[3][0], 275, EPS); + EXPECT_NEAR(poly[3][1], 100, EPS); EXPECT_NEAR(poly[4][0], 300, EPS); - EXPECT_NEAR(poly[4][1], 300, EPS); + EXPECT_NEAR(poly[4][1], 116.6666666666, EPS); - EXPECT_NEAR(poly[5][0], 250, EPS); + EXPECT_NEAR(poly[5][0], 300, EPS); EXPECT_NEAR(poly[5][1], 300, EPS); - EXPECT_NEAR(poly[6][0], 200, EPS); - EXPECT_NEAR(poly[6][1], 250, EPS); + EXPECT_NEAR(poly[6][0], 250, EPS); + EXPECT_NEAR(poly[6][1], 300, EPS); - EXPECT_NEAR(poly[7][0], 175, EPS); - EXPECT_NEAR(poly[7][1], 300, EPS); + EXPECT_NEAR(poly[7][0], 200, EPS); + EXPECT_NEAR(poly[7][1], 250, EPS); - EXPECT_NEAR(poly[8][0], 125, EPS); + EXPECT_NEAR(poly[8][0], 175, EPS); EXPECT_NEAR(poly[8][1], 300, EPS); - EXPECT_NEAR(poly[9][0], 100, EPS); - EXPECT_NEAR(poly[9][1], 250, EPS); + EXPECT_NEAR(poly[9][0], 125, EPS); + EXPECT_NEAR(poly[9][1], 300, EPS); + + EXPECT_NEAR(poly[10][0], 100, EPS); + EXPECT_NEAR(poly[10][1], 250, EPS); } /* @@ -1945,13 +2211,13 @@ TEST(primal_clip, polygon_intersects_polygon) // Check vertices EXPECT_NEAR(poly[0][0], 0, EPS); - EXPECT_NEAR(poly[0][1], 1, EPS); + EXPECT_NEAR(poly[0][1], 0, EPS); - EXPECT_NEAR(poly[1][0], 0, EPS); - EXPECT_NEAR(poly[1][1], 0, EPS); + EXPECT_NEAR(poly[1][0], 0.3, EPS); + EXPECT_NEAR(poly[1][1], 0.3, EPS); - EXPECT_NEAR(poly[2][0], 0.3, EPS); - EXPECT_NEAR(poly[2][1], 0.3, EPS); + EXPECT_NEAR(poly[2][0], 0, EPS); + EXPECT_NEAR(poly[2][1], 1, EPS); } } @@ -2097,11 +2363,83 @@ TEST(primal_clip, polygon_clip_regression) // Comparisons constexpr float EPS = 1.6e-5f; EXPECT_EQ(clippedShape.numVertices(), 4); - for(int i = 0; i < 4; i++) + EXPECT_TRUE(polygonsEqual(clippedShape, expectedPoly, EPS)); +} + +//------------------------------------------------------------------------------ +// These test cases were found by clipping actual data in Axom. Basically a clipping +// plane passes through (or very close to) one of the polygon vertices. +struct test_cases +{ + using FloatType = double; + using PlaneType = axom::primal::Plane; + using VectorType = typename PlaneType::VectorType; + using PointType = typename PlaneType::PointType; + using PolygonType = axom::primal::Polygon; + + // This function contains a quad that has a really short side. The clipping plane + // went through the polygon very close to the upper left point. The clipping algorithm + // used to make an invalid (0,0) point where it added the point even though + // the plane did not "intersect" the side. + static bool clip(double eps) + { + const auto normal = VectorType {-0.03955235934655436, -0.9992174992813733}; + const FloatType offset = 0.09055408441368087; + const auto P = PlaneType(normal, offset, false); + + PolygonType shape; + shape.addVertex(PointType {0.28, -0.1017083319161494}); + shape.addVertex(PointType {0.28, -0.1019791654925216}); + shape.addVertex(PointType {0.32, -0.1053541654925216}); + shape.addVertex(PointType {0.32, -0.1024583319161494}); + + auto clippedShape = axom::primal::clip(shape, P, eps); + + const PolygonType result5 {PointType {0.28000000204729441622, -0.10170833195453617137}, + PointType {0.28000000000000002665, -0.10170833191614940538}, + PointType {0.28000000000000002665, -0.10197916549252160345}, + PointType {0.32000000000000000666, -0.10535416549252160645}, + PointType {0.32000000000000000666, -0.10329166520683076558}}; + return polygonsEqual(result5, clippedShape, eps); + } + + // This is a different polygon where clip made an invalid output polygon. + static bool clip2(double eps, int expectedVerts) { - EXPECT_NEAR(clippedShape[i][0], expectedPoly[i][0], EPS); - EXPECT_NEAR(clippedShape[i][1], expectedPoly[i][1], EPS); + const auto normal = VectorType {0.9999820004859855116, 0.0059998920029159345801}; + const FloatType offset = 0.46690205915894555933; + const auto P = PlaneType(normal, offset, false); + + PolygonType shape; + shape.addVertex(PointType {0.46841046332037361566, -0.24999999999999977796}); + shape.addVertex(PointType {0.4685774857907649138, -0.24999999999999977796}); + shape.addVertex(PointType {0.46822188956348015365, -0.24640811891631614339}); + + auto clippedShape = axom::primal::clip(shape, P, eps); + + const PolygonType result3 {PointType {0.46841046332037361566, -0.24999999999999952816}, + PointType {0.4685774857907649138, -0.24999999999999977796}, + PointType {0.46839968767712247821, -0.24820405945815776638}}; + + const PolygonType result4 {PointType {0.46841046332037361566, -0.24999999999999952816}, + PointType {0.46841046332037361566, -0.24999999999999977796}, + PointType {0.4685774857907649138, -0.24999999999999977796}, + PointType {0.46839968767712247821, -0.24820405945815776638}}; + + return expectedVerts == 3 ? polygonsEqual(clippedShape, result3, eps) + : polygonsEqual(clippedShape, result4, eps); } +}; + +TEST(primal_clip, polygon_plane_clipping_regressions) +{ + // Try different tolerances since the clipping algorithm is somewhat sensitive + // to it since it helps determine whether points are on the boundary. + EXPECT_TRUE(test_cases::clip(1.e-10)); + EXPECT_TRUE(test_cases::clip(1.e-14)); + + EXPECT_TRUE(test_cases::clip2(1.e-14, 3)); + EXPECT_TRUE(test_cases::clip2(std::numeric_limits::epsilon(), 4)); } //------------------------------------------------------------------------------ diff --git a/src/axom/primal/tests/primal_intersection_volume.cpp b/src/axom/primal/tests/primal_intersection_volume.cpp new file mode 100644 index 0000000000..8672969c2c --- /dev/null +++ b/src/axom/primal/tests/primal_intersection_volume.cpp @@ -0,0 +1,158 @@ +// Copyright (c) Lawrence Livermore National Security, LLC and other +// Axom Project Contributors. See top-level LICENSE and COPYRIGHT +// files for dates and other details. +// +// SPDX-License-Identifier: (BSD-3-Clause) + +#include "axom/primal.hpp" + +#include "axom/fmt.hpp" + +#include "gtest/gtest.h" + +#include + +namespace Primal3D +{ +using PointType = axom::primal::Point; +using VectorType = axom::primal::Vector; +using BoundingBoxType = axom::primal::BoundingBox; +using HexahedronType = axom::primal::Hexahedron; +using TriangleType = axom::primal::Triangle; +using TetrahedronType = axom::primal::Tetrahedron; +using OctahedronType = axom::primal::Octahedron; +using PolyhedronType = axom::primal::Polyhedron; +using PolygonType = axom::primal::Polygon; +using PlaneType = axom::primal::Plane; +using PolyhedronType = axom::primal::Polyhedron; +} // namespace Primal3D + +namespace +{ +using Primal3D::HexahedronType; +using Primal3D::TetrahedronType; + +double intersection_volume_via_hex_triangulation(const HexahedronType& hex, + const TetrahedronType& tet, + double eps) +{ + axom::StackArray tets; + hex.triangulate(tets); + + double vol = 0.; + constexpr bool TRY_FIX_ORIENTATION = true; + for(int i = 0; i < 24; ++i) + { + vol += axom::primal::intersection_volume(tets[i], tet, eps, TRY_FIX_ORIENTATION); + } + return vol; +} + +} // namespace + +TEST(primal_intersection_volume, hex_tet_user_regression_cases) +{ + using namespace Primal3D; + constexpr double sixth = 1. / 6.; + + HexahedronType hex(PointType {42. + sixth, -66, -178.5}, + PointType {52. - sixth, -66, -178.5}, + PointType {52. - sixth, -55, -178.5}, + PointType {42. + sixth, -55, -178.5}, + PointType {42. + sixth, -66, -170}, + PointType {52. - sixth, -66, -170}, + PointType {52. - sixth, -55, -170}, + PointType {42. + sixth, -55, -170}); + + const TetrahedronType cases[] = { + TetrahedronType {PointType {27.5859, -19.5363, -148.01}, + PointType {44.2539, -58.1624, -171.152}, + PointType {43.7957, -57.9539, -146.494}, + PointType {15.8564, -32.9522, -147.246}}, + TetrahedronType {PointType {76.8265, -45.3561, -146.396}, + PointType {79.5055, -43.6324, -171.152}, + PointType {77.7366, -63.3987, -171.152}, + PointType {44.2539, -58.1624, -171.152}}, + TetrahedronType {PointType {77.4836, -63.4271, -145.519}, + PointType {76.8265, -45.3561, -146.396}, + PointType {44.2539, -58.1624, -171.152}, + PointType {43.7957, -57.9539, -146.494}}, + TetrahedronType {PointType {77.4836, -63.4271, -145.519}, + PointType {76.8265, -45.3561, -146.396}, + PointType {77.7366, -63.3987, -171.152}, + PointType {44.2539, -58.1624, -171.152}}, + }; + + // Use intersection volumes computed using exact arithmetic in cgal + const double expected_volumes[] = {0.30774371225334463, + 15.302276033130795, + 0.24319537885473608, + 3.1668745904352349}; + + constexpr bool DO_NOT_FIX_ORIENTATION = false; + constexpr bool TRY_FIX_ORIENTATION = true; + + // clang-format off + constexpr bool plot_all_values = false; + const auto eps_values = plot_all_values + ? std::vector {1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8, + 1e-9, 1e-10,1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16} + : std::vector {1e-10}; + // clang-format on + + // print the header + axom::fmt::print("case, eps, expected, direct, direct_fixed, direct_fixed_flipped, ref_subdiv\n"); + + for(int i = 0; i < 4; ++i) + { + const auto& tet = cases[i]; + const TetrahedronType tet_flipped(tet[1], tet[0], tet[2], tet[3]); + + for(const double eps : eps_values) + { + const double direct_hex_tet = + axom::primal::intersection_volume(hex, tet, eps, DO_NOT_FIX_ORIENTATION); + const double direct_hex_tet_fixed = + axom::primal::intersection_volume(hex, tet, eps, TRY_FIX_ORIENTATION); + const double direct_hex_tet_fixed_flipped = + axom::primal::intersection_volume(hex, tet_flipped, eps, TRY_FIX_ORIENTATION); + const double ref_subdiv_hex_tet = intersection_volume_via_hex_triangulation(hex, tet, eps); + + axom::fmt::print("{},{},{:.17e},{:.17e},{:.17e},{:.17e},{:.17e}\n", + i, + eps, + expected_volumes[i], + direct_hex_tet, + direct_hex_tet_fixed, + direct_hex_tet_fixed_flipped, + ref_subdiv_hex_tet); + + // check that intersection volumes are non-negative + EXPECT_GT(direct_hex_tet, 0.) << "case " << i; + EXPECT_GT(ref_subdiv_hex_tet, 0.) << "case " << i; + EXPECT_GT(direct_hex_tet_fixed_flipped, 0.) << "case " << i; + EXPECT_GT(ref_subdiv_hex_tet, 0.) << "case " << i; + + // check that primal::intersection_volume results matches expectations and other ways to compute it + // we expect about 12 digits of precision to baseline values + if(eps > 1e-13) + { + EXPECT_NEAR(direct_hex_tet_fixed, expected_volumes[i], eps) << "case " << i; + EXPECT_NEAR(direct_hex_tet_fixed, ref_subdiv_hex_tet, eps) << "case " << i; + EXPECT_NEAR(direct_hex_tet_fixed, direct_hex_tet_fixed_flipped, eps) << "case " << i; + EXPECT_NEAR(direct_hex_tet_fixed, ref_subdiv_hex_tet, eps) << "case " << i; + } + } + } +} + +//------------------------------------------------------------------------------ +int main(int argc, char* argv[]) +{ + ::testing::InitGoogleTest(&argc, argv); + axom::slic::SimpleLogger logger; + + int result = RUN_ALL_TESTS(); + + return result; +} diff --git a/src/axom/primal/tests/primal_knot_vector.cpp b/src/axom/primal/tests/primal_knot_vector.cpp index d42c2fc7c1..f162ce0dfd 100644 --- a/src/axom/primal/tests/primal_knot_vector.cpp +++ b/src/axom/primal/tests/primal_knot_vector.cpp @@ -267,6 +267,62 @@ TEST(primal_knotvector, normalize) } } +//------------------------------------------------------------------------------ +TEST(primal_knotvector, derivative_basis_workspace_matches_reference) +{ + { + const int degree = 1; + axom::Array knots {0.0, 0.0, 0.5, 1.0, 1.0}; + primal::KnotVector kv(knots, degree); + + primal::KnotVector::DerivativeBasisWorkspace workspace; + + for(const double t : {0.25, 0.75}) + { + const auto span = kv.findSpan(t); + + const auto ref = kv.derivativeBasisFunctionsBySpan(span, t, 1); + const auto view = kv.derivativeBasisFunctionsBySpan(span, t, 1, workspace); + + ASSERT_EQ(ref.size(), 2); + ASSERT_EQ(ref[0].size(), degree + 1); + ASSERT_EQ(ref[1].size(), degree + 1); + + for(int j = 0; j <= degree; ++j) + { + EXPECT_NEAR(view[0][j], ref[0][j], 1e-14); + EXPECT_NEAR(view[1][j], ref[1][j], 1e-14); + } + } + } + + { + const int degree = 2; + axom::Array knots {0.0, 0.0, 0.0, 0.4, 1.0, 1.0, 1.0}; + primal::KnotVector kv(knots, degree); + + primal::KnotVector::DerivativeBasisWorkspace workspace; + + for(const double t : {0.2, 0.7}) + { + const auto span = kv.findSpan(t); + + const auto ref = kv.derivativeBasisFunctionsBySpan(span, t, 1); + const auto view = kv.derivativeBasisFunctionsBySpan(span, t, 1, workspace); + + ASSERT_EQ(ref.size(), 2); + ASSERT_EQ(ref[0].size(), degree + 1); + ASSERT_EQ(ref[1].size(), degree + 1); + + for(int j = 0; j <= degree; ++j) + { + EXPECT_NEAR(view[0][j], ref[0][j], 1e-14); + EXPECT_NEAR(view[1][j], ref[1][j], 1e-14); + } + } + } +} + //------------------------------------------------------------------------------ TEST(primal_knotvector, insert_knot) { diff --git a/src/axom/primal/tests/primal_nurbs_patch.cpp b/src/axom/primal/tests/primal_nurbs_patch.cpp index e7ea6a9375..c4bd00b3e8 100644 --- a/src/axom/primal/tests/primal_nurbs_patch.cpp +++ b/src/axom/primal/tests/primal_nurbs_patch.cpp @@ -743,8 +743,17 @@ TEST(primal_nurbspatch, first_second_derivatives) { for(auto v : v_pts) { - axom::Array ders; - nPatch.evaluateDerivatives(u, v, 2, ders); + axom::Array ders_1; + axom::Array ders_2; + nPatch.evaluateDerivatives(u, v, 1, ders_1); + nPatch.evaluateDerivatives(u, v, 2, ders_2); + + for(int N = 0; N < DIM; ++N) + { + EXPECT_NEAR(ders_1[0][0][N], ders_2[0][0][N], 1e-10); + EXPECT_NEAR(ders_1[1][0][N], ders_2[1][0][N], 1e-10); + EXPECT_NEAR(ders_1[0][1][N], ders_2[0][1][N], 1e-10); + } auto pt = nPatch.evaluate(u, v); auto pt_u = nPatch.isocurve_v(v).dt(u); @@ -754,16 +763,91 @@ TEST(primal_nurbspatch, first_second_derivatives) for(int N = 0; N < DIM; ++N) { - EXPECT_NEAR(pt[N], ders[0][0][N], 1e-10); - EXPECT_NEAR(pt_u[N], ders[1][0][N], 1e-10); - EXPECT_NEAR(pt_v[N], ders[0][1][N], 1e-10); - EXPECT_NEAR(pt_uu[N], ders[2][0][N], 1e-10); - EXPECT_NEAR(pt_vv[N], ders[0][2][N], 1e-10); + EXPECT_NEAR(pt[N], ders_2[0][0][N], 1e-10); + EXPECT_NEAR(pt_u[N], ders_2[1][0][N], 1e-10); + EXPECT_NEAR(pt_v[N], ders_2[0][1][N], 1e-10); + EXPECT_NEAR(pt_uu[N], ders_2[2][0][N], 1e-10); + EXPECT_NEAR(pt_vv[N], ders_2[0][2][N], 1e-10); } } } } +//------------------------------------------------------------------------------ +TEST(primal_nurbspatch, linear_derivatives_mixed_partial) +{ + constexpr int DIM = 3; + using CoordType = double; + using PointType = primal::Point; + using VectorType = primal::Vector; + using NURBSPatchType = primal::NURBSPatch; + + // Construct a simple polynomial surface that is exactly representable by + // a (quadratic) Bezier patch: + // + // S(u,v) = ( u, v, u*v ) + // + // so that the mixed partial is constant: + // S_uv(u,v) = (0, 0, 1) + constexpr int deg_u = 2; + constexpr int deg_v = 2; + + NURBSPatchType patch(deg_u, deg_v); + + const CoordType ctrl_u[deg_u + 1] = {0.0, 0.5, 1.0}; + const CoordType ctrl_v[deg_v + 1] = {0.0, 0.5, 1.0}; + + for(int i = 0; i <= deg_u; ++i) + { + for(int j = 0; j <= deg_v; ++j) + { + patch(i, j) = PointType {ctrl_u[i], ctrl_v[j], ctrl_u[i] * ctrl_v[j]}; + } + } + + constexpr CoordType u = 0.25; + constexpr CoordType v = 0.75; + + PointType eval; + VectorType Du, Dv, DuDv; + patch.evaluateLinearDerivatives(u, v, eval, Du, Dv, DuDv); + + { + constexpr CoordType eps = 1e-12; + + EXPECT_NEAR(eval[0], u, eps); + EXPECT_NEAR(eval[1], v, eps); + EXPECT_NEAR(eval[2], u * v, eps); + + EXPECT_NEAR(Du[0], 1.0, eps); + EXPECT_NEAR(Du[1], 0.0, eps); + EXPECT_NEAR(Du[2], v, eps); + + EXPECT_NEAR(Dv[0], 0.0, eps); + EXPECT_NEAR(Dv[1], 1.0, eps); + EXPECT_NEAR(Dv[2], u, eps); + + EXPECT_NEAR(DuDv[0], 0.0, eps); + EXPECT_NEAR(DuDv[1], 0.0, eps); + EXPECT_NEAR(DuDv[2], 1.0, eps); + } + + // Validate the mixed partial with finite differences: d/ dv (S_u). + { + constexpr CoordType eps = 1e-6; + PointType eval_plus, eval_minus; + VectorType Du_plus, Dv_plus, Du_minus, Dv_minus; + patch.evaluateFirstDerivatives(u, v + eps, eval_plus, Du_plus, Dv_plus); + patch.evaluateFirstDerivatives(u, v - eps, eval_minus, Du_minus, Dv_minus); + + for(int n = 0; n < DIM; ++n) + { + const CoordType dudv_fd = (Du_plus[n] - Du_minus[n]) / (2.0 * eps); + EXPECT_NEAR(dudv_fd, DuDv[n], 1e-6); + } + } +} + //------------------------------------------------------------------------------ TEST(primal_nurbspatch, knot_insertion) { diff --git a/src/axom/primal/tests/primal_polygon.cpp b/src/axom/primal/tests/primal_polygon.cpp index 95bd6fd112..c6a06d3111 100644 --- a/src/axom/primal/tests/primal_polygon.cpp +++ b/src/axom/primal/tests/primal_polygon.cpp @@ -26,6 +26,32 @@ TEST(primal_polygon, empty) EXPECT_FALSE(poly.isValid()); } +//------------------------------------------------------------------------------ +TEST(primal_polygon, static_copy_and_assignment) +{ + using PolygonType = axom::primal::Polygon; + using PointType = axom::primal::Point; + + const PolygonType source({PointType {0., 0.}, PointType {1., 0.}, PointType {1., 1.}}); + + PolygonType copy(source); + PolygonType assigned; + assigned = source; + + EXPECT_EQ(copy.numVertices(), source.numVertices()); + EXPECT_EQ(assigned.numVertices(), source.numVertices()); + + for(int i = 0; i < source.numVertices(); ++i) + { + EXPECT_EQ(copy[i], source[i]); + EXPECT_EQ(assigned[i], source[i]); + } + + assigned.addVertex(PointType {0., 1.}); + EXPECT_EQ(assigned.numVertices(), 4); + EXPECT_EQ(source.numVertices(), 3); +} + //------------------------------------------------------------------------------ TEST(primal_polygon, winding_number) { diff --git a/src/axom/primal/tests/primal_solid_angle.cpp b/src/axom/primal/tests/primal_solid_angle.cpp index 83b17464b9..8e9833cf44 100644 --- a/src/axom/primal/tests/primal_solid_angle.cpp +++ b/src/axom/primal/tests/primal_solid_angle.cpp @@ -13,6 +13,8 @@ #include "gtest/gtest.h" +#include "axom/primal/geometry/detail/analytic_test_surfaces.hpp" + // C++ headers #include #include @@ -497,171 +499,8 @@ TEST(primal_solid_angle, planar_bezierpatch) } } -axom::Array> make_sphere_biquartic() -{ - using Point3D = primal::Point; - using NPatch = primal::NURBSPatch; - - double rt2 = sqrt(2), rt3 = sqrt(3), rt6 = sqrt(6); - - // Define the nodes and weights for one of six rational, biquartic Bezier patches - // that compose the unit sphere. These will be rotated to form the other 5. - // Nodes and weights obtained from the technical report - // "Tiling the Sphere with Rational Bezier Patches", - // James E. Cobb, University of Utah, 1988 - - // clang-format off - axom::Array node_data = { - Point3D {4*(1-rt3), 4*(1-rt3), 4*(1-rt3)}, Point3D {rt2*(rt3-4), -rt2, rt2*(rt3-4)}, Point3D {4*(1-2*rt3)/3, 0, 4*(1-2*rt3)/3}, Point3D {rt2*(rt3-4), rt2, rt2*(rt3-4)}, Point3D {4*(1-rt3), 4*(rt3-1), 4*(1-rt3)}, - Point3D { -rt2, rt2*(rt3 - 4), rt2*(rt3 - 4)}, Point3D {(2-3*rt3)/2, (2-3*rt3)/2, -(rt3+6)/2}, Point3D {rt2*(2*rt3-7)/3, 0, -5*rt6/3}, Point3D {(2-3*rt3)/2, (3*rt3-2)/2, -(rt3+6)/2}, Point3D { -rt2, rt2*(4-rt3), rt2*(rt3-4)}, - Point3D { 0, 4*(1-2*rt3)/3, 4*(1-2*rt3)/3}, Point3D { 0, rt2*(2*rt3-7)/3, -5*rt6/3}, Point3D {0, 0, 4*(rt3-5)/3}, Point3D { 0, rt2*(7-2*rt3)/3, -5*rt6/3}, Point3D { 0, 4*(2*rt3-1)/3, 4*(1-2*rt3)/3}, - Point3D { rt2, rt2*(rt3 - 4), rt2*(rt3 - 4)}, Point3D {(3*rt3-2)/2, (2-3*rt3)/2, -(rt3+6)/2}, Point3D {rt2*(7-2*rt3)/3, 0, -5*rt6/3}, Point3D {(3*rt3-2)/2, (3*rt3-2)/2, -(rt3+6)/2}, Point3D { rt2, rt2*(4-rt3), rt2*(rt3-4)}, - Point3D {4*(rt3-1), 4*(1-rt3), 4*(1-rt3)}, Point3D {rt2*(4-rt3), -rt2, rt2*(rt3-4)}, Point3D {4*(2*rt3-1)/3, 0, 4*(1-2*rt3)/3}, Point3D {rt2*(4-rt3), rt2, rt2*(rt3-4)}, Point3D {4*(rt3-1), 4*(rt3-1), 4*(1-rt3)}}; - - axom::Array weight_data = { - 4*(3-rt3), rt2*(3*rt3-2), 4*(5-rt3)/3, rt2*(3*rt3-2), 4*(3-rt3), - rt2*(3*rt3-2), (rt3+6)/2, rt2*(rt3+6)/3, (rt3+6)/2, rt2*(3*rt3-2), - 4*(5-rt3)/3, rt2*(rt3+6)/3, 4*(5*rt3-1)/9, rt2*(rt3+6)/3, 4*(5-rt3)/3, - rt2*(3*rt3-2), (rt3+6)/2, rt2*(rt3+6)/3, (rt3+6)/2, rt2*(3*rt3-2), - 4*(3-rt3), rt2*(3*rt3-2), 4*(5-rt3)/3, rt2*(3*rt3-2), 4*(3-rt3)}; - // clang-format on - - axom::Array sphere_faces(6); - for(int n = 0; n < 6; ++n) - { - sphere_faces[n].setParameters(5, 5, 4, 4); - sphere_faces[n].makeRational(); - } - - for(int i = 0; i < 5; ++i) - { - for(int j = 0; j < 5; ++j) - { - const int idx = 5 * i + j; - for(int n = 0; n < 6; ++n) - { - sphere_faces[n].setWeight(i, j, weight_data[idx]); - } - - // Set up each face by rotating one of the patch faces - sphere_faces[0](i, j)[0] = node_data[idx][1]; - sphere_faces[0](i, j)[1] = node_data[idx][0]; - sphere_faces[0](i, j)[2] = node_data[idx][2]; - sphere_faces[0](i, j).array() /= weight_data[idx]; - - sphere_faces[1](i, j)[0] = -node_data[idx][0]; - sphere_faces[1](i, j)[1] = -node_data[idx][1]; - sphere_faces[1](i, j)[2] = -node_data[idx][2]; - sphere_faces[1](i, j).array() /= weight_data[idx]; - - sphere_faces[2](i, j)[0] = node_data[idx][2]; - sphere_faces[2](i, j)[1] = node_data[idx][1]; - sphere_faces[2](i, j)[2] = node_data[idx][0]; - sphere_faces[2](i, j).array() /= weight_data[idx]; - - sphere_faces[3](i, j)[0] = -node_data[idx][1]; - sphere_faces[3](i, j)[1] = -node_data[idx][2]; - sphere_faces[3](i, j)[2] = -node_data[idx][0]; - sphere_faces[3](i, j).array() /= weight_data[idx]; - - sphere_faces[4](i, j)[0] = node_data[idx][0]; - sphere_faces[4](i, j)[1] = node_data[idx][2]; - sphere_faces[4](i, j)[2] = node_data[idx][1]; - sphere_faces[4](i, j).array() /= weight_data[idx]; - - sphere_faces[5](i, j)[0] = -node_data[idx][2]; - sphere_faces[5](i, j)[1] = -node_data[idx][0]; - sphere_faces[5](i, j)[2] = -node_data[idx][1]; - sphere_faces[5](i, j).array() /= weight_data[idx]; - } - } - - return sphere_faces; -} - -axom::Array> make_sphere_bicubic() -{ - // Generate a sphere using (degenerate) bicubic patches - - using Point2D = primal::Point; - using Point3D = primal::Point; - using BCurve = primal::BezierCurve; - using NPatch = primal::NURBSPatch; - - double rt2 = sqrt(2); - - // Define BezierCurves which, when rotated around the z-axis, - // form the top and bottom halves of a sphere. - BCurve top_curve(2), bottom_curve(2); - top_curve[0] = Point2D {0.0, 1.0}; - top_curve[1] = Point2D {1.0, 1.0}; - top_curve[2] = Point2D {1.0, 0.0}; - - bottom_curve[0] = Point2D {1.0, 0.0}; - bottom_curve[1] = Point2D {1.0, -1.0}; - bottom_curve[2] = Point2D {0.0, -1.0}; - - top_curve.makeRational(); - top_curve.setWeight(1, 1.0 / rt2); - - bottom_curve.makeRational(); - bottom_curve.setWeight(1, 1.0 / rt2); - - axom::Array sphere_faces(8); - for(int n = 0; n < 8; ++n) - { - sphere_faces[n].setParameters(3, 3, 2, 2); - sphere_faces[n].makeRational(); - } - - for(int n = 0; n < 2; ++n) - { - auto& curve = (n == 0) ? top_curve : bottom_curve; - - for(int i = 0; i <= 2; ++i) - { - // clang-format off - sphere_faces[4*n + 0](i, 0) = Point3D {curve[i][0], 0.0, curve[i][1]}; - sphere_faces[4*n + 0](i, 1) = Point3D {curve[i][0], curve[i][0], curve[i][1]}; - sphere_faces[4*n + 0](i, 2) = Point3D {0.0, curve[i][0], curve[i][1]}; - - sphere_faces[4*n + 1](i, 0) = Point3D {0.0, curve[i][0], curve[i][1]}; - sphere_faces[4*n + 1](i, 1) = Point3D {-curve[i][0], curve[i][0], curve[i][1]}; - sphere_faces[4*n + 1](i, 2) = Point3D {-curve[i][0], 0.0, curve[i][1]}; - - sphere_faces[4*n + 2](i, 0) = Point3D {-curve[i][0], 0.0, curve[i][1]}; - sphere_faces[4*n + 2](i, 1) = Point3D {-curve[i][0], -curve[i][0], curve[i][1]}; - sphere_faces[4*n + 2](i, 2) = Point3D {0.0, -curve[i][0], curve[i][1]}; - - sphere_faces[4*n + 3](i, 0) = Point3D {0.0, -curve[i][0], curve[i][1]}; - sphere_faces[4*n + 3](i, 1) = Point3D {curve[i][0], -curve[i][0], curve[i][1]}; - sphere_faces[4*n + 3](i, 2) = Point3D {curve[i][0], 0.0, curve[i][1]}; - - double the_weight = curve.isRational() ? curve.getWeight(i) : 1.0; - - sphere_faces[4*n + 0].setWeight(i, 0, the_weight); - sphere_faces[4*n + 1].setWeight(i, 0, the_weight); - sphere_faces[4*n + 2].setWeight(i, 0, the_weight); - sphere_faces[4*n + 3].setWeight(i, 0, the_weight); - - sphere_faces[4*n + 0].setWeight(i, 1, the_weight / rt2); - sphere_faces[4*n + 1].setWeight(i, 1, the_weight / rt2); - sphere_faces[4*n + 2].setWeight(i, 1, the_weight / rt2); - sphere_faces[4*n + 3].setWeight(i, 1, the_weight / rt2); - - sphere_faces[4*n + 0].setWeight(i, 2, the_weight); - sphere_faces[4*n + 1].setWeight(i, 2, the_weight); - sphere_faces[4*n + 2].setWeight(i, 2, the_weight); - sphere_faces[4*n + 3].setWeight(i, 2, the_weight); - //clang-format on - } - } - - return sphere_faces; -} - //------------------------------------------------------------------------------ -TEST(primal_integral, nurbspatch_sphere) +TEST(primal_solid_angle, nurbspatch_sphere) { using Point3D = primal::Point; using Vector3D = primal::Vector; @@ -672,22 +511,22 @@ TEST(primal_integral, nurbspatch_sphere) // Iterate over points of interest, i.e. axis/edge/vertex aligned Vector3D query_directions[12] = {Vector3D({0.0, 0.0, 1.0}).unitVector(), - Vector3D({0.0, 1.0, 0.0}).unitVector(), - Vector3D({1.0, 0.0, 0.0}).unitVector(), - Vector3D({0.0, 1.0, 1.0}).unitVector(), - Vector3D({1.0, 0.0, 1.0}).unitVector(), - Vector3D({1.0, 1.0, 0.0}).unitVector(), - Vector3D({1.0, 1.0, 1.0}).unitVector(), - Vector3D({0.0, 0.1, 1.0}).unitVector(), - Vector3D({0.1, 1.0, 0.0}).unitVector(), - Vector3D({1.0, 0.0, 0.1}).unitVector(), - Vector3D({ 0.126623,-0.701415,-0.701415}).unitVector(), - Vector3D({-0.701415, 0.126623,-0.701415}).unitVector()}; + Vector3D({0.0, 1.0, 0.0}).unitVector(), + Vector3D({1.0, 0.0, 0.0}).unitVector(), + Vector3D({0.0, 1.0, 1.0}).unitVector(), + Vector3D({1.0, 0.0, 1.0}).unitVector(), + Vector3D({1.0, 1.0, 0.0}).unitVector(), + Vector3D({1.0, 1.0, 1.0}).unitVector(), + Vector3D({0.0, 0.1, 1.0}).unitVector(), + Vector3D({0.1, 1.0, 0.0}).unitVector(), + Vector3D({1.0, 0.0, 0.1}).unitVector(), + Vector3D({0.126623, -0.701415, -0.701415}).unitVector(), + Vector3D({-0.701415, 0.126623, -0.701415}).unitVector()}; const double edge_offset = 1e-5; for(int i = 0; i < N; ++i) { - // Pick points that are far from the surface, + // Pick points that are far from the surface, inner_points[i] = Point3D(0.1 * query_directions[i].array()); inner_points[i + N] = Point3D((1.0 - edge_offset) * query_directions[i].array()); @@ -704,21 +543,23 @@ TEST(primal_integral, nurbspatch_sphere) const double quad_tol = 1e-5; const double disk_size = 0.01; const double EPS = 1e-11; - + // Test the points on the biquartic patches - auto sphere_faces = make_sphere_biquartic(); + auto sphere_faces = axom::primal::detail::make_unit_sphere_biquartic(); SLIC_INFO("Evaluating GWN for inner points"); - auto inner_gwn = winding_number(inner_points, sphere_faces, edge_tol, ls_tol, quad_tol, disk_size, EPS); - for (int i = 0; i < N; ++i) + auto inner_gwn = + winding_number(inner_points, sphere_faces, edge_tol, ls_tol, quad_tol, disk_size, EPS); + for(int i = 0; i < N; ++i) { EXPECT_NEAR(inner_gwn[i], 1.0, 6 * quad_tol); EXPECT_NEAR(inner_gwn[i + N], 1.0, 6 * quad_tol); } SLIC_INFO("Evaluating GWN for outer points"); - auto outer_gwn = winding_number(outer_points, sphere_faces, edge_tol, ls_tol, quad_tol, disk_size, EPS); - for (int i = 0; i < N; ++i) + auto outer_gwn = + winding_number(outer_points, sphere_faces, edge_tol, ls_tol, quad_tol, disk_size, EPS); + for(int i = 0; i < N; ++i) { EXPECT_NEAR(outer_gwn[i], 0.0, 6 * quad_tol); EXPECT_NEAR(outer_gwn[i + N], 0.0, 6 * quad_tol); @@ -732,31 +573,31 @@ TEST(primal_integral, nurbspatch_sphere) EXPECT_NEAR(coincident_gwn[i], 0.5, 6 * quad_tol); } - // Test non-memoized version by iterating over points and surfaces + // Test non-memoized version by iterating over points and surfaces SLIC_INFO("Evaluating GWN for inner points, non-memoized"); - for (auto& pt : inner_points) + for(auto& pt : inner_points) { double the_gwn = 0.0; - for( auto & surf : sphere_faces ) + for(auto& surf : sphere_faces) { - the_gwn += winding_number( pt, surf, edge_tol, ls_tol, quad_tol, disk_size, EPS ); + the_gwn += winding_number(pt, surf, edge_tol, ls_tol, quad_tol, disk_size, EPS); } EXPECT_NEAR(the_gwn, 1.0, 6 * quad_tol); } - // Test points near degenerate edges of the biquartic patches - sphere_faces = make_sphere_bicubic(); + // Test points near degenerate edges of the biquadratic patches + sphere_faces = axom::primal::detail::make_unit_sphere_biquadratic(); axom::Array difficult_points(0, 5); - + // Outer points difficult_points.emplace_back(Point3D(0.1 * query_directions[0].array())); difficult_points.emplace_back(Point3D((1.0 - edge_offset) * query_directions[0].array())); - + // Inner points difficult_points.emplace_back(Point3D(2.1 * query_directions[0].array())); difficult_points.emplace_back(Point3D((1.0 + edge_offset) * query_directions[0].array())); - + // Coincident point difficult_points.emplace_back(Point3D(query_directions[0].array())); @@ -764,11 +605,75 @@ TEST(primal_integral, nurbspatch_sphere) auto difficult_gwn = winding_number(difficult_points, sphere_faces, edge_tol, ls_tol, quad_tol, disk_size, EPS); - EXPECT_NEAR(difficult_gwn[0], 1.0, 8 * quad_tol); // Inner point - EXPECT_NEAR(difficult_gwn[1], 1.0, 8 * quad_tol); // Inner point - EXPECT_NEAR(difficult_gwn[2], 0.0, 8 * quad_tol); // Outer point - EXPECT_NEAR(difficult_gwn[3], 0.0, 8 * quad_tol); // Outer point - EXPECT_NEAR(difficult_gwn[4], 0.5, 8 * quad_tol); // Coincident point + EXPECT_NEAR(difficult_gwn[0], 1.0, 8 * quad_tol); // Inner point + EXPECT_NEAR(difficult_gwn[1], 1.0, 8 * quad_tol); // Inner point + EXPECT_NEAR(difficult_gwn[2], 0.0, 8 * quad_tol); // Outer point + EXPECT_NEAR(difficult_gwn[3], 0.0, 8 * quad_tol); // Outer point + EXPECT_NEAR(difficult_gwn[4], 0.5, 8 * quad_tol); // Coincident point +} + +//------------------------------------------------------------------------------ +TEST(primal_solid_angle, teardrop_regression_test) +{ + using Point3D = primal::Point; + + const double edge_tol = 1e-6; + const double ls_tol = 1e-10; + const double quad_tol = 1e-5; + const double disk_size = 0.01; + const double EPS = 1e-11; + + // Test the points on a teardrop for which + // the bottom portion is a bicubic sphere, + // the top portion is defined by the solid of revolution of a cubic Bezier curve + const auto teardrop_shape = axom::primal::detail::make_teardrop(); + + auto is_in_teardrop = [](Point3D x) -> bool { + const double radius = std::sqrt(x[0] * x[0] + x[1] * x[1]); + + if(radius > 1.0) + { + return false; + } + else + { + // The vertical cross-section of the tip is given by 3sin(1/3 * asin(1-2x)) + x - 0.5 + double fun = 3 * std::sin(1.0 / 3.0 * std::asin(1 - 2 * radius)) + radius - 0.5; + return (x[2] <= fun) && + ((x[2] > -1.0) || std::sqrt(x[0] * x[0] + x[1] * x[1] + (x[2] + 1.0) * (x[2] + 1.0) <= 1.0)); + } + }; + + // Define a grid of points + constexpr int npts = 21; + double x_pts[npts]; + double y_pts[npts]; + double z_pts[npts]; + + axom::numerics::linspace(-1.1, 1.1, x_pts, npts); + axom::numerics::linspace(-1.1, 1.1, y_pts, npts); + axom::numerics::linspace(-2.1, 1.1, z_pts, npts); + + constexpr int tot_npts = npts * npts * npts; + axom::Array query_arr(0, tot_npts); + axom::Array true_containment_arr(0, tot_npts); + + for(int n = 0; n < tot_npts; ++n) + { + const Point3D query {x_pts[(n / npts / npts) % npts], y_pts[(n / npts) % npts], z_pts[n % npts]}; + + query_arr.emplace_back(query); + true_containment_arr.emplace_back(is_in_teardrop(query)); + } + + const auto gwn_array = + axom::primal::winding_number(query_arr, teardrop_shape, edge_tol, ls_tol, quad_tol, disk_size, EPS); + + for(int n = 0; n < tot_npts; ++n) + { + const bool calc_containment = (std::round(gwn_array[n]) != 0); + EXPECT_EQ(calc_containment, true_containment_arr[n]); + } } int main(int argc, char** argv) diff --git a/src/axom/quest/CMakeLists.txt b/src/axom/quest/CMakeLists.txt index 8cf2389473..35e0451286 100644 --- a/src/axom/quest/CMakeLists.txt +++ b/src/axom/quest/CMakeLists.txt @@ -54,6 +54,9 @@ set( quest_headers io/STLWriter.hpp io/ProEReader.hpp + ## Generalized Winding Numbers + FastApproximateGWN.hpp + ## quest interface interface/internal/mpicomm_wrapper.hpp interface/internal/QuestHelpers.hpp @@ -95,6 +98,7 @@ set( quest_sources if(MFEM_FOUND) list(APPEND quest_headers io/MFEMReader.hpp) + list(APPEND quest_headers GWNMethods.hpp) list(APPEND quest_sources io/MFEMReader.cpp) endif() @@ -168,7 +172,8 @@ if(AXOM_ENABLE_KLEE AND AXOM_ENABLE_SIDRE) detail/clipping/SphereClipper.hpp detail/clipping/MonotonicZSORClipper.hpp detail/clipping/SORClipper.hpp - detail/clipping/MeshClipperImpl.hpp) + detail/clipping/MeshClipperImpl.hpp + util/make_clipper_strategy.hpp) list(APPEND quest_sources ShapeMesh.cpp MeshClipper.cpp @@ -179,7 +184,8 @@ if(AXOM_ENABLE_KLEE AND AXOM_ENABLE_SIDRE) detail/clipping/SphereClipper.cpp detail/clipping/MonotonicZSORClipper.cpp detail/clipping/SORClipper.cpp - detail/clipping/MeshClipperImpl.hpp) + detail/clipping/MeshClipperImpl.hpp + util/make_clipper_strategy.cpp) # MeshClipperImpl uses RAJA algorithms directly. list(APPEND quest_depends_on RAJA) diff --git a/src/axom/quest/Discretize.cpp b/src/axom/quest/Discretize.cpp index 3974c2c271..0082b47b21 100644 --- a/src/axom/quest/Discretize.cpp +++ b/src/axom/quest/Discretize.cpp @@ -126,7 +126,7 @@ bool discretize(const SphereType& sphere, int levels, axom::Array& out, octcount = count_sphere_octahedra(levels); - out = axom::Array(octcount, octcount); + out.resize(octcount); // index points to an octahedron of the last generation. We'll generate // new octahedra based on out[index]. diff --git a/src/axom/quest/Discretize.hpp b/src/axom/quest/Discretize.hpp index 9f87ae2720..b0a9ddb987 100644 --- a/src/axom/quest/Discretize.hpp +++ b/src/axom/quest/Discretize.hpp @@ -51,7 +51,8 @@ bool discretize(const SphereType& s, int levels, axom::Array& out, int& /*! * \brief Given a 2D polyline revolved around the positive X-axis, allocate * and return a list of Octahedra approximating the shape. - * \param [in] polyline The polyline to revolve around the X-axis + * \param [in] polyline The polyline to revolve around the X-axis. + * Data should be in a host-accessible memory space. * \param [in] len The number of points in \a polyline * \param [in] levels The number of refinements to perform, in addition to * a central level-zero octahedron in each segment diff --git a/src/axom/quest/FastApproximateGWN.hpp b/src/axom/quest/FastApproximateGWN.hpp new file mode 100644 index 0000000000..e599c6c502 --- /dev/null +++ b/src/axom/quest/FastApproximateGWN.hpp @@ -0,0 +1,435 @@ +// Copyright (c) 2017-2025, Lawrence Livermore National Security, LLC and +// other Axom Project Developers. See the top-level LICENSE file for details. +// +// SPDX-License-Identifier: (BSD-3-Clause) +#ifndef AXOM_QUEST_FAST_APPROXIMATE_GWN_HPP +#define AXOM_QUEST_FAST_APPROXIMATE_GWN_HPP +#include "axom/primal.hpp" + +#include + +namespace axom +{ +namespace quest +{ +namespace detail +{ + +/// Computes the total number of moments for a given degree and order, i.e. +/// ndim + ndim^2 + ... + ndim^(ord + 1) +constexpr int get_num_moment_entries(int ndim, int ord) +{ + int n_entries = 0; + for(int i = 0; i < ord + 1; ++i) + { + int power = 1; + for(int j = 0; j < i + 1; ++j) + { + power *= ndim; + } + n_entries += power; + } + return n_entries; +} +} // namespace detail + +/* + * \class GWN Moment Data + * + * \brief A class to compute and store the geometric moment data which parameterizes the + * Taylor expansion of a GWN approximation for a cluster of geometric primitives. + * \tparam T The numeric type + * \tparam NDIMS The number of spatial dimensions of the geometric primitives (2 or 3) + * \tparam ORD The order of the Taylor expansion (0, 1, or 2) + * + * Stores arrays `rm` of raw moments and `ec` of Taylor expansion coefficients, as only the + * latter is used to compute the approximated GWN. Transforming raw moments to expansion coefficients + * requires knowing the center of the expansion, which we take as the centroid of the collection. + * + * Stores double `a` and vector `ap` which are the total unsigned area and weighted centroid of + * the collection of geometric objects. + */ +template +class GWNMomentData +{ + static_assert((NDIMS == 2 || NDIMS == 3), "Must be defined in 2 or 3 dimensions"); + static_assert(0 <= ORD && ORD <= 2, "Only supported for orders 0, 1, or 2"); + + static constexpr int NumberOfEntries = detail::get_num_moment_entries(NDIMS, ORD); + + /// Addition overload to find the sum of two sets of raw moments. + /// TODO: Technically, the raw moments for b1 and b2 can be deallocated after this + /// function is called, which would decrease the memory footprint + friend GWNMomentData operator+(GWNMomentData& b1, GWNMomentData& b2) + { + GWNMomentData b_out; + + b_out.a = b1.a + b2.a; + b_out.ap = b1.ap + b2.ap; + + for(int i = 0; i < NumberOfEntries; ++i) + { + b_out.rm[i] = b1.rm[i] + b2.rm[i]; + } + + b_out.compute_coefficients(); + + return b_out; + } + +public: + GWNMomentData() = default; + + /// Construct moments from a 3D triangle + explicit GWNMomentData(const axom::primal::Triangle& a_tri) + { + static_assert(NDIMS == 3, "GWN Moments for triangles are defined only for 3D"); + + // Track the centroid across the tree, and return the rest of the data + auto centroid = a_tri.centroid(); + a = a_tri.area(); + ap[0] = a * centroid[0]; + ap[1] = a * centroid[1]; + ap[2] = a * centroid[2]; + + auto normal = 0.5 * a_tri.normal(); + rm[0] = normal[0]; + rm[1] = normal[1]; + rm[2] = normal[2]; + + if constexpr(ORD >= 1) + { + int m = 3; + for(int i = 0; i < 9; ++i, ++m) + { + // In tensor product notation, equal to + // centroid \otimes normal + rm[m] = normal[i % 3] * centroid[i / 3]; + } + + if constexpr(ORD >= 2) + { + constexpr auto twlv = 1.0 / 12.0; + const auto ab = axom::primal::Vector {a_tri[0].array() + a_tri[1].array()}; + const auto bc = axom::primal::Vector {a_tri[1].array() + a_tri[2].array()}; + const auto ac = axom::primal::Vector {a_tri[0].array() + a_tri[2].array()}; + + for(int i = 0; i < 27; ++i, ++m) + { + // 1/12 * (ab \otimes ab + bc \otimes bc + ac \otimes ac) \otimes normal + rm[m] = twlv * normal[i % 3] * + (ab[i / 9] * ab[(i / 3) % 3] + bc[i / 9] * bc[(i / 3) % 3] + ac[i / 9] * ac[(i / 3) % 3]); + } + } + } + + compute_coefficients(); + } + + /// Construct moments from a 2D Segment + explicit GWNMomentData(const axom::primal::Segment& s) + : GWNMomentData(s.source(), s.target()) + { } + + /// Construct moments from the endpoints of a 2D segment + explicit GWNMomentData(const axom::primal::Point& p0, const axom::primal::Point& p1) + { + static_assert(NDIMS == 2, "GWN Moments for segments are defined only for 2D"); + + const auto x0 = p0[0]; + const auto y0 = p0[1]; + const auto x1 = p1[0]; + const auto y1 = p1[1]; + + // Needed to track the centroid across the tree + const auto dx = x1 - x0; + const auto dy = y0 - y1; // actually -dy since it was more useful. + a = sqrt(dx * dx + dy * dy); + ap[0] = a * 0.5 * (x0 + x1); + ap[1] = a * 0.5 * (y0 + y1); + + const auto x0x0 = x0 * x0; + const auto x0x1 = x0 * x1; + const auto x1x1 = x1 * x1; + + const auto y0y0 = y0 * y0; + const auto y0y1 = y0 * y1; + const auto y1y1 = y1 * y1; + + const auto x0y0 = x0 * y0; + const auto x0y1 = x0 * y1; + const auto x1y0 = x1 * y0; + const auto x1y1 = x1 * y1; + + rm[0] = dy; + rm[1] = dx; + + if constexpr(ORD >= 1) + { + rm[2] = 0.5 * dy * (x0 + x1); + rm[3] = 0.5 * (x1x1 - x0x0); + rm[4] = 0.5 * (y0y0 - y1y1); + rm[5] = 0.5 * (dx) * (y0 + y1); + + if constexpr(ORD == 2) + { + const auto A = (x0x0 + x0x1 + x1x1) / 3.0; + rm[6] = dy * A; + const auto B = (x0y0 + 0.5 * (x0y1 + x1y0) + x1y1) / 3.0; + rm[7] = dy * B; + rm[8] = rm[7]; + const auto C = (y0y0 + y0y1 + y1y1) / 3.0; + rm[9] = dy * C; + rm[10] = dx * A; + rm[11] = dx * B; + rm[12] = rm[11]; + rm[13] = dx * C; + } + } + + compute_coefficients(); + } + + /// Computes the approximated GWN field at the given query. + /// Formulae are taken from "Fast Winding Numbers for Soups and Clouds" by + /// Barill et al. (2018) + double approx_winding_number(axom::primal::Point query) const + { + if(axom::utilities::isNearlyEqual(std::abs(a), 0.0)) return 0.0; + + T terms[3] = {0.0, 0.0, 0.0}; + axom::primal::Vector pq(query, getCenter()); + const double norm = pq.norm(); + + if constexpr(NDIMS == 2) + { + const axom::primal::Vector F1 {ec[0], ec[1]}; + axom::primal::Vector G1 {pq[0], pq[1]}; + + const auto norm_to_2 = norm * norm; + terms[0] = F1.dot(G1) / norm_to_2; + + if constexpr(ORD >= 1) + { + const axom::primal::Vector F2 {ec[2], ec[3], ec[4], ec[5]}; + axom::primal::Vector G2 {pq[0] * pq[0] - pq[1] * pq[1], 2 * pq[0] * pq[1], 0.0, 0.0}; + G2[2] = G2[1]; + G2[3] = -G2[0]; + + const auto norm_to_4 = norm_to_2 * norm * norm; + terms[1] = -F2.dot(G2) / norm_to_4; + + if constexpr(ORD == 2) + { + const axom::primal::Vector + F3 {ec[6], ec[7], ec[8], ec[9], ec[10], ec[11], ec[12], ec[13]}; + const double g0 = 2 * pq[0] * (pq[0] * pq[0] - 3 * pq[1] * pq[1]); + const double g1 = 2 * pq[1] * (3 * pq[0] * pq[0] - pq[1] * pq[1]); + axom::primal::Vector G3 {g0, g1, g1, -g0, g1, -g0, -g0, -g1}; + + const auto norm_to_6 = norm_to_4 * norm * norm; + terms[2] = F3.dot(G3) / norm_to_6; + } + } + + return -0.5 * M_1_PI * (terms[0] + terms[1] + terms[2]); + } + + if constexpr(NDIMS == 3) + { + const axom::primal::Vector F1 {ec[0], ec[1], ec[2]}; + axom::primal::Vector G1 {pq[0], pq[1], pq[2]}; + + const auto norm_to_3 = norm * norm * norm; + terms[0] = F1.dot(G1) / norm_to_3; + + if constexpr(ORD >= 1) + { + const axom::primal::Vector + F2 {ec[3], ec[4], ec[5], ec[6], ec[7], ec[8], ec[9], ec[10], ec[11]}; + // clang-format off + axom::primal::Vector G2_1{ 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 }; + axom::primal::Vector G2_2{ pq[0] * pq[0], pq[1] * pq[0], pq[2] * pq[0], + pq[0] * pq[1], pq[1] * pq[1], pq[2] * pq[1], + pq[0] * pq[2], pq[1] * pq[2], pq[2] * pq[2] }; + // clang-format on + + const auto norm_to_5 = norm_to_3 * norm * norm; + terms[1] = F2.dot(G2_1 * (1. / norm_to_3) - G2_2 * (3. / norm_to_5)); + + if constexpr(ORD >= 2) + { + const axom::primal::Vector F3 { + ec[12], ec[13], ec[14], ec[15], ec[16], ec[17], ec[18], ec[19], ec[20], + ec[21], ec[22], ec[23], ec[24], ec[25], ec[26], ec[27], ec[28], ec[29], + ec[30], ec[31], ec[32], ec[33], ec[34], ec[35], ec[36], ec[37], ec[38]}; + + // clang-format off + axom::primal::Vector G3_1{ 3 * pq[0], pq[1], pq[2], pq[1], pq[0], 0, pq[2], 0, pq[0], pq[1], pq[0], 0, pq[0],3 * pq[1], pq[2], 0, pq[2], pq[1], pq[2], 0, pq[0], 0, pq[2], pq[1], pq[0], pq[1], 3 * pq[2] }; + axom::primal::Vector G3_2{ pq[0] * pq[0] * pq[0], pq[0] * pq[0] * pq[1], pq[0] * pq[0] * pq[2], pq[0] * pq[1] * pq[0], pq[0] * pq[1] * pq[1], pq[0] * pq[1] * pq[2], pq[0] * pq[2] * pq[0], pq[0] * pq[2] * pq[1], pq[0] * pq[2] * pq[2], + pq[1] * pq[0] * pq[0], pq[1] * pq[0] * pq[1], pq[1] * pq[0] * pq[2], pq[1] * pq[1] * pq[0], pq[1] * pq[1] * pq[1], pq[1] * pq[1] * pq[2], pq[1] * pq[2] * pq[0], pq[1] * pq[2] * pq[1], pq[1] * pq[2] * pq[2], + pq[2] * pq[0] * pq[0], pq[2] * pq[0] * pq[1], pq[2] * pq[0] * pq[2], pq[2] * pq[1] * pq[0], pq[2] * pq[1] * pq[1], pq[2] * pq[1] * pq[2], pq[2] * pq[2] * pq[0], pq[2] * pq[2] * pq[1], pq[2] * pq[2] * pq[2] }; + // clang-format on + + // The formula in [Barill 2018] incorrectly lists (-1. / norm_to_5) + const auto norm_to_7 = norm_to_5 * norm * norm; + terms[2] = F3.dot(G3_1 * (-3. / norm_to_5) + G3_2 * (15. / norm_to_7)); + } + } + + return 0.25 * M_1_PI * (terms[0] + terms[1] + terms[2]); + } + } + + /// Return the center of the Taylor expansion + axom::primal::Point getCenter() const + { + if(a == 0) + { + return axom::primal::Point {}; + } + + return axom::primal::Point((ap / a).array()); + } + +private: + /// Transform raw moments into expansion coefficients + void compute_coefficients() + { + auto p = getCenter(); + + for(int i = 0; i < NDIMS; ++i) + { + ec[i] = rm[i]; + } + + if constexpr(ORD >= 1) + { + int m = NDIMS; + for(int i = 0; i < NDIMS * NDIMS; ++i, ++m) + { + ec[m] = rm[m] - p[i / NDIMS] * rm[i % NDIMS]; + } + + if constexpr(ORD == 2) + { + for(int i = 0; i < NDIMS * NDIMS * NDIMS; ++i, ++m) + { + // Example values for NDIMS = 2 + const int A = (i / NDIMS / NDIMS) % NDIMS; // 0, 0, 0, 0, 1, 1, 1, 1 + const int B = (i / NDIMS) % NDIMS; // 0, 0, 1, 1, 0, 0, 1, 1 + const int C = (i / 1) % NDIMS; // 0, 1, 0, 1, 0, 1, 0, 1 + const int D = i % (NDIMS * NDIMS); // 0, 1, 2, 3, 0, 1, 2, 3 + + ec[m] = 0.5 * + (rm[m] - p[A] * rm[NDIMS + D] - p[B] * rm[(A + 1) * NDIMS + C] + p[A] * p[B] * rm[C]); + } + } + } + } + +public: + // Store accumulated values across the node's children + axom::primal::Vector ap; // Weighted centroid + double a {}; + + // Raw moments + axom::StackArray rm {}; + + // Expansion coefficients + axom::StackArray ec {}; +}; + +/*! + * \brief Evaluate a hierarchical approximation of the GWN for the shape in + * `leaf_objects`, encompassed by `traverser`'s BVH + * + * Traverse the BVH at the input `query`. + * For any node which is considered "far-away", approximate the GWN for that node + * For any node which is a leaf (i.e. close to the query), compute the GWN directly + * + * \tparam T Numeric type of geometric primitives + * \tparam NDIMS The spatial dimensions of the shape (2 or 3) + * \tparam ORD The number of terms in the Taylor expansion + * \tparam LeafGeometry The type of the objects which could require direct evaluation + * \tparam TraverserType The derived type of the traverser for the BVH tree + * \param [in] query The query point at which to evaluate the GWN + * \param [in] traverser A traverser for the BVH tree + * \param [in] leaf_objects A view of all individual geometric objects in the shape, + * indexed by position in the BVH tree + * \param [in] internal_moments A view of GWNMomentData objects for each internal node + * of the BVH tree, each representing a cluster of leaf objects + * \param [in] wt A structure of possible tolerances for GWN evaluation to permit + * flexible evaluation for many different type of leaf objects + * \param [in] beta An "accuracy parameter" which scales at what distance from an AABB a query + * point is considered to be "far-away". + * + * The default parameter beta = 2.0 is suggested by the work + * "Fast Winding Numbers for Soups and Clouds" by Barill et al. (2018) + * + * \return The approximated GWN at the query point + */ +template +double fast_approximate_winding_number(const primal::Point& query, + const TraverserType& traverser, + const ArrayView& leaf_objects, + const ArrayView>& internal_moments, + const primal::WindingTolerances& wt, + double beta = 2.0) +{ + double gwn = 0.0; + + const auto leaf_objects_view = leaf_objects; + const auto internal_moments_view = internal_moments; + using LeafGeom = std::decay_t; + + auto bbContain = [&gwn, &internal_moments_view, &beta](const primal::Point& query, + const primal::BoundingBox& bvhBbox, + std::int32_t node_index) -> bool { + const bool near_tree = + axom::primal::squared_distance(query, internal_moments_view[node_index].getCenter()) < + beta * beta * bvhBbox.range().squared_norm() / 4; + + // If we're inside an internal node bbox, need to keep recurring + if(near_tree) + { + return true; + } + // If we're outside an internal node bbox, we can add its contribution to the GWN + else + { + gwn += internal_moments_view[node_index].approx_winding_number(query); + return false; + } + }; + + if constexpr(std::is_same_v>) + { + auto leaf_gwn = [&query, &gwn, leaf_objects_view, &wt](std::int32_t currentNode, + const std::int32_t* leafNodes) -> void { + const auto idx = leafNodes[currentNode]; + gwn += axom::primal::winding_number(query, leaf_objects_view[idx], wt.edge_tol, wt.EPS); + }; + + traverser.traverse_tree(query, leaf_gwn, bbContain); + } + + if constexpr(std::is_same_v>) + { + auto leaf_gwn = [&query, &gwn, leaf_objects_view, &wt](std::int32_t currentNode, + const std::int32_t* leafNodes) -> void { + const auto idx = leafNodes[currentNode]; + gwn += axom::primal::winding_number(query, leaf_objects_view[idx], wt.edge_tol); + }; + + traverser.traverse_tree(query, leaf_gwn, bbContain); + } + // Support for other leaf types forthcoming... + + return gwn; +} + +} // end namespace quest +} // end namespace axom + +#endif diff --git a/src/axom/quest/GWNMethods.hpp b/src/axom/quest/GWNMethods.hpp new file mode 100644 index 0000000000..18323b7621 --- /dev/null +++ b/src/axom/quest/GWNMethods.hpp @@ -0,0 +1,927 @@ +// Copyright (c) Lawrence Livermore National Security, LLC and other +// Axom Project Contributors. See top-level LICENSE and COPYRIGHT +// files for dates and other details. +// +// SPDX-License-Identifier: (BSD-3-Clause) + +/** + * \file GWNMethods.hpp + * + * \brief Helper classes and type traits for GWN Evaluation methods + */ + +#ifndef AXOM_QUEST_GWN_METHODS_HPP_ +#define AXOM_QUEST_GWN_METHODS_HPP_ + +#include "axom/config.hpp" +#include "axom/core.hpp" +#include "axom/slic.hpp" +#include "axom/spin.hpp" +#include "axom/primal.hpp" + +#include "axom/quest/FastApproximateGWN.hpp" +#include "axom/quest/util/mesh_helpers.hpp" + +#include "axom/fmt.hpp" + +#include "mfem.hpp" + +namespace axom +{ +namespace quest +{ + +//------------------------------------------------------------------------------ +// Query-mesh helpers +//------------------------------------------------------------------------------ + +/// Helper function to set up the mesh and associated winding and inout fields. +/// Uses an mfem::DataCollection to hold everything together. +void setup_gwn_mesh(mfem::DataCollection& dc, mfem::Mesh* query_mesh, int queryOrder) +{ + AXOM_ANNOTATE_SCOPE("setup_mesh"); + + dc.SetOwnData(true); + dc.SetMesh(query_mesh); + + const int dim = query_mesh->Dimension(); + + // Create grid functions for the winding field; will take care of fes and fec memory via MakeOwner() + auto* winding_fec = new mfem::H1Pos_FECollection(queryOrder, dim); + auto* winding_fes = new mfem::FiniteElementSpace(query_mesh, winding_fec, 1); + mfem::GridFunction* winding = new mfem::GridFunction(winding_fes); + winding->MakeOwner(winding_fec); + + // Create grid functions for the inout field; will take care of fes and fec memory via MakeOwner() + auto* inout_fec = new mfem::H1Pos_FECollection(queryOrder, dim); + auto* inout_fes = new mfem::FiniteElementSpace(query_mesh, inout_fec, 1); + mfem::GridFunction* inout = new mfem::GridFunction(inout_fes); + inout->MakeOwner(inout_fec); + + dc.RegisterField("winding", winding); + dc.RegisterField("inout", inout); +} + +/// Query grid setup; has some dimension-specific types; +/// if user did not provide a bounding box, use shape bounding box scaled by 10% +template +void generate_gwn_query_mesh(mfem::DataCollection& dc, + const axom::primal::BoundingBox& shape_bbox, + const std::vector& boxMins, + const std::vector& boxMaxs, + const std::vector& boxResolution, + int queryOrder) +{ + AXOM_ANNOTATE_SCOPE("generate_query_mesh"); + + const int query_dim = static_cast(boxResolution.size()); + const bool has_query_box = !boxMins.empty(); + + constexpr double scale_factor = 1.1; + if(query_dim == 2) + { + using Point2D = primal::Point; + using BoundingBox2D = primal::BoundingBox; + + const auto query_res = axom::NumericArray(boxResolution.data()); + const auto query_box = has_query_box + ? BoundingBox2D(Point2D(boxMins.data()), Point2D(boxMaxs.data())) + : BoundingBox2D(Point2D({shape_bbox.getMin()[0], shape_bbox.getMin()[1]}), + Point2D({shape_bbox.getMax()[0], shape_bbox.getMax()[1]})) + .scale(scale_factor); + + SLIC_INFO( + axom::fmt::format("Query grid resolution {} within bounding box {}", query_res, query_box)); + + mfem::Mesh* query_mesh = + axom::quest::util::make_cartesian_mfem_mesh_2D(query_box, query_res, queryOrder); + + setup_gwn_mesh(dc, query_mesh, queryOrder); + } + else + { + using Point3D = primal::Point; + using BoundingBox3D = primal::BoundingBox; + + const auto query_res = axom::NumericArray(boxResolution.data()); + const auto query_box = has_query_box + ? BoundingBox3D(Point3D(boxMins.data()), Point3D(boxMaxs.data())) + : BoundingBox3D( + Point3D({shape_bbox.getMin()[0], shape_bbox.getMin()[1], shape_bbox.getMin()[2]}), + Point3D({shape_bbox.getMax()[0], shape_bbox.getMax()[1], shape_bbox.getMax()[2]})) + .scale(scale_factor); + + SLIC_INFO( + axom::fmt::format("Query grid resolution {} within bounding box {}", query_res, query_box)); + + mfem::Mesh* query_mesh = + axom::quest::util::make_cartesian_mfem_mesh_3D(query_box, query_res, queryOrder); + + setup_gwn_mesh(dc, query_mesh, queryOrder); + } +} + +//------------------------------------------------------------------------------ +// Query classes +//------------------------------------------------------------------------------ + +///@{ +/// \name Query methods for 2D GWN applications + +class DirectGWN2D +{ +public: + using CurveArrayType = axom::Array>; + using NURBSCacheArray = axom::Array>; + + DirectGWN2D() = default; + + /// \brief Define view for NURBS data. + /// If memoization is used, allocate a cache for each curve. + void preprocess(const CurveArrayType& input_curves, bool use_memoization = true) + { + m_input_curves_view = input_curves.view(); + if(m_input_curves_view.size() <= 0) + { + SLIC_WARNING("Quest: Input shape contains no curves; skipping preprocessing."); + return; + } + + axom::utilities::Timer timer(true); + { + AXOM_ANNOTATE_SCOPE("preprocessing"); + if(use_memoization) + { + m_nurbs_caches.reserve(input_curves.size()); + for(const auto& curv : input_curves) + { + m_nurbs_caches.emplace_back(curv); + } + } + } + timer.stop(); + AXOM_ANNOTATE_METADATA("preprocessing_time", timer.elapsed(), ""); + SLIC_INFO(axom::fmt::format("Direct query preprocessing (loading curves{}): {} s", + use_memoization ? " and memoization caches" : "", + timer.elapsedTimeInSec())); + } + + /*! + * \brief Evaluate the GWN for a query grid at the DOFs of the \a dc query mesh + * + * \param [in] dc A query grid to be evaluated at the DOFs + * \param [in] tol A collection of possible tolerances for GWN evaluation + */ + void query(mfem::DataCollection& dc, const primal::WindingTolerances& tol) + { + if(!dc.HasField("winding") || !dc.HasField("inout")) + { + SLIC_WARNING( + axom::fmt::format("Quest: Input data collection has no field `{}`. Exiting Early.", + dc.HasField("winding") ? "inout" : "winding")); + } + + if(m_input_curves_view.empty()) + { + SLIC_WARNING("Quest: Skipping query; Input shape not properly initialized."); + return; + } + + auto* query_mesh = dc.GetMesh(); + auto& winding = *dc.GetField("winding"); + auto& inout = *dc.GetField("inout"); + + const auto num_query_points = query_mesh->GetNodalFESpace()->GetNDofs(); + + auto query_point = [&query_mesh](int idx) -> axom::primal::Point { + axom::primal::Point pt; + query_mesh->GetNode(idx, pt.data()); + return pt; + }; + + axom::utilities::Timer query_timer(true); + { + AXOM_ANNOTATE_SCOPE("query"); + const primal::WindingTolerances tol_copy = tol; + const auto input_curves_view = m_input_curves_view; + + // Use non-memoized form + if(m_nurbs_caches.empty()) + { + axom::for_all(num_query_points, [=, &winding, &inout](axom::IndexType nidx) { + const auto q = query_point(static_cast(nidx)); + double wn {}; + for(const auto& cache : input_curves_view) + { + wn += axom::primal::winding_number(q, cache, tol_copy.edge_tol, tol_copy.EPS); + } + winding[static_cast(nidx)] = wn; + inout[static_cast(nidx)] = std::lround(wn); + }); + } + else // Use memoized form + { + const auto nurbs_caches_view = m_nurbs_caches.view(); + axom::for_all(num_query_points, [=, &winding, &inout](axom::IndexType nidx) { + const auto q = query_point(static_cast(nidx)); + double wn {}; + for(const auto& cache : nurbs_caches_view) + { + wn += axom::primal::winding_number(q, cache, tol_copy.edge_tol, tol_copy.EPS); + } + winding[static_cast(nidx)] = wn; + inout[static_cast(nidx)] = std::lround(wn); + }); + } + } + query_timer.stop(); + + const double query_time_s = query_timer.elapsed(); + const double ms_per_query = query_timer.elapsedTimeInMilliSec() / num_query_points; + SLIC_INFO(axom::fmt::format( + axom::utilities::locale(), + "Querying {:L} samples in winding number field with{} memoization took {:.3Lf} seconds" + " (@ {:.0Lf} queries per second; {:.6Lf} ms per query)", + num_query_points, + m_nurbs_caches.empty() ? "out" : "", + query_time_s, + num_query_points / query_time_s, + ms_per_query)); + AXOM_ANNOTATE_METADATA("query_points", num_query_points, ""); + AXOM_ANNOTATE_METADATA("query_time", query_time_s, ""); + } + +private: + axom::ArrayView> m_input_curves_view; + NURBSCacheArray m_nurbs_caches; +}; + +template +class PolylineGWN2D +{ +public: + using Point2D = axom::primal::Point; + using BoxType = axom::primal::BoundingBox; + using CurveArrayType = axom::Array>; + using SegmentType = axom::primal::Segment; + using GWNMoments = axom::quest::GWNMomentData; + + PolylineGWN2D() = default; + + /// \brief Load polyline data into primal::Segments. + /// If fast-approximation is used, construct BVH + void preprocess(axom::mint::UnstructuredMesh* poly_mesh, + bool useDirectEval) + { + if(poly_mesh == nullptr || poly_mesh->getNumberOfCells() <= 0) + { + SLIC_WARNING("Quest: Input mesh contains no segments; skipping preprocessing."); + return; + } + + axom::utilities::Timer timer(true); + axom::utilities::Timer stage_timer(false); + + AXOM_ANNOTATE_SCOPE("preprocessing"); + + stage_timer.start(); + { + AXOM_ANNOTATE_SCOPE("extract_segments"); + + m_segments.resize(poly_mesh->getNumberOfCells()); + auto segments_view = m_segments.view(); + + axom::mint::for_all_cells( + poly_mesh, + AXOM_LAMBDA(axom::IndexType cellIdx, + const axom::numerics::Matrix& coords, + const axom::IndexType* /*nodeIds*/) { + segments_view[cellIdx] = + SegmentType {Point2D {coords(0, 0), coords(1, 0)}, Point2D {coords(0, 1), coords(1, 1)}}; + }); + } + stage_timer.stop(); + SLIC_INFO(axom::fmt::format(" Preprocessing stage (extract_segments): {} s", + stage_timer.elapsedTimeInSec())); + + // If direct evaluation is preferred, skip BVH initialization + if(!useDirectEval) + { + stage_timer.reset(); + stage_timer.start(); + { + AXOM_ANNOTATE_SCOPE("bvh_init"); + const int nlines = m_segments.size(); + axom::Array aabbs(nlines, nlines); + auto aabbs_view = aabbs.view(); + const auto segments_view = m_segments.view(); + + axom::for_all( + nlines, + AXOM_LAMBDA(axom::IndexType i) { + aabbs_view[i] = BoxType {segments_view[i].source(), segments_view[i].target()}; + }); + m_bvh.initialize(aabbs_view, nlines); + } + stage_timer.stop(); + SLIC_INFO( + axom::fmt::format(" Preprocessing stage (bvh): {} s", stage_timer.elapsedTimeInSec())); + + stage_timer.reset(); + stage_timer.start(); + { + AXOM_ANNOTATE_SCOPE("moments"); + const auto segments_view = m_segments.view(); + + auto compute_moments = [segments_view](std::int32_t currentNode, + const std::int32_t* leafNodes) -> GWNMoments { + const auto idx = leafNodes[currentNode]; + return GWNMoments(segments_view[idx]); + }; + + const auto traverser = m_bvh.getTraverser(); + m_internal_moments = traverser.reduce_tree(compute_moments); + } + stage_timer.stop(); + SLIC_INFO( + axom::fmt::format(" Preprocessing stage (moments): {} s", stage_timer.elapsedTimeInSec())); + } + timer.stop(); + SLIC_INFO(axom::fmt::format("Total preprocessing: {} s", timer.elapsedTimeInSec())); + } + + /*! + * \brief Evaluate the GWN for a query grid at the DOFs of the \a dc query mesh + * + * \param [in] dc A query grid to be evaluated at the DOFs + * \param [in] tol A collection of possible tolerances for GWN evaluation + */ + void query(mfem::DataCollection& dc, const primal::WindingTolerances& tol) + { + if(!dc.HasField("winding") || !dc.HasField("inout")) + { + SLIC_WARNING( + axom::fmt::format("Quest: Input data collection has no field `{}`. Exiting Early.", + dc.HasField("winding") ? "inout" : "winding")); + } + + if(m_segments.empty()) + { + SLIC_WARNING("Quest: Skipping query; Input shape not properly initialized."); + return; + } + + const auto* query_mesh = dc.GetMesh(); + auto& winding = *dc.GetField("winding"); + auto& inout = *dc.GetField("inout"); + + const auto num_query_points = query_mesh->GetNodalFESpace()->GetNDofs(); + + auto query_point = [query_mesh](axom::IndexType idx) -> Point2D { + axom::primal::Point pt({0., 0.}); + query_mesh->GetNode(static_cast(idx), pt.data()); + return pt; + }; + + axom::utilities::Timer query_timer(true); + { + AXOM_ANNOTATE_SCOPE("query"); + + const auto segments_view = m_segments.view(); + const primal::WindingTolerances tol_copy = tol; + + // Use fast approximation + if(m_bvh.isInitialized()) + { + const auto traverser = m_bvh.getTraverser(); + const auto internal_moments_view = m_internal_moments.view(); + + axom::for_all(num_query_points, [=, &winding, &inout](axom::IndexType index) { + const double wn = axom::quest::fast_approximate_winding_number(query_point(index), + traverser, + segments_view, + internal_moments_view, + tol_copy); + + winding[static_cast(index)] = wn; + inout[static_cast(index)] = std::lround(wn); + }); + } + // Use direct formula + else + { + axom::for_all(num_query_points, [=, &winding, &inout](axom::IndexType index) { + const axom::primal::Point q = query_point(static_cast(index)); + double wn {}; + for(const auto& seg : segments_view) + { + wn += axom::primal::winding_number(q, seg, tol_copy.edge_tol); + } + + winding[static_cast(index)] = wn; + inout[static_cast(index)] = std::lround(wn); + }); + } + } + query_timer.stop(); + + const double query_time_s = query_timer.elapsed(); + const double ms_per_query = query_timer.elapsedTimeInMilliSec() / num_query_points; + SLIC_INFO(axom::fmt::format(axom::utilities::locale(), + "Querying {:L} samples in winding number field took {:.3Lf} seconds" + " (@ {:.0Lf} queries per second; {:.5Lf} ms per query)", + num_query_points, + query_time_s, + num_query_points / query_time_s, + ms_per_query)); + AXOM_ANNOTATE_METADATA("query_points", num_query_points, ""); + AXOM_ANNOTATE_METADATA("query_time", query_time_s, ""); + } + +private: + // For the procsesed input curves/BVH leaf nodes + axom::Array m_segments; + + // Only needed for fast approximation method + axom::Array m_internal_moments; + axom::spin::BVH<2, axom::SEQ_EXEC> m_bvh; +}; +///@} + +///@{ +/// \name Query methods for 3D GWN applications +class DirectGWN3D +{ +public: + using PatchArrayType = axom::Array>; + using NURBSCacheArray = axom::Array>; + + DirectGWN3D() = default; + + /// \brief Define view for NURBS data. + /// If memoization is used, allocate a cache for each patch. + void preprocess(const PatchArrayType& input_patches, bool use_memoization = true) + { + m_input_patches_view = input_patches.view(); + if(m_input_patches_view.size() <= 0) + { + SLIC_WARNING("Quest: Input shape contains no patches; skipping preprocessing."); + return; + } + + axom::utilities::Timer timer(true); + { + AXOM_ANNOTATE_SCOPE("preprocessing"); + if(use_memoization) + { + m_nurbs_caches.reserve(input_patches.size()); + for(const auto& patch : input_patches) + { + m_nurbs_caches.emplace_back(patch); + } + } + } + timer.stop(); + AXOM_ANNOTATE_METADATA("preprocessing_time", timer.elapsed(), ""); + SLIC_INFO(axom::fmt::format("Direct query preprocessing (loading surfaces{}): {} s", + use_memoization ? " and memoization caches" : "", + timer.elapsedTimeInSec())); + } + + /*! + * \brief Evaluate the GWN for a query grid at the DOFs of the \a dc query mesh + * + * \param [in] dc A query grid to be evaluated at the DOFs + * \param [in] tol A collection of possible tolerances for GWN evaluation + * \param [in] slice_z If the dc mesh is 2D, the GWN will be evaluated on a slice + * parallel to the x-y plane with this offset on the z-axis + */ + void query(mfem::DataCollection& dc, + const primal::WindingTolerances& tol, + const double slice_z = 0.0) const + { + if(!dc.HasField("winding") || !dc.HasField("inout")) + { + SLIC_WARNING( + axom::fmt::format("Quest: Input data collection has no field `{}`. Exiting Early.", + dc.HasField("winding") ? "inout" : "winding")); + } + + if(m_input_patches_view.empty()) + { + SLIC_WARNING("Quest: Skipping query; Input shape not properly initialized."); + return; + } + + auto* query_mesh = dc.GetMesh(); + auto& winding = *dc.GetField("winding"); + auto& inout = *dc.GetField("inout"); + + const auto num_query_points = query_mesh->GetNodalFESpace()->GetNDofs(); + + auto query_point = [query_mesh, slice_z](int idx) -> axom::primal::Point { + axom::primal::Point pt({0., 0., slice_z}); + query_mesh->GetNode(idx, pt.data()); + return pt; + }; + + axom::utilities::Timer query_timer(true); + { + AXOM_ANNOTATE_SCOPE("query"); + const primal::WindingTolerances tol_copy = tol; + const auto input_patches_view = m_input_patches_view; + + // Use non-memoized form + if(m_nurbs_caches.empty()) + { + axom::for_all(num_query_points, [=, &winding, &inout](axom::IndexType nidx) { + const auto q = query_point(static_cast(nidx)); + double wn {}; + for(const auto& patch : input_patches_view) + { + wn += axom::primal::winding_number(q, + patch, + tol_copy.edge_tol, + tol_copy.ls_tol, + tol_copy.quad_tol, + tol_copy.disk_size, + tol_copy.EPS); + } + winding[static_cast(nidx)] = wn; + inout[static_cast(nidx)] = std::lround(wn); + }); + } + else // Use memoized form + { + const auto nurbs_patches_view = m_nurbs_caches.view(); + axom::for_all(num_query_points, [=, &winding, &inout](axom::IndexType nidx) { + const auto q = query_point(static_cast(nidx)); + double wn {}; + for(const auto& cache : nurbs_patches_view) + { + wn += axom::primal::winding_number(q, + cache, + tol_copy.edge_tol, + tol_copy.ls_tol, + tol_copy.quad_tol, + tol_copy.disk_size, + tol_copy.EPS); + } + winding[static_cast(nidx)] = wn; + inout[static_cast(nidx)] = std::lround(wn); + }); + } + } + query_timer.stop(); + + const double query_time_s = query_timer.elapsed(); + const double ms_per_query = query_timer.elapsedTimeInMilliSec() / num_query_points; + SLIC_INFO(axom::fmt::format( + axom::utilities::locale(), + "Querying {:L} samples in winding number field with{} memoization took {:.3Lf} seconds" + " (@ {:.0Lf} queries per second; {:.6Lf} ms per query)", + num_query_points, + m_nurbs_caches.empty() ? "out" : "", + query_time_s, + num_query_points / query_time_s, + ms_per_query)); + AXOM_ANNOTATE_METADATA("query_points", num_query_points, ""); + AXOM_ANNOTATE_METADATA("query_time", query_time_s, ""); + } + +private: + axom::ArrayView> m_input_patches_view; + NURBSCacheArray m_nurbs_caches; +}; + +template +class TriangleGWN3D +{ +public: + using Point3D = axom::primal::Point; + using BoxType = axom::primal::BoundingBox; + using TriangleType = axom::primal::Triangle; + using GWNMoments = axom::quest::GWNMomentData; + + TriangleGWN3D() = default; + + /// \brief Load mesh data into primal::Triangles. + /// If fast-approximation is used, construct BVH + void preprocess(axom::mint::UnstructuredMesh* tri_mesh, bool useDirectEval) + { + axom::utilities::Timer timer(true); + axom::utilities::Timer stage_timer(false); + + AXOM_ANNOTATE_SCOPE("preprocessing"); + + const auto ntris = tri_mesh->getNumberOfCells(); + if(ntris <= 0) + { + SLIC_WARNING("Quest: Input mesh contains no triangles; skipping preprocessing."); + return; + } + + stage_timer.start(); + { + AXOM_ANNOTATE_SCOPE("extract_triangles"); + + // Iterate over mesh nodes and get a bounding box for the shape + BoxType shape_bbox; + BoxType* shape_bbox_ptr = &shape_bbox; + axom::mint::for_all_nodes( + tri_mesh, + AXOM_LAMBDA(axom::IndexType, double x, double y, double z) { + shape_bbox_ptr->addPoint(Point3D {x, y, z}); + }); + + // Extract the triangles from the mesh into axom primitives, + // scaled and translated so that `shape_box` is centered at the origin + // and has roughly unit volume. Otherwise, small triangles introduce numerical issues + m_shape_center = shape_bbox.getCentroid(); + const auto longest_dim = shape_bbox.getLongestDimension(); + m_scale = shape_bbox.getMax()[longest_dim] - shape_bbox.getMin()[longest_dim]; + const auto shape_center = m_shape_center; + const double scale = m_scale; + + m_triangles.resize(ntris); + auto triangles_view = m_triangles.view(); + axom::mint::for_all_cells( + tri_mesh, + AXOM_LAMBDA(axom::IndexType cellIdx, + const axom::numerics::Matrix& coords, + const axom::IndexType* /*nodeIds*/) { + triangles_view[cellIdx] = + TriangleType {Point3D {(coords(0, 0) - shape_center[0]) / scale, + (coords(1, 0) - shape_center[1]) / scale, + (coords(2, 0) - shape_center[2]) / scale}, + Point3D {(coords(0, 1) - shape_center[0]) / scale, + (coords(1, 1) - shape_center[1]) / scale, + (coords(2, 1) - shape_center[2]) / scale}, + Point3D {(coords(0, 2) - shape_center[0]) / scale, + (coords(1, 2) - shape_center[1]) / scale, + (coords(2, 2) - shape_center[2]) / scale}}; + }); + } + stage_timer.stop(); + SLIC_INFO(axom::fmt::format(" Preprocessing stage (extract_triangles): {} s", + stage_timer.elapsedTimeInSec())); + + // If direct evaluation is preferred, skip BVH initialization + if(!useDirectEval) + { + stage_timer.reset(); + stage_timer.start(); + { + AXOM_ANNOTATE_SCOPE("bvh_init"); + axom::Array aabbs(ntris, ntris); + auto aabbs_view = aabbs.view(); + const auto triangles_view = m_triangles.view(); + + axom::for_all( + ntris, + AXOM_LAMBDA(axom::IndexType i) { + aabbs_view[i] = + BoxType {triangles_view[i][0], triangles_view[i][1], triangles_view[i][2]}; + }); + m_bvh.initialize(aabbs_view, ntris); + } + stage_timer.stop(); + SLIC_INFO( + axom::fmt::format(" Preprocessing stage (bvh): {} s", stage_timer.elapsedTimeInSec())); + + stage_timer.reset(); + stage_timer.start(); + { + AXOM_ANNOTATE_SCOPE("moments"); + const auto triangles_view = m_triangles.view(); + + auto compute_moments = [triangles_view](std::int32_t currentNode, + const std::int32_t* leafNodes) -> GWNMoments { + const auto idx = leafNodes[currentNode]; + return GWNMoments(triangles_view[idx]); + }; + + const auto traverser = m_bvh.getTraverser(); + m_internal_moments = traverser.reduce_tree(compute_moments); + } + stage_timer.stop(); + SLIC_INFO( + axom::fmt::format(" Preprocessing stage (moments): {} s", stage_timer.elapsedTimeInSec())); + } + timer.stop(); + + SLIC_INFO(axom::fmt::format("Total preprocessing: {} s", timer.elapsedTimeInSec())); + } + /*! + * \brief Evaluate the GWN for a query grid at the DOFs of the \a dc query mesh + * + * \param [in] dc A query grid to be evaluated at the DOFs + * \param [in] tol A collection of possible tolerances for GWN evaluation + * \param [in] slice_z If the dc mesh is 2D, the GWN will be evaluated on a slice + * parallel to the x-y plane with this offset on the z-axis + */ + void query(mfem::DataCollection& dc, const primal::WindingTolerances& tol, const double slice_z = 0.0) + { + if(!dc.HasField("winding") || !dc.HasField("inout")) + { + SLIC_WARNING( + axom::fmt::format("Quest: Skipping query; Input data collection has no field `{}`.", + dc.HasField("winding") ? "inout" : "winding")); + return; + } + + if(m_triangles.empty()) + { + SLIC_WARNING("Quest: Skipping query; Input shape not properly initialized."); + return; + } + + const auto* query_mesh = dc.GetMesh(); + auto& winding = *dc.GetField("winding"); + auto& inout = *dc.GetField("inout"); + + const auto num_query_points = query_mesh->GetNodalFESpace()->GetNDofs(); + + // Get the query point from the mesh, scaled to the proper normalization + const auto& ctr = m_shape_center; + const auto& scl = m_scale; + auto scaled_query_point = + [query_mesh, slice_z, ctr, scl](axom::IndexType idx) -> axom::primal::Point { + axom::primal::Point pt({0., 0., slice_z}); + query_mesh->GetNode(static_cast(idx), pt.data()); + pt.array() = (pt.array() - ctr.array()) / scl; + return pt; + }; + + axom::utilities::Timer query_timer(true); + { + AXOM_ANNOTATE_SCOPE("query"); + + const auto triangles_view = m_triangles.view(); + const primal::WindingTolerances tol_copy = tol; + + // Use fast approximation + if(m_bvh.isInitialized()) + { + const auto traverser = m_bvh.getTraverser(); + const auto internal_moments_view = m_internal_moments.view(); + + axom::for_all(num_query_points, [=, &winding, &inout](axom::IndexType index) { + const double wn = axom::quest::fast_approximate_winding_number(scaled_query_point(index), + traverser, + triangles_view, + internal_moments_view, + tol_copy); + + winding[static_cast(index)] = wn; + inout[static_cast(index)] = std::lround(wn); + }); + } + // Use direct formula + else + { + axom::for_all(num_query_points, [=, &winding, &inout](axom::IndexType index) { + const auto q = scaled_query_point(static_cast(index)); + double wn {}; + for(const auto& tri : triangles_view) + { + wn += axom::primal::winding_number(q, tri, tol_copy.edge_tol, tol_copy.EPS); + } + + winding[static_cast(index)] = wn; + inout[static_cast(index)] = std::lround(wn); + }); + } + } + query_timer.stop(); + + const double query_time_s = query_timer.elapsed(); + const double ms_per_query = query_timer.elapsedTimeInMilliSec() / num_query_points; + SLIC_INFO(axom::fmt::format(axom::utilities::locale(), + "Querying {:L} samples in winding number field took {:.3Lf} seconds" + " (@ {:.0Lf} queries per second; {:.5Lf} ms per query)", + num_query_points, + query_time_s, + num_query_points / query_time_s, + ms_per_query)); + AXOM_ANNOTATE_METADATA("query_points", num_query_points, ""); + AXOM_ANNOTATE_METADATA("query_time", query_time_s, ""); + } + +private: + // For the procsesed input curves/BVH leaf nodes + axom::Array m_triangles; + + // Only needed for fast approximation method + axom::Array m_internal_moments; + axom::spin::BVH<3, axom::SEQ_EXEC> m_bvh; + + // Parameters for normalization + axom::primal::Point m_shape_center; + double m_scale; +}; +///@} + +//------------------------------------------------------------------------------ +// Type Traits +//------------------------------------------------------------------------------ + +enum class GWNInputType +{ + Curve, + Polyline, + Surface, + Triangulation +}; + +template +struct gwn_input_traits; + +template +struct gwn_input_traits> + : std::integral_constant +{ }; + +template <> +struct gwn_input_traits + : std::integral_constant +{ }; + +template +struct gwn_input_traits> + : std::integral_constant +{ }; + +template <> +struct gwn_input_traits + : std::integral_constant +{ }; + +template +inline constexpr GWNInputType gwn_input_type_v = gwn_input_traits::value; + +//------------------------------------------------------------------------------ +// Compute postprocessing stats +//------------------------------------------------------------------------------ + +struct FieldStats +{ + double dof_l2 {}; + double dof_linf {}; + double l2 {}; + double min {}; + double max {}; +}; + +FieldStats compute_field_stats(const mfem::GridFunction& gf) +{ + FieldStats s {}; + + s.dof_l2 = gf.Norml2(); + s.dof_linf = gf.Normlinf(); + s.min = gf.Min(); + s.max = gf.Max(); + + // Compute L2 norm over the physical domain: sqrt( Integral gf^2 dOmega ) + // We do this by assembling b_i = Integral phi_i * gf dOmega, then taking dot(gf, b). + auto* fes = const_cast(gf.FESpace()); + auto* gf_ptr = const_cast(&gf); + mfem::GridFunctionCoefficient gf_coeff(gf_ptr); + mfem::LinearForm gf_sq_form(fes); + gf_sq_form.AddDomainIntegrator(new mfem::DomainLFIntegrator(gf_coeff)); + gf_sq_form.Assemble(); + + const double integral_gf_sq = gf * gf_sq_form; + s.l2 = std::sqrt(std::max(0.0, integral_gf_sq)); + + return s; +} + +struct IntegralStats +{ + double integral {}; + double domain_volume {}; +}; + +IntegralStats compute_integrals(const mfem::GridFunction& gf) +{ + IntegralStats s {}; + + auto* fes = const_cast(gf.FESpace()); + mfem::ConstantCoefficient one(1.0); + mfem::LinearForm vol_form(fes); + vol_form.AddDomainIntegrator(new mfem::DomainLFIntegrator(one)); + vol_form.Assemble(); + + s.integral = gf * vol_form; + + mfem::GridFunction unity(fes); + unity.ProjectCoefficient(one); + s.domain_volume = unity * vol_form; + + return s; +} + +} // namespace quest +} // namespace axom +#endif diff --git a/src/axom/quest/IntersectionShaper.hpp b/src/axom/quest/IntersectionShaper.hpp index 852afda1cb..ea12ad1499 100644 --- a/src/axom/quest/IntersectionShaper.hpp +++ b/src/axom/quest/IntersectionShaper.hpp @@ -1969,13 +1969,15 @@ class IntersectionShaper : public Shaper if(m_bpGrp) { auto fieldsGrp = m_bpGrp->getGroup("fields"); - SLIC_ERROR_IF(fieldsGrp == nullptr, "Input blueprint mesh lacks the 'fields' Group/Node."); - for(auto& group : fieldsGrp->groups()) + if(fieldsGrp != nullptr) { - std::string materialName = fieldNameToMaterialName(group.getName()); - if(!materialName.empty()) + for(auto& group : fieldsGrp->groups()) { - materialNames.emplace_back(materialName); + std::string materialName = fieldNameToMaterialName(group.getName()); + if(!materialName.empty()) + { + materialNames.emplace_back(materialName); + } } } } diff --git a/src/axom/quest/LinearizeCurves.hpp b/src/axom/quest/LinearizeCurves.hpp index de09eaa048..9a6393c99e 100644 --- a/src/axom/quest/LinearizeCurves.hpp +++ b/src/axom/quest/LinearizeCurves.hpp @@ -25,7 +25,7 @@ class LinearizeCurves { public: using NURBSCurve = axom::primal::NURBSCurve; - using CurveArrayView = axom::ArrayView; + using CurveArrayView = axom::ArrayView; using SegmentMesh = mint::UnstructuredMesh; public: diff --git a/src/axom/quest/MeshClipper.cpp b/src/axom/quest/MeshClipper.cpp index 2223c02eb0..c36f76eb72 100644 --- a/src/axom/quest/MeshClipper.cpp +++ b/src/axom/quest/MeshClipper.cpp @@ -29,12 +29,12 @@ MeshClipper::MeshClipper(quest::experimental::ShapeMesh& shapeMesh, , m_screenLevel(3) { // Initialize statistics used by this class. - m_counterStats["cellsIn"].set_int64(0); - m_counterStats["cellsOn"].set_int64(0); - m_counterStats["cellsOut"].set_int64(0); - m_counterStats["tetsIn"].set_int64(0); - m_counterStats["tetsOn"].set_int64(0); - m_counterStats["tetsOut"].set_int64(0); + m_counterStats["cellsIn"].set(axom::IndexType {0}); + m_counterStats["cellsOn"].set(axom::IndexType {0}); + m_counterStats["cellsOut"].set(axom::IndexType {0}); + m_counterStats["tetsIn"].set(axom::IndexType {0}); + m_counterStats["tetsOn"].set(axom::IndexType {0}); + m_counterStats["tetsOut"].set(axom::IndexType {0}); } void MeshClipper::clip(axom::Array& ovlap) @@ -67,12 +67,17 @@ void MeshClipper::clip(axom::ArrayView ovlap) SLIC_ASSERT(ovlap.size() == m_shapeMesh.getCellCount()); SLIC_ASSERT(ovlap.getAllocatorID() == m_shapeMesh.getAllocatorID()); - auto& cellsInCount = *m_counterStats["cellsIn"].as_int64_ptr(); - auto& cellsOnCount = *m_counterStats["cellsOn"].as_int64_ptr(); - auto& cellsOutCount = *m_counterStats["cellsOut"].as_int64_ptr(); - auto& tetsInCount = *m_counterStats["tetsIn"].as_int64_ptr(); - auto& tetsOnCount = *m_counterStats["tetsOn"].as_int64_ptr(); - auto& tetsOutCount = *m_counterStats["tetsOut"].as_int64_ptr(); + auto getIndexTypeReference = [](conduit::Node& n) -> axom::IndexType& { + axom::IndexType* ptr = n.value(); + return *ptr; + }; + + auto& cellsInCount = getIndexTypeReference(m_counterStats["cellsIn"]); + auto& cellsOnCount = getIndexTypeReference(m_counterStats["cellsOn"]); + auto& cellsOutCount = getIndexTypeReference(m_counterStats["cellsOut"]); + auto& tetsInCount = getIndexTypeReference(m_counterStats["tetsIn"]); + auto& tetsOnCount = getIndexTypeReference(m_counterStats["tetsOn"]); + auto& tetsOutCount = getIndexTypeReference(m_counterStats["tetsOut"]); // Try to label cells as inside, outside or on shape boundary axom::Array cellLabels; @@ -260,13 +265,16 @@ void MeshClipper::accumulateClippingStats(conduit::Node& curStats, const conduit "MeshClipper statistic must be integer" " (at least until a need for floats arises)."); auto& currentStat = curStats[newStat.name()]; + const axom::IndexType newStatValue = newStat.value(); if(currentStat.dtype().is_empty()) { - currentStat.set_int64(newStat.as_int64()); + currentStat.set(newStatValue); } else { - *currentStat.as_int64_ptr() += newStat.as_int64(); + axom::IndexType currentStatValue = currentStat.value(); + currentStatValue += newStatValue; + currentStat.set(currentStatValue); } } } @@ -284,19 +292,20 @@ conduit::Node MeshClipper::getGlobalClippingStats() const #if defined(AXOM_USE_MPI) // Do sum and max reductions. - axom::Array sums(0, sumNode.number_of_children()); + axom::Array sums(0, sumNode.number_of_children()); for(int i = 0; i < sumNode.number_of_children(); ++i) { - sums.push_back(locNode.child(i).as_int64()); + const axom::IndexType value = locNode.child(i).value(); + sums.push_back(value); } - axom::Array maxs(sums); + axom::Array maxs(sums); globalReduce(maxs, MPI_MAX); globalReduce(sums, MPI_SUM); for(int i = 0; i < sumNode.number_of_children(); ++i) { - *maxNode.child(i).as_int64_ptr() = maxs[i]; - *sumNode.child(i).as_int64_ptr() = sums[i]; + maxNode.child(i).set(maxs[i]); + sumNode.child(i).set(sums[i]); } #endif diff --git a/src/axom/quest/MeshClipper.hpp b/src/axom/quest/MeshClipper.hpp index 48645ada80..e1c68851f0 100644 --- a/src/axom/quest/MeshClipper.hpp +++ b/src/axom/quest/MeshClipper.hpp @@ -215,9 +215,9 @@ class MeshClipper //!@brief Count the number of labels of each type. virtual void getLabelCounts(axom::ArrayView labels, - std::int64_t& inCount, - std::int64_t& onCount, - std::int64_t& outCount) = 0; + axom::IndexType& inCount, + axom::IndexType& onCount, + axom::IndexType& outCount) = 0; ShapeMesh& getShapeMesh() { return m_myClipper.m_shapeMesh; } @@ -263,9 +263,9 @@ class MeshClipper //!@name Convenience methods //!@brief Count the number of labels of each type. void getLabelCounts(const axom::Array& labels, - std::int64_t& inCount, - std::int64_t& onCount, - std::int64_t& outCount) + axom::IndexType& inCount, + axom::IndexType& onCount, + axom::IndexType& outCount) { m_impl->getLabelCounts(labels, inCount, onCount, outCount); } diff --git a/src/axom/quest/detail/clipping/HexClipper.cpp b/src/axom/quest/detail/clipping/HexClipper.cpp index 8afd9e9ce3..abc0b9cf00 100644 --- a/src/axom/quest/detail/clipping/HexClipper.cpp +++ b/src/axom/quest/detail/clipping/HexClipper.cpp @@ -206,7 +206,7 @@ AXOM_HOST_DEVICE inline MeshClipperStrategy::LabelType HexClipper::polyhedronToL const BoundingBox3DType& vertsBb, const BoundingBox3DType& hexBb, const axom::ArrayView& hexTets, - const axom::StackArray& surfaceTriangles) const + const axom::StackArray& surfaceTriangles) { /* If vertsBb and hexBb don't intersect, nothing intersects. diff --git a/src/axom/quest/detail/clipping/HexClipper.hpp b/src/axom/quest/detail/clipping/HexClipper.hpp index d64bee91ca..8465426694 100644 --- a/src/axom/quest/detail/clipping/HexClipper.hpp +++ b/src/axom/quest/detail/clipping/HexClipper.hpp @@ -101,12 +101,12 @@ class HexClipper : public MeshClipperStrategy * error and the way we use it doesn't lead to real errors. */ template - AXOM_HOST_DEVICE inline LabelType polyhedronToLabel( + AXOM_HOST_DEVICE static inline LabelType polyhedronToLabel( const Polyhedron& verts, const BoundingBox3DType& vertsBb, const BoundingBox3DType& hexBb, const axom::ArrayView& hexTets, - const axom::StackArray& surfaceTriangles) const; + const axom::StackArray& surfaceTriangles); void extractClipperInfo(); diff --git a/src/axom/quest/detail/clipping/MeshClipperImpl.hpp b/src/axom/quest/detail/clipping/MeshClipperImpl.hpp index 69f366494a..242258fa03 100644 --- a/src/axom/quest/detail/clipping/MeshClipperImpl.hpp +++ b/src/axom/quest/detail/clipping/MeshClipperImpl.hpp @@ -9,15 +9,10 @@ #include "axom/config.hpp" -#ifndef AXOM_USE_RAJA - #error "quest::MeshClipper requires RAJA." -#endif - #include "axom/quest/MeshClipperStrategy.hpp" #include "axom/quest/MeshClipper.hpp" #include "axom/spin/BVH.hpp" #include "axom/primal/geometry/CoordinateTransformer.hpp" -#include "RAJA/RAJA.hpp" namespace axom { @@ -137,7 +132,6 @@ class MeshClipperImpl : public MeshClipper::Impl * the same index more than once. Write conflicts are thus avoided. * Thanks to Jason Burmark for recommending this approach. */ - using ScanPolicy = typename axom::execution_space::loop_policy; const axom::IndexType labelCount = labels.size(); @@ -156,8 +150,7 @@ class MeshClipperImpl : public MeshClipper::Impl onCountReduce += isOn; }); - RAJA::inclusive_scan_inplace(RAJA::make_span(tmpLabels.data(), tmpLabels.size()), - RAJA::operators::plus {}); + axom::inclusive_scan_inplace(tmpLabelsView); // Space for output index list axom::IndexType onCount = onCountReduce.get(); @@ -212,14 +205,14 @@ class MeshClipperImpl : public MeshClipper::Impl void copyTo(conduit::Node& stats) { // Place clip counts in statistics container. - std::int64_t clipsInCount = inSum.get(); - std::int64_t clipsOnCount = onSum.get(); - std::int64_t clipsOutCount = outSum.get(); - std::int64_t clipsMissCount = missSum.get(); - stats["clipsIn"].set_int64(clipsInCount); - stats["clipsOn"].set_int64(clipsOnCount); - stats["clipsOut"].set_int64(clipsOutCount); - stats["clipsMiss"].set_int64(clipsMissCount); + IndexType clipsInCount = inSum.get(); + IndexType clipsOnCount = onSum.get(); + IndexType clipsOutCount = outSum.get(); + IndexType clipsMissCount = missSum.get(); + stats["clipsIn"].set(clipsInCount); + stats["clipsOn"].set(clipsOnCount); + stats["clipsOut"].set(clipsOutCount); + stats["clipsMiss"].set(clipsMissCount); stats["clipsSum"] = clipsInCount + clipsOnCount + clipsOutCount; } }; @@ -490,7 +483,7 @@ class MeshClipperImpl : public MeshClipper::Impl AXOM_ANNOTATE_END("MeshClipper:clipLoop"); clipStats.copyTo(statistics); - statistics["clipsCandidates"].set_int64(candidates.size()); + statistics["clipsCandidates"].set(static_cast(candidates.size())); } // end of computeClipVolumes3DTets() function /*! @@ -621,7 +614,6 @@ class MeshClipperImpl : public MeshClipper::Impl const ClippingStats& clipStats, int screenLevel) { - using ATOMIC_POL = typename axom::execution_space::atomic_policy; constexpr bool tryFixOrientation = false; if(screenLevel >= 3) { @@ -634,7 +626,7 @@ class MeshClipperImpl : public MeshClipper::Impl if(geomLabel == LabelType::LABEL_IN) { auto contribVol = geomPieceVolume(geomPiece); - RAJA::atomicAdd(overlapVolume, contribVol); + axom::atomicAdd(overlapVolume, contribVol); clipStats.inSum += 1; return geomLabel; } @@ -647,7 +639,7 @@ class MeshClipperImpl : public MeshClipper::Impl // Poly is valid auto contribVol = poly.volume(); SLIC_ASSERT(contribVol >= 0); - RAJA::atomicAdd(overlapVolume, contribVol); + axom::atomicAdd(overlapVolume, contribVol); } else { @@ -900,18 +892,16 @@ class MeshClipperImpl : public MeshClipper::Impl } void getLabelCounts(axom::ArrayView labels, - std::int64_t& inCount, - std::int64_t& onCount, - std::int64_t& outCount) override + IndexType& inCount, + IndexType& onCount, + IndexType& outCount) override { AXOM_ANNOTATE_SCOPE("MeshClipper::getLabelCounts"); - using ReducePolicy = typename axom::execution_space::reduce_policy; - using LoopPolicy = typename execution_space::loop_policy; - RAJA::ReduceSum inSum(0); - RAJA::ReduceSum onSum(0); - RAJA::ReduceSum outSum(0); - RAJA::forall( - RAJA::RangeSegment(0, labels.size()), + axom::ReduceSum inSum(0); + axom::ReduceSum onSum(0); + axom::ReduceSum outSum(0); + axom::for_all( + labels.size(), AXOM_LAMBDA(axom::IndexType cellId) { const auto& label = labels[cellId]; if(label == LabelType::LABEL_OUT) @@ -927,9 +917,9 @@ class MeshClipperImpl : public MeshClipper::Impl onSum += 1; } }); - inCount = static_cast(inSum.get()); - onCount = static_cast(onSum.get()); - outCount = static_cast(outSum.get()); + inCount = inSum.get(); + onCount = onSum.get(); + outCount = outSum.get(); } private: diff --git a/src/axom/quest/detail/clipping/MonotonicZSORClipper.cpp b/src/axom/quest/detail/clipping/MonotonicZSORClipper.cpp index d00f518a91..1e3ff965a5 100644 --- a/src/axom/quest/detail/clipping/MonotonicZSORClipper.cpp +++ b/src/axom/quest/detail/clipping/MonotonicZSORClipper.cpp @@ -375,11 +375,9 @@ void MonotonicZSORClipper::computeCurveBoxes(quest::experimental::ShapeMesh& sha axom::ArrayView cellLengths = shapeMesh.getCellLengths(); - using ReducePolicy = typename axom::execution_space::reduce_policy; - using LoopPolicy = typename execution_space::loop_policy; - RAJA::ReduceSum sumCharLength(0.0); - RAJA::forall( - RAJA::RangeSegment(0, cellCount), + axom::ReduceSum sumCharLength(0.0); + axom::for_all( + cellCount, AXOM_LAMBDA(axom::IndexType cellId) { sumCharLength += cellLengths[cellId]; }); double avgCharLength = sumCharLength.get() / cellCount; @@ -536,12 +534,10 @@ bool MonotonicZSORClipper::getGeometryAsOctsImpl(quest::experimental::ShapeMesh& const auto cellCount = shapeMesh.getCellCount(); // Compute an average characteristic length for the mesh cells. - using ReducePolicy = typename axom::execution_space::reduce_policy; - using LoopPolicy = typename execution_space::loop_policy; axom::ArrayView cellVolumes = shapeMesh.getCellVolumes(); - RAJA::ReduceSum sumVolume(0.0); - RAJA::forall( - RAJA::RangeSegment(0, cellCount), + axom::ReduceSum sumVolume(0.0); + axom::for_all( + cellCount, AXOM_LAMBDA(axom::IndexType cellId) { sumVolume += cellVolumes[cellId]; }); double avgVolume = sumVolume.get() / cellCount; double avgCharLength = pow(avgVolume, 1. / 3); diff --git a/src/axom/quest/detail/clipping/MonotonicZSORClipper.hpp b/src/axom/quest/detail/clipping/MonotonicZSORClipper.hpp index a6bbc1b1eb..a0e5b93306 100644 --- a/src/axom/quest/detail/clipping/MonotonicZSORClipper.hpp +++ b/src/axom/quest/detail/clipping/MonotonicZSORClipper.hpp @@ -184,9 +184,9 @@ class MonotonicZSORClipper : public MeshClipperStrategy * @tparam PolyhedronType Either TetrahedronType or HexahedronType. */ template - AXOM_HOST_DEVICE BoundingBox2DType estimateBoundingBoxInRz(const PolyhedronType& vertices); + AXOM_HOST_DEVICE static BoundingBox2DType estimateBoundingBoxInRz(const PolyhedronType& vertices); - AXOM_HOST_DEVICE inline MeshClipperStrategy::LabelType rzBbToLabel( + AXOM_HOST_DEVICE static inline MeshClipperStrategy::LabelType rzBbToLabel( const BoundingBox2DType& bbInRz, const axom::ArrayView& bbOn, const axom::ArrayView& bbUnder); diff --git a/src/axom/quest/detail/clipping/Plane3DClipper.cpp b/src/axom/quest/detail/clipping/Plane3DClipper.cpp index 1b52dedb90..6d93ea9cb4 100644 --- a/src/axom/quest/detail/clipping/Plane3DClipper.cpp +++ b/src/axom/quest/detail/clipping/Plane3DClipper.cpp @@ -368,7 +368,6 @@ void Plane3DClipper::specializedClipTetsImpl(quest::experimental::ShapeMesh& sha conduit::Node& statistics) { constexpr double EPS = 1e-10; - using ATOMIC_POL = typename axom::execution_space::atomic_policy; auto meshTets = shapeMesh.getCellsAsTets(); IndexType tetCount = tetIds.size(); @@ -382,7 +381,7 @@ void Plane3DClipper::specializedClipTetsImpl(quest::experimental::ShapeMesh& sha const auto& tet = meshTets[tetId]; primal::Polyhedron overlap = primal::clip(tet, plane, EPS); double vol = overlap.volume(); - RAJA::atomicAdd(ovlap.data() + cellId, vol); + axom::atomicAdd(ovlap.data() + cellId, vol); }); // Because the tet screening is perfect, all tets in tetIds are on the plane. diff --git a/src/axom/quest/detail/clipping/SphereClipper.cpp b/src/axom/quest/detail/clipping/SphereClipper.cpp index a788848692..9c50c6da04 100644 --- a/src/axom/quest/detail/clipping/SphereClipper.cpp +++ b/src/axom/quest/detail/clipping/SphereClipper.cpp @@ -177,7 +177,7 @@ void SphereClipper::labelTetsInOutImpl(quest::experimental::ShapeMesh& shapeMesh template AXOM_HOST_DEVICE inline MeshClipperStrategy::LabelType SphereClipper::polyhedronToLabel( const Polyhedron& verts, - const SphereType& sphere) const + const SphereType& sphere) { /* If bounding box of polyhedron is more than the radius distance diff --git a/src/axom/quest/detail/clipping/SphereClipper.hpp b/src/axom/quest/detail/clipping/SphereClipper.hpp index 64e8e75853..3b96391fb2 100644 --- a/src/axom/quest/detail/clipping/SphereClipper.hpp +++ b/src/axom/quest/detail/clipping/SphereClipper.hpp @@ -83,8 +83,9 @@ class SphereClipper : public MeshClipperStrategy //!@brief Compute LabelType for a polyhedron (hex or tet in our case). template - AXOM_HOST_DEVICE inline MeshClipperStrategy::LabelType polyhedronToLabel(const Polyhedron& verts, - const SphereType& sphere) const; + AXOM_HOST_DEVICE static inline MeshClipperStrategy::LabelType polyhedronToLabel( + const Polyhedron& verts, + const SphereType& sphere); void extractClipperInfo(); diff --git a/src/axom/quest/detail/clipping/TetMeshClipper.cpp b/src/axom/quest/detail/clipping/TetMeshClipper.cpp index 834ba31cd6..9f241dff4a 100644 --- a/src/axom/quest/detail/clipping/TetMeshClipper.cpp +++ b/src/axom/quest/detail/clipping/TetMeshClipper.cpp @@ -656,10 +656,102 @@ void TetMeshClipper::extractClipperInfo() SLIC_ERROR_IF(isMultiDomain, "TetMeshClipper does not support multi-domain tet meshes yet."); SLIC_ASSERT(conduit::blueprint::mesh::topology::dims(topoNode) == 3); + SLIC_ASSERT(topoNode.fetch_existing("elements/shape").as_string() == "tet"); m_tetCount = conduit::blueprint::mesh::topology::length(topoNode); m_coordsetName = topoNode.fetch_existing("coordset").as_string(); + + bool fixOrientation = false; + if(m_info.has_child("fixOrientation")) + { + fixOrientation = bool(m_info.fetch_existing("fixOrientation").as_int()); + } + +#if defined(AXOM_RUNTIME_POLICY_USE_OPENMP) + using HOST_EXEC = axom::OMP_EXEC; +#else + using HOST_EXEC = axom::SEQ_EXEC; +#endif + auto& connNode = topoNode.fetch_existing("elements/connectivity"); + if(connNode.dtype().id() != bump::utilities::cpp2conduit::id) + { + // Change connectivity index type to IndexType. + const auto srcIndexId = connNode.dtype().id(); + const IndexType connLen = connNode.dtype().number_of_elements(); + conduit::DataType dstConnType(axom::bump::utilities::cpp2conduit::id, connLen); + conduit::Node tmpConnNode(dstConnType); + IndexType* newPtr = static_cast(tmpConnNode.data_ptr()); + + if(connNode.dtype().id() == bump::utilities::cpp2conduit::id) + { + auto curPtr = connNode.as_int32_ptr(); + axom::for_all(connLen, AXOM_LAMBDA(IndexType i) { newPtr[i] = curPtr[i]; }); + } + else if(connNode.dtype().id() == bump::utilities::cpp2conduit::id) + { + auto curPtr = connNode.as_int64_ptr(); + axom::for_all(connLen, AXOM_LAMBDA(IndexType i) { newPtr[i] = curPtr[i]; }); + } + else + { + SLIC_ERROR(axom::fmt::format("Unrecognized connectivity index type with conduit type id {}", + srcIndexId)); + } + connNode.swap(tmpConnNode); + } + + auto& coordSet = m_tetMesh.fetch_existing("coordsets").fetch_existing(m_coordsetName); + checkTetOrientations(connNode, coordSet, fixOrientation); +} + +template +void TetMeshClipper::checkTetOrientations(conduit::Node& connNode, + const conduit::Node& coordSet, + bool fixOrientation) +{ + const IndexType tetCount = connNode.dtype().number_of_elements() / 4; + axom::ArrayView connArray(static_cast(connNode.data_ptr()), + axom::StackArray {tetCount, 4}); + + const IndexType pointCount = coordSet.fetch_existing("values/x").dtype().number_of_elements(); + axom::ArrayView x(coordSet.fetch_existing("values/x").as_double_ptr(), pointCount); + axom::ArrayView y(coordSet.fetch_existing("values/y").as_double_ptr(), pointCount); + axom::ArrayView z(coordSet.fetch_existing("values/z").as_double_ptr(), pointCount); + + constexpr double eps = 1e-12; + axom::for_all( + tetCount, + AXOM_LAMBDA(IndexType iTet) { + Point3DType verts[4]; + for(int vi = 0; vi < 4; ++vi) + { + int iPoint = connArray(iTet, vi); + verts[vi] = Point3DType {axom::NumericArray {x[iPoint], y[iPoint], z[iPoint]}}; + } + + TetrahedronType tet(verts[0], verts[1], verts[2], verts[3]); + const auto signedVol = tet.signedVolume(); + if(signedVol < -eps) + { + if(fixOrientation) + { + std::swap(connArray(iTet, 2), connArray(iTet, 3)); + } + else + { +#if defined(AXOM_DEVICE_CODE) + SLIC_ASSERT(!(signedVol < -eps)); +#else + SLIC_ERROR(axom::fmt::format( + "TetMeshClipper: input tet[{}] is inverted, with volume {}. Please fix or add " + "'fixOrientation: 1' to the input klee::Geometry's hierarchical data.", + iTet, + signedVol)); +#endif + } + } + }); } bool TetMeshClipper::isValidTetMesh(const conduit::Node& tetMesh, std::string& whyBad) const diff --git a/src/axom/quest/detail/clipping/TetMeshClipper.hpp b/src/axom/quest/detail/clipping/TetMeshClipper.hpp index 520863d629..a901930054 100644 --- a/src/axom/quest/detail/clipping/TetMeshClipper.hpp +++ b/src/axom/quest/detail/clipping/TetMeshClipper.hpp @@ -113,6 +113,17 @@ class TetMeshClipper : public MeshClipperStrategy // Extract clipper info from MeshClipperStrategy::m_info. void extractClipperInfo(); + /*! + * @brief Check tet orientations, and possibly fix bad ones. + * + * If fixOrientation is true, fix inverted tets by swapping their + * last two vertex indices. + */ + template + void checkTetOrientations(conduit::Node& connNode, + const conduit::Node& coordSet, + bool fixOrientation); + // Check validity of tetMesh for our purposes. bool isValidTetMesh(const conduit::Node& tetMesh, std::string& whyBad) const; diff --git a/src/axom/quest/detail/shaping/PrimitiveSampler.hpp b/src/axom/quest/detail/shaping/PrimitiveSampler.hpp index aa9ac5ff33..9894800051 100644 --- a/src/axom/quest/detail/shaping/PrimitiveSampler.hpp +++ b/src/axom/quest/detail/shaping/PrimitiveSampler.hpp @@ -135,11 +135,9 @@ class PrimitiveSampler SLIC_INFO_ROOT("Mesh bounding box: " << m_bbox); -#if defined(AXOM_USE_RAJA) // Print out the total volume of all the tetrahedra auto prim_view = m_primitives.view(); - using REDUCE_POL = typename axom::execution_space::reduce_policy; - RAJA::ReduceSum total_tet_vol(0.0); + axom::ReduceSum total_tet_vol(0.0); axom::for_all( num_cells, AXOM_LAMBDA(axom::IndexType i) { total_tet_vol += prim_view[i].volume(); }); @@ -147,7 +145,6 @@ class PrimitiveSampler SLIC_INFO_ROOT(axom::fmt::format(axom::utilities::locale(), "Total volume of all generated tetrahedra is {:.2Lf}", total_tet_vol.get())); -#endif //defined(AXOM_USE_RAJA) } void initSpatialIndex() diff --git a/src/axom/quest/examples/CMakeLists.txt b/src/axom/quest/examples/CMakeLists.txt index 3d8eeeeee1..fd2215ee43 100644 --- a/src/axom/quest/examples/CMakeLists.txt +++ b/src/axom/quest/examples/CMakeLists.txt @@ -651,8 +651,8 @@ endif() if( MFEM_FOUND) axom_add_executable( - NAME quest_winding_number_ex - SOURCES quest_winding_number.cpp + NAME quest_winding_number_2d_ex + SOURCES quest_winding_number_2d.cpp OUTPUT_DIR ${EXAMPLE_OUTPUT_DIRECTORY} DEPENDS_ON axom mfem cli11 fmt FOLDER axom/quest/examples @@ -669,14 +669,60 @@ if(MFEM_FOUND AND OPENCASCADE_FOUND) ) if(AXOM_ENABLE_TESTS AND AXOM_DATA_DIR) - axom_add_test( - NAME quest_winding_number_3d_tet_slice - COMMAND quest_winding_number_3d_ex - --input ${quest_data_dir}/step/tet.step - --output-prefix wn3d_tet_slice - query_mesh --min -0.5 -0.5 --max 0.5 0.5 --res 3 3 --slice-z 0.0 --order 1) - set_tests_properties(quest_winding_number_3d_tet_slice PROPERTIES - PASS_REGULAR_EXPRESSION "4 patches .* 12 trimming curves") + # 3D query regression-style runs over several STEP models. + # Keep query grids small enough that Debug builds run quickly. + # These tests validate that we produce stable summary stats for the winding/inout fields. + set(_wn3d_step_models connector sliced_cylinder teardrop tet boxed_sphere) + foreach(_model ${_wn3d_step_models}) + # Keep float comparisons fairly strict: match several significant digits in scientific notation. + # NOTE: CTest treats PASS_REGULAR_EXPRESSION lists as "any-of", so we must use a + # single regex string (per model) that matches the INOUT_STATS. + set(_res_i 10) + set(_res_j 10) + set(_res_k 10) + set(_pass_regex "INOUT_STATS:.*pos_dofs=.*neg_dofs=") + if(_model STREQUAL "connector") + set(_res_i 5) + set(_res_j 5) + set(_res_k 5) + string(CONCAT _pass_regex + "INOUT_STATS:.*" + "pos_dofs=14.*" + "neg_dofs=0") + elseif(_model STREQUAL "sliced_cylinder") + string(CONCAT _pass_regex + "INOUT_STATS:.*" + "pos_dofs=445.*" + "neg_dofs=0") + elseif(_model STREQUAL "teardrop") + string(CONCAT _pass_regex + "INOUT_STATS:.*" + "pos_dofs=293.*" + "neg_dofs=0") + elseif(_model STREQUAL "tet") + string(CONCAT _pass_regex + "INOUT_STATS:.*" + "pos_dofs=65.*" + "neg_dofs=0") + elseif(_model STREQUAL "boxed_sphere") + string(CONCAT _pass_regex + "INOUT_STATS:.*" + "pos_dofs=473.*" + "neg_dofs=0") + endif() + + set(_testname "quest_winding_number_3d_${_model}_res${_res_i}") + axom_add_test( + NAME ${_testname} + COMMAND quest_winding_number_3d_ex + --input ${quest_data_dir}/step/${_model}.step + --output-prefix wn3d_${_model}_res${_res_i} + --no-vis + --stats + query_mesh --res ${_res_i} ${_res_j} ${_res_k} --order 1) + set_tests_properties(${_testname} PROPERTIES + PASS_REGULAR_EXPRESSION "${_pass_regex}") + endforeach() endif() endif() diff --git a/src/axom/quest/examples/make_shapes.py b/src/axom/quest/examples/make_shapes.py index d01b0f4dc4..b6f8c5a322 100644 --- a/src/axom/quest/examples/make_shapes.py +++ b/src/axom/quest/examples/make_shapes.py @@ -1,65 +1,72 @@ import math + def lerp_point(p0, p1, t): """ Linearly interpolate 2 points. """ - return ((1. - t)*p0[0] + t*p1[0], (1. - t)*p0[1] + t*p1[1]) + return ((1. - t) * p0[0] + t * p1[0], (1. - t) * p0[1] + t * p1[1]) + class mfem: - """ + """ This class represents 1D contours that can be written to MFEM format. """ - def __init__(self): - self.elemCount = 0 - self.vertCount = 0 - self.elemIds = [] - self.points = [] - self.points_ho = [] - - def add_edge2(self, elem, p0, p1): - p2 = lerp_point(p0, p1, 1./3.) - p3 = lerp_point(p0, p1, 2./3.) - self.add_edge4(elem, (p0, p2, p3, p1)) - - def add_edge4(self, elem, p): - self.elemIds.append(elem) - self.points.append(p[0]) - self.points.append(p[3]) - self.points_ho.append(p[2]) - self.points_ho.append(p[1]) - self.elemCount = self.elemCount + 1 - self.vertCount = self.vertCount + 2 - - def write(self, f): - f.write("MFEM NURBS mesh v1.0\ndimension\n1\n\n") - f.write("elements\n") - f.write(f"{self.elemCount}\n") - for i in range(self.elemCount): - f.write(f"{self.elemIds[i]} 1 {2*i} {2*i+1}\n") - f.write("\nboundary\n0\n\n") - f.write(f"edges\n{self.elemCount}\n") - for i in range(self.elemCount): - f.write(f"{i} 0 1\n") - f.write(f"\nvertices\n{self.vertCount}\n\n") - f.write(f"knotvectors\n{self.elemCount}\n") - for i in range(self.elemCount): - f.write("3 4 0 0 0 0 1 1 1 1\n") - f.write("\nweights\n") - for i in range(self.vertCount): - f.write("1 1\n") - f.write("\nFiniteElementSpace\n") - f.write("FiniteElementCollection: NURBS\n") - f.write("VDim: 2\n") - f.write("Ordering: 1\n") - i = 0 - while i < self.vertCount: - f.write(f"{self.points[i][0]} {self.points[i][1]} {self.points[(i+1)][0]} {self.points[(i+1)][1]}\n") - i = i + 2 - i = 0 - while i < self.vertCount: - f.write(f"{self.points_ho[i][0]} {self.points_ho[i][1]} {self.points_ho[(i+1)][0]} {self.points_ho[(i+1)][1]}\n") - i = i + 2 + + def __init__(self): + self.elemCount = 0 + self.vertCount = 0 + self.elemIds = [] + self.points = [] + self.points_ho = [] + + def add_edge2(self, elem, p0, p1): + p2 = lerp_point(p0, p1, 1. / 3.) + p3 = lerp_point(p0, p1, 2. / 3.) + self.add_edge4(elem, (p0, p2, p3, p1)) + + def add_edge4(self, elem, p): + self.elemIds.append(elem) + self.points.append(p[0]) + self.points.append(p[3]) + self.points_ho.append(p[2]) + self.points_ho.append(p[1]) + self.elemCount = self.elemCount + 1 + self.vertCount = self.vertCount + 2 + + def write(self, f): + f.write("MFEM NURBS mesh v1.0\ndimension\n1\n\n") + f.write("elements\n") + f.write(f"{self.elemCount}\n") + for i in range(self.elemCount): + f.write(f"{self.elemIds[i]} 1 {2*i} {2*i+1}\n") + f.write("\nboundary\n0\n\n") + f.write(f"edges\n{self.elemCount}\n") + for i in range(self.elemCount): + f.write(f"{i} 0 1\n") + f.write(f"\nvertices\n{self.vertCount}\n\n") + f.write(f"knotvectors\n{self.elemCount}\n") + for i in range(self.elemCount): + f.write("3 4 0 0 0 0 1 1 1 1\n") + f.write("\nweights\n") + for i in range(self.vertCount): + f.write("1 1\n") + f.write("\nFiniteElementSpace\n") + f.write("FiniteElementCollection: NURBS\n") + f.write("VDim: 2\n") + f.write("Ordering: 1\n") + i = 0 + while i < self.vertCount: + f.write( + f"{self.points[i][0]} {self.points[i][1]} {self.points[(i+1)][0]} {self.points[(i+1)][1]}\n" + ) + i = i + 2 + i = 0 + while i < self.vertCount: + f.write( + f"{self.points_ho[i][0]} {self.points_ho[i][1]} {self.points_ho[(i+1)][0]} {self.points_ho[(i+1)][1]}\n" + ) + i = i + 2 def add_polygon(data, elem, pts): @@ -68,47 +75,41 @@ def add_polygon(data, elem, pts): """ npts = len(pts) if npts < 3: - raise "Not enough points" + raise "Not enough points" else: - for i in range(npts): - nexti = (i + 1) % npts - data.add_edge2(elem, pts[i], pts[nexti]) + for i in range(npts): + nexti = (i + 1) % npts + data.add_edge2(elem, pts[i], pts[nexti]) + -def add_circle(data, elem, origin, radius, reverse = False): +def add_circle(data, elem, origin, radius, reverse=False): """ Add a circle to the MFEM dataset using multiple contours. If reverse is true then the contours will be added in the opposite orientation, indicating that we want to remove the region from the shape. """ + def reverse_points(pts): return (pts[3], pts[2], pts[1], pts[0]) k = 0.5522847498 p0 = (radius * 1., radius * 0.) p1 = (radius * 1., radius * k) - p2 = (radius * k, radius * 1.) + p2 = (radius * k, radius * 1.) p3 = (radius * 0., radius * 1.) - segments = ( # segment 0 - ((origin[0] + p0[0], origin[1] + p0[1]), - (origin[0] + p1[0], origin[1] + p1[1]), - (origin[0] + p2[0], origin[1] + p2[1]), - (origin[0] + p3[0], origin[1] + p3[1])), - # segment 1 - ((origin[0] - p3[0], origin[1] + p3[1]), - (origin[0] - p2[0], origin[1] + p2[1]), - (origin[0] - p1[0], origin[1] + p1[1]), - (origin[0] - p0[0], origin[1] + p0[1])), - # segment 2 - ((origin[0] - p0[0], origin[1] - p0[1]), - (origin[0] - p1[0], origin[1] - p1[1]), - (origin[0] - p2[0], origin[1] - p2[1]), - (origin[0] - p3[0], origin[1] - p3[1])), - # segment 3 - ((origin[0] + p3[0], origin[1] - p3[1]), - (origin[0] + p2[0], origin[1] - p2[1]), - (origin[0] + p1[0], origin[1] - p1[1]), - (origin[0] + p0[0], origin[1] - p0[1]))) + segments = ( # segment 0 + ((origin[0] + p0[0], origin[1] + p0[1]), (origin[0] + p1[0], origin[1] + p1[1]), + (origin[0] + p2[0], origin[1] + p2[1]), (origin[0] + p3[0], origin[1] + p3[1])), + # segment 1 + ((origin[0] - p3[0], origin[1] + p3[1]), (origin[0] - p2[0], origin[1] + p2[1]), + (origin[0] - p1[0], origin[1] + p1[1]), (origin[0] - p0[0], origin[1] + p0[1])), + # segment 2 + ((origin[0] - p0[0], origin[1] - p0[1]), (origin[0] - p1[0], origin[1] - p1[1]), + (origin[0] - p2[0], origin[1] - p2[1]), (origin[0] - p3[0], origin[1] - p3[1])), + # segment 3 + ((origin[0] + p3[0], origin[1] - p3[1]), (origin[0] + p2[0], origin[1] - p2[1]), + (origin[0] + p1[0], origin[1] - p1[1]), (origin[0] + p0[0], origin[1] - p0[1]))) if reverse: data.add_edge4(elem, reverse_points(segments[3])) @@ -121,6 +122,7 @@ def reverse_points(pts): data.add_edge4(elem, segments[2]) data.add_edge4(elem, segments[3]) + def gear(): """ Generate an MFEM shaping dataset that contains multiple contours that are @@ -134,7 +136,7 @@ def gear(): for i in range(n): a = i * (2 * math.pi) / n r = 0.75 - add_circle(m, 1, (r*math.cos(a), r*math.sin(a)), 0.1, reverse=True) + add_circle(m, 1, (r * math.cos(a), r * math.sin(a)), 0.1, reverse=True) # Make some teeth n = 45 for i in range(n): @@ -144,9 +146,9 @@ def gear(): a3 = a + (2 * math.pi) / 90 r1 = 0.99 r2 = 1.1 - p0 = (r1*math.cos(a3), r1*math.sin(a3)) - p1 = (r1*math.cos(a1), r1*math.sin(a1)) - p2 = (r2*math.cos(a2), r2*math.sin(a2)) + p0 = (r1 * math.cos(a3), r1 * math.sin(a3)) + p1 = (r1 * math.cos(a1), r1 * math.sin(a1)) + p2 = (r2 * math.cos(a2), r2 * math.sin(a2)) add_polygon(m, 1, (p0, p1, p2)) with open("gear.mesh", "wt") as f: @@ -162,36 +164,38 @@ def gear(): s.write(f" path: gear.mesh\n") s.close() + def open_polygons(): """ Generate an MFEM shaping dataset that contains open polygons. """ + def single_polygon(data, elem, extents, t): - c0 = (extents[0], extents[2]) - c1 = (extents[1], extents[2]) - c2 = (extents[1], extents[3]) - c3 = (extents[0], extents[3]) - - p0 = lerp_point(c0, c1, 0.5) - p1 = c1 - p2 = c2 - p3 = lerp_point(c2, c3, 0.5) - data.add_edge4(elem, (p0, p1, p2, p3)) - - m = lerp_point(c0, c3, 0.5) - m0 = lerp_point(m, c3, t) - q0 = lerp_point(p3, m0, 0.) - q1 = lerp_point(p3, m0, 1./3.) - q2 = lerp_point(p3, m0, 2./3.) - q3 = lerp_point(p3, m0, 1.) - data.add_edge4(elem, (q0, q1, q2, q3)) - - m1 = lerp_point(m, c0, t) - r0 = lerp_point(m1, p0, 0.) - r1 = lerp_point(m1, p0, 1./3.) - r2 = lerp_point(m1, p0, 2./3.) - r3 = lerp_point(m1, p0, 1.) - data.add_edge4(elem, (r0, r1, r2, r3)) + c0 = (extents[0], extents[2]) + c1 = (extents[1], extents[2]) + c2 = (extents[1], extents[3]) + c3 = (extents[0], extents[3]) + + p0 = lerp_point(c0, c1, 0.5) + p1 = c1 + p2 = c2 + p3 = lerp_point(c2, c3, 0.5) + data.add_edge4(elem, (p0, p1, p2, p3)) + + m = lerp_point(c0, c3, 0.5) + m0 = lerp_point(m, c3, t) + q0 = lerp_point(p3, m0, 0.) + q1 = lerp_point(p3, m0, 1. / 3.) + q2 = lerp_point(p3, m0, 2. / 3.) + q3 = lerp_point(p3, m0, 1.) + data.add_edge4(elem, (q0, q1, q2, q3)) + + m1 = lerp_point(m, c0, t) + r0 = lerp_point(m1, p0, 0.) + r1 = lerp_point(m1, p0, 1. / 3.) + r2 = lerp_point(m1, p0, 2. / 3.) + r3 = lerp_point(m1, p0, 1.) + data.add_edge4(elem, (r0, r1, r2, r3)) s = open("open_polygons.yaml", "wt") s.write("dimensions: 2\n") @@ -200,36 +204,36 @@ def single_polygon(data, elem, extents, t): ext = [-2, 2, -2, 2] n = 4 for j in range(n): - for i in range(n): - idx = j * n + i - t = float(idx) / (n * n - 1) - dx = (ext[1] - ext[0]) / n - dy = (ext[3] - ext[2]) / n - margin = dx * 0.05 - e = (ext[0] + i * dx + margin, - ext[0] + (i+1)*dx - margin, - ext[2] + j * dy + margin, - ext[2] + (j+1)*dy - margin) - - m = mfem() - elem = 1 # All shapes have 1 element - single_polygon(m, elem, e, t) - mat = "open_polygons%02d" % idx - filename = mat + ".mesh" - with open(filename, "wt") as f: - m.write(f) - f.close() - - s.write(f" - name: {mat}\n") - s.write(f" material: poly\n") - s.write(" geometry:\n") - s.write(" format: mfem\n") - s.write(f" path: {filename}\n") + for i in range(n): + idx = j * n + i + t = float(idx) / (n * n - 1) + dx = (ext[1] - ext[0]) / n + dy = (ext[3] - ext[2]) / n + margin = dx * 0.05 + e = (ext[0] + i * dx + margin, ext[0] + (i + 1) * dx - margin, ext[2] + j * dy + margin, + ext[2] + (j + 1) * dy - margin) + + m = mfem() + elem = 1 # All shapes have 1 element + single_polygon(m, elem, e, t) + mat = "open_polygons%02d" % idx + filename = mat + ".mesh" + with open(filename, "wt") as f: + m.write(f) + f.close() + + s.write(f" - name: {mat}\n") + s.write(f" material: poly\n") + s.write(" geometry:\n") + s.write(" format: mfem\n") + s.write(f" path: {filename}\n") s.close() + def main(): gear() open_polygons() + if __name__ == "__main__": main() diff --git a/src/axom/quest/examples/quest_winding_number.cpp b/src/axom/quest/examples/quest_winding_number.cpp deleted file mode 100644 index 428ef0da88..0000000000 --- a/src/axom/quest/examples/quest_winding_number.cpp +++ /dev/null @@ -1,271 +0,0 @@ -// Copyright (c) Lawrence Livermore National Security, LLC and other -// Axom Project Contributors. See top-level LICENSE and COPYRIGHT -// files for dates and other details. -// -// SPDX-License-Identifier: (BSD-3-Clause) - -/*! - * \file quest_winding_number.cpp - * \brief Example that computes the winding number of a grid of points - * against a collection of 2D parametric rational curves. - * Supports MFEM meshes in the cubic positive Bernstein basis or the (rational) - * NURBS basis. - */ - -#include "axom/config.hpp" -#include "axom/core.hpp" -#include "axom/slic.hpp" -#include "axom/primal.hpp" -#include "axom/quest.hpp" -#include "axom/quest/interface/internal/QuestHelpers.hpp" - -#include "axom/CLI11.hpp" -#include "axom/fmt.hpp" - -#include "mfem.hpp" - -namespace primal = axom::primal; -using Point2D = primal::Point; -using NURBSCurve2D = primal::NURBSCurve; -using CurveGWNCache = primal::detail::NURBSCurveGWNCache; -using BoundingBox2D = primal::BoundingBox; - -/// Helper function to set up the mesh and associated winding and inout fields; uses an mfem::DataCollection to hold everything together -void setup_mesh(mfem::DataCollection& dc, - const BoundingBox2D& query_box, - const axom::NumericArray& query_res, - int queryOrder) -{ - AXOM_ANNOTATE_SCOPE("setup_mesh"); - - constexpr int DIM = 2; - - dc.SetOwnData(true); - - mfem::Mesh* query_mesh = - axom::quest::util::make_cartesian_mfem_mesh_2D(query_box, query_res, queryOrder); - dc.SetMesh(query_mesh); - - // Create grid functions for the winding field; will take care of fes and fec memory via MakeOwner() - auto* winding_fec = new mfem::H1_FECollection(queryOrder, DIM); - auto* winding_fes = new mfem::FiniteElementSpace(query_mesh, winding_fec, 1); - mfem::GridFunction* winding = new mfem::GridFunction(winding_fes); - winding->MakeOwner(winding_fec); - - // Create grid functions for the inout field; will take care of fes and fec memory via MakeOwner() - auto* inout_fec = new mfem::H1_FECollection(queryOrder, DIM); - auto* inout_fes = new mfem::FiniteElementSpace(query_mesh, inout_fec, 1); - mfem::GridFunction* inout = new mfem::GridFunction(inout_fes); - inout->MakeOwner(inout_fec); - - dc.RegisterField("winding", winding); - dc.RegisterField("inout", inout); -} - -template -void run_query(mfem::DataCollection& dc, const CurveArray& curves) -{ - AXOM_ANNOTATE_SCOPE("run_query"); - - auto* query_mesh = dc.GetMesh(); - auto& winding = *dc.GetField("winding"); - auto& inout = *dc.GetField("inout"); - - // Utility function to get query point from query index - const auto num_query_points = query_mesh->GetNodalFESpace()->GetNDofs(); - auto query_point = [&query_mesh](int idx) -> Point2D { - Point2D pt; - query_mesh->GetNode(idx, pt.data()); - return pt; - }; - - // Query the winding numbers at each degree of freedom (DoF) of the query mesh. - // The loop below independently checks every curve for each query point. - for(int nidx = 0; nidx < num_query_points; ++nidx) - { - const Point2D q = query_point(nidx); - double wn {}; - for(const auto& c : curves) - { - wn += axom::primal::winding_number(q, c); - } - - winding[nidx] = wn; - inout[nidx] = std::round(wn); - } -} - -int main(int argc, char** argv) -{ - axom::slic::SimpleLogger raii_logger; - - axom::CLI::App app { - "Load mesh containing collection of curves" - " and optionally generate a query mesh of winding numbers."}; - - std::string inputFile; - std::string outputPrefix = {"winding"}; - - bool verbose {false}; - std::string annotationMode {"none"}; - bool memoized {true}; - bool vis {true}; - - // Query mesh parameters - std::vector boxMins; - std::vector boxMaxs; - std::vector boxResolution; - int queryOrder {1}; - - app.add_option("-i,--input", inputFile) - ->description("MFEM mesh containing contours (1D segments)") - ->required() - ->check(axom::CLI::ExistingFile); - - app.add_option("-o,--output-prefix", outputPrefix) - ->description( - "Prefix for output 2D query mesh (in MFEM format) mesh containing " - "winding number calculations") - ->capture_default_str(); - - app.add_flag("-v,--verbose", verbose, "verbose output")->capture_default_str(); - app.add_flag("--memoized,!--no-memoized", memoized, "Cache geometric data during query?") - ->capture_default_str(); - app.add_flag("--vis,!--no-vis", vis, "Should we write out the results for visualization?") - ->capture_default_str(); - -#ifdef AXOM_USE_CALIPER - app.add_option("--caliper", annotationMode) - ->description( - "caliper annotation mode. Valid options include 'none' and 'report'. " - "Use 'help' to see full list.") - ->capture_default_str() - ->check(axom::utilities::ValidCaliperMode); -#endif - - auto* query_mesh_subcommand = - app.add_subcommand("query_mesh")->description("Options for setting up a query mesh")->fallthrough(); - auto* minbb = query_mesh_subcommand->add_option("--min", boxMins) - ->description("Min bounds for box mesh (x,y)") - ->expected(2); - auto* maxbb = query_mesh_subcommand->add_option("--max", boxMaxs) - ->description("Max bounds for box mesh (x,y)") - ->expected(2); - query_mesh_subcommand->add_option("--res", boxResolution) - ->description("Resolution of the box mesh (i,j)") - ->expected(2) - ->required(); - query_mesh_subcommand->add_option("--order", queryOrder) - ->description("polynomial order of the query mesh") - ->check(axom::CLI::PositiveNumber); - - // add some requirements -- if user provides minbb or maxbb, we need both - minbb->needs(maxbb); - maxbb->needs(minbb); - - CLI11_PARSE(app, argc, argv); - - axom::utilities::raii::AnnotationsWrapper annotation_raii_wrapper(annotationMode); - AXOM_ANNOTATE_SCOPE("winding number example"); - - axom::Array curves; - { - AXOM_ANNOTATE_SCOPE("read_mesh"); - - axom::quest::MFEMReader mfem_reader; - mfem_reader.setFileName(inputFile); - - const int ret = mfem_reader.read(curves); - if(ret != axom::quest::MFEMReader::READ_SUCCESS) - { - return 1; - } - } - // Extract the curves and compute their bounding boxes along the way - BoundingBox2D bbox; - axom::Array memoized_curves; - { - AXOM_ANNOTATE_SCOPE("preprocessing"); - - axom::utilities::Timer preproc_timer(true); - int count {0}; - for(const auto& cur : curves) - { - SLIC_INFO_IF(verbose, axom::fmt::format("Element {}: {}", count++, cur)); - - bbox.addBox(cur.boundingBox()); - - // Add curves to GWN Cache objects that dynamically store intermediate - // curve subdivisions to be reused across query points - if(memoized) - { - memoized_curves.emplace_back(CurveGWNCache(cur)); - } - } - preproc_timer.stop(); - - SLIC_INFO(axom::fmt::format(axom::utilities::locale(), - "Preprocessing curves took {:.4Lf} seconds", - preproc_timer.elapsed())); - AXOM_ANNOTATE_METADATA("preprocessing_time", preproc_timer.elapsed(), ""); - } - SLIC_INFO(axom::fmt::format("Curve mesh bounding box: {}", bbox)); - - // Early return if user didn't set up a query mesh - if(boxResolution.empty()) - { - return 0; - } - - // Generate a Cartesian (high order) mesh for the query points - const bool has_query_box = boxMins.size() > 0; - const auto query_res = axom::NumericArray(boxResolution.data()); - const auto query_box = has_query_box - ? BoundingBox2D(Point2D(boxMins.data()), Point2D(boxMaxs.data())) - : BoundingBox2D(bbox.getMin(), bbox.getMax()).scale(1.05); - - mfem::DataCollection dc("winding_query"); - setup_mesh(dc, query_box, query_res, queryOrder); - - // Run the query (optionally, with memoization) - { - axom::utilities::Timer query_timer(true); - if(memoized) - { - run_query(dc, memoized_curves); - } - else - { - run_query(dc, curves); - } - query_timer.stop(); - - const int ndofs = dc.GetField("winding")->FESpace()->GetNDofs(); - SLIC_INFO(axom::fmt::format(axom::utilities::locale(), - "Querying {:L} samples in winding number field took {:.3Lf} seconds" - " (@ {:.0Lf} queries per second; {:.5Lf} ms per query)", - ndofs, - query_timer.elapsed(), - ndofs / query_timer.elapsed(), - query_timer.elapsedTimeInMilliSec() / ndofs)); - AXOM_ANNOTATE_METADATA("query_points", ndofs, ""); - AXOM_ANNOTATE_METADATA("query_time", query_timer.elapsed(), ""); - } - - // Save the query mesh and fields to disk using a format that can be viewed in VisIt - if(vis) - { - AXOM_ANNOTATE_SCOPE("dump_mesh"); - - mfem::VisItDataCollection windingDC(outputPrefix, dc.GetMesh()); - windingDC.RegisterField("winding", dc.GetField("winding")); - windingDC.RegisterField("inout", dc.GetField("inout")); - windingDC.Save(); - - SLIC_INFO(axom::fmt::format("Outputting generated mesh '{}' to '{}'", - windingDC.GetCollectionName(), - axom::utilities::filesystem::getCWD())); - } - - return 0; -} diff --git a/src/axom/quest/examples/quest_winding_number_2d.cpp b/src/axom/quest/examples/quest_winding_number_2d.cpp new file mode 100644 index 0000000000..f6e32b7767 --- /dev/null +++ b/src/axom/quest/examples/quest_winding_number_2d.cpp @@ -0,0 +1,381 @@ +// Copyright (c) Lawrence Livermore National Security, LLC and other +// Axom Project Contributors. See top-level LICENSE and COPYRIGHT +// files for dates and other details. +// +// SPDX-License-Identifier: (BSD-3-Clause) + +/*! + * \file quest_winding_number.cpp + * \brief Example that computes the winding number of a grid of points + * against a collection of 2D parametric rational curves. + * Supports MFEM meshes in the cubic positive Bernstein basis or the (rational) + * NURBS basis. + */ + +#include "axom/config.hpp" +#include "axom/core.hpp" +#include "axom/slic.hpp" +#include "axom/primal.hpp" +#include "axom/spin.hpp" +#include "axom/quest.hpp" +#include "axom/quest/interface/internal/QuestHelpers.hpp" + +#include "axom/CLI11.hpp" +#include "axom/fmt.hpp" + +#include "mfem.hpp" + +#include + +namespace primal = axom::primal; +namespace quest = axom::quest; + +using Point2D = primal::Point; +using BoundingBox2D = primal::BoundingBox; + +using NURBSCurve2D = primal::NURBSCurve; + +//------------------------------------------------------------------------------ +// CLI input +//------------------------------------------------------------------------------ + +class Input +{ +public: + std::string inputFile; + std::string outputPrefix = {"winding2d"}; + + bool verbose {false}; + std::string annotationMode {"none"}; + bool memoized {true}; + bool vis {true}; + bool stats {false}; + + const std::array valid_algorithms {"direct", "fast-approximation"}; + std::string algorithm {valid_algorithms[1]}; // fast-approximation + + bool linearize {false}; + int approximation_order {2}; + + bool useUniformLinearization; + int segmentsPerKnotSpan {10}; + double percentError {1.0}; + + // Query mesh parameters + std::vector boxMins; + std::vector boxMaxs; + std::vector boxResolution; + int queryOrder {1}; + + primal::WindingTolerances tol; + + void parse(int argc, char** argv, axom::CLI::App& app) + { + app.add_option("-i,--input", inputFile) + ->description("MFEM mesh containing contours (1D segments)") + ->required() + ->check(axom::CLI::ExistingFile); + + app.add_option("-o,--output-prefix", outputPrefix) + ->description( + "Prefix for output 2D query mesh (in MFEM format) mesh containing " + "winding number calculations") + ->capture_default_str(); + + app.add_flag("-v,--verbose", verbose, "verbose output")->capture_default_str(); + app.add_flag("--memoized,!--no-memoized", memoized, "Cache geometric data during query?") + ->capture_default_str(); + app.add_flag("--vis,!--no-vis", vis, "Should we write out the results for visualization?") + ->capture_default_str(); + app.add_flag("--stats,!--no-stats", stats, "Compute summary stats for query fields?") + ->capture_default_str(); + + // Options for query tolerances + app.add_option("--edge-tol", tol.edge_tol) + ->description("Relative edge tolerance for queries") + ->check(axom::CLI::PositiveNumber) + ->capture_default_str(); + app.add_option("--eps-tol", tol.EPS) + ->description("Additional generic tolerance parameter") + ->check(axom::CLI::PositiveNumber) + ->capture_default_str(); + +#ifdef AXOM_USE_CALIPER + app.add_option("--caliper", annotationMode) + ->description( + "caliper annotation mode. Valid options include 'none' and 'report'. " + "Use 'help' to see full list.") + ->capture_default_str() + ->check(axom::utilities::ValidCaliperMode); +#endif + + // Options for triangulation of the input STEP file + auto* linearize_curves_subcommand = + app.add_subcommand("linearize_curves") + ->description("Options for linearizing NURBS curves. Default is ") + ->fallthrough(); + + auto* nsegments = + linearize_curves_subcommand->add_option("--num-segments", segmentsPerKnotSpan) + ->description( + "Number of segments for each knot span of each input curve for a uniform linearization.") + ->check(axom::CLI::PositiveNumber) + ->capture_default_str(); + auto* perror = + linearize_curves_subcommand->add_option("--percent-error", percentError) + ->description( + "The percent of error that is acceptable to stop refinement during non-uniform " + "linearization.") + ->check(axom::CLI::Range(0.0f, 100.0f)) + ->capture_default_str(); + linearize_curves_subcommand->add_option("--algorithm", algorithm) + ->description( + "Use direct evaluation instead of fast, heirarchical approximation? (significantly " + "slower, slightly more precise)") + ->capture_default_str() + ->check(axom::CLI::IsMember(valid_algorithms)); + linearize_curves_subcommand + ->add_option("--approximation-order", + approximation_order, + "The order of the Taylor expansion (lower is faster, less precise)") + ->expected(0, 2) + ->capture_default_str(); + + auto* query_mesh_subcommand = + app.add_subcommand("query_mesh")->description("Options for setting up a query mesh")->fallthrough(); + auto* minbb = query_mesh_subcommand->add_option("--min", boxMins) + ->description("Min bounds for box mesh (x,y)") + ->expected(2); + auto* maxbb = query_mesh_subcommand->add_option("--max", boxMaxs) + ->description("Max bounds for box mesh (x,y)") + ->expected(2); + query_mesh_subcommand->add_option("--res", boxResolution) + ->description("Resolution of the box mesh (i,j)") + ->expected(2) + ->required(); + query_mesh_subcommand->add_option("--order", queryOrder) + ->description("polynomial order of the query mesh") + ->check(axom::CLI::PositiveNumber); + + // add some requirements -- if user provides minbb or maxbb, we need both + minbb->needs(maxbb); + maxbb->needs(minbb); + + // If a user provides a number of refinements, we can't have a percent error + nsegments->excludes(perror); + useUniformLinearization = nsegments->count() > 0; + + app.parse(argc, argv); + + linearize = app.got_subcommand("linearize_curves"); + } +}; + +using GWNQueryType = std::variant, + axom::quest::PolylineGWN2D<1>, + axom::quest::PolylineGWN2D<2>>; + +GWNQueryType make_gwn_query(bool linearize_curves, int approximation_order) +{ + if(linearize_curves) + { + if(approximation_order == 0) + { + return axom::quest::PolylineGWN2D<0> {}; + } + else if(approximation_order == 1) + { + return axom::quest::PolylineGWN2D<1> {}; + } + else + { + return axom::quest::PolylineGWN2D<2> {}; + } + } + + return axom::quest::DirectGWN2D {}; +} + +int main(int argc, char** argv) +{ + axom::slic::SimpleLogger raii_logger; + + // Parse command line arguments into input + Input input; + axom::CLI::App app { + "Load mesh containing collection of curves" + " and optionally generate a query mesh of winding numbers."}; + + try + { + input.parse(argc, argv, app); + } + catch(const axom::CLI::ParseError& e) + { + return app.exit(e); + } + + axom::utilities::raii::AnnotationsWrapper annotation_raii_wrapper(input.annotationMode); + AXOM_ANNOTATE_SCOPE("winding number example"); + + // Read curves from the MFEM mesh + axom::Array curves; + { + AXOM_ANNOTATE_SCOPE("read_mesh"); + + axom::quest::MFEMReader mfem_reader; + mfem_reader.setFileName(input.inputFile); + + const int ret = mfem_reader.read(curves); + if(ret != axom::quest::MFEMReader::READ_SUCCESS) + { + SLIC_ERROR("Failed to read MFEM file."); + return 1; + } + } + + // Linearize the input curves if asked for + axom::mint::UnstructuredMesh poly_mesh(2, axom::mint::SEGMENT); + if(input.linearize) + { + AXOM_ANNOTATE_SCOPE("linearization"); + + axom::utilities::Timer timer(true); + axom::quest::LinearizeCurves lc; + if(input.useUniformLinearization) + { + lc.getLinearMeshUniform(curves.view(), &poly_mesh, input.segmentsPerKnotSpan); + } + else + { + lc.getLinearMeshNonUniform(curves.view(), &poly_mesh, input.percentError); + } + timer.stop(); + + SLIC_INFO(axom::fmt::format( + axom::utilities::locale(), + "Discretized {} curves with {} segments in each knot span for a total of {:L} segments.", + curves.size(), + input.segmentsPerKnotSpan, + poly_mesh.getNumberOfCells())); + SLIC_INFO( + axom::fmt::format("Preprocessing stage (linearization): {} s", timer.elapsedTimeInSec())); + } + + // Early return if user didn't set up a query mesh + if(input.boxResolution.empty()) + { + return 0; + } + + // Extract the curves and compute their bounding boxes along the way + BoundingBox2D shape_bbox; + for(const auto& cur : curves) + { + shape_bbox.addBox(cur.boundingBox()); + } + SLIC_INFO(axom::fmt::format("Curve mesh bounding box: {}", shape_bbox)); + + // Query grid setup; + // if user did not provide a bounding box, user input bounding box scaled by 10% + mfem::DataCollection dc("winding_query"); + { + // Create the desired winding number query instance + auto wn_query = make_gwn_query(app.got_subcommand("linearize_curves"), input.approximation_order); + + // Generate the query grid and fields + quest::generate_gwn_query_mesh(dc, + shape_bbox, + input.boxMins, + input.boxMaxs, + input.boxResolution, + input.queryOrder); + + // Run the preprocess + std::visit( + [&](auto& wn) { + using T = std::decay_t; + if constexpr(quest::gwn_input_type_v == quest::GWNInputType::Curve) + { + wn.preprocess(curves, input.memoized); + } + else if constexpr(quest::gwn_input_type_v == quest::GWNInputType::Polyline) + { + wn.preprocess(&poly_mesh, input.algorithm == "direct"); + } + }, + wn_query); + + // Run the query + std::visit([&](auto& wn) { wn.query(dc, input.tol); }, wn_query); + } + + // Postprocess query results: norms, ranges, and integral statistics + if(input.stats) + { + AXOM_ANNOTATE_SCOPE("postprocess"); + + auto& winding = *dc.GetField("winding"); + auto& inout = *dc.GetField("inout"); + + const auto winding_stats = axom::quest::compute_field_stats(winding); + const auto inout_stats = axom::quest::compute_field_stats(inout); + const auto inout_integrals = axom::quest::compute_integrals(inout); + + std::int64_t pos_inout_dofs = 0; + std::int64_t neg_inout_dofs = 0; + for(int i = 0; i < inout.Size(); ++i) + { + const double v = inout[i]; + if(v > 0.0) + { + ++pos_inout_dofs; + } + else if(v < 0.0) + { + ++neg_inout_dofs; + } + } + + SLIC_INFO( + axom::fmt::format("WN_STATS: dof_l2={:.6e} dof_linf={:.6e} l2={:.6e} min={:.6e} max={:.6e}", + winding_stats.dof_l2, + winding_stats.dof_linf, + winding_stats.l2, + winding_stats.min, + winding_stats.max)); + + SLIC_INFO(axom::fmt::format( + "INOUT_STATS: dof_l2={:.6e} dof_linf={:.6e} l2={:.6e} min={:.6e} max={:.6e} volume={:.6e} " + "domain_volume={:.6e} vol_frac={:.6e} pos_dofs={} neg_dofs={}", + inout_stats.dof_l2, + inout_stats.dof_linf, + inout_stats.l2, + inout_stats.min, + inout_stats.max, + inout_integrals.integral, + inout_integrals.domain_volume, + (inout_integrals.domain_volume > 0.0 ? inout_integrals.integral / inout_integrals.domain_volume + : 0.0), + pos_inout_dofs, + neg_inout_dofs)); + } + + // Save the query mesh and fields to disk using a format that can be viewed in VisIt + if(input.vis) + { + AXOM_ANNOTATE_SCOPE("dump_mesh"); + + mfem::VisItDataCollection windingDC(input.outputPrefix, dc.GetMesh()); + windingDC.RegisterField("winding", dc.GetField("winding")); + windingDC.RegisterField("inout", dc.GetField("inout")); + windingDC.Save(); + + SLIC_INFO(axom::fmt::format("Outputting generated mesh '{}' to '{}'", + windingDC.GetCollectionName(), + axom::utilities::filesystem::getCWD())); + } + + return 0; +} diff --git a/src/axom/quest/examples/quest_winding_number_3d.cpp b/src/axom/quest/examples/quest_winding_number_3d.cpp index 12f8bacc11..5dda1c53eb 100644 --- a/src/axom/quest/examples/quest_winding_number_3d.cpp +++ b/src/axom/quest/examples/quest_winding_number_3d.cpp @@ -25,97 +25,28 @@ #include "axom/CLI11.hpp" #include "axom/fmt.hpp" +#include "axom/core/utilities/StringUtilities.hpp" + #include "mfem.hpp" +#include + namespace primal = axom::primal; +namespace quest = axom::quest; using Point3D = primal::Point; -using BoundingBox2D = primal::BoundingBox; using BoundingBox3D = primal::BoundingBox; -using NURBSPatch3D = axom::quest::STEPReader::NURBSPatch; -using PatchGWNCache = primal::detail::NURBSPatchGWNCache; +using NURBSPatch3D = quest::STEPReader::NURBSPatch; +using Triangle3D = primal::Triangle; -struct WindingTolerances -{ - double ls_tol {1e-6}; - double quad_tol {1e-6}; - double disk_size {0.01}; - double edge_tol {1e-8}; - double EPS {1e-8}; -}; +//------------------------------------------------------------------------------ +// CLI input +//------------------------------------------------------------------------------ -/// Helper function to set up the mesh and associated winding and inout fields. -/// Uses an mfem::DataCollection to hold everything together. -void setup_mesh(mfem::DataCollection& dc, mfem::Mesh* query_mesh, int queryOrder) +class Input { - AXOM_ANNOTATE_SCOPE("setup_mesh"); - - dc.SetOwnData(true); - dc.SetMesh(query_mesh); - - const int dim = query_mesh->Dimension(); - - // Create grid functions for the winding field; will take care of fes and fec memory via MakeOwner() - auto* winding_fec = new mfem::H1Pos_FECollection(queryOrder, dim); - auto* winding_fes = new mfem::FiniteElementSpace(query_mesh, winding_fec, 1); - mfem::GridFunction* winding = new mfem::GridFunction(winding_fes); - winding->MakeOwner(winding_fec); - - // Create grid functions for the inout field; will take care of fes and fec memory via MakeOwner() - auto* inout_fec = new mfem::H1Pos_FECollection(queryOrder, dim); - auto* inout_fes = new mfem::FiniteElementSpace(query_mesh, inout_fec, 1); - mfem::GridFunction* inout = new mfem::GridFunction(inout_fes); - inout->MakeOwner(inout_fec); - - dc.RegisterField("winding", winding); - dc.RegisterField("inout", inout); -} - -template -void run_query(mfem::DataCollection& dc, - const PatchArrayType& patches, - const WindingTolerances& tol, - const double slice_z = 0.0) -{ - AXOM_ANNOTATE_SCOPE("run_query"); - - auto* query_mesh = dc.GetMesh(); - auto& winding = *dc.GetField("winding"); - auto& inout = *dc.GetField("inout"); - - const auto num_query_points = query_mesh->GetNodalFESpace()->GetNDofs(); - - auto query_point = [&](int idx) -> Point3D { - Point3D pt({0., 0., slice_z}); - query_mesh->GetNode(idx, pt.data()); - return pt; - }; - - for(int nidx = 0; nidx < num_query_points; ++nidx) - { - const Point3D q = query_point(nidx); - double wn {}; - for(const auto& patch : patches) - { - wn += axom::primal::winding_number(q, - patch, - tol.edge_tol, - tol.ls_tol, - tol.quad_tol, - tol.disk_size, - tol.EPS); - } - - winding[nidx] = wn; - inout[nidx] = std::round(wn); - } -} - -int main(int argc, char** argv) -{ - axom::slic::SimpleLogger raii_logger; - +public: std::string inputFile; std::string outputPrefix {"winding3d"}; @@ -124,19 +55,26 @@ int main(int argc, char** argv) bool memoized {true}; bool vis {true}; bool validate {false}; + bool stats {false}; + + const std::array valid_algorithms {"direct", "fast-approximation"}; + std::string algorithm {valid_algorithms[1]}; // fast-approximation + + bool triangulate {false}; + double linear_deflection {0.1}; + double angular_deflection {0.5}; + bool deflection_is_relative {false}; + int approximation_order {2}; std::vector boxMins; std::vector boxMaxs; std::vector boxResolution; int queryOrder {1}; double sliceZ {0.0}; - WindingTolerances tol; - axom::CLI::App app { - "Load a STEP file containing trimmed NURBS patches " - "and optionally generate a query grid of generalized winding numbers."}; + primal::WindingTolerances tol; - // Command line options and validation + void parse(int argc, char** argv, axom::CLI::App& app) { app.add_option("-i,--input", inputFile) ->description("Input STEP file containing a trimmed NURBS BRep") @@ -154,6 +92,43 @@ int main(int argc, char** argv) ->capture_default_str(); app.add_flag("--vis,!--no-vis", vis, "Should we write out the results for visualization?") ->capture_default_str(); + app.add_flag("--stats,!--no-stats", stats, "Compute summary stats for query fields?") + ->capture_default_str(); + + // Options for triangulation of the input STEP file + auto* triangulate_step_subcommand = app.add_subcommand("triangulate_step") + ->description("Options for triangulating NURBS surfaces") + ->fallthrough(); + + triangulate_step_subcommand->add_option("--linear-deflection", linear_deflection) + ->description( + "Maximum allowed deviation between the original geometry and the triangulation.") + ->check(axom::CLI::PositiveNumber) + ->capture_default_str(); + triangulate_step_subcommand->add_option("--angular-deflection", angular_deflection) + ->description( + "Maximum allowed angular deviation (in radians) between normals of adjacent triangles.") + ->check(axom::CLI::PositiveNumber) + ->capture_default_str(); + triangulate_step_subcommand + ->add_flag( + "--is-relative", + deflection_is_relative, + "Is linear deflection in relative to local edge lengths (true) or mesh units (false)") + ->capture_default_str(); + + triangulate_step_subcommand->add_option("--algorithm", algorithm) + ->description( + "Use direct evaluation instead of fast, heirarchical approximation? (significantly " + "slower, slightly more precise)") + ->capture_default_str() + ->check(axom::CLI::IsMember(valid_algorithms)); + triangulate_step_subcommand + ->add_option("--expansion-order", + approximation_order, + "The order of the Taylor expansion (lower is faster, less precise)") + ->expected(0, 2) + ->capture_default_str(); // Options for query tolerances; for now, only expose the line search and quadrature tolerances app.add_option("--ls-tol", tol.ls_tol) @@ -249,148 +224,266 @@ int main(int argc, char** argv) } } }); + + app.parse(argc, argv); + + triangulate = app.got_subcommand("triangulate_step"); + } +}; + +using GWNQueryType = std::variant, + axom::quest::TriangleGWN3D<1>, + axom::quest::TriangleGWN3D<2>>; + +GWNQueryType make_gwn_query(Input input) +{ + if(input.triangulate) + { + if(input.approximation_order == 0) + { + return axom::quest::TriangleGWN3D<0> {}; + } + else if(input.approximation_order == 1) + { + return axom::quest::TriangleGWN3D<1> {}; + } + else + { + return axom::quest::TriangleGWN3D<2> {}; + } } - CLI11_PARSE(app, argc, argv); + return axom::quest::DirectGWN3D {}; +} + +int main(int argc, char** argv) +{ + axom::slic::SimpleLogger raii_logger; + + // Parse command line arguments into input + Input input; + axom::CLI::App app { + "Load a STEP file containing trimmed NURBS patches " + "and optionally generate a query grid of generalized winding numbers."}; - axom::utilities::raii::AnnotationsWrapper annotation_raii_wrapper(annotationMode); + try + { + input.parse(argc, argv, app); + } + catch(const axom::CLI::ParseError& e) + { + return app.exit(e); + } + + axom::utilities::raii::AnnotationsWrapper annotation_raii_wrapper(input.annotationMode); AXOM_ANNOTATE_SCOPE("3D winding number example"); - axom::utilities::Timer step_read_timer(true); - axom::quest::STEPReader step_reader; - step_reader.setFileName(inputFile); - step_reader.setVerbosity(verbose); + // Bounding box for input shape + BoundingBox3D shape_bbox; + + // Declare possible geometry input types + axom::mint::UnstructuredMesh tri_mesh(3, axom::mint::TRIANGLE); + axom::Array patches; + if(axom::utilities::string::endsWith(input.inputFile, ".stl")) { - AXOM_ANNOTATE_SCOPE("read_step"); + AXOM_ANNOTATE_SCOPE("read_stl"); + + axom::quest::STLReader stl_reader; + stl_reader.setFileName(input.inputFile); + + axom::utilities::Timer read_timer(true); + const int ret = stl_reader.read(); - const int ret = step_reader.read(validate); if(ret != 0) { - SLIC_ERROR(axom::fmt::format("Failed to read STEP file '{}'", inputFile)); + SLIC_ERROR(axom::fmt::format("Failed to read STL file '{}'", input.inputFile)); return 1; } - } - const auto& patches = step_reader.getPatchArray(); - step_read_timer.stop(); - SLIC_INFO(step_reader.getBRepStats()); - SLIC_INFO(axom::fmt::format("STEP file units: {}", step_reader.getFileUnits())); - SLIC_INFO(axom::fmt::format(axom::utilities::locale(), - "Loaded {} trimmed NURBS patches in {:.3Lf} seconds", - patches.size(), - step_read_timer.elapsed())); + stl_reader.getMesh(&tri_mesh); + read_timer.stop(); - // Early return if user didn't set up a query mesh - if(boxResolution.empty()) - { - return 0; - } + BoundingBox3D* shape_bbox_ptr = &shape_bbox; + axom::mint::for_all_nodes( + &tri_mesh, + AXOM_LAMBDA(axom::IndexType, double x, double y, double z) { + shape_bbox_ptr->addPoint(Point3D {x, y, z}); + }); - // Preprocessing: Extract the patches and compute their bounding boxes along the way - BoundingBox3D bbox; - axom::Array memoized_patches(0, memoized ? patches.size() : 0); + SLIC_INFO(axom::fmt::format(axom::utilities::locale(), + "Loaded {} triangles in {:.3Lf} seconds", + stl_reader.getNumFaces(), + read_timer.elapsed())); + } + else if(axom::utilities::string::endsWith(input.inputFile, ".step")) { - AXOM_ANNOTATE_SCOPE("preprocessing"); + AXOM_ANNOTATE_SCOPE("read_step"); + + axom::quest::STEPReader step_reader; + step_reader.setFileName(input.inputFile); + step_reader.setVerbosity(input.verbose); + + axom::utilities::Timer read_timer(true); + const int ret = step_reader.read(input.validate); + if(ret != 0) + { + SLIC_ERROR(axom::fmt::format("Failed to read STEP file '{}'", input.inputFile)); + return 1; + } + read_timer.stop(); + + shape_bbox = step_reader.getBRepBoundingBox(); - axom::utilities::Timer preproc_timer(true); - int count {0}; - for(const auto& patch : patches) + int num_trimming_curves = 0; + for(const auto& patch : step_reader.getPatchArray()) { - auto pbox = patch.boundingBox(); - bbox.addBox(pbox); + num_trimming_curves += patch.getNumTrimmingCurves(); + } - SLIC_INFO_IF(verbose, axom::fmt::format("Patch {} bbox: {}", count++, pbox)); + SLIC_INFO(step_reader.getBRepStats()); + SLIC_INFO(axom::fmt::format("STEP file units: {}", step_reader.getFileUnits())); + SLIC_INFO(axom::fmt::format( + axom::utilities::locale(), + "Loaded {} trimmed NURBS patches (with {} trimming curves) in {:.3Lf} seconds", + patches.size(), + num_trimming_curves, + read_timer.elapsed())); - if(memoized) + if(input.triangulate) + { + read_timer.reset(); + read_timer.start(); + AXOM_ANNOTATE_SCOPE("triangulation"); + const int tc = step_reader.getTriangleMesh(&tri_mesh, + input.linear_deflection, + input.angular_deflection, + input.deflection_is_relative, + /* trimmed */ true); + if(tc != 0) { - memoized_patches.emplace_back(PatchGWNCache(patch)); + SLIC_ERROR("Failed to triangulate STEP geometry."); + return 1; } + read_timer.stop(); + + SLIC_INFO( + axom::fmt::format(axom::utilities::locale(), + "Triangulated geometry with deflection {} and angular deflection {}" + " containing {:L} triangles in {:.3Lf} seconds", + input.linear_deflection, + input.angular_deflection, + tri_mesh.getNumberOfCells(), + read_timer.elapsed())); } - preproc_timer.stop(); + else + { + patches = step_reader.getPatchArray(); + } + } + else + { + SLIC_WARNING(axom::fmt::format("Unsupported file type for input {}", input.inputFile)); + } - SLIC_INFO(axom::fmt::format(axom::utilities::locale(), - "Preprocessing patches took {:.3Lf} seconds", - preproc_timer.elapsed())); - AXOM_ANNOTATE_METADATA("preprocessing_time", preproc_timer.elapsed(), ""); + // Early return if user didn't set up a query mesh + if(input.boxResolution.empty()) + { + return 0; } - SLIC_INFO(axom::fmt::format("Patch collection bounding box: {}", bbox)); // Query grid setup; has some dimension-specific types; // if user did not provide a bounding box, user input bounding box scaled by 10% mfem::DataCollection dc("winding_query"); - - const int query_dim = boxResolution.size(); - const bool has_query_box = boxMins.size() > 0; - constexpr double scale_factor = 1.1; - if(query_dim == 2) { - using Point2D = primal::Point; - const auto query_res = axom::NumericArray(boxResolution.data()); - const auto query_box = has_query_box - ? BoundingBox2D(Point2D(boxMins.data()), Point2D(boxMaxs.data())) - : BoundingBox2D(Point2D({bbox.getMin()[0], bbox.getMin()[1]}), - Point2D({bbox.getMax()[0], bbox.getMax()[1]})) - .scale(scale_factor); - - SLIC_INFO( - axom::fmt::format("Query grid resolution {} within bounding box {}", query_res, query_box)); - - mfem::Mesh* query_mesh = - axom::quest::util::make_cartesian_mfem_mesh_2D(query_box, query_res, queryOrder); + // Create the desired winding number query instance + auto wn_query = make_gwn_query(input); + + // Generate the query grid and fields + quest::generate_gwn_query_mesh(dc, + shape_bbox, + input.boxMins, + input.boxMaxs, + input.boxResolution, + input.queryOrder); + + // Run the preprocess + std::visit( + [&](auto& wn) { + using T = std::decay_t; + if constexpr(quest::gwn_input_type_v == quest::GWNInputType::Surface) + { + wn.preprocess(patches, input.memoized); + } + else if constexpr(quest::gwn_input_type_v == quest::GWNInputType::Triangulation) + { + wn.preprocess(&tri_mesh, input.algorithm == "direct"); + } + }, + wn_query); - setup_mesh(dc, query_mesh, queryOrder); - AXOM_ANNOTATE_METADATA("query_dimension", 2, ""); + // Run the query + std::visit([&](auto& wn) { wn.query(dc, input.tol, input.sliceZ); }, wn_query); } - else - { - using Point3D = primal::Point; - const auto query_res = axom::NumericArray(boxResolution.data()); - const auto query_box = has_query_box - ? BoundingBox3D(Point3D(boxMins.data()), Point3D(boxMaxs.data())) - : BoundingBox3D(bbox.getMin(), bbox.getMax()).scale(scale_factor); - SLIC_INFO( - axom::fmt::format("Query grid resolution {} within bounding box {}", query_res, query_box)); + // Postprocess query results: norms, ranges, and integral statistics + if(input.stats) + { + AXOM_ANNOTATE_SCOPE("postprocess"); - mfem::Mesh* query_mesh = - axom::quest::util::make_cartesian_mfem_mesh_3D(query_box, query_res, queryOrder); + auto& winding = *dc.GetField("winding"); + auto& inout = *dc.GetField("inout"); - setup_mesh(dc, query_mesh, queryOrder); - AXOM_ANNOTATE_METADATA("query_dimension", 3, ""); - } + const auto winding_stats = axom::quest::compute_field_stats(winding); + const auto inout_stats = axom::quest::compute_field_stats(inout); + const auto inout_integrals = axom::quest::compute_integrals(inout); - // Run the query - { - axom::utilities::Timer query_timer(true); - if(memoized) - { - run_query(dc, memoized_patches, tol, sliceZ); - } - else + std::int64_t pos_inout_dofs = 0; + std::int64_t neg_inout_dofs = 0; + for(int i = 0; i < inout.Size(); ++i) { - run_query(dc, patches, tol, sliceZ); + const double v = inout[i]; + if(v > 0.0) + { + ++pos_inout_dofs; + } + else if(v < 0.0) + { + ++neg_inout_dofs; + } } - query_timer.stop(); - const int ndofs = dc.GetField("winding")->FESpace()->GetNDofs(); - SLIC_INFO(axom::fmt::format(axom::utilities::locale(), - "Querying {:L} samples in winding number field took {:.3Lf} seconds" - " (@ {:.0Lf} queries per second; {:.2Lf} ms per query)", - ndofs, - query_timer.elapsed(), - ndofs / query_timer.elapsed(), - query_timer.elapsedTimeInMilliSec() / ndofs)); - AXOM_ANNOTATE_METADATA("query_points", ndofs, ""); - AXOM_ANNOTATE_METADATA("query_time", query_timer.elapsed(), ""); + SLIC_INFO( + axom::fmt::format("WN_STATS: dof_l2={:.6e} dof_linf={:.6e} l2={:.6e} min={:.6e} max={:.6e}", + winding_stats.dof_l2, + winding_stats.dof_linf, + winding_stats.l2, + winding_stats.min, + winding_stats.max)); + + SLIC_INFO(axom::fmt::format( + "INOUT_STATS: dof_l2={:.6e} dof_linf={:.6e} l2={:.6e} min={:.6e} max={:.6e} volume={:.6e} " + "domain_volume={:.6e} vol_frac={:.6e} pos_dofs={} neg_dofs={}", + inout_stats.dof_l2, + inout_stats.dof_linf, + inout_stats.l2, + inout_stats.min, + inout_stats.max, + inout_integrals.integral, + inout_integrals.domain_volume, + (inout_integrals.domain_volume > 0.0 ? inout_integrals.integral / inout_integrals.domain_volume + : 0.0), + pos_inout_dofs, + neg_inout_dofs)); } // Save the query mesh and fields to disk using a format that can be viewed in VisIt - if(vis) + if(input.vis) { AXOM_ANNOTATE_SCOPE("dump_mesh"); - mfem::VisItDataCollection windingDC(outputPrefix, dc.GetMesh()); + mfem::VisItDataCollection windingDC(input.outputPrefix, dc.GetMesh()); windingDC.RegisterField("winding", dc.GetField("winding")); windingDC.RegisterField("inout", dc.GetField("inout")); windingDC.Save(); diff --git a/src/axom/quest/interface/setup.py b/src/axom/quest/interface/setup.py index 831eecddf5..ecb6a7a439 100644 --- a/src/axom/quest/interface/setup.py +++ b/src/axom/quest/interface/setup.py @@ -10,18 +10,16 @@ module = Extension( 'quest', - sources=[ - 'python/pyQUESTmodule.cpp' - ], + sources=['python/pyQUESTmodule.cpp'], language='c++', - include_dirs = None, -# libraries = ['tcl83'], -# library_dirs = ['/usr/local/lib'], -# extra_compile_args = [ '-O0', '-g' ], -# extra_link_args = + include_dirs=None, + # libraries = ['tcl83'], + # library_dirs = ['/usr/local/lib'], + # extra_compile_args = [ '-O0', '-g' ], + # extra_link_args = ) setup( name='quest', - ext_modules = [module], + ext_modules=[module], ) diff --git a/src/axom/quest/io/STEPReader.cpp b/src/axom/quest/io/STEPReader.cpp index b8838983e2..3487687156 100644 --- a/src/axom/quest/io/STEPReader.cpp +++ b/src/axom/quest/io/STEPReader.cpp @@ -26,6 +26,7 @@ #include "opencascade/BRepLib.hxx" #include "opencascade/BRepMesh_IncrementalMesh.hxx" #include "opencascade/BRepTools.hxx" +#include "opencascade/BRepBndLib.hxx" #include "opencascade/Geom_BSplineSurface.hxx" #include "opencascade/Geom_RectangularTrimmedSurface.hxx" #include "opencascade/Geom_Surface.hxx" @@ -1520,6 +1521,29 @@ std::string STEPReader::getBRepStats() const return axom::fmt::to_string(out); } +axom::primal::BoundingBox STEPReader::getBRepBoundingBox(bool useTriangulation) const +{ + if(!m_stepProcessor->isLoaded()) + { + SLIC_WARNING("Cannot compute bounding box until calling STEPReader::read()"); + return axom::primal::BoundingBox {}; + } + + const auto shape = m_stepProcessor->getShape(); + + Bnd_Box box; + box.SetVoid(); + + BRepBndLib::Add(shape, box, useTriangulation); + box.SetGap(0.0); + + Standard_Real xmin, ymin, zmin, xmax, ymax, zmax; + box.Get(xmin, ymin, zmin, xmax, ymax, zmax); + + return axom::primal::BoundingBox {axom::primal::Point {xmin, ymin, zmin}, + axom::primal::Point {xmax, ymax, zmax}}; +} + STEPReader::~STEPReader() { if(m_stepProcessor) diff --git a/src/axom/quest/io/STEPReader.hpp b/src/axom/quest/io/STEPReader.hpp index 68353890e1..4570a696b2 100644 --- a/src/axom/quest/io/STEPReader.hpp +++ b/src/axom/quest/io/STEPReader.hpp @@ -66,9 +66,15 @@ class STEPReader PatchArray& getPatchArray() { return m_patches; } const PatchArray& getPatchArray() const { return m_patches; } + /// Get the number of patches in the read file + int numPatches() { return m_patches.size(); } + /// Returns some information about the loaded BRep std::string getBRepStats() const; + /// Returns an AABB for the loaded BRep as evaluated by OpenCascade + axom::primal::BoundingBox getBRepBoundingBox(bool useTriangulation = false) const; + /*! * \brief Generates a triangulated representation of the STEP file as a Mint unstructured triangle mesh. * diff --git a/src/axom/quest/tests/CMakeLists.txt b/src/axom/quest/tests/CMakeLists.txt index 3f5ecaaf09..59bba00c24 100644 --- a/src/axom/quest/tests/CMakeLists.txt +++ b/src/axom/quest/tests/CMakeLists.txt @@ -86,7 +86,7 @@ endif() # Tests that use MFEM when available #------------------------------------------------------------------------------ -if(MFEM_FOUND AND AXOM_ENABLE_SIDRE) +if(MFEM_FOUND) function(add_quest_mfem_test test_name) axom_add_executable( NAME ${test_name} @@ -110,8 +110,15 @@ if(MFEM_FOUND AND AXOM_ENABLE_SIDRE) ) endfunction() - add_quest_mfem_test(quest_point_in_cell_mfem) + if(AXOM_ENABLE_SIDRE) + add_quest_mfem_test(quest_point_in_cell_mfem) + endif() + if(AXOM_DATA_DIR) + add_quest_mfem_test(quest_gwn_methods) + endif() + + if(AXOM_DATA_DIR AND AXOM_ENABLE_SIDRE) add_quest_mfem_test(quest_mfem_reader) endif() endif() diff --git a/src/axom/quest/tests/quest_gwn_methods.cpp b/src/axom/quest/tests/quest_gwn_methods.cpp new file mode 100644 index 0000000000..886594caaf --- /dev/null +++ b/src/axom/quest/tests/quest_gwn_methods.cpp @@ -0,0 +1,345 @@ +// Copyright (c) Lawrence Livermore National Security, LLC and other +// Axom Project Contributors. See top-level LICENSE and COPYRIGHT +// files for dates and other details. +// +// SPDX-License-Identifier: (BSD-3-Clause) + +#include "axom/config.hpp" +#include "axom/core.hpp" +#include "axom/mint.hpp" +#include "axom/slic.hpp" + +#include "axom/quest/LinearizeCurves.hpp" +#include "axom/quest/GWNMethods.hpp" +#include "axom/quest/FastApproximateGWN.hpp" +#include "axom/quest/io/MFEMReader.hpp" +#include "axom/quest/util/mesh_helpers.hpp" + +#include "gtest/gtest.h" + +#include "mfem.hpp" + +#include +#include + +// For use in the 3D test cases +#ifdef AXOM_USE_OPENCASCADE + #include "axom/quest/io/STEPReader.hpp" +#endif + +//------------------------------------------------------------------------------ +std::string pjoin(const std::string &str) { return str; } + +std::string pjoin(const char *str) { return std::string(str); } + +template +std::string pjoin(const std::string &str, Args... args) +{ + return axom::utilities::filesystem::joinPath(str, pjoin(args...)); +} + +template +std::string pjoin(const char *str, Args... args) +{ + return axom::utilities::filesystem::joinPath(std::string(str), pjoin(args...)); +} +//------------------------------------------------------------------------------ + +//------------------------------------------------------------------------------ +TEST(quest_gwn_methods, gwn_moment_data_segment) +{ + using Point2D = axom::primal::Point; + using Moments = axom::quest::GWNMomentData; + + constexpr double EPS = 1e-14; + + // Combine two segments into a cluster and verify raw moments, centroid, and + // expansion coefficients. Values are chosen to make exact expectations. + Moments s1(Point2D {0.0, 0.0}, Point2D {1.0, 0.0}); + Moments s2(Point2D {0.0, 1.0}, Point2D {0.0, 2.0}); + Moments cluster = s1 + s2; + + EXPECT_NEAR(cluster.a, 2.0, EPS); + EXPECT_NEAR(cluster.ap[0], 0.5, EPS); + EXPECT_NEAR(cluster.ap[1], 1.5, EPS); + + const auto center = cluster.getCenter(); + EXPECT_NEAR(center[0], 0.25, EPS); + EXPECT_NEAR(center[1], 0.75, EPS); + + // Raw moments (rm) + EXPECT_NEAR(cluster.rm[0], -1.0, EPS); // dy + EXPECT_NEAR(cluster.rm[1], 1.0, EPS); // dx + EXPECT_NEAR(cluster.rm[2], 0.0, EPS); // 0.5*dy*(x0+x1) + EXPECT_NEAR(cluster.rm[3], 0.5, EPS); // 0.5*(x1^2-x0^2) + EXPECT_NEAR(cluster.rm[4], -1.5, EPS); // 0.5*(y0^2-y1^2) + EXPECT_NEAR(cluster.rm[5], 0.0, EPS); // 0.5*dx*(y0+y1) + EXPECT_NEAR(cluster.rm[6], 0.0, EPS); + EXPECT_NEAR(cluster.rm[7], 0.0, EPS); + EXPECT_NEAR(cluster.rm[8], 0.0, EPS); + EXPECT_NEAR(cluster.rm[9], -7.0 / 3.0, EPS); + EXPECT_NEAR(cluster.rm[10], 1.0 / 3.0, EPS); + EXPECT_NEAR(cluster.rm[11], 0.0, EPS); + EXPECT_NEAR(cluster.rm[12], 0.0, EPS); + EXPECT_NEAR(cluster.rm[13], 0.0, EPS); + + // Expansion coefficients (ec) + EXPECT_NEAR(cluster.ec[0], -1.0, EPS); + EXPECT_NEAR(cluster.ec[1], 1.0, EPS); + EXPECT_NEAR(cluster.ec[2], 0.25, EPS); + EXPECT_NEAR(cluster.ec[3], 0.25, EPS); + EXPECT_NEAR(cluster.ec[4], -0.75, EPS); + EXPECT_NEAR(cluster.ec[5], -0.75, EPS); + EXPECT_NEAR(cluster.ec[6], -1.0 / 32.0, EPS); + EXPECT_NEAR(cluster.ec[7], -3.0 / 32.0, EPS); + EXPECT_NEAR(cluster.ec[8], 3.0 / 32.0, EPS); + EXPECT_NEAR(cluster.ec[9], -121.0 / 96.0, EPS); + EXPECT_NEAR(cluster.ec[10], 25.0 / 96.0, EPS); + EXPECT_NEAR(cluster.ec[11], -3.0 / 32.0, EPS); + EXPECT_NEAR(cluster.ec[12], 27.0 / 32.0, EPS); + EXPECT_NEAR(cluster.ec[13], 9.0 / 32.0, EPS); + + // Verify that cluster raw moments are sum of segment moments + for(int i = 0; i < cluster.rm.size(); ++i) + { + EXPECT_NEAR(s1.rm[i] + s2.rm[i], cluster.rm[i], EPS); + } +} + +//------------------------------------------------------------------------------ +TEST(quest_gwn_methods, gwn_moment_data_triangle) +{ + using Point3D = axom::primal::Point; + using Tri3D = axom::primal::Triangle; + using Moments = axom::quest::GWNMomentData; + + constexpr double EPS = 1e-14; + + // Right triangle in the XY plane. + const Tri3D tri(Point3D {0.0, 0.0, 0.0}, Point3D {1.0, 0.0, 0.0}, Point3D {0.0, 1.0, 0.0}); + const Moments m(tri); + + // Area and centroid accumulation. + EXPECT_NEAR(m.a, 0.5, EPS); + EXPECT_NEAR(m.ap[0], 1.0 / 6.0, EPS); + EXPECT_NEAR(m.ap[1], 1.0 / 6.0, EPS); + EXPECT_NEAR(m.ap[2], 0.0, EPS); + + const auto center = m.getCenter(); + EXPECT_NEAR(center[0], 1.0 / 3.0, EPS); + EXPECT_NEAR(center[1], 1.0 / 3.0, EPS); + EXPECT_NEAR(center[2], 0.0, EPS); + + // Selected raw moments (rm): normal-only and a few higher-order entries. + EXPECT_NEAR(m.rm[0], 0.0, EPS); + EXPECT_NEAR(m.rm[1], 0.0, EPS); + EXPECT_NEAR(m.rm[2], 0.5, EPS); + EXPECT_NEAR(m.rm[5], 1.0 / 6.0, EPS); + EXPECT_NEAR(m.rm[8], 1.0 / 6.0, EPS); + EXPECT_NEAR(m.rm[14], 1.0 / 12.0, EPS); + EXPECT_NEAR(m.rm[17], 1.0 / 24.0, EPS); + EXPECT_NEAR(m.rm[23], 1.0 / 24.0, EPS); + EXPECT_NEAR(m.rm[26], 1.0 / 12.0, EPS); + + // Selected expansion coefficients (ec): first-order terms cancel at centroid. + EXPECT_NEAR(m.ec[0], 0.0, EPS); + EXPECT_NEAR(m.ec[1], 0.0, EPS); + EXPECT_NEAR(m.ec[2], 0.5, EPS); + EXPECT_NEAR(m.ec[5], 0.0, EPS); + EXPECT_NEAR(m.ec[8], 0.0, EPS); + EXPECT_NEAR(m.ec[14], 1.0 / 72.0, EPS); + EXPECT_NEAR(m.ec[17], -1.0 / 144.0, EPS); + EXPECT_NEAR(m.ec[23], -1.0 / 144.0, EPS); + EXPECT_NEAR(m.ec[26], 1.0 / 72.0, EPS); +} + +//------------------------------------------------------------------------------ +TEST(quest_gwn_methods, mfem_mesh_linearization) +{ + using NURBSCurve2D = axom::primal::NURBSCurve; + const std::string fileName = pjoin(AXOM_DATA_DIR, "contours", "svg", "mfem_logo_simp.mesh"); + + // Read the curves from the MFEM mesh + axom::quest::MFEMReader mfem_reader; + mfem_reader.setFileName(fileName); + + axom::Array curves; + const int ret = mfem_reader.read(curves); + if(ret != 0) + { + SLIC_ERROR(axom::fmt::format("Failed to read STEP file '{}'", fileName)); + } + + // Get a linearization of the shape + axom::mint::UnstructuredMesh poly_mesh(2, axom::mint::SEGMENT); + axom::quest::LinearizeCurves lc; + lc.getLinearMeshUniform(curves.view(), &poly_mesh, 10); + + // Get bounding box of the shape + // Extract the curves and compute their bounding boxes along the way + axom::primal::BoundingBox shape_bbox; + for(const auto &cur : curves) + { + shape_bbox.addBox(cur.boundingBox()); + } + + const std::vector resolution {10, 10}; + const int query_order = 1; + + // Generate three query grids and fields + axom::Array dc(0, 3); + std::string names[] = {"direct", "polyline", "polyline_fast"}; + for(int i = 0; i < 3; ++i) + { + dc.emplace_back(axom::fmt::format("gwn_{}", names[i])); + axom::quest::generate_gwn_query_mesh(dc[i], + shape_bbox, + std::vector {}, + std::vector {}, + resolution, + query_order); + } + + // Create tolerance object + axom::primal::WindingTolerances tol; + constexpr bool useDirectPolyline = true; + + //// Run three different kinds of GWN query //// + // We expect all three fields to return the same values in this case because + // of the specific arrangement of query points and linearization. + // In general, discretizing the shape can result in different GWN values + // for query points near to individual curves. + + // Direct + SLIC_INFO("Testing Direct Evaluation"); + axom::quest::DirectGWN2D gwn_direct {}; + gwn_direct.preprocess(curves); + gwn_direct.query(dc[0], tol); + + // Linearized + SLIC_INFO("Testing Direct Evaluation of Triangulation"); + axom::quest::PolylineGWN2D<0> gwn_polyline {}; + gwn_polyline.preprocess(&poly_mesh, useDirectPolyline); + gwn_polyline.query(dc[1], tol); + + // Linearized, fast approximation + SLIC_INFO("Testing Fast-Approximate Evaluation of Triangulation"); + axom::quest::PolylineGWN2D<0> gwn_polyline_fast {}; + gwn_polyline_fast.preprocess(&poly_mesh, !useDirectPolyline); + gwn_polyline_fast.query(dc[2], tol); + + // Compare the in-out values between the three fields + const auto *query_mesh = dc[0].GetMesh(); + const auto num_query_points = query_mesh->GetNodalFESpace()->GetNDofs(); + + auto &inout_direct = *dc[0].GetField("inout"); + auto &inout_polyline = *dc[1].GetField("inout"); + auto &inout_polyline_fast = *dc[2].GetField("inout"); + + for(int i = 0; i < num_query_points; ++i) + { + EXPECT_EQ(inout_direct[i], inout_polyline[i]); + EXPECT_EQ(inout_direct[i], inout_polyline_fast[i]); + } +} + +#ifdef AXOM_USE_OPENCASCADE +//------------------------------------------------------------------------------ +TEST(quest_gwn_methods, step_file_triangulation) +{ + const std::string fileName = pjoin(AXOM_DATA_DIR, "quest", "step", "nut.step"); + + // Read the step file + axom::quest::STEPReader step_reader; + step_reader.setFileName(fileName); + + constexpr bool validate = false; + const int ret = step_reader.read(validate); + if(ret != 0) + { + SLIC_ERROR(axom::fmt::format("Failed to read STEP file '{}'", fileName)); + } + + // Get patches from the shape + const auto patches = step_reader.getPatchArray(); + + // Get a triangulation of the shape + axom::mint::UnstructuredMesh tri_mesh(3, axom::mint::TRIANGLE); + step_reader.getTriangleMesh(&tri_mesh, 0.01, 0.5); + + // Get bounding box of the shape + axom::primal::BoundingBox shape_bbox = step_reader.getBRepBoundingBox(); + const std::vector resolution {5, 5, 5}; + const int query_order = 1; + + // Generate three query grids and fields + axom::Array dc(0, 3); + std::string names[] = {"direct", "tri", "tri_fast"}; + for(int i = 0; i < 3; ++i) + { + dc.emplace_back(axom::fmt::format("gwn_{}", names[i])); + axom::quest::generate_gwn_query_mesh(dc[i], + shape_bbox, + std::vector {}, + std::vector {}, + resolution, + query_order); + } + + // Create tolerance object + axom::primal::WindingTolerances tol; + constexpr bool useDirectTriangle = true; + + //// Run three different kinds of GWN query //// + // We expect all three fields to return the same values in this case because + // of the specific arrangement of query points and triangulation. + // In general, triangulating the shape can result in different GWN values + // for query points near to individual surfaces. + + // Direct + SLIC_INFO("Testing Direct Evaluation"); + axom::quest::DirectGWN3D gwn_direct {}; + gwn_direct.preprocess(patches); + gwn_direct.query(dc[0], tol); + + // Triangulated + SLIC_INFO("Testing Direct Evaluation of Polyline"); + axom::quest::TriangleGWN3D<0> gwn_tri {}; + gwn_tri.preprocess(&tri_mesh, useDirectTriangle); + gwn_tri.query(dc[1], tol); + + // Triangulated, fast approximation + SLIC_INFO("Testing Fast-Approximate Evaluation of Polyline"); + axom::quest::TriangleGWN3D<0> gwn_tri_fast {}; + gwn_tri_fast.preprocess(&tri_mesh, !useDirectTriangle); + gwn_tri_fast.query(dc[2], tol); + + // Compare the in-out values between the three fields + const auto *query_mesh = dc[0].GetMesh(); + const auto num_query_points = query_mesh->GetNodalFESpace()->GetNDofs(); + + auto &inout_direct = *dc[0].GetField("inout"); + auto &inout_tri = *dc[1].GetField("inout"); + auto &inout_tri_fast = *dc[2].GetField("inout"); + + for(int i = 0; i < num_query_points; ++i) + { + EXPECT_EQ(inout_direct[i], inout_tri[i]); + EXPECT_EQ(inout_direct[i], inout_tri_fast[i]); + } +} +#endif + +//------------------------------------------------------------------------------ +int main(int argc, char *argv[]) +{ + int result = 0; + + ::testing::InitGoogleTest(&argc, argv); + + axom::slic::SimpleLogger logger; + + result = RUN_ALL_TESTS(); + + return result; +} diff --git a/src/axom/quest/tests/quest_mesh_clipper.cpp b/src/axom/quest/tests/quest_mesh_clipper.cpp index ffccd8cfe7..c6f29506c3 100644 --- a/src/axom/quest/tests/quest_mesh_clipper.cpp +++ b/src/axom/quest/tests/quest_mesh_clipper.cpp @@ -35,6 +35,7 @@ #include "axom/quest/detail/clipping/SphereClipper.hpp" #include "axom/quest/detail/clipping/TetClipper.hpp" #include "axom/quest/detail/clipping/TetMeshClipper.hpp" +#include "axom/quest/util/make_clipper_strategy.hpp" #include "axom/core/utilities/FileUtilities.hpp" #include "axom/fmt.hpp" @@ -50,12 +51,6 @@ #include "mpi.h" #endif -// RAJA -#if !defined(AXOM_USE_RAJA) - #error quest_mesh_clipper example require RAJA -#endif -#include "RAJA/RAJA.hpp" - // C/C++ includes #include #include @@ -251,8 +246,8 @@ struct Input std::stringstream pol_sstr; pol_sstr << "Set runtime policy for intersection-based sampling method."; + pol_sstr << "\nSet to 'seq' or 0 to use the sequential policy."; #if defined(AXOM_USE_RAJA) && defined(AXOM_USE_UMPIRE) - pol_sstr << "\nSet to 'seq' or 0 to use the RAJA sequential policy."; #ifdef AXOM_USE_OPENMP pol_sstr << "\nSet to 'omp' or 1 to use the RAJA OpenMP policy."; #endif @@ -615,7 +610,7 @@ axom::klee::Geometry createGeom_TetMesh(sidre::DataStore& ds, const std::string& tetMesh.appendNode(+lll, -lll, +lll); axom::IndexType conn0[4] = {0, 1, 2, 3}; tetMesh.appendCell(conn0); - axom::IndexType conn1[4] = {4, 5, 6, 7}; + axom::IndexType conn1[4] = {4, 5, 7, 6}; // intentionally inverted to exercise fixOrientation. tetMesh.appendCell(conn1); axom::IndexType conn2[4] = {1, 2, 3, 5}; tetMesh.appendCell(conn2); @@ -1066,8 +1061,7 @@ double sumMaterialVolumesImpl(sidre::Group* meshGrp, const std::string& material axom::sidre::View* volFrac = meshGrp->getView(vfFieldValuesPath); axom::ArrayView volFracView(volFrac->getArray(), cellCount); - using ReducePolicy = typename axom::execution_space::reduce_policy; - RAJA::ReduceSum localVol(0); + axom::ReduceSum localVol(0); axom::for_all( cellCount, AXOM_LAMBDA(axom::IndexType i) { localVol += volFracView[i] * elementVolsView[i]; }); @@ -1239,6 +1233,7 @@ int main(int argc, char** argv) axom::Array> geomStrategies; geomStrategies.reserve(params.testGeom.size()); SLIC_ERROR_IF(params.getBoxDim() != 3, "This example is only in 3D."); + using quest::experimental::util::make_clipper_strategy; for(const auto& tg : params.testGeom) { if(geomReps.count(tg) == 0) @@ -1247,55 +1242,44 @@ int main(int argc, char** argv) } std::string name = axom::fmt::format("{}.{}", tg, geomReps[tg]++); + std::shared_ptr strat; if(tg == "plane") { - geomStrategies.push_back( - std::make_shared(createGeom_Plane(name), name)); + strat = make_clipper_strategy(createGeom_Plane(name), name); } else if(tg == "hex") { - geomStrategies.push_back( - std::make_shared(createGeom_Hex(name), name)); + strat = make_clipper_strategy(createGeom_Hex(name), name); } else if(tg == "sphere") { - geomStrategies.push_back( - std::make_shared(createGeom_Sphere(name), name)); + strat = make_clipper_strategy(createGeom_Sphere(name), name); } else if(tg == "tetmesh") { - geomStrategies.push_back( - std::make_shared(createGeom_TetMesh(ds, name), - name)); + strat = make_clipper_strategy(createGeom_TetMesh(ds, name), name); } else if(tg == "cupmesh") { - geomStrategies.push_back( - std::make_shared(createGeom_CupMesh(ds, name), - name)); + strat = make_clipper_strategy(createGeom_CupMesh(ds, name), name); } else if(tg == "tet") { - geomStrategies.push_back( - std::make_shared(createGeom_Tet(name), name)); + strat = make_clipper_strategy(createGeom_Tet(name), name); } else if(tg == "cyl") { - geomStrategies.push_back( - std::make_shared(createGeom_Cylinder(name), - name)); + strat = make_clipper_strategy(createGeom_Cylinder(name), name); } else if(tg == "cone") { - geomStrategies.push_back( - std::make_shared(createGeom_Cone(name), - name)); + strat = make_clipper_strategy(createGeom_Cone(name), name); } else if(tg == "sor") { - geomStrategies.push_back( - std::make_shared(createGeom_Sor(name), name)); + strat = make_clipper_strategy(createGeom_Sor(name), name); } + geomStrategies.push_back(strat); } { @@ -1390,8 +1374,7 @@ int main(int argc, char** argv) ovlap = axom::Array(ovlap, hostAllocId); } auto ovlapView = ovlap.view(); - using reduce_policy = typename axom::execution_space::reduce_policy; - RAJA::ReduceSum ovlapSumReduce(0.0); + axom::ReduceSum ovlapSumReduce(0.0); axom::for_all( ovlap.size(), AXOM_LAMBDA(axom::IndexType i) { ovlapSumReduce += ovlapView[i]; }); diff --git a/src/axom/quest/util/make_clipper_strategy.cpp b/src/axom/quest/util/make_clipper_strategy.cpp new file mode 100644 index 0000000000..9eec1e0efd --- /dev/null +++ b/src/axom/quest/util/make_clipper_strategy.cpp @@ -0,0 +1,81 @@ +// Copyright (c) Lawrence Livermore National Security, LLC and other +// Axom Project Contributors. See top-level LICENSE and COPYRIGHT +// files for dates and other details. +// +// SPDX-License-Identifier: (BSD-3-Clause) + +#include "axom/config.hpp" + +#ifdef AXOM_USE_SIDRE + #include "axom/quest/util/make_clipper_strategy.hpp" + #include "axom/quest/detail/clipping/Plane3DClipper.hpp" + #include "axom/quest/detail/clipping/TetClipper.hpp" + #include "axom/quest/detail/clipping/TetMeshClipper.hpp" + #include "axom/quest/detail/clipping/HexClipper.hpp" + #include "axom/quest/detail/clipping/SphereClipper.hpp" + #include "axom/quest/detail/clipping/MonotonicZSORClipper.hpp" + #include "axom/quest/detail/clipping/SORClipper.hpp" + #include "axom/slic/interface/slic_macros.hpp" + +namespace axom +{ +namespace quest +{ +namespace experimental +{ +namespace util +{ + +std::shared_ptr make_clipper_strategy(const axom::klee::Geometry& kleeGeometry, + const std::string& name) +{ + std::shared_ptr strategy; + + const std::string& format = kleeGeometry.getFormat(); + + if(format == "plane3D") + { + strategy.reset(new Plane3DClipper(kleeGeometry, name)); + } + else if(format == "tet3D") + { + strategy.reset(new TetClipper(kleeGeometry, name)); + } + else if(format == "blueprint-tets") + { + strategy.reset(new TetMeshClipper(kleeGeometry, name)); + } + else if(format == "hex3D") + { + strategy.reset(new HexClipper(kleeGeometry, name)); + } + else if(format == "sphere3D") + { + strategy.reset(new SphereClipper(kleeGeometry, name)); + } + else if(format == "sor3D") + { + strategy.reset(new SORClipper(kleeGeometry, name)); + } + else if(format == "cyl3D") + { + strategy.reset(new MonotonicZSORClipper(kleeGeometry, name)); + } + else if(format == "cone3D") + { + strategy.reset(new MonotonicZSORClipper(kleeGeometry, name)); + } + else + { + SLIC_WARNING( + axom::fmt::format("klee::Geometry format {} is not supported by MeshClipper.", format)); + } + + return strategy; +} + +} // namespace util +} // namespace experimental +} // namespace quest +} // namespace axom +#endif // AXOM_USE_SIDRE diff --git a/src/axom/quest/util/make_clipper_strategy.hpp b/src/axom/quest/util/make_clipper_strategy.hpp new file mode 100644 index 0000000000..754662cbb8 --- /dev/null +++ b/src/axom/quest/util/make_clipper_strategy.hpp @@ -0,0 +1,50 @@ +// Copyright (c) Lawrence Livermore National Security, LLC and other +// Axom Project Contributors. See top-level LICENSE and COPYRIGHT +// files for dates and other details. +// +// SPDX-License-Identifier: (BSD-3-Clause) + +#ifndef AXOM_MAKE_CLIPPER_STRATEGY_HPP +#define AXOM_MAKE_CLIPPER_STRATEGY_HPP + +#include "axom/config.hpp" + +// MeshClipper depends on sidre +#ifdef AXOM_USE_SIDRE + + #include "axom/klee/Geometry.hpp" + #include "axom/quest/MeshClipperStrategy.hpp" + +namespace axom +{ +namespace quest +{ +namespace experimental +{ +namespace util +{ + +/*! + * @brief Return a new MeshClipperStrategy implementation + * to clip the specified klee Geometry. + * @param [in] kleeGeometry + * @param [in] name Name of strategy instance. + * If unspecified, the selected implementation will provide a default name. + * + * This method chooses the correct implementations for known + * klee geometry formats. It issues a warning for unrecognized + * formats. + * + * @return Pointer to new MeshClipperStrategy, or null if the + * specified geometry is not an axom-provided one. + */ +std::shared_ptr make_clipper_strategy(const axom::klee::Geometry& kleeGeometry, + const std::string& name = ""); + +} // namespace util +} // namespace experimental +} // namespace quest +} // namespace axom + +#endif // AXOM_USE_SIDRE +#endif // AXOM_MAKE_CLIPPER_STRATEGY_HPP diff --git a/src/axom/quest/util/mesh_helpers.cpp b/src/axom/quest/util/mesh_helpers.cpp index b14f22c18c..95443b1b24 100644 --- a/src/axom/quest/util/mesh_helpers.cpp +++ b/src/axom/quest/util/mesh_helpers.cpp @@ -240,30 +240,41 @@ axom::sidre::Group* make_unstructured_blueprint_box_mesh_2d(axom::sidre::Group* void convert_blueprint_structured_explicit_to_unstructured_3d(axom::sidre::Group* meshGrp, const std::string& topoName, - axom::runtime_policy::Policy runtimePolicy) + axom::runtime_policy::Policy runtimePolicy, + const std::string& ugTopoName) { if(runtimePolicy == axom::runtime_policy::Policy::seq) { - convert_blueprint_structured_explicit_to_unstructured_impl_3d(meshGrp, topoName); + convert_blueprint_structured_explicit_to_unstructured_3d_impl( + meshGrp, + topoName, + ugTopoName.empty() ? topoName : ugTopoName); } #if defined(AXOM_RUNTIME_POLICY_USE_OPENMP) if(runtimePolicy == axom::runtime_policy::Policy::omp) { - convert_blueprint_structured_explicit_to_unstructured_impl_3d(meshGrp, topoName); + convert_blueprint_structured_explicit_to_unstructured_3d_impl( + meshGrp, + topoName, + ugTopoName.empty() ? topoName : ugTopoName); } #endif #if defined(AXOM_RUNTIME_POLICY_USE_CUDA) if(runtimePolicy == axom::runtime_policy::Policy::cuda) { - convert_blueprint_structured_explicit_to_unstructured_impl_3d>(meshGrp, - topoName); + convert_blueprint_structured_explicit_to_unstructured_3d_impl>( + meshGrp, + topoName, + ugTopoName.empty() ? topoName : ugTopoName); } #endif #if defined(AXOM_RUNTIME_POLICY_USE_HIP) if(runtimePolicy == axom::runtime_policy::Policy::hip) { - convert_blueprint_structured_explicit_to_unstructured_impl_3d>(meshGrp, - topoName); + convert_blueprint_structured_explicit_to_unstructured_3d_impl>( + meshGrp, + topoName, + ugTopoName.empty() ? topoName : ugTopoName); } #endif } @@ -274,57 +285,73 @@ void convert_blueprint_structured_explicit_to_unstructured_2d(axom::sidre::Group { if(runtimePolicy == axom::runtime_policy::Policy::seq) { - convert_blueprint_structured_explicit_to_unstructured_impl_2d(meshGrp, topoName); + convert_blueprint_structured_explicit_to_unstructured_2d_impl(meshGrp, topoName); } #if defined(AXOM_RUNTIME_POLICY_USE_OPENMP) if(runtimePolicy == axom::runtime_policy::Policy::omp) { - convert_blueprint_structured_explicit_to_unstructured_impl_2d(meshGrp, topoName); + convert_blueprint_structured_explicit_to_unstructured_2d_impl(meshGrp, topoName); } #endif #if defined(AXOM_RUNTIME_POLICY_USE_CUDA) if(runtimePolicy == axom::runtime_policy::Policy::cuda) { - convert_blueprint_structured_explicit_to_unstructured_impl_2d>(meshGrp, + convert_blueprint_structured_explicit_to_unstructured_2d_impl>(meshGrp, topoName); } #endif #if defined(AXOM_RUNTIME_POLICY_USE_HIP) if(runtimePolicy == axom::runtime_policy::Policy::hip) { - convert_blueprint_structured_explicit_to_unstructured_impl_2d>(meshGrp, + convert_blueprint_structured_explicit_to_unstructured_2d_impl>(meshGrp, topoName); } #endif } template -void convert_blueprint_structured_explicit_to_unstructured_impl_3d(axom::sidre::Group* meshGrp, - const std::string& topoName) +void convert_blueprint_structured_explicit_to_unstructured_3d_impl(axom::sidre::Group* meshGrp, + const std::string& topoName, + const std::string& ugTopoName) { AXOM_ANNOTATE_SCOPE("convert_to_unstructured"); // Note: MSVC required `static` to pass DIM to the axom::for_all w/ C++14 // this restriction might be lifted w/ C++17 static constexpr int DIM = 3; - const std::string& coordsetName = - meshGrp->getView("topologies/" + topoName + "/coordset")->getString(); + sidre::Group* topologiesGrp = meshGrp->getGroup("topologies"); + axom::sidre::Group* topoGrp = topologiesGrp->getGroup(topoName); + axom::sidre::Group* ugTopoGrp = + ugTopoName == topoName ? topoGrp : topologiesGrp->createGroup(ugTopoName); + + const std::string& coordsetName = topoGrp->getView("coordset")->getString(); sidre::Group* coordsetGrp = meshGrp->getGroup("coordsets")->getGroup(coordsetName); SLIC_ASSERT(std::string(coordsetGrp->getView("type")->getString()) == "explicit"); - axom::sidre::Group* topoGrp = meshGrp->getGroup("topologies")->getGroup(topoName); - axom::sidre::View* topoTypeView = topoGrp->getView("type"); - SLIC_ASSERT(std::string(topoTypeView->getString()) == "structured"); - topoTypeView->setString("unstructured"); - topoGrp->createView("elements/shape")->setString("hex"); + if(!ugTopoGrp->hasView("coordset")) + { + ugTopoGrp->createViewString("coordset", coordsetName); + } + else + { + SLIC_ASSERT(ugTopoGrp->getView("coordset")->isString()); + SLIC_ASSERT(std::string(ugTopoGrp->getView("coordset")->getString()) == coordsetName); + } + + SLIC_ASSERT(std::string(topoGrp->getView("type")->getString()) == "structured"); + axom::sidre::View* ugTopoTypeView = + ugTopoGrp == topoGrp ? ugTopoGrp->getView("type") : ugTopoGrp->createView("type"); + ugTopoTypeView->setString("unstructured"); + axom::sidre::View* shapeView = ugTopoGrp->createView("elements/shape"); + shapeView->setString("hex"); axom::sidre::Group* topoElemGrp = topoGrp->getGroup("elements"); axom::sidre::Group* topoDimsGrp = topoElemGrp->getGroup("dims"); // Assuming no ghost, but we should eventually support ghosts. - SLIC_ASSERT(!topoGrp->hasGroup("elements/offsets")); - SLIC_ASSERT(!topoGrp->hasGroup("elements/strides")); + SLIC_ASSERT(!topoElemGrp->hasGroup("offsets")); + SLIC_ASSERT(!topoElemGrp->hasGroup("strides")); const axom::StackArray cShape { axom::IndexType(topoDimsGrp->getView("i")->getNode().to_value()), @@ -336,10 +363,10 @@ void convert_blueprint_structured_explicit_to_unstructured_impl_3d(axom::sidre:: const axom::StackArray connShape {cCount, 8}; axom::sidre::View* connView = - topoGrp->createViewWithShapeAndAllocate("elements/connectivity", - axom::sidre::detail::SidreTT::id, - 2, - connShape.begin()); + ugTopoGrp->createViewWithShapeAndAllocate("elements/connectivity", + axom::sidre::detail::SidreTT::id, + 2, + connShape.begin()); axom::ArrayView connArrayView( static_cast(connView->getVoidPtr()), connShape); @@ -371,16 +398,16 @@ void convert_blueprint_structured_explicit_to_unstructured_impl_3d(axom::sidre:: { AXOM_ANNOTATE_BEGIN("add_extra"); /* - Constructing a mint mesh from meshGrp fails unless we add some - extra data. Blueprint doesn't require this extra data. (The mesh - passes conduit's Blueprint verification.) This should be fixed, - or we should write better blueprint support utilities. - */ + * Constructing a mint mesh from meshGrp fails unless we add some + * extra data. Blueprint doesn't require this extra data. (The mesh + * passes conduit's Blueprint verification.) This should be fixed, + * or we should write better blueprint support utilities. + */ /* - Make the coordinate arrays 2D to use mint::Mesh. - For some reason, mint::Mesh requires the arrays to be - 2D, even though the second dimension is always 1. - */ + * Make the coordinate arrays 2D to use mint::Mesh. + * For some reason, mint::Mesh requires the arrays to be + * 2D, even though the second dimension is always 1. + */ axom::IndexType curShape[2]; int curDim; auto* valuesGrp = coordsetGrp->getGroup("values"); @@ -392,7 +419,7 @@ void convert_blueprint_structured_explicit_to_unstructured_impl_3d(axom::sidre:: valuesGrp->getView("z")->reshapeArray(2, vertsShape); // Make connectivity array 2D for the same reason. - auto* elementsGrp = topoGrp->getGroup("elements"); + auto* elementsGrp = ugTopoGrp->getGroup("elements"); auto* connView = elementsGrp->getView("connectivity"); curDim = connView->getShape(2, curShape); constexpr axom::IndexType NUM_VERTS_PER_HEX = 8; @@ -407,8 +434,6 @@ void convert_blueprint_structured_explicit_to_unstructured_impl_3d(axom::sidre:: // mint::Mesh requires connectivity strides, even though Blueprint doesn't. elementsGrp->createViewScalar("stride", NUM_VERTS_PER_HEX); - // mint::Mesh requires field group, even though Blueprint doesn't. - meshGrp->createGroup("fields"); AXOM_ANNOTATE_END("add_extra"); } @@ -424,7 +449,7 @@ void convert_blueprint_structured_explicit_to_unstructured_impl_3d(axom::sidre:: } template -void convert_blueprint_structured_explicit_to_unstructured_impl_2d(axom::sidre::Group* meshGrp, +void convert_blueprint_structured_explicit_to_unstructured_2d_impl(axom::sidre::Group* meshGrp, const std::string& topoName) { AXOM_ANNOTATE_SCOPE("convert_to_unstructured"); @@ -495,16 +520,16 @@ void convert_blueprint_structured_explicit_to_unstructured_impl_2d(axom::sidre:: { AXOM_ANNOTATE_SCOPE("add_extra"); /* - Constructing a mint mesh from meshGrp fails unless we add some - extra data. Blueprint doesn't require this extra data. (The mesh - passes conduit's Blueprint verification.) This should be fixed, - or we should write better blueprint support utilities. - */ + * Constructing a mint mesh from meshGrp fails unless we add some + * extra data. Blueprint doesn't require this extra data. (The mesh + * passes conduit's Blueprint verification.) This should be fixed, + * or we should write better blueprint support utilities. + */ /* - Make the coordinate arrays 2D to use mint::Mesh. - For some reason, mint::Mesh requires the arrays to be - 2D, even though the second dimension is always 1. - */ + * Make the coordinate arrays 2D to use mint::Mesh. + * For some reason, mint::Mesh requires the arrays to be + * 2D, even though the second dimension is always 1. + */ axom::IndexType curShape[2] = {}; auto* valuesGrp = coordsetGrp->getGroup("values"); SLIC_ASSERT(valuesGrp != nullptr); @@ -526,9 +551,6 @@ void convert_blueprint_structured_explicit_to_unstructured_impl_2d(axom::sidre:: // mint::Mesh requires connectivity strides, even though Blueprint doesn't. constexpr axom::IndexType BIT_SPECIFIC_NUM_VERTS_PER_QUAD = 4; elementsGrp->createViewScalar("stride", BIT_SPECIFIC_NUM_VERTS_PER_QUAD); - - // mint::Mesh requires field group, even though Blueprint doesn't. - meshGrp->createGroup("fields"); } return; diff --git a/src/axom/quest/util/mesh_helpers.hpp b/src/axom/quest/util/mesh_helpers.hpp index c4e62bbe12..d0ebc9ebe1 100644 --- a/src/axom/quest/util/mesh_helpers.hpp +++ b/src/axom/quest/util/mesh_helpers.hpp @@ -153,6 +153,8 @@ axom::sidre::Group* make_unstructured_blueprint_box_mesh_2d( * \param runtimePolicy Runtime policy, see axom::runtime_policy. * Memory in \c meshGrp must be compatible with the * specified policy. + * \param ugTopoName Name of the unstructured topology to create. + * Defaults to topoName. * * All input mesh data are expected to have the allocator id of * meshGrp->getDefaultAllocatorID(). On output, they will also have @@ -161,18 +163,20 @@ axom::sidre::Group* make_unstructured_blueprint_box_mesh_2d( */ void convert_blueprint_structured_explicit_to_unstructured_3d(axom::sidre::Group* meshGrp, const std::string& topoName, - axom::runtime_policy::Policy runtimePolicy); + axom::runtime_policy::Policy runtimePolicy, + const std::string& ugTopoName = ""); template -void convert_blueprint_structured_explicit_to_unstructured_impl_3d(axom::sidre::Group* meshGrp, - const std::string& topoName); +void convert_blueprint_structured_explicit_to_unstructured_3d_impl(axom::sidre::Group* meshGrp, + const std::string& topoName, + const std::string& ugTopoName); void convert_blueprint_structured_explicit_to_unstructured_2d(axom::sidre::Group* meshGrp, const std::string& topoName, axom::runtime_policy::Policy runtimePolicy); template -void convert_blueprint_structured_explicit_to_unstructured_impl_2d(axom::sidre::Group* meshGrp, +void convert_blueprint_structured_explicit_to_unstructured_2d_impl(axom::sidre::Group* meshGrp, const std::string& topoName); #if defined(AXOM_USE_CONDUIT) diff --git a/src/axom/sidre/CMakeLists.txt b/src/axom/sidre/CMakeLists.txt index e48c2fec7b..22fbdb8f63 100644 --- a/src/axom/sidre/CMakeLists.txt +++ b/src/axom/sidre/CMakeLists.txt @@ -119,6 +119,9 @@ if(AXOM_ENABLE_MPI) blt_list_append(TO sidre_depends ELEMENTS scr IF SCR_FOUND) endif() +if(NANOBIND_FOUND) + list(APPEND sidre_depends conduit::conduit_python) +endif() axom_add_library(NAME sidre SOURCES ${sidre_sources} diff --git a/src/axom/sidre/core/ConduitMemory.cpp b/src/axom/sidre/core/ConduitMemory.cpp index 5b77f0287d..141bcbb9ff 100644 --- a/src/axom/sidre/core/ConduitMemory.cpp +++ b/src/axom/sidre/core/ConduitMemory.cpp @@ -24,8 +24,9 @@ void ConduitMemory::privateRegisterAllocator() }; m_deallocCallback = deallocator; #if defined(AXOM_CONDUIT_USES_STD_FUNCTION) + const auto axomId = m_axomId; m_allocCallback = [=](size_t itemCount, size_t itemByteSize) -> void* { - void* ptr = axom::allocate(itemCount * itemByteSize, m_axomId); + void* ptr = axom::allocate(itemCount * itemByteSize, axomId); return ptr; }; m_conduitId = register_allocator(m_allocCallback, m_deallocCallback); diff --git a/src/axom/sidre/examples/sidre_createdatastore_Py.py b/src/axom/sidre/examples/sidre_createdatastore_Py.py index 253ea1ef70..292fd22774 100644 --- a/src/axom/sidre/examples/sidre_createdatastore_Py.py +++ b/src/axom/sidre/examples/sidre_createdatastore_Py.py @@ -11,29 +11,29 @@ # The python interface is a work-in-progress, and does not yet support # all the features in the C++ source. -def create_datastore(region): - ds = pysidre.DataStore() - root = ds.getRoot() - - # Create two attributes - ds.createAttributeScalar("vis", 0) - ds.createAttributeScalar("restart", 1) - - # Create group children of root group - state = root.createGroup("state") - nodes = root.createGroup("nodes") - fields = root.createGroup("fields") - - # Populate "state" group - state.createViewScalar("cycle", 25) - state.createViewScalar("time", 1.2562e-2) - state.createViewString("name", "sample_20171206_a") - - N = 16 - nodecount = N * N * N - eltcount = (N - 1) * (N - 1) * (N - 1) - """ +def create_datastore(region): + ds = pysidre.DataStore() + root = ds.getRoot() + + # Create two attributes + ds.createAttributeScalar("vis", 0) + ds.createAttributeScalar("restart", 1) + + # Create group children of root group + state = root.createGroup("state") + nodes = root.createGroup("nodes") + fields = root.createGroup("fields") + + # Populate "state" group + state.createViewScalar("cycle", 25) + state.createViewScalar("time", 1.2562e-2) + state.createViewString("name", "sample_20171206_a") + + N = 16 + nodecount = N * N * N + eltcount = (N - 1) * (N - 1) * (N - 1) + """ Populate "nodes" group "x", "y", and "z" are three views into a shared Sidre buffer object that @@ -41,12 +41,11 @@ def create_datastore(region): each node in a 16 x 16 x 16 hexahedron mesh. Each view is described by number of elements, offset, and stride into that data. """ - buff = ds.createBuffer(pysidre.TypeID.DOUBLE_ID, 3 * nodecount).allocate() - nodes.createView("x", buff).apply(pysidre.TypeID.DOUBLE_ID, nodecount, 0, 3) - nodes.createView("y", buff).apply(pysidre.TypeID.DOUBLE_ID, nodecount, 1, 3) - nodes.createView("z", buff).apply(pysidre.TypeID.DOUBLE_ID, nodecount, 2, 3) - - """ + buff = ds.createBuffer(pysidre.TypeID.DOUBLE_ID, 3 * nodecount).allocate() + nodes.createView("x", buff).apply(pysidre.TypeID.DOUBLE_ID, nodecount, 0, 3) + nodes.createView("y", buff).apply(pysidre.TypeID.DOUBLE_ID, nodecount, 1, 3) + nodes.createView("z", buff).apply(pysidre.TypeID.DOUBLE_ID, nodecount, 2, 3) + """ Populate "fields" group "temp" is a view into a buffer that is not shared with another View. @@ -55,100 +54,102 @@ def create_datastore(region): and stride (1). These Views could point to data associated with each of the 15 x 15 x 15 hexahedron elements defined by the nodes above. """ - temp = fields.createViewAndAllocate("temp", pysidre.TypeID.DOUBLE_ID, eltcount) - rho = fields.createViewAndAllocate("rho", pysidre.TypeID.DOUBLE_ID, eltcount) + temp = fields.createViewAndAllocate("temp", pysidre.TypeID.DOUBLE_ID, eltcount) + rho = fields.createViewAndAllocate("rho", pysidre.TypeID.DOUBLE_ID, eltcount) - # Explicitly set values for the "vis" Attribute on the "temp" and "rho" buffers. - temp.setAttributeScalar("vis", 1) - rho.setAttributeScalar("vis", 1) + # Explicitly set values for the "vis" Attribute on the "temp" and "rho" buffers. + temp.setAttributeScalar("vis", 1) + rho.setAttributeScalar("vis", 1) - # The "fields" Group also contains a child Group "ext" which holds a pointer - # to an externally owned integer array. Although Sidre does not own the - # data, the data can still be described to Sidre. - ext = fields.createGroup("ext") + # The "fields" Group also contains a child Group "ext" which holds a pointer + # to an externally owned integer array. Although Sidre does not own the + # data, the data can still be described to Sidre. + ext = fields.createGroup("ext") - # numpy of int region has been passed in as a function argument. As with "temp" - # and "rho", view "region" has default offset and stride. - ext.createView("region", region).apply(pysidre.TypeID.INT_ID, eltcount) + # numpy of int region has been passed in as a function argument. As with "temp" + # and "rho", view "region" has default offset and stride. + ext.createView("region", region).apply(pysidre.TypeID.INT_ID, eltcount) - return ds + return ds def access_datastore(ds): - # Retrieve Group pointers - root = ds.getRoot() - state = root.getGroup("state") - nodes = root.getGroup("nodes") - fields = root.getGroup("fields") - - # Accessing a Group that is not there gives None - # Requesting a nonexistent View also gives None - goofy = root.getGroup("goofy") - if goofy == None: - print("No such group: goofy") - else: - print("Something is very wrong!") - - # Access items in "state" group - cycle = state.getView("cycle").getDataInt() - time = state.getView("time").getDataFloat() - name = state.getView("name").getString() - - # Access some items in "nodes" and "fields" groups - y = nodes.getView("y").getDataArray() - ystride = nodes.getView("y").getStride() - temp = fields.getView("temp").getDataArray() - region = fields.getView("ext/region").getDataArray() - - # Nudge the 3rd node, adjust temp and region of the 3rd element - y[2 * ystride] += 0.0032 - temp[2] *= 1.0021 - region[2] = 6 - - return ds + # Retrieve Group pointers + root = ds.getRoot() + state = root.getGroup("state") + nodes = root.getGroup("nodes") + fields = root.getGroup("fields") + + # Accessing a Group that is not there gives None + # Requesting a nonexistent View also gives None + goofy = root.getGroup("goofy") + if goofy == None: + print("No such group: goofy") + else: + print("Something is very wrong!") + + # Access items in "state" group + cycle = state.getView("cycle").getDataInt() + time = state.getView("time").getDataFloat() + name = state.getView("name").getString() + + # Access some items in "nodes" and "fields" groups + y = nodes.getView("y").getDataArray() + ystride = nodes.getView("y").getStride() + temp = fields.getView("temp").getDataArray() + region = fields.getView("ext/region").getDataArray() + + # Nudge the 3rd node, adjust temp and region of the 3rd element + y[2 * ystride] += 0.0032 + temp[2] *= 1.0021 + region[2] = 6 + + return ds + def iterate_datastore(ds): - fill_line = "=" * 80 - print(fill_line) - - # iterate through the attributes in ds - print("The datastore has the following attributes:") - for attr in ds.attributes(): - print(f"* [{attr.getIndex()}] '{attr.getName()}' of type " - f"{attr.getTypeID()} " - - # Requires conduit::Node information - # f"and default value: {attr.getDefaultNodeRef().to_yaml()}\n" - ) - - # iterate through the buffers in ds - print(fill_line) - print("The datastore has the following buffers:") - for buff in ds.buffers(): - print(f"* [{buff.getIndex()}] " - f"{'Allocated' if buff.isAllocated() else 'Unallocated'} buffer with " - f"{buff.getNumElements()} elements of type {buff.getTypeID()} with " - f"{buff.getNumViews()} views") - print(fill_line) - - # iterate through the groups of the root group - print("The root group has the following groups:") - for grp in ds.getRoot().groups(): - print(f"* [{grp.getIndex()}] '{grp.getName()}' with " - f"{grp.getNumGroups()} groups and {grp.getNumViews()} views") - print(fill_line) - - # iterate through the views of the 'state' group - print("The 'state' group has the following views:") - for view in ds.getRoot().getGroup("state").views(): - print(f"* [{view.getIndex()}] '{view.getName()}' -- " - f"{'Allocated' if view.isAllocated() else 'Unallocated'} view of type " - f"{view.getTypeID()} and {view.getNumElements()} elements") - print(fill_line) - - -if __name__=="__main__": - region = np.zeros(3375, dtype = int) - ds = create_datastore(region) - access_datastore(ds) - iterate_datastore(ds) + fill_line = "=" * 80 + print(fill_line) + + # iterate through the attributes in ds + print("The datastore has the following attributes:") + for attr in ds.attributes(): + print( + f"* [{attr.getIndex()}] '{attr.getName()}' of type " + f"{attr.getTypeID()} " + + # Requires conduit::Node information + # f"and default value: {attr.getDefaultNodeRef().to_yaml()}\n" + ) + + # iterate through the buffers in ds + print(fill_line) + print("The datastore has the following buffers:") + for buff in ds.buffers(): + print(f"* [{buff.getIndex()}] " + f"{'Allocated' if buff.isAllocated() else 'Unallocated'} buffer with " + f"{buff.getNumElements()} elements of type {buff.getTypeID()} with " + f"{buff.getNumViews()} views") + print(fill_line) + + # iterate through the groups of the root group + print("The root group has the following groups:") + for grp in ds.getRoot().groups(): + print(f"* [{grp.getIndex()}] '{grp.getName()}' with " + f"{grp.getNumGroups()} groups and {grp.getNumViews()} views") + print(fill_line) + + # iterate through the views of the 'state' group + print("The 'state' group has the following views:") + for view in ds.getRoot().getGroup("state").views(): + print(f"* [{view.getIndex()}] '{view.getName()}' -- " + f"{'Allocated' if view.isAllocated() else 'Unallocated'} view of type " + f"{view.getTypeID()} and {view.getNumElements()} elements") + print(fill_line) + + +if __name__ == "__main__": + region = np.zeros(3375, dtype=int) + ds = create_datastore(region) + access_datastore(ds) + iterate_datastore(ds) diff --git a/src/axom/sidre/interface/c_fortran/genfsidresplicer.py b/src/axom/sidre/interface/c_fortran/genfsidresplicer.py index ad5d4edf1a..417967c730 100644 --- a/src/axom/sidre/interface/c_fortran/genfsidresplicer.py +++ b/src/axom/sidre/interface/c_fortran/genfsidresplicer.py @@ -14,19 +14,23 @@ # types to use for generic routines types = ( - ( 'int', 'integer(C_INT)', 'SIDRE_INT_ID'), - ( 'long', 'integer(C_LONG)', 'SIDRE_LONG_ID'), - ( 'float', 'real(C_FLOAT)', 'SIDRE_FLOAT_ID'), - ( 'double', 'real(C_DOUBLE)', 'SIDRE_DOUBLE_ID'), + ('int', 'integer(C_INT)', 'SIDRE_INT_ID'), + ('long', 'integer(C_LONG)', 'SIDRE_LONG_ID'), + ('float', 'real(C_FLOAT)', 'SIDRE_FLOAT_ID'), + ('double', 'real(C_DOUBLE)', 'SIDRE_DOUBLE_ID'), ) # maximum number of dimensions of generic routines maxdims = 4 + def XXnum_metabuffers(): - return len(types) * (maxdims + 1) # include scalars + return len(types) * (maxdims + 1) # include scalars + + ###################################################################### + def group_get_scalar(d): """Create methods on Group to get a scalar. """ @@ -45,6 +49,7 @@ def group_get_scalar(d): value = c_view_get_data_{typename}(view) end subroutine group_get_scalar_{typename}""".format(**d) + def group_set_scalar(d): """Create methods on Group to set a scalar. """ @@ -63,6 +68,7 @@ def group_set_scalar(d): call c_view_set_scalar_{typename}(view, value) end subroutine group_set_scalar_{typename}""".format(**d) + def group_create_array_view(d): # typename - part of function name # nd - number of dimensions @@ -100,9 +106,10 @@ def group_create_array_view(d): call c_group_create_view_external_bufferify( & grp%cxxmem, name, lname, addr, rv%cxxmem) call c_view_apply_type_shape(rv%cxxmem, type, {rank}, extents) -end function group_create_array_view_{typename}{nd}""".format( - extents_decl=extents_decl, - extents_asgn=extents_asgn, **d) +end function group_create_array_view_{typename}{nd}""".format(extents_decl=extents_decl, + extents_asgn=extents_asgn, + **d) + def group_set_array_data_ptr(d): """ @@ -149,9 +156,10 @@ def group_set_array_data_ptr(d): call c_view_set_external_data_ptr_only(view, addr) ! call c_view_apply_type_shape(rv%cxxmem, type, {rank}, extents) endif -end subroutine group_set_array_data_ptr_{typename}{nd}""".format( - extents_decl=extents_decl, - extents_asgn=extents_asgn, **d) +end subroutine group_set_array_data_ptr_{typename}{nd}""".format(extents_decl=extents_decl, + extents_asgn=extents_asgn, + **d) + def view_set_array_data_ptr(d): """ @@ -191,9 +199,10 @@ def view_set_array_data_ptr(d): #endif call c_view_set_external_data_ptr_only(view%cxxmem, addr) ! call c_view_apply_type_shape(rv%cxxmem, type, {rank}, extents) -end subroutine view_set_array_data_ptr_{typename}{nd}""".format( - extents_decl=extents_decl, - extents_asgn=extents_asgn, **d) +end subroutine view_set_array_data_ptr_{typename}{nd}""".format(extents_decl=extents_decl, + extents_asgn=extents_asgn, + **d) + def print_get_data(d): # typename - part of function name @@ -265,6 +274,7 @@ class AddMethods(object): gen1, & genn """ + def __init__(self, wrap_class): self.wrap_class = wrap_class self.lines = [] @@ -272,7 +282,8 @@ def __init__(self, wrap_class): @staticmethod def type_bound_procedure_part(d): - return 'procedure :: {stem}_{typename}{nd}{suffix} => {wrap_class}_{stem}_{typename}{nd}{suffix}'.format(**d) + return 'procedure :: {stem}_{typename}{nd}{suffix} => {wrap_class}_{stem}_{typename}{nd}{suffix}'.format( + **d) @staticmethod def type_bound_procedure_generic(d): @@ -288,11 +299,11 @@ def gen_type_bound(self): extra = dict( wrap_class=self.wrap_class, stem=stem, - ) + ) extra.update(kwargs) foreach_type(lines, AddMethods.type_bound_procedure_part, scalar=scalar, **extra) foreach_type(generics, AddMethods.type_bound_procedure_generic, scalar=scalar, **extra) - + lines.append('generic :: {stem} => &'.format(stem=stem)) for gen in generics[:-1]: lines.append(' ' + gen + ', &') @@ -314,10 +325,9 @@ def foreach_type(lines, fcn, scalar=False, **kwargs): lbound = [] for nd in range(maxdims + 1): shape.append(':') - lbound.append('lbound(value,%d)' % (nd+1)) - d = dict( - suffix='' # suffix of function name - ) + lbound.append('lbound(value,%d)' % (nd + 1)) + d = dict(suffix='' # suffix of function name + ) d.update(kwargs) indx = 0 for typetuple in types: @@ -325,10 +335,10 @@ def foreach_type(lines, fcn, scalar=False, **kwargs): # scalar values # XXX - generic does not distinguish between pointer and non-pointer -# d['rank'] = -1 -# d['nd'] = 'scalar' -# d['shape'] = '' -# lines.append(fcn(d)) + # d['rank'] = -1 + # d['nd'] = 'scalar' + # d['shape'] = '' + # lines.append(fcn(d)) # scalar pointers d['index'] = indx @@ -343,7 +353,7 @@ def foreach_type(lines, fcn, scalar=False, **kwargs): else: d['nd'] = '_scalar' lines.append(fcn(d)) - for nd in range(1,maxdims+1): + for nd in range(1, maxdims + 1): d['index'] = indx indx += 1 d['rank'] = nd @@ -352,8 +362,10 @@ def foreach_type(lines, fcn, scalar=False, **kwargs): d['lower_bound'] = '(' + ','.join(lbound[:nd]) + ')' lines.append(fcn(d)) + #---------------------------------------------------------------------- + def group_string(): """Text for functions with get and set strings for a group. @@ -391,6 +403,7 @@ def group_string(): #---------------------------------------------------------------------- + def gen_fortran(): """Generate splicers used by Shroud. """ @@ -420,7 +433,6 @@ def gen_fortran(): print(group_string()) print('! splicer end class.Group.additional_functions') - # View t = AddMethods('view') t.add_method('get_data', print_get_data, suffix='_ptr') @@ -440,6 +452,7 @@ def gen_fortran(): print(line) print('! splicer end class.View.additional_functions') + ###################################################################### if __name__ == '__main__': diff --git a/src/axom/sidre/nanobind_sidre.cpp b/src/axom/sidre/nanobind_sidre.cpp index f0620aed40..a9132745ff 100644 --- a/src/axom/sidre/nanobind_sidre.cpp +++ b/src/axom/sidre/nanobind_sidre.cpp @@ -17,6 +17,9 @@ #include "core/DataStore.hpp" #include "core/Group.hpp" +// Separate Conduit header for python functionality +#include "conduit_python.hpp" + namespace nb = nanobind; using namespace nb::literals; @@ -151,6 +154,60 @@ void bindIterator(nb::module_& m, const char* iterator_name) nb::keep_alive<0, 1>()); } +/*! + * \brief Helper function that converts a C++ Conduit Node into a python nanobind object + * that is of type Node in python. + * + * \param [in] node C++ Conduit Node + * + * \return A python nanobind object + */ +nb::object nodeToNbObject(conduit::Node& node) +{ + // Setup conduit python c api + if(import_conduit() < 0) + { + SLIC_ERROR("Failed to import Conduit Python C-API"); + } + + // 0 - python owns => false + PyObject* wrapped = PyConduit_Node_Python_Wrap(&node, 0); + + SLIC_ERROR_IF(!wrapped, "PyObject is null"); + SLIC_ERROR_IF(!PyConduit_Node_Check(wrapped), "PyObject is not a Conduit Node"); + + // Return nb::object + return nb::steal(wrapped); +} + +/*! + * \brief Helper function that converts a python nanobind object that is of type Node + * in python into a C++ Conduit Node. + * + * \param [in] node C++ Conduit Node + * \pre The python nanobind object must be of type Node in python + * + * \return A python nanobind object + */ +conduit::Node& nbObjectToNode(nb::object& o) +{ + // Setup conduit python C API + if(import_conduit() < 0) + { + SLIC_ERROR("Failed to import Conduit Python C-API"); + } + + PyObject* obj = o.ptr(); + SLIC_ERROR_IF(!obj, "PyObject is null"); + SLIC_ERROR_IF(!PyConduit_Node_Check(obj), "PyObject is not a Conduit Node"); + + // Turn python PyObject into C++ conduit::Node + conduit::Node* cpp_node = PyConduit_Node_Get_Node_Ptr(obj); + SLIC_ERROR_IF(!cpp_node, "Failed to get underlying conduit::Node pointer"); + + return *cpp_node; +} + NB_MODULE(pysidre, m_sidre) { m_sidre.doc() = "A python extension for Axom's Sidre component"; @@ -674,18 +731,30 @@ NB_MODULE(pysidre, m_sidre) // Requires conduit::Node information // Node reference getters - // .def("getAttributeNodeRef", - // nb::overload_cast(&View::getAttributeNodeRef), - // nb::rv_policy::reference, - // "Return reference to Attribute Node (by index)") - // .def("getAttributeNodeRef", - // nb::overload_cast(&View::getAttributeNodeRef), - // nb::rv_policy::reference, - // "Return reference to Attribute Node (by name)") - // .def("getAttributeNodeRef", - // nb::overload_cast(&View::getAttributeNodeRef), - // nb::rv_policy::reference, - // "Return reference to Attribute Node (by pointer)") + .def( + "getAttributeNodeRef", + [](View& self, IndexType idx) { + conduit::Node& node = const_cast(self.getAttributeNodeRef(idx)); + return nodeToNbObject(node); + }, + nb::rv_policy::reference, + "Return reference to Attribute Node (by index)") + .def( + "getAttributeNodeRef", + [](View& self, const std::string& name) { + conduit::Node& node = const_cast(self.getAttributeNodeRef(name)); + return nodeToNbObject(node); + }, + nb::rv_policy::reference, + "Return reference to Attribute Node (by name)") + .def( + "getAttributeNodeRef", + [](View& self, const Attribute* attr) { + conduit::Node& node = const_cast(self.getAttributeNodeRef(attr)); + return nodeToNbObject(node); + }, + nb::rv_policy::reference, + "Return reference to Attribute Node (by pointer)") // Attribute index iteration .def("getFirstValidAttrValueIndex", @@ -973,6 +1042,17 @@ NB_MODULE(pysidre, m_sidre) .def("print", nb::overload_cast<>(&Group::print, nb::const_), "Print JSON description of data Group to stdout.") + + .def( + "createExternalLayout", + [](Group& self, nb::object& o, const Attribute* attr) { + conduit::Node& cpp_node = nbObjectToNode(o); + return self.createExternalLayout(cpp_node, attr); + }, + "Copy data Group external layout to given Conduit node.", + nb::arg("n"), + nb::arg("attr") = nb::none()) + .def("isEquivalentTo", &Group::isEquivalentTo, "Return true if this Group is equivalent to given Group; else false.", @@ -991,7 +1071,7 @@ NB_MODULE(pysidre, m_sidre) nb::overload_cast(&Group::load), "Load a Group hierarchy from a file into this Group", nb::arg("path"), - nb::arg("protocol"), + nb::arg("protocol") = Group::getDefaultIOProtocol(), nb::arg("preserve_contents") = false) .def("loadExternalData", @@ -1016,14 +1096,14 @@ NB_MODULE(pysidre, m_sidre) &Attribute::setDefaultString, "Set default value of Attribute as string. Return true if successfully changed.") - // Requires conduit::Node information - // .def("setDefaultNodeRef", - // &Attribute::setDefaultNodeRef, - // "Set default value of Attribute as a Node reference.") - .def("getDefaultNodeRef", - &Attribute::getDefaultNodeRef, - nb::rv_policy::reference, - "Return default value of Attribute as Node reference.") + .def( + "getDefaultNodeRef", + [](Attribute& self) { + conduit::Node& node = const_cast(self.getDefaultNodeRef()); + return nodeToNbObject(node); + }, + nb::rv_policy::reference, + "Return default value of Attribute as Node reference.") .def("getTypeID", &Attribute::getTypeID, "Return type of Attribute."); } diff --git a/src/axom/sidre/tests/CMakeLists.txt b/src/axom/sidre/tests/CMakeLists.txt index 7dd9ccbde0..53c153e580 100644 --- a/src/axom/sidre/tests/CMakeLists.txt +++ b/src/axom/sidre/tests/CMakeLists.txt @@ -121,19 +121,10 @@ if(NANOBIND_FOUND AND AXOM_ENABLE_PYTHON_TESTS) foreach(test ${python_sidre_tests}) get_filename_component( test_name ${test} NAME_WE ) - # Copy python test file to build - axom_configure_file ("${test}" - "${TEST_OUTPUT_DIRECTORY}/${test}" COPYONLY) - - # Run unit test with pytest - # "-p no:cacheprovider" disables caching - # - # Need to invoke with "python3 -m pytest" to get generated nanobind library added to search path: - # https://docs.pytest.org/en/latest/explanation/pythonpath.html#invoking-pytest-versus-python-m-pytest - add_test (NAME ${test_name} - COMMAND ${Python_EXECUTABLE} -m pytest -s -p no:cacheprovider ${TEST_OUTPUT_DIRECTORY}/${test} - WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/lib - ) + axom_add_python_test( NAME ${test_name} + SOURCE ${test} + OUTPUT_DIR ${TEST_OUTPUT_DIRECTORY} + ) endforeach() endif() diff --git a/src/axom/sidre/tests/sidre_attribute_Py.py b/src/axom/sidre/tests/sidre_attribute_Py.py index 0ec5b4b7f8..0867ef1e01 100644 --- a/src/axom/sidre/tests/sidre_attribute_Py.py +++ b/src/axom/sidre/tests/sidre_attribute_Py.py @@ -6,6 +6,7 @@ import pysidre import numpy as np +import conduit # Global attribute values, used by multiple tests g_name_color = "color" @@ -34,918 +35,914 @@ g_attr_null = None if pysidre.AXOM_USE_HDF5: - g_nprotocols = 3 - g_protocols = ["sidre_json", "sidre_hdf5", "json"] + g_nprotocols = 3 + g_protocols = ["sidre_json", "sidre_hdf5", "json"] else: - g_nprotocols = 2 - g_protocols = ["sidre_json", "json"] + g_nprotocols = 2 + g_protocols = ["sidre_json", "json"] g_protocol_saves_attributes = { - "sidre_hdf5", - "sidre_conduit_json", - "sidre_json", - "sidre_layout_json" + "sidre_hdf5", "sidre_conduit_json", "sidre_json", "sidre_layout_json" } + # ------------------------------------------------------------------------------ # Create attribute in a Datastore def test_create_attr(): - print("Some warnings are expected in the 'create_attr' test") - - ds = pysidre.DataStore() - - nattrs = ds.getNumAttributes() - assert nattrs == 0 - - has_index = ds.hasAttribute(0) - assert not has_index - has_name = ds.hasAttribute(g_name_color) - assert not has_name - - # Create string attribute - color = ds.createAttributeString(g_name_color, g_color_none) - assert color is not None - assert color.getTypeID() == pysidre.TypeID.CHAR8_STR_ID - - attr_index = color.getIndex() - assert attr_index == 0 - - nattrs = ds.getNumAttributes() - assert nattrs == 1 - - has_name = ds.hasAttribute(g_name_color) - assert has_name - has_index = ds.hasAttribute(0) - assert has_index - - # Try to change default to a different type. - # Check template of setDefaultScalar. - ok = color.setDefaultScalar(1) - assert not ok - ok = color.setDefaultScalar(3.14) - assert not ok - - # Change to legal values. - ok = color.setDefaultString("unknown") - assert ok - ok = color.setDefaultString("string") # non-const string - assert ok - - attr = ds.getAttribute(g_name_color) - assert attr == color - attrc = ds.getAttribute(g_name_color) - assert attrc == color - - attr = ds.getAttribute(0) - assert attr == color - attrc = ds.getAttribute(0) - assert attrc == color - - ds.destroyAttribute(color) - nattrs = ds.getNumAttributes() - assert nattrs == 0 - has_name = ds.hasAttribute(g_name_color) - assert not has_name - # At this point color points to deallocated memory - - # Create additional attributes - dump = ds.createAttributeScalar(g_name_dump, g_dump_no) - assert dump is not None - - attr_index = dump.getIndex() - assert attr_index == 0 - - size = ds.createAttributeScalar(g_name_size, g_size_small) - assert size is not None - - attr_index = size.getIndex() - assert attr_index == 1 - - nattrs = ds.getNumAttributes() - assert nattrs == 2 - - ok = dump.setDefaultScalar(1) - assert ok - # try to change default to a different type - ok = dump.setDefaultString(g_name_dump) - assert not ok - ok = dump.setDefaultString("yes") - assert not ok - ok = dump.setDefaultScalar(3.1415) - assert not ok - - ds.destroyAllAttributes() - nattrs = ds.getNumAttributes() - assert nattrs == 0 + print("Some warnings are expected in the 'create_attr' test") + + ds = pysidre.DataStore() + + nattrs = ds.getNumAttributes() + assert nattrs == 0 + + has_index = ds.hasAttribute(0) + assert not has_index + has_name = ds.hasAttribute(g_name_color) + assert not has_name + + # Create string attribute + color = ds.createAttributeString(g_name_color, g_color_none) + assert color is not None + assert color.getTypeID() == pysidre.TypeID.CHAR8_STR_ID + + attr_index = color.getIndex() + assert attr_index == 0 + + nattrs = ds.getNumAttributes() + assert nattrs == 1 + + has_name = ds.hasAttribute(g_name_color) + assert has_name + has_index = ds.hasAttribute(0) + assert has_index + + # Try to change default to a different type. + # Check template of setDefaultScalar. + ok = color.setDefaultScalar(1) + assert not ok + ok = color.setDefaultScalar(3.14) + assert not ok + + # Change to legal values. + ok = color.setDefaultString("unknown") + assert ok + ok = color.setDefaultString("string") # non-const string + assert ok + + attr = ds.getAttribute(g_name_color) + assert attr == color + attrc = ds.getAttribute(g_name_color) + assert attrc == color + + attr = ds.getAttribute(0) + assert attr == color + attrc = ds.getAttribute(0) + assert attrc == color + + ds.destroyAttribute(color) + nattrs = ds.getNumAttributes() + assert nattrs == 0 + has_name = ds.hasAttribute(g_name_color) + assert not has_name + # At this point color points to deallocated memory + + # Create additional attributes + dump = ds.createAttributeScalar(g_name_dump, g_dump_no) + assert dump is not None + + attr_index = dump.getIndex() + assert attr_index == 0 + + size = ds.createAttributeScalar(g_name_size, g_size_small) + assert size is not None + + attr_index = size.getIndex() + assert attr_index == 1 + + nattrs = ds.getNumAttributes() + assert nattrs == 2 + + ok = dump.setDefaultScalar(1) + assert ok + # try to change default to a different type + ok = dump.setDefaultString(g_name_dump) + assert not ok + ok = dump.setDefaultString("yes") + assert not ok + ok = dump.setDefaultScalar(3.1415) + assert not ok + + ds.destroyAllAttributes() + nattrs = ds.getNumAttributes() + assert nattrs == 0 def test_view_attr(): - print("Some warnings are expected in the 'view_attr' test") + print("Some warnings are expected in the 'view_attr' test") - ds = pysidre.DataStore() + ds = pysidre.DataStore() - # Create all attributes for DataStore - attr_color = ds.createAttributeString(g_name_color, g_color_none) - assert attr_color is not None + # Create all attributes for DataStore + attr_color = ds.createAttributeString(g_name_color, g_color_none) + assert attr_color is not None - attr_animal = ds.createAttributeString(g_name_animal, g_animal_none) - assert attr_animal is not None + attr_animal = ds.createAttributeString(g_name_animal, g_animal_none) + assert attr_animal is not None - root = ds.getRoot() + root = ds.getRoot() - # ---------------------------------------- - # Set the first attribute in a Group - grp1 = root.createGroup("grp1") - view1a = grp1.createView(g_namea) - assert view1a is not None + # ---------------------------------------- + # Set the first attribute in a Group + grp1 = root.createGroup("grp1") + view1a = grp1.createView(g_namea) + assert view1a is not None - assert not view1a.hasAttributeValue(g_attr_null) - assert not view1a.hasAttributeValue(attr_color) + assert not view1a.hasAttributeValue(g_attr_null) + assert not view1a.hasAttributeValue(attr_color) - # Check values of unset attributes - out1x = view1a.getAttributeString(attr_color) - assert out1x == g_color_none + # Check values of unset attributes + out1x = view1a.getAttributeString(attr_color) + assert out1x == g_color_none - out1y = view1a.getAttributeString(attr_animal) - assert out1y == g_animal_none + out1y = view1a.getAttributeString(attr_animal) + assert out1y == g_animal_none - ok = view1a.setAttributeString(attr_color, g_color_red) - assert ok + ok = view1a.setAttributeString(attr_color, g_color_red) + assert ok - assert view1a.hasAttributeValue(attr_color) + assert view1a.hasAttributeValue(attr_color) - out = view1a.getAttributeString(attr_color) - assert out == g_color_red + out = view1a.getAttributeString(attr_color) + assert out == g_color_red - # reset attribute value - ok = view1a.setAttributeString(attr_color, g_color_blue) - assert ok + # reset attribute value + ok = view1a.setAttributeString(attr_color, g_color_blue) + assert ok - out1b = view1a.getAttributeString(attr_color) - assert out1b == g_color_blue + out1b = view1a.getAttributeString(attr_color) + assert out1b == g_color_blue - # Check second, unset attribute. Should be default value - assert not view1a.hasAttributeValue(attr_animal) - out1d = view1a.getAttributeString(attr_animal) - assert out1d == g_animal_none + # Check second, unset attribute. Should be default value + assert not view1a.hasAttributeValue(attr_animal) + out1d = view1a.getAttributeString(attr_animal) + assert out1d == g_animal_none - # Now set second attribute - ok = view1a.setAttributeString(attr_animal, g_animal_dog) - assert ok + # Now set second attribute + ok = view1a.setAttributeString(attr_animal, g_animal_dog) + assert ok - out1c = view1a.getAttributeString(attr_animal) - assert out1c == g_animal_dog + out1c = view1a.getAttributeString(attr_animal) + assert out1c == g_animal_dog - # ---------------------------------------- - # Set the second attribute in a Group - grp2 = root.createGroup("grp2") + # ---------------------------------------- + # Set the second attribute in a Group + grp2 = root.createGroup("grp2") - view2a = grp2.createView(g_namea) - assert view2a is not None + view2a = grp2.createView(g_namea) + assert view2a is not None - assert not view2a.hasAttributeValue(attr_color) - assert not view2a.hasAttributeValue(attr_animal) + assert not view2a.hasAttributeValue(attr_color) + assert not view2a.hasAttributeValue(attr_animal) - ok = view2a.setAttributeString(attr_animal, g_animal_dog) - assert ok + ok = view2a.setAttributeString(attr_animal, g_animal_dog) + assert ok - assert not view2a.hasAttributeValue(attr_color) - assert view2a.hasAttributeValue(attr_animal) + assert not view2a.hasAttributeValue(attr_color) + assert view2a.hasAttributeValue(attr_animal) - out2a = view2a.getAttributeString(attr_animal) - assert out2a == g_animal_dog + out2a = view2a.getAttributeString(attr_animal) + assert out2a == g_animal_dog - # Get the first, unset, attribute - out2b = view2a.getAttributeString(attr_color) - assert out2b == g_color_none + # Get the first, unset, attribute + out2b = view2a.getAttributeString(attr_color) + assert out2b == g_color_none - # Now set first attribute - ok = view2a.setAttributeString(attr_color, g_color_red) - assert ok + # Now set first attribute + ok = view2a.setAttributeString(attr_color, g_color_red) + assert ok - assert view2a.hasAttributeValue(attr_color) - assert view2a.hasAttributeValue(attr_animal) + assert view2a.hasAttributeValue(attr_color) + assert view2a.hasAttributeValue(attr_animal) - out2c = view2a.getAttributeString(attr_color) - assert out2c == g_color_red + out2c = view2a.getAttributeString(attr_color) + assert out2c == g_color_red - # Try to get a scalar from string - novalue = view2a.getAttributeScalarInt(attr_color) - assert novalue == 0 + # Try to get a scalar from string + novalue = view2a.getAttributeScalarInt(attr_color) + assert novalue == 0 - # ---------------------------------------- - # Set attribute on second View in a Group - grp3 = root.createGroup("grp3") - view3a = grp3.createView(g_namea) - assert view3a is not None - view3b = grp3.createView(g_nameb) - assert view3b is not None + # ---------------------------------------- + # Set attribute on second View in a Group + grp3 = root.createGroup("grp3") + view3a = grp3.createView(g_namea) + assert view3a is not None + view3b = grp3.createView(g_nameb) + assert view3b is not None - ok = view3b.setAttributeString(attr_animal, g_animal_dog) - assert ok + ok = view3b.setAttributeString(attr_animal, g_animal_dog) + assert ok - assert not view3b.hasAttributeValue(attr_color) - assert view3b.hasAttributeValue(attr_animal) + assert not view3b.hasAttributeValue(attr_color) + assert view3b.hasAttributeValue(attr_animal) - out3a = view3b.getAttributeString(attr_animal) - assert out3a == g_animal_dog + out3a = view3b.getAttributeString(attr_animal) + assert out3a == g_animal_dog - # ---------------------------------------- - # Moving a view should preserve attributes - grp4 = root.createGroup("grp4") + # ---------------------------------------- + # Moving a view should preserve attributes + grp4 = root.createGroup("grp4") - grp4.moveView(view3b) + grp4.moveView(view3b) - out4a = view3b.getAttributeString(attr_animal) - assert out4a == g_animal_dog + out4a = view3b.getAttributeString(attr_animal) + assert out4a == g_animal_dog - # Create an attribute which will be destroyed - view3a.setAttributeString(attr_animal, g_animal_dog) + # Create an attribute which will be destroyed + view3a.setAttributeString(attr_animal, g_animal_dog) - grp3.destroyView(g_namea) - grp4.destroyView(g_nameb) + grp3.destroyView(g_namea) + grp4.destroyView(g_nameb) def test_view_int_and_double(): - print("Some warnings are expected in the 'view_int_and_double' test") + print("Some warnings are expected in the 'view_int_and_double' test") - ds = pysidre.DataStore() + ds = pysidre.DataStore() - # Create all attributes for DataStore - attr_dump = ds.createAttributeScalar(g_name_dump, g_dump_no) - assert attr_dump is not None - assert attr_dump.getTypeID() == pysidre.TypeID.INT32_ID + # Create all attributes for DataStore + attr_dump = ds.createAttributeScalar(g_name_dump, g_dump_no) + assert attr_dump is not None + assert attr_dump.getTypeID() == pysidre.TypeID.INT32_ID - attr_size = ds.createAttributeScalar(g_name_size, g_size_small) - assert attr_size is not None - assert attr_size.getTypeID() == pysidre.TypeID.FLOAT64_ID + attr_size = ds.createAttributeScalar(g_name_size, g_size_small) + assert attr_size is not None + assert attr_size.getTypeID() == pysidre.TypeID.FLOAT64_ID - root = ds.getRoot() + root = ds.getRoot() - # ---------------------------------------- - # Create a View - grp1 = root.createGroup("grp1") - view1a = grp1.createView(g_namea) - assert view1a is not None + # ---------------------------------------- + # Create a View + grp1 = root.createGroup("grp1") + view1a = grp1.createView(g_namea) + assert view1a is not None - # Get default values - dump = view1a.getAttributeScalarInt(attr_dump) - assert dump == g_dump_no + # Get default values + dump = view1a.getAttributeScalarInt(attr_dump) + assert dump == g_dump_no - size = view1a.getAttributeScalarFloat(attr_size) - assert size == g_size_small + size = view1a.getAttributeScalarFloat(attr_size) + assert size == g_size_small - # Set values - ok = view1a.setAttributeScalar(attr_dump, g_dump_yes) - assert ok - dump = -1 # clear value - dump = view1a.getAttributeScalarInt(attr_dump) - assert dump == g_dump_yes + # Set values + ok = view1a.setAttributeScalar(attr_dump, g_dump_yes) + assert ok + dump = -1 # clear value + dump = view1a.getAttributeScalarInt(attr_dump) + assert dump == g_dump_yes - ok = view1a.setAttributeScalar(attr_size, g_size_medium) - assert ok - size = 0.0 # clear value - size = view1a.getAttributeScalarFloat(attr_size) - assert size == g_size_medium + ok = view1a.setAttributeScalar(attr_size, g_size_medium) + assert ok + size = 0.0 # clear value + size = view1a.getAttributeScalarFloat(attr_size) + assert size == g_size_medium - # Set values with incorrect types - ok = view1a.setAttributeScalar(attr_dump, g_size_small) - assert not ok - ok = view1a.setAttributeString(attr_dump, g_namea) - assert not ok - ok = view1a.setAttributeString(attr_dump, "g_namea") - assert not ok + # Set values with incorrect types + ok = view1a.setAttributeScalar(attr_dump, g_size_small) + assert not ok + ok = view1a.setAttributeString(attr_dump, g_namea) + assert not ok + ok = view1a.setAttributeString(attr_dump, "g_namea") + assert not ok - # Try to get a string from a scalar - nostr = view1a.getAttributeString(attr_dump) - # In Python, might return None or empty string - assert nostr is None or nostr == "" + # Try to get a string from a scalar + nostr = view1a.getAttributeString(attr_dump) + # In Python, might return None or empty string + assert nostr is None or nostr == "" - i = -1 - i = view1a.getAttributeScalarInt(g_attr_null) - assert i == 0 + i = -1 + i = view1a.getAttributeScalarInt(g_attr_null) + assert i == 0 def test_set_default(): - print("Some warnings are expected in the 'set_default' test") + print("Some warnings are expected in the 'set_default' test") - ds = pysidre.DataStore() + ds = pysidre.DataStore() - # Create all attributes for DataStore - attr_dump = ds.createAttributeScalar(g_name_dump, g_dump_no) - assert attr_dump is not None - assert attr_dump.getTypeID() == pysidre.TypeID.INT32_ID + # Create all attributes for DataStore + attr_dump = ds.createAttributeScalar(g_name_dump, g_dump_no) + assert attr_dump is not None + assert attr_dump.getTypeID() == pysidre.TypeID.INT32_ID - attr_size = ds.createAttributeScalar(g_name_size, g_size_small) - assert attr_size is not None - assert attr_size.getTypeID() == pysidre.TypeID.FLOAT64_ID + attr_size = ds.createAttributeScalar(g_name_size, g_size_small) + assert attr_size is not None + assert attr_size.getTypeID() == pysidre.TypeID.FLOAT64_ID - root = ds.getRoot() + root = ds.getRoot() - # ---------------------------------------- - # Create a View - grp1 = root.createGroup("grp1") - view1a = grp1.createView(g_namea) - assert view1a is not None + # ---------------------------------------- + # Create a View + grp1 = root.createGroup("grp1") + view1a = grp1.createView(g_namea) + assert view1a is not None - # reset unset attribute 1 - assert not view1a.hasAttributeValue(attr_dump) + # reset unset attribute 1 + assert not view1a.hasAttributeValue(attr_dump) - ok = view1a.setAttributeToDefault(attr_dump) - assert ok + ok = view1a.setAttributeToDefault(attr_dump) + assert ok - assert not view1a.hasAttributeValue(attr_dump) + assert not view1a.hasAttributeValue(attr_dump) - # Set value - ok = view1a.setAttributeScalar(attr_dump, g_dump_yes) - assert ok - assert view1a.hasAttributeValue(attr_dump) + # Set value + ok = view1a.setAttributeScalar(attr_dump, g_dump_yes) + assert ok + assert view1a.hasAttributeValue(attr_dump) - # reset set attribute 1 - ok = view1a.setAttributeToDefault(attr_dump) - assert ok - assert not view1a.hasAttributeValue(attr_dump) + # reset set attribute 1 + ok = view1a.setAttributeToDefault(attr_dump) + assert ok + assert not view1a.hasAttributeValue(attr_dump) - # reset unset attribute 2 - assert not view1a.hasAttributeValue(attr_size) + # reset unset attribute 2 + assert not view1a.hasAttributeValue(attr_size) - ok = view1a.setAttributeToDefault(attr_size) - assert ok + ok = view1a.setAttributeToDefault(attr_size) + assert ok - assert not view1a.hasAttributeValue(attr_size) + assert not view1a.hasAttributeValue(attr_size) - # Check errors - ok = view1a.setAttributeToDefault(g_attr_null) - assert not ok + # Check errors + ok = view1a.setAttributeToDefault(g_attr_null) + assert not ok # ------------------------------------------------------------------------------ # get attribute as Conduit::Node - -# Requires conduit::Node information -""" def test_as_node(): - print("Some warnings are expected in the 'as_node' test") + print("Some warnings are expected in the 'as_node' test") - ds = pysidre.DataStore() + ds = pysidre.DataStore() - # Create attributes for DataStore - attr_color = ds.createAttributeString(g_name_color, g_color_none) - assert attr_color is not None + # Create attributes for DataStore + attr_color = ds.createAttributeString(g_name_color, g_color_none) + assert attr_color is not None - attr_dump = ds.createAttributeScalar(g_name_dump, g_dump_no) - assert attr_dump is not None + attr_dump = ds.createAttributeScalar(g_name_dump, g_dump_no) + assert attr_dump is not None - root = ds.getRoot() + root = ds.getRoot() - # ---------------------------------------- - # Set the first attribute in a Group - grp1 = root.createGroup("grp1") - view1a = grp1.createView(g_namea) - assert view1a is not None + # ---------------------------------------- + # Set the first attribute in a Group + grp1 = root.createGroup("grp1") + view1a = grp1.createView(g_namea) + assert view1a is not None - ok = view1a.setAttributeString(attr_color, g_color_red) - assert ok + ok = view1a.setAttributeString(attr_color, g_color_red) + assert ok - node1 = view1a.getAttributeNodeRef(attr_color) - assert node1.as_string() == g_color_red + node1 = view1a.getAttributeNodeRef(attr_color) + assert node1.value() == g_color_red - node2 = view1a.getAttributeNodeRef(attr_dump) - assert node2.as_int() == g_dump_no + node2 = view1a.getAttributeNodeRef(attr_dump) + assert node2.value() == g_dump_no - node3 = view1a.getAttributeNodeRef(g_attr_null) - assert node3.schema().dtype().is_empty() -""" + # Not expected to work because "None" is not type Attribute + # (different behavior from C++ in case of nullptr) + # node3 = view1a.getAttributeNodeRef(g_attr_null) + # assert node3.schema().dtype() == DataType.empty() def test_overloads(): - print("Some warnings are expected in the 'overloads' test") - - ds = pysidre.DataStore() - - # Create string and scalar attributes - attr_color = ds.createAttributeString(g_name_color, g_color_none) - assert attr_color is not None - icolor = attr_color.getIndex() - assert icolor == 0 - - attr_dump = ds.createAttributeScalar(g_name_dump, g_dump_no) - assert attr_dump is not None - idump = attr_dump.getIndex() - assert idump == 1 - - assert attr_color == ds.getAttribute(g_name_color) - assert attr_color == ds.getAttribute(icolor) - - # ---------------------------------------- - root = ds.getRoot() - view = root.createView("view1") - - # string - ok = view.setAttributeString(attr_color, g_color_red) - assert ok - ok = view.setAttributeString(icolor, g_color_red) - assert ok - ok = view.setAttributeString(g_name_color, g_color_red) - assert ok - - attr1a = view.getAttributeString(attr_color) - assert attr1a == g_color_red - attr2a = view.getAttributeString(icolor) - assert attr2a == g_color_red - attr3a = view.getAttributeString(g_name_color) - assert attr3a == g_color_red - - # scalar - ok = view.setAttributeScalar(attr_dump, g_dump_yes) - assert ok - ok = view.setAttributeScalar(idump, g_dump_yes) - assert ok - ok = view.setAttributeScalar(g_name_dump, g_dump_yes) - assert ok - - attr1b = view.getAttributeScalarInt(attr_dump) - assert attr1b == g_dump_yes - attr2b = view.getAttributeScalarInt(idump) - assert attr2b == g_dump_yes - attr3b = view.getAttributeScalarInt(g_name_dump) - assert attr3b == g_dump_yes - - assert view.getAttributeScalarInt(attr_dump) == g_dump_yes - assert view.getAttributeScalarInt(idump) == g_dump_yes - assert view.getAttributeScalarInt(g_name_dump) == g_dump_yes - - # Requires conduit::Node information - """ - node1 = view.getAttributeNodeRef(attr_dump) - assert node1.as_int() == g_dump_yes - node2 = view.getAttributeNodeRef(idump) - assert node2.as_int() == g_dump_yes - node3 = view.getAttributeNodeRef(g_name_dump) - assert node3.as_int() == g_dump_yes - """ - - assert view.hasAttributeValue(attr_dump) - assert view.hasAttributeValue(idump) - assert view.hasAttributeValue(g_name_dump) - - ok = view.setAttributeToDefault(attr_dump) - assert ok - ok = view.setAttributeToDefault(idump) - assert ok - ok = view.setAttributeToDefault(g_name_dump) - assert ok - - # Attribute no longer set - assert not view.hasAttributeValue(attr_dump) - assert not view.hasAttributeValue(idump) - assert not view.hasAttributeValue(g_name_dump) - - # Check some errors - assert view.getAttributeScalarInt(g_attr_null) == 0 - assert view.getAttributeScalarInt(pysidre.InvalidIndex) == 0 - assert view.getAttributeScalarInt("noname") == 0 + print("Some warnings are expected in the 'overloads' test") + + ds = pysidre.DataStore() + + # Create string and scalar attributes + attr_color = ds.createAttributeString(g_name_color, g_color_none) + assert attr_color is not None + icolor = attr_color.getIndex() + assert icolor == 0 + + attr_dump = ds.createAttributeScalar(g_name_dump, g_dump_no) + assert attr_dump is not None + idump = attr_dump.getIndex() + assert idump == 1 + + assert attr_color == ds.getAttribute(g_name_color) + assert attr_color == ds.getAttribute(icolor) + + # ---------------------------------------- + root = ds.getRoot() + view = root.createView("view1") + + # string + ok = view.setAttributeString(attr_color, g_color_red) + assert ok + ok = view.setAttributeString(icolor, g_color_red) + assert ok + ok = view.setAttributeString(g_name_color, g_color_red) + assert ok + + attr1a = view.getAttributeString(attr_color) + assert attr1a == g_color_red + attr2a = view.getAttributeString(icolor) + assert attr2a == g_color_red + attr3a = view.getAttributeString(g_name_color) + assert attr3a == g_color_red + + # scalar + ok = view.setAttributeScalar(attr_dump, g_dump_yes) + assert ok + ok = view.setAttributeScalar(idump, g_dump_yes) + assert ok + ok = view.setAttributeScalar(g_name_dump, g_dump_yes) + assert ok + + attr1b = view.getAttributeScalarInt(attr_dump) + assert attr1b == g_dump_yes + attr2b = view.getAttributeScalarInt(idump) + assert attr2b == g_dump_yes + attr3b = view.getAttributeScalarInt(g_name_dump) + assert attr3b == g_dump_yes + + assert view.getAttributeScalarInt(attr_dump) == g_dump_yes + assert view.getAttributeScalarInt(idump) == g_dump_yes + assert view.getAttributeScalarInt(g_name_dump) == g_dump_yes + + node1 = view.getAttributeNodeRef(attr_dump) + assert node1.value() == g_dump_yes + node2 = view.getAttributeNodeRef(idump) + assert node2.value() == g_dump_yes + node3 = view.getAttributeNodeRef(g_name_dump) + assert node3.value() == g_dump_yes + + assert view.hasAttributeValue(attr_dump) + assert view.hasAttributeValue(idump) + assert view.hasAttributeValue(g_name_dump) + + ok = view.setAttributeToDefault(attr_dump) + assert ok + ok = view.setAttributeToDefault(idump) + assert ok + ok = view.setAttributeToDefault(g_name_dump) + assert ok + + # Attribute no longer set + assert not view.hasAttributeValue(attr_dump) + assert not view.hasAttributeValue(idump) + assert not view.hasAttributeValue(g_name_dump) + + # Check some errors + assert view.getAttributeScalarInt(g_attr_null) == 0 + assert view.getAttributeScalarInt(pysidre.InvalidIndex) == 0 + assert view.getAttributeScalarInt("noname") == 0 def test_loop_attributes(): - ds = pysidre.DataStore() - - # Create attributes for DataStore - color = ds.createAttributeString(g_name_color, g_color_none) - icolor = color.getIndex() - assert icolor == 0 - - dump = ds.createAttributeScalar(g_name_dump, g_dump_no) - idump = dump.getIndex() - assert idump == 1 - - size = ds.createAttributeScalar(g_name_size, g_size_small) - isize = size.getIndex() - assert isize == 2 - - # Loop over attribute indices in DataStore - idx1 = ds.getFirstValidAttributeIndex() - assert idx1 == 0 - idx2 = ds.getNextValidAttributeIndex(idx1) - assert idx2 == 1 - idx3 = ds.getNextValidAttributeIndex(idx2) - assert idx3 == 2 - idx4 = ds.getNextValidAttributeIndex(idx3) - assert idx4 == pysidre.InvalidIndex - idx5 = ds.getNextValidAttributeIndex(idx4) - assert idx5 == pysidre.InvalidIndex - - # ---------------------------------------- - root = ds.getRoot() - - # set all attributes - view1 = root.createView("view1") - view1.setAttributeString(color, g_color_red) - view1.setAttributeScalar(dump, g_dump_yes) - view1.setAttributeScalar(size, g_size_large) - - idx1 = view1.getFirstValidAttrValueIndex() - assert idx1 == 0 - idx2 = view1.getNextValidAttrValueIndex(idx1) - assert idx2 == 1 - idx3 = view1.getNextValidAttrValueIndex(idx2) - assert idx3 == 2 - idx4 = view1.getNextValidAttrValueIndex(idx3) - assert idx4 == pysidre.InvalidIndex - - # set first attribute - view2 = root.createView("view2") - view2.setAttributeString(color, g_color_red) - - idx1 = view2.getFirstValidAttrValueIndex() - assert idx1 == 0 - idx2 = view2.getNextValidAttrValueIndex(idx1) - assert idx2 == pysidre.InvalidIndex - - # set last attribute - view3 = root.createView("view3") - view3.setAttributeScalar(size, g_size_large) - - idx1 = view3.getFirstValidAttrValueIndex() - assert idx1 == 2 - idx2 = view3.getNextValidAttrValueIndex(idx1) - assert idx2 == pysidre.InvalidIndex - - # set first and last attributes - view4 = root.createView("view4") - view4.setAttributeString(color, g_color_red) - view4.setAttributeScalar(size, g_size_large) - - idx1 = view4.getFirstValidAttrValueIndex() - assert idx1 == 0 - idx2 = view4.getNextValidAttrValueIndex(idx1) - assert idx2 == 2 - idx3 = view4.getNextValidAttrValueIndex(idx2) - assert idx3 == pysidre.InvalidIndex - - # no attributes - view5 = root.createView("view5") - - idx1 = view5.getFirstValidAttrValueIndex() - assert idx1 == pysidre.InvalidIndex - idx2 = view5.getNextValidAttrValueIndex(idx1) - assert idx2 == pysidre.InvalidIndex + ds = pysidre.DataStore() + + # Create attributes for DataStore + color = ds.createAttributeString(g_name_color, g_color_none) + icolor = color.getIndex() + assert icolor == 0 + + dump = ds.createAttributeScalar(g_name_dump, g_dump_no) + idump = dump.getIndex() + assert idump == 1 + + size = ds.createAttributeScalar(g_name_size, g_size_small) + isize = size.getIndex() + assert isize == 2 + + # Loop over attribute indices in DataStore + idx1 = ds.getFirstValidAttributeIndex() + assert idx1 == 0 + idx2 = ds.getNextValidAttributeIndex(idx1) + assert idx2 == 1 + idx3 = ds.getNextValidAttributeIndex(idx2) + assert idx3 == 2 + idx4 = ds.getNextValidAttributeIndex(idx3) + assert idx4 == pysidre.InvalidIndex + idx5 = ds.getNextValidAttributeIndex(idx4) + assert idx5 == pysidre.InvalidIndex + + # ---------------------------------------- + root = ds.getRoot() + + # set all attributes + view1 = root.createView("view1") + view1.setAttributeString(color, g_color_red) + view1.setAttributeScalar(dump, g_dump_yes) + view1.setAttributeScalar(size, g_size_large) + + idx1 = view1.getFirstValidAttrValueIndex() + assert idx1 == 0 + idx2 = view1.getNextValidAttrValueIndex(idx1) + assert idx2 == 1 + idx3 = view1.getNextValidAttrValueIndex(idx2) + assert idx3 == 2 + idx4 = view1.getNextValidAttrValueIndex(idx3) + assert idx4 == pysidre.InvalidIndex + + # set first attribute + view2 = root.createView("view2") + view2.setAttributeString(color, g_color_red) + + idx1 = view2.getFirstValidAttrValueIndex() + assert idx1 == 0 + idx2 = view2.getNextValidAttrValueIndex(idx1) + assert idx2 == pysidre.InvalidIndex + + # set last attribute + view3 = root.createView("view3") + view3.setAttributeScalar(size, g_size_large) + + idx1 = view3.getFirstValidAttrValueIndex() + assert idx1 == 2 + idx2 = view3.getNextValidAttrValueIndex(idx1) + assert idx2 == pysidre.InvalidIndex + + # set first and last attributes + view4 = root.createView("view4") + view4.setAttributeString(color, g_color_red) + view4.setAttributeScalar(size, g_size_large) + + idx1 = view4.getFirstValidAttrValueIndex() + assert idx1 == 0 + idx2 = view4.getNextValidAttrValueIndex(idx1) + assert idx2 == 2 + idx3 = view4.getNextValidAttrValueIndex(idx2) + assert idx3 == pysidre.InvalidIndex + + # no attributes + view5 = root.createView("view5") + + idx1 = view5.getFirstValidAttrValueIndex() + assert idx1 == pysidre.InvalidIndex + idx2 = view5.getNextValidAttrValueIndex(idx1) + assert idx2 == pysidre.InvalidIndex def test_iterate_attributes(): - ds = pysidre.DataStore() + ds = pysidre.DataStore() - # Create attributes for DataStore - color = ds.createAttributeString(g_name_color, g_color_none) - icolor = color.getIndex() - assert icolor == 0 + # Create attributes for DataStore + color = ds.createAttributeString(g_name_color, g_color_none) + icolor = color.getIndex() + assert icolor == 0 - dump = ds.createAttributeScalar(g_name_dump, g_dump_no) - idump = dump.getIndex() - assert idump == 1 + dump = ds.createAttributeScalar(g_name_dump, g_dump_no) + idump = dump.getIndex() + assert idump == 1 - size = ds.createAttributeScalar(g_name_size, g_size_small) - isize = size.getIndex() - assert isize == 2 + size = ds.createAttributeScalar(g_name_size, g_size_small) + isize = size.getIndex() + assert isize == 2 - for attr in ds.attributes(): - idx = attr.getIndex() - if idx == 0: - assert attr.getName() == g_name_color - elif idx == 1: - assert attr.getName() == g_name_dump - elif idx == 2: - assert attr.getName() == g_name_size - else: - raise AssertionError(f"Unexpected attribute: {{id:{idx}, name:'{attr.getName()}'}}") + for attr in ds.attributes(): + idx = attr.getIndex() + if idx == 0: + assert attr.getName() == g_name_color + elif idx == 1: + assert attr.getName() == g_name_dump + elif idx == 2: + assert attr.getName() == g_name_size + else: + raise AssertionError(f"Unexpected attribute: {{id:{idx}, name:'{attr.getName()}'}}") - # Destroy all attributes and check for empty - ds.destroyAllAttributes() - assert ds.getNumAttributes() == 0 + # Destroy all attributes and check for empty + ds.destroyAllAttributes() + assert ds.getNumAttributes() == 0 - for attr in ds.attributes(): - raise AssertionError(f"Expected no attributes, but found: {{id:{attr.getIndex()}, name:'{attr.getName()}'}}") + for attr in ds.attributes(): + raise AssertionError( + f"Expected no attributes, but found: {{id:{attr.getIndex()}, name:'{attr.getName()}'}}") def test_save_attributes(): - # Setup test data - idata = np.zeros(5, dtype=int) - file_path_base = "sidre_attribute_datastore_" + # Setup test data + idata = np.zeros(5, dtype=int) + file_path_base = "sidre_attribute_datastore_" - ds1 = pysidre.DataStore() - root1 = ds1.getRoot() + ds1 = pysidre.DataStore() + root1 = ds1.getRoot() - # Create attributes for DataStore - color = ds1.createAttributeString(g_name_color, g_color_none) - assert color is not None + # Create attributes for DataStore + color = ds1.createAttributeString(g_name_color, g_color_none) + assert color is not None - dump = ds1.createAttributeScalar(g_name_dump, g_dump_no) - assert dump is not None + dump = ds1.createAttributeScalar(g_name_dump, g_dump_no) + assert dump is not None - size = ds1.createAttributeScalar(g_name_size, g_size_small) - assert size is not None + size = ds1.createAttributeScalar(g_name_size, g_size_small) + assert size is not None - assert ds1.getNumAttributes() == 3 + assert ds1.getNumAttributes() == 3 - # empty - view1a = root1.createView("empty") - view1a.setAttributeString(color, "color-empty") - view1a.setAttributeScalar(dump, g_dump_yes) - view1a.setAttributeScalar(size, g_size_small) - - # buffer - view1b = root1.createViewAndAllocate("buffer", pysidre.TypeID.INT_ID, 5) - bdata = view1b.getDataArray() - view1b.setAttributeString(color, "color-buffer") - view1b.setAttributeScalar(size, g_size_medium) + # empty + view1a = root1.createView("empty") + view1a.setAttributeString(color, "color-empty") + view1a.setAttributeScalar(dump, g_dump_yes) + view1a.setAttributeScalar(size, g_size_small) + + # buffer + view1b = root1.createViewAndAllocate("buffer", pysidre.TypeID.INT_ID, 5) + bdata = view1b.getDataArray() + view1b.setAttributeString(color, "color-buffer") + view1b.setAttributeScalar(size, g_size_medium) - # external - view1c = root1.createView("external", pysidre.TypeID.INT_ID, 5, idata) - view1c.setAttributeScalar(size, g_size_large) + # external + view1c = root1.createView("external", pysidre.TypeID.INT_ID, 5, idata) + view1c.setAttributeScalar(size, g_size_large) - # scalar - view1d = root1.createViewScalar("scalar", 1) - view1d.setAttributeString(color, "color-scalar") + # scalar + view1d = root1.createViewScalar("scalar", 1) + view1d.setAttributeString(color, "color-scalar") - # string - view1e = root1.createViewString("string", "value") - view1e.setAttributeString(color, "color-string") + # string + view1e = root1.createViewString("string", "value") + view1e.setAttributeString(color, "color-string") - # empty without attributes - root1.createView("empty-no-attributes") + # empty without attributes + root1.createView("empty-no-attributes") - for i in range(5): - idata[i] = i - bdata[i] = i + for i in range(5): + idata[i] = i + bdata[i] = i - # ---------------------------------------- + # ---------------------------------------- - # Save using all protocols - for i in range(g_nprotocols): - file_path = file_path_base + g_protocols[i] - root1.save(file_path, g_protocols[i]) + # Save using all protocols + for i in range(g_nprotocols): + file_path = file_path_base + g_protocols[i] + root1.save(file_path, g_protocols[i]) - # Delete ds1 reference to simulate closing the file - del ds1 + # Delete ds1 reference to simulate closing the file + del ds1 - # ---------------------------------------- + # ---------------------------------------- - # Only restore sidre_hdf5 protocol - for i in range(g_nprotocols): - if g_protocols[i] != "sidre_hdf5": - continue + # Only restore sidre_hdf5 protocol + for i in range(g_nprotocols): + if g_protocols[i] != "sidre_hdf5": + continue - file_path = file_path_base + g_protocols[i] + file_path = file_path_base + g_protocols[i] - ds2 = pysidre.DataStore() - root2 = ds2.getRoot() + ds2 = pysidre.DataStore() + root2 = ds2.getRoot() - root2.load(file_path, g_protocols[i]) - assert ds2.getNumAttributes() == 3 + root2.load(file_path, g_protocols[i]) + assert ds2.getNumAttributes() == 3 - # Asserts requires conduit::Node information - # Check available attributes - attr_color = ds2.getAttribute(g_name_color) - #assert attr_color.getDefaultNodeRef().as_string() == g_color_none + # Asserts requires conduit::Node information + # Check available attributes + attr_color = ds2.getAttribute(g_name_color) + assert attr_color.getDefaultNodeRef().value() == g_color_none - attr_dump = ds2.getAttribute(g_name_dump) - #assert attr_dump.getDefaultNodeRef().as_int() == g_dump_no + attr_dump = ds2.getAttribute(g_name_dump) + assert attr_dump.getDefaultNodeRef().value() == g_dump_no - attr_size = ds2.getAttribute(g_name_size) - #assert attr_size.getDefaultNodeRef().as_double() == g_size_small + attr_size = ds2.getAttribute(g_name_size) + assert attr_size.getDefaultNodeRef().value() == g_size_small - # Check attributes assigned to Views + # Check attributes assigned to Views - view2a = root2.getView("empty") - assert view2a.hasAttributeValue(g_name_color) - assert view2a.hasAttributeValue(g_name_dump) - assert view2a.hasAttributeValue(g_name_size) - assert view2a.getAttributeString(attr_color) == "color-empty" - assert view2a.getAttributeScalarInt(attr_dump) == g_dump_yes - assert view2a.getAttributeScalarFloat(attr_size) == g_size_small + view2a = root2.getView("empty") + assert view2a.hasAttributeValue(g_name_color) + assert view2a.hasAttributeValue(g_name_dump) + assert view2a.hasAttributeValue(g_name_size) + assert view2a.getAttributeString(attr_color) == "color-empty" + assert view2a.getAttributeScalarInt(attr_dump) == g_dump_yes + assert view2a.getAttributeScalarFloat(attr_size) == g_size_small - view2b = root2.getView("buffer") - assert view2b.hasAttributeValue(g_name_color) - assert not view2b.hasAttributeValue(g_name_dump) - assert view2b.hasAttributeValue(g_name_size) - assert view2b.getAttributeString(attr_color) == "color-buffer" - assert view2b.getAttributeScalarFloat(attr_size) == g_size_medium + view2b = root2.getView("buffer") + assert view2b.hasAttributeValue(g_name_color) + assert not view2b.hasAttributeValue(g_name_dump) + assert view2b.hasAttributeValue(g_name_size) + assert view2b.getAttributeString(attr_color) == "color-buffer" + assert view2b.getAttributeScalarFloat(attr_size) == g_size_medium - view2c = root2.getView("external") - assert not view2c.hasAttributeValue(g_name_color) - assert not view2c.hasAttributeValue(g_name_dump) - assert view2c.hasAttributeValue(g_name_size) - assert view2c.getAttributeScalarFloat(attr_size) == g_size_large + view2c = root2.getView("external") + assert not view2c.hasAttributeValue(g_name_color) + assert not view2c.hasAttributeValue(g_name_dump) + assert view2c.hasAttributeValue(g_name_size) + assert view2c.getAttributeScalarFloat(attr_size) == g_size_large - view2d = root2.getView("scalar") - assert view2d.hasAttributeValue(g_name_color) - assert not view2d.hasAttributeValue(g_name_dump) - assert not view2d.hasAttributeValue(g_name_size) - assert view2d.getAttributeString(attr_color) == "color-scalar" + view2d = root2.getView("scalar") + assert view2d.hasAttributeValue(g_name_color) + assert not view2d.hasAttributeValue(g_name_dump) + assert not view2d.hasAttributeValue(g_name_size) + assert view2d.getAttributeString(attr_color) == "color-scalar" - view2e = root2.getView("string") - assert view2e.hasAttributeValue(g_name_color) - assert not view2e.hasAttributeValue(g_name_dump) - assert not view2e.hasAttributeValue(g_name_size) - assert view2e.getAttributeString(attr_color) == "color-string" + view2e = root2.getView("string") + assert view2e.hasAttributeValue(g_name_color) + assert not view2e.hasAttributeValue(g_name_dump) + assert not view2e.hasAttributeValue(g_name_size) + assert view2e.getAttributeString(attr_color) == "color-string" - view2f = root2.getView("empty-no-attributes") - assert not view2f.hasAttributeValue(g_name_color) - assert not view2f.hasAttributeValue(g_name_dump) - assert not view2f.hasAttributeValue(g_name_size) + view2f = root2.getView("empty-no-attributes") + assert not view2f.hasAttributeValue(g_name_color) + assert not view2f.hasAttributeValue(g_name_dump) + assert not view2f.hasAttributeValue(g_name_size) - del ds2 + del ds2 def test_save_by_attribute(): - idata = np.zeros(5, dtype=int) - jdata = np.zeros(5, dtype=int) - file_path_base = "sidre_attribute_by_attribute_" + idata = np.zeros(5, dtype=int) + jdata = np.zeros(5, dtype=int) + file_path_base = "sidre_attribute_by_attribute_" - ds1 = pysidre.DataStore() - root1 = ds1.getRoot() + ds1 = pysidre.DataStore() + root1 = ds1.getRoot() - # Create attributes for DataStore - dump = ds1.createAttributeScalar(g_name_dump, g_dump_no) - assert dump is not None + # Create attributes for DataStore + dump = ds1.createAttributeScalar(g_name_dump, g_dump_no) + assert dump is not None - # scalar - root1.createViewScalar("view1", 1).setAttributeScalar(dump, g_dump_yes) - root1.createViewScalar("view2", 2) + # scalar + root1.createViewScalar("view1", 1).setAttributeScalar(dump, g_dump_yes) + root1.createViewScalar("view2", 2) - # Create a deep path with and without attribute - root1.createViewScalar("grp1a/grp1b/view3", 3) - root1.createViewScalar("grp2a/view4", 4) # make sure empty "views" not saved - root1.createViewScalar("grp2a/grp2b/view5", 5).setAttributeScalar(dump, g_dump_yes) - root1.createView("view6", pysidre.TypeID.INT32_ID, 5, idata).setAttributeScalar(dump, g_dump_yes) - root1.createView("grp3a/grp3b/view7", pysidre.TypeID.INT32_ID, 5, jdata) + # Create a deep path with and without attribute + root1.createViewScalar("grp1a/grp1b/view3", 3) + root1.createViewScalar("grp2a/view4", 4) # make sure empty "views" not saved + root1.createViewScalar("grp2a/grp2b/view5", 5).setAttributeScalar(dump, g_dump_yes) + root1.createView("view6", pysidre.TypeID.INT32_ID, 5, + idata).setAttributeScalar(dump, g_dump_yes) + root1.createView("grp3a/grp3b/view7", pysidre.TypeID.INT32_ID, 5, jdata) - for i in range(5): - idata[i] = i - jdata[i] = i + 10 + for i in range(5): + idata[i] = i + jdata[i] = i + 10 - # ---------------------------------------- + # ---------------------------------------- - # Save with attribute filter - for i in range(g_nprotocols): - file_path = file_path_base + g_protocols[i] - root1.save(file_path, g_protocols[i], dump) + # Save with attribute filter + for i in range(g_nprotocols): + file_path = file_path_base + g_protocols[i] + root1.save(file_path, g_protocols[i], dump) - # Delete ds1 reference to simulate closing the file - del ds1 + # Delete ds1 reference to simulate closing the file + del ds1 - # ---------------------------------------- + # ---------------------------------------- - # Only restore sidre_hdf5 protocol - for i in range(g_nprotocols): - if g_protocols[i] != "sidre_hdf5": - continue + # Only restore sidre_hdf5 protocol + for i in range(g_nprotocols): + if g_protocols[i] != "sidre_hdf5": + continue - file_path = file_path_base + g_protocols[i] - ds2 = pysidre.DataStore() - root2 = ds2.getRoot() - root2.load(file_path, g_protocols[i]) + file_path = file_path_base + g_protocols[i] + ds2 = pysidre.DataStore() + root2 = ds2.getRoot() + root2.load(file_path, g_protocols[i]) - # Only views with the dump attribute should exist - assert root2.hasView("view1") - assert not root2.hasView("view2") - assert not root2.hasView("grp1a/grp1b/view3") - assert not root2.hasView("grp2a/view4") - assert root2.hasView("grp2a/grp2b/view5") - assert root2.hasView("view6") - assert not root2.hasView("grp3a/grp3b/view7") + # Only views with the dump attribute should exist + assert root2.hasView("view1") + assert not root2.hasView("view2") + assert not root2.hasView("grp1a/grp1b/view3") + assert not root2.hasView("grp2a/view4") + assert root2.hasView("grp2a/grp2b/view5") + assert root2.hasView("view6") + assert not root2.hasView("grp3a/grp3b/view7") - del ds2 + del ds2 def test_save_load_group_with_attributes_new_ds(): - for protocol in g_protocols: - ext = "hdf5" if protocol.endswith("hdf5") else "json" - filename = f"saveFile_{protocol}.{ext}" + for protocol in g_protocols: + ext = "hdf5" if protocol.endswith("hdf5") else "json" + filename = f"saveFile_{protocol}.{ext}" + + # Set up first datastore and save to disk + ds1 = pysidre.DataStore() + ds1.createAttributeScalar("attr", 10) + ds1.createAttributeString(g_name_color, g_color_none) - # Set up first datastore and save to disk - ds1 = pysidre.DataStore() - ds1.createAttributeScalar("attr", 10) - ds1.createAttributeString(g_name_color, g_color_none) + gr1 = ds1.getRoot().createGroup("gr") + gr1.createViewScalar("scalar1", 1) + gr1.createViewScalar("scalar2", 2).setAttributeString(g_name_color, g_color_red) + gr1.createViewScalar("scalar3", 3).setAttributeString(g_name_color, g_color_blue) - gr1 = ds1.getRoot().createGroup("gr") - gr1.createViewScalar("scalar1", 1) - gr1.createViewScalar("scalar2", 2).setAttributeString(g_name_color, g_color_red) - gr1.createViewScalar("scalar3", 3).setAttributeString(g_name_color, g_color_blue) + assert ds1.getNumAttributes() == 2 + assert (pysidre.TypeID.INT32_ID == ds1.getAttribute("attr").getTypeID() + or pysidre.TypeID.INT64_ID == ds1.getAttribute("attr").getTypeID()) + assert pysidre.TypeID.CHAR8_STR_ID == ds1.getAttribute(g_name_color).getTypeID() - assert ds1.getNumAttributes() == 2 - assert (pysidre.TypeID.INT32_ID == ds1.getAttribute("attr").getTypeID() or - pysidre.TypeID.INT64_ID == ds1.getAttribute("attr").getTypeID()) - assert pysidre.TypeID.CHAR8_STR_ID == ds1.getAttribute(g_name_color).getTypeID() + assert not gr1.getView("scalar1").hasAttributeValue(g_name_color) - assert not gr1.getView("scalar1").hasAttributeValue(g_name_color) + assert gr1.getView("scalar2").hasAttributeValue(g_name_color) + assert gr1.getView("scalar2").getAttributeString(g_name_color) == g_color_red - assert gr1.getView("scalar2").hasAttributeValue(g_name_color) - assert gr1.getView("scalar2").getAttributeString(g_name_color) == g_color_red + assert gr1.getView("scalar3").hasAttributeValue(g_name_color) + assert gr1.getView("scalar3").getAttributeString(g_name_color) == g_color_blue - assert gr1.getView("scalar3").hasAttributeValue(g_name_color) - assert gr1.getView("scalar3").getAttributeString(g_name_color) == g_color_blue + gr1.save(filename, protocol) - gr1.save(filename, protocol) + # Check if protocol supports saving attributes + if protocol not in g_protocol_saves_attributes: + print(f"Skipping attribute load tests for protocol '{protocol}' -- " + "it doesn't support saving attributes") + continue - # Check if protocol supports saving attributes - if protocol not in g_protocol_saves_attributes: - print(f"Skipping attribute load tests for protocol '{protocol}' -- " - "it doesn't support saving attributes") - continue + # Load second datastore from saved data + ds2 = pysidre.DataStore() + gr2 = ds2.getRoot().createGroup("gr") + gr2.load(filename, protocol) - # Load second datastore from saved data - ds2 = pysidre.DataStore() - gr2 = ds2.getRoot().createGroup("gr") - gr2.load(filename, protocol) + assert ds2.getNumAttributes() == 2 + assert (pysidre.TypeID.INT32_ID == ds2.getAttribute("attr").getTypeID() + or pysidre.TypeID.INT64_ID == ds2.getAttribute("attr").getTypeID()) + assert pysidre.TypeID.CHAR8_STR_ID == ds2.getAttribute(g_name_color).getTypeID() - assert ds2.getNumAttributes() == 2 - assert (pysidre.TypeID.INT32_ID == ds2.getAttribute("attr").getTypeID() or - pysidre.TypeID.INT64_ID == ds2.getAttribute("attr").getTypeID()) - assert pysidre.TypeID.CHAR8_STR_ID == ds2.getAttribute(g_name_color).getTypeID() + assert gr2.hasView("scalar1") + assert not gr2.getView("scalar1").hasAttributeValue(g_name_color) - assert gr2.hasView("scalar1") - assert not gr2.getView("scalar1").hasAttributeValue(g_name_color) + assert gr2.hasView("scalar2") + assert gr2.getView("scalar2").hasAttributeValue(g_name_color) + assert gr2.getView("scalar2").getAttributeString(g_name_color) == g_color_red - assert gr2.hasView("scalar2") - assert gr2.getView("scalar2").hasAttributeValue(g_name_color) - assert gr2.getView("scalar2").getAttributeString(g_name_color) == g_color_red + assert gr2.hasView("scalar3") + assert gr2.getView("scalar3").hasAttributeValue(g_name_color) + assert gr2.getView("scalar3").getAttributeString(g_name_color) == g_color_blue - assert gr2.hasView("scalar3") - assert gr2.getView("scalar3").hasAttributeValue(g_name_color) - assert gr2.getView("scalar3").getAttributeString(g_name_color) == g_color_blue + # Compare attributes between ds1 and ds2 + assert ds1.getNumAttributes() == ds2.getNumAttributes() + assert ds1.getAttribute(g_name_color).getName() == ds2.getAttribute(g_name_color).getName() + assert ds1.getAttribute(g_name_color).getTypeID() == ds2.getAttribute( + g_name_color).getTypeID() - # Compare attributes between ds1 and ds2 - assert ds1.getNumAttributes() == ds2.getNumAttributes() - assert ds1.getAttribute(g_name_color).getName() == ds2.getAttribute(g_name_color).getName() - assert ds1.getAttribute(g_name_color).getTypeID() == ds2.getAttribute(g_name_color).getTypeID() - - # Requires conduit::Node information - # assert ds1.getAttribute(g_name_color).getDefaultNodeRef().to_string() == ds2.getAttribute(g_name_color).getDefaultNodeRef().to_string() + assert ds1.getAttribute(g_name_color).getDefaultNodeRef().value() == ds2.getAttribute( + g_name_color).getDefaultNodeRef().value() def test_save_load_group_with_attributes_same_ds(): - for protocol in g_protocols: - ext = "hdf5" if protocol.endswith("hdf5") else "json" - filename = f"saveFile_{protocol}.{ext}" + for protocol in g_protocols: + ext = "hdf5" if protocol.endswith("hdf5") else "json" + filename = f"saveFile_{protocol}.{ext}" - print(f"Checking attribute save/load w/ protocol '{protocol}' using file '{filename}'") + print(f"Checking attribute save/load w/ protocol '{protocol}' using file '{filename}'") - # Create the DataStore and attributes - ds = pysidre.DataStore() - ds.createAttributeScalar("attr", 10) - ds.createAttributeString(g_name_color, g_color_none) + # Create the DataStore and attributes + ds = pysidre.DataStore() + ds.createAttributeScalar("attr", 10) + ds.createAttributeString(g_name_color, g_color_none) - # Attach some attributes to views - gr = ds.getRoot().createGroup("gr") - gr.createViewScalar("scalar1", 1) - gr.createViewScalar("scalar2", 2).setAttributeString(g_name_color, g_color_red) - gr.createViewScalar("scalar3", 3).setAttributeString(g_name_color, g_color_blue) + # Attach some attributes to views + gr = ds.getRoot().createGroup("gr") + gr.createViewScalar("scalar1", 1) + gr.createViewScalar("scalar2", 2).setAttributeString(g_name_color, g_color_red) + gr.createViewScalar("scalar3", 3).setAttributeString(g_name_color, g_color_blue) - assert ds.getNumAttributes() == 2 + assert ds.getNumAttributes() == 2 - assert not gr.getView("scalar1").hasAttributeValue(g_name_color) + assert not gr.getView("scalar1").hasAttributeValue(g_name_color) - assert gr.getView("scalar2").hasAttributeValue(g_name_color) - assert gr.getView("scalar2").getAttributeString(g_name_color) == g_color_red + assert gr.getView("scalar2").hasAttributeValue(g_name_color) + assert gr.getView("scalar2").getAttributeString(g_name_color) == g_color_red - assert gr.getView("scalar3").hasAttributeValue(g_name_color) - assert gr.getView("scalar3").getAttributeString(g_name_color) == g_color_blue + assert gr.getView("scalar3").hasAttributeValue(g_name_color) + assert gr.getView("scalar3").getAttributeString(g_name_color) == g_color_blue - gr.save(filename, protocol) + gr.save(filename, protocol) - # Check if protocol supports saving attributes - if protocol not in g_protocol_saves_attributes: - print(f"Skipping attribute load tests for protocol '{protocol}' -- " - "it doesn't support saving attributes") - continue + # Check if protocol supports saving attributes + if protocol not in g_protocol_saves_attributes: + print(f"Skipping attribute load tests for protocol '{protocol}' -- " + "it doesn't support saving attributes") + continue - # First load: check that things are still as expected after loading - gr.load(filename, protocol) - assert ds.getNumAttributes() == 2 - assert not gr.getView("scalar1").hasAttributeValue(g_name_color) - assert gr.getView("scalar2").hasAttributeValue(g_name_color) - assert gr.getView("scalar2").getAttributeString(g_name_color) == g_color_red - assert gr.getView("scalar3").hasAttributeValue(g_name_color) - assert gr.getView("scalar3").getAttributeString(g_name_color) == g_color_blue + # First load: check that things are still as expected after loading + gr.load(filename, protocol) + assert ds.getNumAttributes() == 2 + assert not gr.getView("scalar1").hasAttributeValue(g_name_color) + assert gr.getView("scalar2").hasAttributeValue(g_name_color) + assert gr.getView("scalar2").getAttributeString(g_name_color) == g_color_red + assert gr.getView("scalar3").hasAttributeValue(g_name_color) + assert gr.getView("scalar3").getAttributeString(g_name_color) == g_color_blue - # Second load: check that changes to attributes get overwritten when loading - ds.destroyAttribute("attr") - gr.getView("scalar1").setAttributeString(g_name_color, g_color_red) - gr.getView("scalar2").setAttributeToDefault(g_name_color) - gr.getView("scalar3").setAttributeString(g_name_color, g_color_red) + # Second load: check that changes to attributes get overwritten when loading + ds.destroyAttribute("attr") + gr.getView("scalar1").setAttributeString(g_name_color, g_color_red) + gr.getView("scalar2").setAttributeToDefault(g_name_color) + gr.getView("scalar3").setAttributeString(g_name_color, g_color_red) - assert ds.getNumAttributes() == 1 + assert ds.getNumAttributes() == 1 - # Reload group from file; this should revert changes - gr.load(filename, protocol) + # Reload group from file; this should revert changes + gr.load(filename, protocol) - # Check that things are reverted after loading - assert ds.getNumAttributes() == 2 - assert not gr.getView("scalar1").hasAttributeValue(g_name_color) - assert gr.getView("scalar2").hasAttributeValue(g_name_color) - assert gr.getView("scalar2").getAttributeString(g_name_color) == g_color_red - assert gr.getView("scalar3").hasAttributeValue(g_name_color) - assert gr.getView("scalar3").getAttributeString(g_name_color) == g_color_blue \ No newline at end of file + # Check that things are reverted after loading + assert ds.getNumAttributes() == 2 + assert not gr.getView("scalar1").hasAttributeValue(g_name_color) + assert gr.getView("scalar2").hasAttributeValue(g_name_color) + assert gr.getView("scalar2").getAttributeString(g_name_color) == g_color_red + assert gr.getView("scalar3").hasAttributeValue(g_name_color) + assert gr.getView("scalar3").getAttributeString(g_name_color) == g_color_blue diff --git a/src/axom/sidre/tests/sidre_buffer_Py.py b/src/axom/sidre/tests/sidre_buffer_Py.py index bc19b828be..a42db76480 100644 --- a/src/axom/sidre/tests/sidre_buffer_Py.py +++ b/src/axom/sidre/tests/sidre_buffer_Py.py @@ -9,120 +9,121 @@ NUM_BYTES_INT_32 = 4 + def test_create_buffers(): - ds = pysidre.DataStore() - assert ds.getNumBuffers() == 0 + ds = pysidre.DataStore() + assert ds.getNumBuffers() == 0 - dbuff_0 = ds.createBuffer() - assert ds.getNumBuffers() == 1 - assert dbuff_0.getIndex() == 0 + dbuff_0 = ds.createBuffer() + assert ds.getNumBuffers() == 1 + assert dbuff_0.getIndex() == 0 - dbuff_1 = ds.createBuffer() - assert ds.getNumBuffers() == 2 - assert dbuff_1.getIndex() == 1 + dbuff_1 = ds.createBuffer() + assert ds.getNumBuffers() == 2 + assert dbuff_1.getIndex() == 1 - # Destroy by index - ds.destroyBuffer(0) - assert ds.getNumBuffers() == 1 + # Destroy by index + ds.destroyBuffer(0) + assert ds.getNumBuffers() == 1 - dbuff_0b = ds.createBuffer() - assert ds.getNumBuffers() == 2 - assert dbuff_0b.getIndex() == 0 + dbuff_0b = ds.createBuffer() + assert ds.getNumBuffers() == 2 + assert dbuff_0b.getIndex() == 0 - ds.print() + ds.print() def test_alloc_buffer_for_int_array(): - ds = pysidre.DataStore() - dbuff = ds.createBuffer() - elem_count = 10 + ds = pysidre.DataStore() + dbuff = ds.createBuffer() + elem_count = 10 + + dbuff.allocate(pysidre.TypeID.INT32_ID, elem_count) - dbuff.allocate(pysidre.TypeID.INT32_ID, elem_count) + # Should be a warning and no-op, buffer is already allocated, we don't want + # to re-allocate and leak memory. + dbuff.allocate() - # Should be a warning and no-op, buffer is already allocated, we don't want - # to re-allocate and leak memory. - dbuff.allocate() + assert dbuff.getTypeID() == pysidre.TypeID.INT32_ID + assert dbuff.getNumElements() == elem_count + assert dbuff.getTotalBytes() == NUM_BYTES_INT_32 * elem_count - assert dbuff.getTypeID() == pysidre.TypeID.INT32_ID - assert dbuff.getNumElements() == elem_count - assert dbuff.getTotalBytes() == NUM_BYTES_INT_32 * elem_count + data = dbuff.getDataArray() - data = dbuff.getDataArray() + assert type(data[0]) == np.int32 - assert type(data[0]) == np.int32 - - for i in range(elem_count): - data[i] = i * i + for i in range(elem_count): + data[i] = i * i - for i in range(elem_count): - assert data[i] == i * i + for i in range(elem_count): + assert data[i] == i * i - dbuff.print() - ds.print() + dbuff.print() + ds.print() def test_init_buffer_for_int_array(): - elem_count = 10 + elem_count = 10 - ds = pysidre.DataStore() - dbuff = ds.createBuffer() + ds = pysidre.DataStore() + dbuff = ds.createBuffer() - dbuff.allocate(pysidre.TypeID.INT32_ID, elem_count) + dbuff.allocate(pysidre.TypeID.INT32_ID, elem_count) - assert dbuff.getTypeID() == pysidre.TypeID.INT32_ID - assert dbuff.getNumElements() == elem_count - assert dbuff.getTotalBytes() == NUM_BYTES_INT_32 * elem_count + assert dbuff.getTypeID() == pysidre.TypeID.INT32_ID + assert dbuff.getNumElements() == elem_count + assert dbuff.getTotalBytes() == NUM_BYTES_INT_32 * elem_count - data = dbuff.getDataArray() + data = dbuff.getDataArray() - assert type(data[0]) == np.int32 + assert type(data[0]) == np.int32 - for i in range(elem_count): - data[i] = i * i + for i in range(elem_count): + data[i] = i * i - for i in range(elem_count): - assert data[i] == i * i + for i in range(elem_count): + assert data[i] == i * i - dbuff.print() - ds.print() + dbuff.print() + ds.print() def test_realloc_buffer(): - orig_elem_count = 5 - mod_elem_count = 10 + orig_elem_count = 5 + mod_elem_count = 10 - ds = pysidre.DataStore() - dbuff = ds.createBuffer() + ds = pysidre.DataStore() + dbuff = ds.createBuffer() - dbuff.allocate(pysidre.TypeID.INT32_ID, orig_elem_count) + dbuff.allocate(pysidre.TypeID.INT32_ID, orig_elem_count) - assert dbuff.getTypeID() == pysidre.TypeID.INT32_ID - assert dbuff.getNumElements() == orig_elem_count - assert dbuff.getTotalBytes() == NUM_BYTES_INT_32 * orig_elem_count + assert dbuff.getTypeID() == pysidre.TypeID.INT32_ID + assert dbuff.getNumElements() == orig_elem_count + assert dbuff.getTotalBytes() == NUM_BYTES_INT_32 * orig_elem_count - data = dbuff.getDataArray() + data = dbuff.getDataArray() - for i in range(orig_elem_count): - data[i] = orig_elem_count + for i in range(orig_elem_count): + data[i] = orig_elem_count - for i in range(orig_elem_count): - assert data[i] == orig_elem_count + for i in range(orig_elem_count): + assert data[i] == orig_elem_count - dbuff.reallocate(mod_elem_count) + dbuff.reallocate(mod_elem_count) - assert dbuff.getTypeID() == pysidre.TypeID.INT32_ID - assert dbuff.getNumElements() == mod_elem_count - assert dbuff.getTotalBytes() == NUM_BYTES_INT_32 * mod_elem_count + assert dbuff.getTypeID() == pysidre.TypeID.INT32_ID + assert dbuff.getNumElements() == mod_elem_count + assert dbuff.getTotalBytes() == NUM_BYTES_INT_32 * mod_elem_count - data = dbuff.getDataArray() + data = dbuff.getDataArray() - assert type(data[0]) == np.int32 + assert type(data[0]) == np.int32 - for i in range(orig_elem_count,mod_elem_count): - data[i] = mod_elem_count + for i in range(orig_elem_count, mod_elem_count): + data[i] = mod_elem_count - for i in range(0,mod_elem_count): - value = orig_elem_count - if i > 4: - value = mod_elem_count - assert data[i] == value \ No newline at end of file + for i in range(0, mod_elem_count): + value = orig_elem_count + if i > 4: + value = mod_elem_count + assert data[i] == value diff --git a/src/axom/sidre/tests/sidre_datastore_unit_Py.py b/src/axom/sidre/tests/sidre_datastore_unit_Py.py index e646d5a11a..d90f0b5b38 100644 --- a/src/axom/sidre/tests/sidre_datastore_unit_Py.py +++ b/src/axom/sidre/tests/sidre_datastore_unit_Py.py @@ -7,74 +7,76 @@ import pysidre import random + def verify_empty_group_named(dg, name): - assert dg.getName() == name - - assert dg.getNumGroups() == 0 - assert not dg.hasGroup(-1) - assert not dg.hasGroup(0) - assert not dg.hasGroup(1) - assert not dg.hasGroup("some_name") - assert dg.getGroupIndex("some_other_name") == pysidre.InvalidIndex - assert dg.getFirstValidGroupIndex() == pysidre.InvalidIndex - assert dg.getNextValidGroupIndex(0) == pysidre.InvalidIndex - assert dg.getNextValidGroupIndex(4) == pysidre.InvalidIndex - - assert dg.getNumViews() == 0 - assert not dg.hasView(-1) - assert not dg.hasView(0) - assert not dg.hasView(1) - assert not dg.hasView("some_name") - assert dg.getViewIndex("some_other_name") == pysidre.InvalidIndex - assert dg.getFirstValidViewIndex() == pysidre.InvalidIndex - assert dg.getNextValidViewIndex(0) == pysidre.InvalidIndex - assert dg.getNextValidViewIndex(4) == pysidre.InvalidIndex + assert dg.getName() == name + + assert dg.getNumGroups() == 0 + assert not dg.hasGroup(-1) + assert not dg.hasGroup(0) + assert not dg.hasGroup(1) + assert not dg.hasGroup("some_name") + assert dg.getGroupIndex("some_other_name") == pysidre.InvalidIndex + assert dg.getFirstValidGroupIndex() == pysidre.InvalidIndex + assert dg.getNextValidGroupIndex(0) == pysidre.InvalidIndex + assert dg.getNextValidGroupIndex(4) == pysidre.InvalidIndex + + assert dg.getNumViews() == 0 + assert not dg.hasView(-1) + assert not dg.hasView(0) + assert not dg.hasView(1) + assert not dg.hasView("some_name") + assert dg.getViewIndex("some_other_name") == pysidre.InvalidIndex + assert dg.getFirstValidViewIndex() == pysidre.InvalidIndex + assert dg.getNextValidViewIndex(0) == pysidre.InvalidIndex + assert dg.getNextValidViewIndex(4) == pysidre.InvalidIndex + def verify_buffer_identity(ds, bs): - bufcount = len(bs) + bufcount = len(bs) - # Does ds contain the number of buffers we expect? - assert ds.getNumBuffers() == bufcount + # Does ds contain the number of buffers we expect? + assert ds.getNumBuffers() == bufcount - # Does ds contain the buffer IDs and pointers we expect? - iterated_count = 0 - idx = ds.getFirstValidBufferIndex() - while idx != pysidre.InvalidIndex and iterated_count < bufcount: - assert idx in bs - if idx in bs: - assert bs[idx] == ds.getBuffer(idx) - idx = ds.getNextValidBufferIndex(idx) - iterated_count += 1 + # Does ds contain the buffer IDs and pointers we expect? + iterated_count = 0 + idx = ds.getFirstValidBufferIndex() + while idx != pysidre.InvalidIndex and iterated_count < bufcount: + assert idx in bs + if idx in bs: + assert bs[idx] == ds.getBuffer(idx) + idx = ds.getNextValidBufferIndex(idx) + iterated_count += 1 - # Have we iterated over exactly the number of buffers we expect, finishing on InvalidIndex? - assert iterated_count == bufcount - assert idx == pysidre.InvalidIndex + # Have we iterated over exactly the number of buffers we expect, finishing on InvalidIndex? + assert iterated_count == bufcount + assert idx == pysidre.InvalidIndex def test_default_ctor(): - ds = pysidre.DataStore() + ds = pysidre.DataStore() - # After construction, the DataStore should contain no buffers. - assert ds.getNumBuffers() == 0 - assert not ds.hasBuffer(-15) - assert not ds.hasBuffer(-1) - assert not ds.hasBuffer(0) - assert not ds.hasBuffer(1) - assert not ds.hasBuffer(8) + # After construction, the DataStore should contain no buffers. + assert ds.getNumBuffers() == 0 + assert not ds.hasBuffer(-15) + assert not ds.hasBuffer(-1) + assert not ds.hasBuffer(0) + assert not ds.hasBuffer(1) + assert not ds.hasBuffer(8) - assert ds.getFirstValidBufferIndex() == pysidre.InvalidIndex - assert ds.getNextValidBufferIndex(0) == pysidre.InvalidIndex - assert ds.getNextValidBufferIndex(4) == pysidre.InvalidIndex + assert ds.getFirstValidBufferIndex() == pysidre.InvalidIndex + assert ds.getNextValidBufferIndex(0) == pysidre.InvalidIndex + assert ds.getNextValidBufferIndex(4) == pysidre.InvalidIndex - # The new DataStore should contain exactly one group, the root group. - # The root group should be named "" and should contain no views and no groups. - dg = ds.getRoot() + # The new DataStore should contain exactly one group, the root group. + # The root group should be named "" and should contain no views and no groups. + dg = ds.getRoot() - assert dg is not None - assert dg == dg.getParent() - assert dg.getDataStore() == ds + assert dg is not None + assert dg == dg.getParent() + assert dg.getDataStore() == ds - verify_empty_group_named(dg, "") + verify_empty_group_named(dg, "") # The dtor destroys all buffers and deletes the root group. @@ -388,7 +390,7 @@ def test_loop_create_delete_buffers_iterate(): bs = {} idxlist = [] - initbufcount = 50 # Arbitrary number of buffers + initbufcount = 50 # Arbitrary number of buffers # Initially, create some buffers of varying size for i in range(initbufcount): @@ -398,7 +400,7 @@ def test_loop_create_delete_buffers_iterate(): bs[idx] = b idxlist.append(idx) - totalrounds = 100 # Arbitrary number of rounds + totalrounds = 100 # Arbitrary number of rounds for round in range(totalrounds): # In each round, choose a random number of buffers to delete or create delta = irhall(5) @@ -428,4 +430,4 @@ def test_loop_create_delete_buffers_iterate(): bs[addid] = buf idxlist.append(addid) - verify_buffer_identity(ds, bs) \ No newline at end of file + verify_buffer_identity(ds, bs) diff --git a/src/axom/sidre/tests/sidre_external_Py.py b/src/axom/sidre/tests/sidre_external_Py.py index 564230831f..d08c1145b2 100644 --- a/src/axom/sidre/tests/sidre_external_Py.py +++ b/src/axom/sidre/tests/sidre_external_Py.py @@ -6,143 +6,319 @@ import pysidre import numpy as np +from conduit import Node + +############################################################################### +# Tests from sidre_external.cpp +############################################################################### + def test_create_external_view(): - ds = pysidre.DataStore() - root = ds.getRoot() + ds = pysidre.DataStore() + root = ds.getRoot() + + length = 11 + ndims = 1 + shape = np.array([length]) + + idata = np.array(range(length)) + print(f"PYTHON SIDE: idata type is {type(idata[0])}") + print(f"PYTHON SIDE: idata is {idata}") + + for i in range(8): + view = None + match i: + case 0: + view = root.createView("data0", pysidre.TypeID.INT64_ID, length, idata) + case 1: + view = root.createView("data1", pysidre.TypeID.INT64_ID, + length).setExternalData(idata) + case 2: + view = root.createView("data2").setExternalData(pysidre.TypeID.INT64_ID, length, + idata) + case 3: + view = root.createView("data3", idata).apply(pysidre.TypeID.INT64_ID, length) + case 4: + view = root.createViewWithShape("data4", pysidre.TypeID.INT64_ID, ndims, shape, + idata) + case 5: + view = root.createViewWithShape("data5", pysidre.TypeID.INT64_ID, ndims, + shape).setExternalData(idata) + case 6: + view = root.createView("data6").setExternalData(pysidre.TypeID.INT64_ID, ndims, + shape, idata) + case 7: + view = root.createView("data7", idata).apply(pysidre.TypeID.INT64_ID, ndims, shape) + + assert view is not None + assert root.getNumViews() == i + 1 + + assert view.isDescribed() + assert view.isAllocated() + assert view.isApplied() + + assert view.isExternal() + assert not view.isOpaque() + + assert view.getTypeID() == pysidre.TypeID.INT64_ID + assert view.getNumElements() == length + + view.print() + + idata_chk = view.getDataArray() + assert np.array_equal(idata_chk, idata) + + for ii in range(length): + assert idata_chk[ii] == idata[ii] + + +def test_verify_external_layout(): + ds = pysidre.DataStore() + root = ds.getRoot() + + SZ = 11 + extData = np.zeros(SZ, dtype=np.int64) + + print("""Tests that the hierarchy generated by Group::createExternalLayout() + consists only of groups and views + associated with external pointers (described or undescribed).""") + + # Create some internal views + root.createViewAndAllocate("int/desc/bufferview", pysidre.TypeID.INT64_ID, SZ) + root.createViewScalar("int/scalar/scalarview", SZ) + root.createViewString("int/string/stringview", "A string") + + # Sanity check on internal views + assert not root.getView("int/desc/bufferview").isExternal() + assert root.getView("int/desc/bufferview").isDescribed() + assert not root.getView("int/scalar/scalarview").isExternal() + assert root.getView("int/scalar/scalarview").isDescribed() + assert not root.getView("int/string/stringview").isExternal() + assert root.getView("int/string/stringview").isDescribed() + + # Check that the generated external layout is empty + emptyNode = Node() + root.createExternalLayout(emptyNode) + + print("External node's json before adding external data (should be empty):\n\t", + emptyNode.to_json()) + + assert emptyNode.number_of_children() == 0 + + # Create some external views + root.createView("ext/desc/external_desc", pysidre.TypeID.INT64_ID, SZ, extData) + root.createView("ext/undesc/external_opaque").setExternalData(extData) + + # Sanity check on the external views + assert root.getView("ext/desc/external_desc").isExternal() + assert root.getView("ext/desc/external_desc").isDescribed() + + assert root.getView("ext/undesc/external_opaque").isExternal() + assert not root.getView("ext/undesc/external_opaque").isDescribed() + + # Initialize the data so we can test it later + bufData = root.getView("int/desc/bufferview").getDataArray() + for i in range(SZ): + extData[i] = i + bufData[i] = 100 + i + + # Check that the generated external layout matches expectation + # Copy the external layout into a conduit node and test the layout + node = Node() + root.createExternalLayout(node) + + print("External node's json:\n\t", node.to_json()) + + assert node.number_of_children() == 1 + assert node.has_path("ext") + assert node["ext"].number_of_children() == 2 + + # Described external views are present and we can access the data + assert node.has_path("ext/desc") + assert node.has_path("ext/desc/external_desc") + extLayoutData = node["ext/desc/external_desc"] + for i in range(SZ): + assert extData[i] == extLayoutData[i] + + # Opaque views are not present, but their containing groups are present + assert node.has_path("ext/undesc") + assert not node.has_path("ext/undesc/external_opaque") + + # Buffer and scalar views are not present in the external layout + assert not node.has_path("int") + + +def test_save_load_external_view(): + if not pysidre.AXOM_USE_HDF5: + print("pysidre.Group.loadExternalData() is only implemented for the 'sidre_hdf5' protocol") + return + + ds = pysidre.DataStore() + root = ds.getRoot() + + length = 11 + + idata = np.array([ii for ii in range(length)], dtype=np.int64) + ddata = np.array([ii * 2.0 for ii in range(length)], dtype=np.float64) + + # Create views with external data + root.createView("idata", idata).apply(pysidre.TypeID.INT64_ID, length) + root.createView("ddata", ddata).apply(pysidre.TypeID.FLOAT64_ID, length) + assert root.getNumViews() == 2 + + root.save("sidre_external_save_load_external_view", "sidre_hdf5") - length = 11 + ds2 = pysidre.DataStore() + load_group = ds2.getRoot() - idata = np.array(range(length)) - print(f"PYTHON SIDE: idata type is {type(idata[0])}") - print(f"PYTHON SIDE: idata is {idata}") + # Load from file, the Views with external data will be described but + # have no pointer to data + load_group.load("sidre_external_save_load_external_view") - ddata = np.array([x * 2.0 for x in range(length)]) - print(f"PYTHON SIDE: ddata type is {type(ddata[0])}") - print(f"PYTHON SIDE: ddata is {ddata}") + # Verify load_group has external Views named "idata" and "ddata" + assert load_group.hasView("idata") + assert load_group.hasView("ddata") + load_idata = load_group.getView("idata") + load_ddata = load_group.getView("ddata") + assert load_idata.isExternal() + assert load_ddata.isExternal() + assert load_idata.getNumElements() == length + assert load_ddata.getNumElements() == length + assert load_idata.getTypeID() == pysidre.TypeID.INT64_ID + assert load_ddata.getTypeID() == pysidre.TypeID.FLOAT64_ID - iview = root.createView("idata", idata) - iview.apply(pysidre.TypeID.INT64_ID, length) - iview.print() + # Create arrays that will serve as locations for external data + new_idata = np.zeros(length, dtype=np.int64) + new_ddata = np.zeros(length, dtype=np.float64) - dview = root.createView("ddata", ddata) - dview.apply(pysidre.TypeID.FLOAT64_ID, length) - dview.print() + # Set the new arrays' pointers into the Views + load_idata.setExternalData(new_idata) + load_ddata.setExternalData(new_ddata) - assert root.getNumViews() == 2 + # Load external data; values located in the file will be loaded into + # the storage identified by the external pointers + load_group.loadExternalData("sidre_external_save_load_external_view") - idata_chk = iview.getDataArray() - assert len(idata_chk) == length - assert np.array_equal(idata_chk, idata) + # The pointer retrieved from each View is the same address as the new + # arrays + idata_chk = load_group.getView("idata").getDataArray() + assert np.array_equal(idata_chk, new_idata) - ddata_chk = dview.getDataArray() - assert len(ddata_chk) == length - assert np.array_equal(ddata_chk, ddata) + # idata_chk has been loaded with the values from the file, which must + # be the same as the original idata array that was saved + for ii in range(length): + assert idata_chk[ii] == idata[ii] + + ddata_chk = load_group.getView("ddata").getDataArray() + assert np.array_equal(ddata_chk, new_ddata) + for ii in range(length): + assert ddata_chk[ii] == ddata[ii] + + +############################################################################### +# Tests from sidre_external_F.f +############################################################################### # External numpy array via python # Register with datastore then # Query metadata using datastore API. def test_external_int(): - ds = pysidre.DataStore() - root = ds.getRoot() + ds = pysidre.DataStore() + root = ds.getRoot() - iarray = np.array(range(1,11)) + iarray = np.array(range(1, 11)) - view = root.createView("iarray", iarray) - view.apply(pysidre.TypeID.INT64_ID, 10) + view = root.createView("iarray", iarray) + view.apply(pysidre.TypeID.INT64_ID, 10) - assert view.isExternal() == True - assert view.getTypeID() == pysidre.TypeID.INT64_ID - assert view.getNumElements() == np.size(iarray) - assert view.getNumDimensions() == 1 + assert view.isExternal() == True + assert view.getTypeID() == pysidre.TypeID.INT64_ID + assert view.getNumElements() == np.size(iarray) + assert view.getNumDimensions() == 1 - extents = np.zeros(7) - rank,extents = view.getShape(7, extents) - assert rank == 1 - assert extents[0] == np.size(iarray) + extents = np.zeros(7) + rank, extents = view.getShape(7, extents) + assert rank == 1 + assert extents[0] == np.size(iarray) - ipointer = view.getDataArray() - assert np.array_equal(ipointer, iarray) + ipointer = view.getDataArray() + assert np.array_equal(ipointer, iarray) def test_external_int_3d(): - ds = pysidre.DataStore() - root = ds.getRoot() + ds = pysidre.DataStore() + root = ds.getRoot() - # create 3D numpy array - iarray = np.empty((2, 3, 4), dtype=int) + # create 3D numpy array + iarray = np.empty((2, 3, 4), dtype=int) - for i in range(2): - for j in range(3): - for k in range(4): - iarray[i, j, k] = (i+1)*100 + (j+1)*10 + (k+1) - view = root.createView("iarray", iarray) - view.apply(pysidre.TypeID.INT64_ID, 3, np.array([2,3,4])) + for i in range(2): + for j in range(3): + for k in range(4): + iarray[i, j, k] = (i + 1) * 100 + (j + 1) * 10 + (k + 1) + view = root.createView("iarray", iarray) + view.apply(pysidre.TypeID.INT64_ID, 3, np.array([2, 3, 4])) - assert view.isExternal() == True - assert view.getTypeID() == pysidre.TypeID.INT64_ID - assert view.getNumElements() == np.size(iarray) - assert view.getNumDimensions() == 3 + assert view.isExternal() == True + assert view.getTypeID() == pysidre.TypeID.INT64_ID + assert view.getNumElements() == np.size(iarray) + assert view.getNumDimensions() == 3 - extents = np.zeros(7) - rank,extents = view.getShape(7, extents) - assert rank == 3 - assert extents[0] == iarray.shape[0] - assert extents[1] == iarray.shape[1] - assert extents[2] == iarray.shape[2] + extents = np.zeros(7) + rank, extents = view.getShape(7, extents) + assert rank == 3 + assert extents[0] == iarray.shape[0] + assert extents[1] == iarray.shape[1] + assert extents[2] == iarray.shape[2] - ipointer = view.getDataArray() - assert np.array_equal(ipointer, iarray) + ipointer = view.getDataArray() + assert np.array_equal(ipointer, iarray) # check other types def test_external_float(): - ds = pysidre.DataStore() - root = ds.getRoot() + ds = pysidre.DataStore() + root = ds.getRoot() - darray = np.array([(i + 0.5) for i in range(1,11)]) - view = root.createView("darray", darray) - view.apply(pysidre.TypeID.FLOAT64_ID, 10) + darray = np.array([(i + 0.5) for i in range(1, 11)]) + view = root.createView("darray", darray) + view.apply(pysidre.TypeID.FLOAT64_ID, 10) - assert view.getTypeID() == pysidre.TypeID.FLOAT64_ID - assert view.getNumElements() == np.size(darray) + assert view.getTypeID() == pysidre.TypeID.FLOAT64_ID + assert view.getNumElements() == np.size(darray) - dpointer = view.getDataArray() - assert np.array_equal(dpointer, darray) + dpointer = view.getDataArray() + assert np.array_equal(dpointer, darray) # Datastore owns a multi-dimension array. def test_datastore_int_3d(): - ds = pysidre.DataStore() - root = ds.getRoot() - extents_in = [2,3,4] - - view = root.createViewWithShapeAndAllocate("iarray", pysidre.TypeID.INT32_ID, 3, extents_in) - - ipointer = view.getDataArray() - - assert view.getTypeID() == pysidre.TypeID.INT32_ID - assert view.getNumElements() == np.size(ipointer) - assert view.getNumDimensions() == 3 - assert view.getNumDimensions() == ipointer.ndim - - extents = np.zeros(7) - rank,extents = view.getShape(7, extents) - assert rank == 3 - assert extents[0] == ipointer.shape[0] - assert extents[1] == ipointer.shape[1] - assert extents[2] == ipointer.shape[2] - - # Reshape as 1D using shape - extents_in[0] = np.size(ipointer) - view.apply(pysidre.TypeID.INT32_ID, 1, np.array([extents_in[0]])) - assert view.getNumElements() == np.size(ipointer) - - # Reshape as 1D using length - view.apply(pysidre.TypeID.INT32_ID, extents_in[0]) - assert view.getNumElements() == np.size(ipointer) - - -# Corresponding fortran test implementation needs to be fixed -# def test_save_load_external_view(): + ds = pysidre.DataStore() + root = ds.getRoot() + extents_in = [2, 3, 4] + + view = root.createViewWithShapeAndAllocate("iarray", pysidre.TypeID.INT32_ID, 3, extents_in) + + ipointer = view.getDataArray() + + assert view.getTypeID() == pysidre.TypeID.INT32_ID + assert view.getNumElements() == np.size(ipointer) + assert view.getNumDimensions() == 3 + assert view.getNumDimensions() == ipointer.ndim + + extents = np.zeros(7) + rank, extents = view.getShape(7, extents) + assert rank == 3 + assert extents[0] == ipointer.shape[0] + assert extents[1] == ipointer.shape[1] + assert extents[2] == ipointer.shape[2] + + # Reshape as 1D using shape + extents_in[0] = np.size(ipointer) + view.apply(pysidre.TypeID.INT32_ID, 1, np.array([extents_in[0]])) + assert view.getNumElements() == np.size(ipointer) + + # Reshape as 1D using length + view.apply(pysidre.TypeID.INT32_ID, extents_in[0]) + assert view.getNumElements() == np.size(ipointer) diff --git a/src/axom/sidre/tests/sidre_group_Py.py b/src/axom/sidre/tests/sidre_group_Py.py index e1b8954195..18a68df4f8 100644 --- a/src/axom/sidre/tests/sidre_group_Py.py +++ b/src/axom/sidre/tests/sidre_group_Py.py @@ -8,594 +8,585 @@ import numpy as np if pysidre.AXOM_USE_HDF5: - NPROTOCOLS = 3 - PROTOCOLS = ["sidre_json", "sidre_hdf5", "json"] + NPROTOCOLS = 3 + PROTOCOLS = ["sidre_json", "sidre_hdf5", "json"] else: - NPROTOCOLS = 2 - PROTOCOLS = ["sidre_json", "json"] + NPROTOCOLS = 2 + PROTOCOLS = ["sidre_json", "json"] # ------------------------------------------------------------------------------ # getName() # ------------------------------------------------------------------------------ def test_get_name(): - ds = pysidre.DataStore() - root = ds.getRoot() - grp = root.createGroup("test") + ds = pysidre.DataStore() + root = ds.getRoot() + grp = root.createGroup("test") - assert grp.getName() == "test" + assert grp.getName() == "test" - grp2 = root.getGroup("foo") - assert grp2 == None + grp2 = root.getGroup("foo") + assert grp2 == None # ------------------------------------------------------------------------------ # getPath(), getPathName() # ------------------------------------------------------------------------------ def test_get_path_name(): - ds = pysidre.DataStore() - root = ds.getRoot() - group = root.createGroup("test/a/b/c") - grp2 = root.getGroup("test/a") - grp3 = root.getGroup("test") + ds = pysidre.DataStore() + root = ds.getRoot() + group = root.createGroup("test/a/b/c") + grp2 = root.getGroup("test/a") + grp3 = root.getGroup("test") - assert root.getName() == "" - assert root.getPath() == "" - assert root.getPathName() == "" + assert root.getName() == "" + assert root.getPath() == "" + assert root.getPathName() == "" - assert grp2.getName() == "a" - assert grp2.getPath() == "test" - assert grp2.getPathName() == "test/a" + assert grp2.getName() == "a" + assert grp2.getPath() == "test" + assert grp2.getPathName() == "test/a" - assert grp3.getName() == "test" - assert grp3.getPath() == "" - assert grp3.getPathName() == "test" + assert grp3.getName() == "test" + assert grp3.getPath() == "" + assert grp3.getPathName() == "test" - assert group.getName() == "c" - assert group.getPath() == "test/a/b" - assert group.getPathName() == "test/a/b/c" + assert group.getName() == "c" + assert group.getPath() == "test/a/b" + assert group.getPathName() == "test/a/b/c" #------------------------------------------------------------------------------ # createGroup(), getGroup(), hasGroup() with path strings #------------------------------------------------------------------------------ def test_group_with_path(): - ds = pysidre.DataStore() - root = ds.getRoot() - - # Test full path access when building incrementally - group = root.createGroup("test1").createGroup("test2").createGroup("test3") - group2 = root.getGroup("test1/test2/test3") - - assert group2 is not None - assert group == group2 - - # Test incremental access when building full path - groupP = root.createGroup("testA/testB/testC") - groupP2 = root.getGroup("testA").getGroup("testB").getGroup("testC") - - assert groupP2 is not None - assert groupP == groupP2 - # test non-const getGroup() with path - groupPParent = root.getGroup("testA/testB") - assert groupP.getParent() == groupPParent - assert groupP.getParent().getName() == "testB" - - # Now verify that code will not create missing groups. - root.createGroup("testa").createGroup("testb").createGroup("testc") - group_bada = root.getGroup("BAD/testb/testc") - group_badb = root.getGroup("testa/BAD/testc") - group_badc = root.getGroup("testa/testb/BAD") - - assert group_bada is None - assert group_badb is None - assert group_badc is None - - # Test hasGroup with paths. - assert not root.hasGroup("BAD/testb/testc") - assert not root.hasGroup("testa/BAD/testc") - assert not root.hasGroup("testa/testb/BAD") - - assert root.hasGroup("test1") - assert root.hasGroup("test1/test2") - assert root.hasGroup("test1/test2/test3") - group_testa = root.getGroup("testa") - assert group_testa.hasGroup("testb") - assert group_testa.hasGroup("testb/testc") - assert not group_testa.hasGroup("testb/BAD") - assert not group_testa.hasGroup("testb/testc/BAD") - - assert root.getNumGroups() == 3 - assert root.hasGroup(0) - assert root.hasGroup(1) - assert root.hasGroup(2) - assert not root.hasGroup(3) - assert not root.hasGroup(pysidre.InvalidIndex) - - testbnumgroups = group_testa.getGroup("testb").getNumGroups() - group_cdup = group_testa.createGroup("testb/testc") - - assert group_cdup is None - assert group_testa.getGroup("testb").getNumGroups() == testbnumgroups + ds = pysidre.DataStore() + root = ds.getRoot() + + # Test full path access when building incrementally + group = root.createGroup("test1").createGroup("test2").createGroup("test3") + group2 = root.getGroup("test1/test2/test3") + + assert group2 is not None + assert group == group2 + + # Test incremental access when building full path + groupP = root.createGroup("testA/testB/testC") + groupP2 = root.getGroup("testA").getGroup("testB").getGroup("testC") + + assert groupP2 is not None + assert groupP == groupP2 + # test non-const getGroup() with path + groupPParent = root.getGroup("testA/testB") + assert groupP.getParent() == groupPParent + assert groupP.getParent().getName() == "testB" + + # Now verify that code will not create missing groups. + root.createGroup("testa").createGroup("testb").createGroup("testc") + group_bada = root.getGroup("BAD/testb/testc") + group_badb = root.getGroup("testa/BAD/testc") + group_badc = root.getGroup("testa/testb/BAD") + + assert group_bada is None + assert group_badb is None + assert group_badc is None + + # Test hasGroup with paths. + assert not root.hasGroup("BAD/testb/testc") + assert not root.hasGroup("testa/BAD/testc") + assert not root.hasGroup("testa/testb/BAD") + + assert root.hasGroup("test1") + assert root.hasGroup("test1/test2") + assert root.hasGroup("test1/test2/test3") + group_testa = root.getGroup("testa") + assert group_testa.hasGroup("testb") + assert group_testa.hasGroup("testb/testc") + assert not group_testa.hasGroup("testb/BAD") + assert not group_testa.hasGroup("testb/testc/BAD") + + assert root.getNumGroups() == 3 + assert root.hasGroup(0) + assert root.hasGroup(1) + assert root.hasGroup(2) + assert not root.hasGroup(3) + assert not root.hasGroup(pysidre.InvalidIndex) + + testbnumgroups = group_testa.getGroup("testb").getNumGroups() + group_cdup = group_testa.createGroup("testb/testc") + + assert group_cdup is None + assert group_testa.getGroup("testb").getNumGroups() == testbnumgroups #------------------------------------------------------------------------------ # createGroup(), destroyGroup() with path strings #------------------------------------------------------------------------------ def test_destroy_group_with_path(): - ds = pysidre.DataStore() - root = ds.getRoot() + ds = pysidre.DataStore() + root = ds.getRoot() - # Test full path access when building incrementally - group = root.createGroup("test1/test2/test3") + # Test full path access when building incrementally + group = root.createGroup("test1/test2/test3") - exp_no_groups = 0 - exp_one_group = 1 + exp_no_groups = 0 + exp_one_group = 1 - assert root.getNumGroups() == exp_one_group - assert root.getGroup("test1").getNumGroups() == exp_one_group - assert root.getGroup("test1/test2").getNumGroups() == exp_one_group - assert root.getGroup("test1/test2/test3").getNumGroups() == exp_no_groups + assert root.getNumGroups() == exp_one_group + assert root.getGroup("test1").getNumGroups() == exp_one_group + assert root.getGroup("test1/test2").getNumGroups() == exp_one_group + assert root.getGroup("test1/test2/test3").getNumGroups() == exp_no_groups - root.destroyGroup("test1/test2") + root.destroyGroup("test1/test2") - assert root.getNumGroups() == exp_one_group - assert root.getGroup("test1").getNumGroups() == exp_no_groups - assert not root.hasGroup("test1/test2/test3") - assert not root.hasGroup("test1/test2") + assert root.getNumGroups() == exp_one_group + assert root.getGroup("test1").getNumGroups() == exp_no_groups + assert not root.hasGroup("test1/test2/test3") + assert not root.hasGroup("test1/test2") - root.destroyGroup("test1/BAD") + root.destroyGroup("test1/BAD") - assert root.getNumGroups() == exp_one_group - assert root.getGroup("test1").getNumGroups() == exp_no_groups + assert root.getNumGroups() == exp_one_group + assert root.getGroup("test1").getNumGroups() == exp_no_groups # ------------------------------------------------------------------------------ # Verify getParent() # ------------------------------------------------------------------------------ def test_get_parent(): - ds = pysidre.DataStore() - root = ds.getRoot() - parent = root.createGroup("parent") - child = parent.createGroup("child") + ds = pysidre.DataStore() + root = ds.getRoot() + parent = root.createGroup("parent") + child = parent.createGroup("child") - assert child.getParent() == parent + assert child.getParent() == parent # ------------------------------------------------------------------------------ # Verify getDataStore() # ------------------------------------------------------------------------------ def test_get_datastore(): - ds = pysidre.DataStore() - root = ds.getRoot() - grp = root.createGroup("parent") + ds = pysidre.DataStore() + root = ds.getRoot() + grp = root.createGroup("parent") - assert grp.getDataStore() == ds + assert grp.getDataStore() == ds - other_ds = grp.getDataStore() - assert other_ds == ds + other_ds = grp.getDataStore() + assert other_ds == ds # ------------------------------------------------------------------------------ # Verify getGroup() # ------------------------------------------------------------------------------ def test_get_group(): - ds = pysidre.DataStore() - root = ds.getRoot() + ds = pysidre.DataStore() + root = ds.getRoot() - parent = root.createGroup("parent") - child = parent.createGroup("child") - assert child.getParent() == parent + parent = root.createGroup("parent") + child = parent.createGroup("child") + assert child.getParent() == parent - child1 = parent.getGroup("child") - assert child == child1 + child1 = parent.getGroup("child") + assert child == child1 - child2 = parent.getGroup(0) - assert child == child2 + child2 = parent.getGroup(0) + assert child == child2 - # Check error condition - errgrp = parent.getGroup("non-existent group") - assert errgrp == None + # Check error condition + errgrp = parent.getGroup("non-existent group") + assert errgrp == None # ------------------------------------------------------------------------------ # getView() # ------------------------------------------------------------------------------ def test_get_view(): - ds = pysidre.DataStore() - root = ds.getRoot() + ds = pysidre.DataStore() + root = ds.getRoot() - parent = root.createGroup("parent") - view1 = parent.createView("view") + parent = root.createGroup("parent") + view1 = parent.createView("view") - view2 = parent.getView("view") - assert view1 == view2 + view2 = parent.getView("view") + assert view1 == view2 - view3 = parent.getView(0) - assert view1 == view3 + view3 = parent.getView(0) + assert view1 == view3 - view2 = parent.getView("non-existant view") - assert view2 == None + view2 = parent.getView("non-existant view") + assert view2 == None #------------------------------------------------------------------------------ # createView, hasView(), getView(), destroyView() with path strings #------------------------------------------------------------------------------ def test_view_with_path(): - ds = pysidre.DataStore() - root = ds.getRoot() - - # Test with full path access when building incrementally - view = root.createGroup("group1").createGroup("group2").createView("view1") - view2 = root.getView("group1/group2/view1") - - assert view2 is not None - assert view == view2 - - # Test incremental access when building with full path - viewP = root.createView("groupA/groupB/viewA") - viewP2 = root.getGroup("groupA").getGroup("groupB").getView("viewA") - - assert viewP2 is not None - assert viewP == viewP2 - - # Now verify that bad paths just return None, and don't create missing groups - v_bad1 = root.getView("BAD/groupB/viewA") - v_bad2 = root.getView("groupA/BAD/viewA") - v_bad3 = root.getView("groupA/groupB/BAD") - - assert v_bad1 is None - assert v_bad2 is None - assert v_bad3 is None - - exp_no_groups = 0 - exp_one_group = 1 - exp_two_group = 2 - - assert root.getNumGroups() == exp_two_group - assert root.hasGroup("group1") - assert root.hasGroup("groupA") - assert root.getGroup("group1").getNumGroups() == exp_one_group - assert root.hasGroup("group1/group2") - assert root.getGroup("group1/group2").getNumGroups() == exp_no_groups - assert root.getGroup("group1/group2").getNumViews() == exp_one_group - assert root.getGroup("group1/group2").getView("view1") == view - assert root.getGroup("group1").getView("group2/view1") == view - - assert root.getGroup("groupA").getNumGroups() == exp_one_group - assert root.hasGroup("groupA/groupB") - assert root.getGroup("groupA/groupB").getNumGroups() == exp_no_groups - assert root.getGroup("groupA/groupB").getNumViews() == exp_one_group - assert root.getGroup("groupA/groupB").getView("viewA") == viewP - assert root.getGroup("groupA").getView("groupB/viewA") == viewP - - root.destroyView("group1/group2/view1") - - assert root.getGroup("group1/group2").getNumViews() == exp_no_groups - assert not root.getGroup("group1/group2").hasView("view1") - assert root.getGroup("group1/group2").getView("view1") is None - assert not root.hasView("group1/group2/view1") - assert root.getView("group1/group2/view1") is None - - groupA = root.getGroup("groupA") - assert groupA.hasView("groupB/viewA") - assert groupA.getView("groupB/viewA") == viewP - assert root.hasView("groupA/groupB/viewA") - assert root.getView("groupA/groupB/viewA") == viewP - - groupA.destroyView("groupB/viewA") - - assert groupA.getGroup("groupB").getNumViews() == exp_no_groups - assert not groupA.getGroup("groupB").hasView("viewA") - assert groupA.getGroup("groupB").getView("viewA") is None - assert not groupA.hasView("groupB/viewA") - assert groupA.getView("groupB/viewA") is None - assert root.getView("groupA/groupB/viewA") is None + ds = pysidre.DataStore() + root = ds.getRoot() + + # Test with full path access when building incrementally + view = root.createGroup("group1").createGroup("group2").createView("view1") + view2 = root.getView("group1/group2/view1") + + assert view2 is not None + assert view == view2 + + # Test incremental access when building with full path + viewP = root.createView("groupA/groupB/viewA") + viewP2 = root.getGroup("groupA").getGroup("groupB").getView("viewA") + + assert viewP2 is not None + assert viewP == viewP2 + + # Now verify that bad paths just return None, and don't create missing groups + v_bad1 = root.getView("BAD/groupB/viewA") + v_bad2 = root.getView("groupA/BAD/viewA") + v_bad3 = root.getView("groupA/groupB/BAD") + + assert v_bad1 is None + assert v_bad2 is None + assert v_bad3 is None + + exp_no_groups = 0 + exp_one_group = 1 + exp_two_group = 2 + + assert root.getNumGroups() == exp_two_group + assert root.hasGroup("group1") + assert root.hasGroup("groupA") + assert root.getGroup("group1").getNumGroups() == exp_one_group + assert root.hasGroup("group1/group2") + assert root.getGroup("group1/group2").getNumGroups() == exp_no_groups + assert root.getGroup("group1/group2").getNumViews() == exp_one_group + assert root.getGroup("group1/group2").getView("view1") == view + assert root.getGroup("group1").getView("group2/view1") == view + + assert root.getGroup("groupA").getNumGroups() == exp_one_group + assert root.hasGroup("groupA/groupB") + assert root.getGroup("groupA/groupB").getNumGroups() == exp_no_groups + assert root.getGroup("groupA/groupB").getNumViews() == exp_one_group + assert root.getGroup("groupA/groupB").getView("viewA") == viewP + assert root.getGroup("groupA").getView("groupB/viewA") == viewP + + root.destroyView("group1/group2/view1") + + assert root.getGroup("group1/group2").getNumViews() == exp_no_groups + assert not root.getGroup("group1/group2").hasView("view1") + assert root.getGroup("group1/group2").getView("view1") is None + assert not root.hasView("group1/group2/view1") + assert root.getView("group1/group2/view1") is None + + groupA = root.getGroup("groupA") + assert groupA.hasView("groupB/viewA") + assert groupA.getView("groupB/viewA") == viewP + assert root.hasView("groupA/groupB/viewA") + assert root.getView("groupA/groupB/viewA") == viewP + + groupA.destroyView("groupB/viewA") + + assert groupA.getGroup("groupB").getNumViews() == exp_no_groups + assert not groupA.getGroup("groupB").hasView("viewA") + assert groupA.getGroup("groupB").getView("viewA") is None + assert not groupA.hasView("groupB/viewA") + assert groupA.getView("groupB/viewA") is None + assert root.getView("groupA/groupB/viewA") is None #------------------------------------------------------------------------------ # Verify getViewName() and getViewIndex() #------------------------------------------------------------------------------ def test_get_view_name_index(): - ds = pysidre.DataStore() - root = ds.getRoot() + ds = pysidre.DataStore() + root = ds.getRoot() - parent = root.createGroup("parent") - view1 = parent.createView("view1") - view2 = parent.createView("view2") + parent = root.createGroup("parent") + view1 = parent.createView("view1") + view2 = parent.createView("view2") - assert parent.getNumViews() == 2 + assert parent.getNumViews() == 2 - idx1 = parent.getViewIndex("view1") - idx2 = parent.getViewIndex("view2") + idx1 = parent.getViewIndex("view1") + idx2 = parent.getViewIndex("view2") - name1 = parent.getViewName(idx1) - name2 = parent.getViewName(idx2) + name1 = parent.getViewName(idx1) + name2 = parent.getViewName(idx2) - assert name1 == "view1" - assert view1.getName() == name1 + assert name1 == "view1" + assert view1.getName() == name1 - assert name2 == "view2" - assert view2.getName() == name2 + assert name2 == "view2" + assert view2.getName() == name2 - idx3 = parent.getViewIndex("view3") - assert idx3 == pysidre.InvalidIndex + idx3 = parent.getViewIndex("view3") + assert idx3 == pysidre.InvalidIndex - name3 = parent.getViewName(idx3) - assert name3 == "" - assert not pysidre.nameIsValid(name3) + name3 = parent.getViewName(idx3) + assert name3 == "" + assert not pysidre.nameIsValid(name3) #------------------------------------------------------------------------------ # Verify getFirstValidGroupIndex() and getNextValidGroupIndex() #------------------------------------------------------------------------------ def test_get_first_and_next_group_index(): - ds = pysidre.DataStore() - root = ds.getRoot() + ds = pysidre.DataStore() + root = ds.getRoot() - parent = root.createGroup("parent") - group1 = parent.createGroup("group1") - group2 = parent.createGroup("group2") - assert parent.getNumGroups() == 2 + parent = root.createGroup("parent") + group1 = parent.createGroup("group1") + group2 = parent.createGroup("group2") + assert parent.getNumGroups() == 2 - idx1 = parent.getFirstValidGroupIndex() - idx2 = parent.getNextValidGroupIndex(idx1) - idx3 = parent.getNextValidGroupIndex(idx2) + idx1 = parent.getFirstValidGroupIndex() + idx2 = parent.getNextValidGroupIndex(idx1) + idx3 = parent.getNextValidGroupIndex(idx2) - assert idx1 == 0 - assert idx2 == 1 - assert idx3 == pysidre.InvalidIndex + assert idx1 == 0 + assert idx2 == 1 + assert idx3 == pysidre.InvalidIndex - group1out = parent.getGroup(idx1) - group2out = parent.getGroup(idx2) + group1out = parent.getGroup(idx1) + group2out = parent.getGroup(idx2) - assert group1 == group1out - assert group2 == group2out + assert group1 == group1out + assert group2 == group2out - # Check error conditions - emptygrp = root.createGroup("emptyGroup") - badidx1 = emptygrp.getFirstValidGroupIndex() - badidx2 = emptygrp.getNextValidGroupIndex(badidx1) + # Check error conditions + emptygrp = root.createGroup("emptyGroup") + badidx1 = emptygrp.getFirstValidGroupIndex() + badidx2 = emptygrp.getNextValidGroupIndex(badidx1) - assert badidx1 == pysidre.InvalidIndex - assert badidx2 == pysidre.InvalidIndex + assert badidx1 == pysidre.InvalidIndex + assert badidx2 == pysidre.InvalidIndex #------------------------------------------------------------------------------ # Verify Groups holding items in the list format #------------------------------------------------------------------------------ def test_child_lists(): - ds = pysidre.DataStore() - root = ds.getRoot() - - # parent is a Group in list format. - parent = root.createGroup("parent", True) - - # Create 10 unnamed Groups as children of parent. - for i in range(10): - unnamed_group = parent.createUnnamedGroup() - unnamed_group.createViewScalar("val", i) - - # Create 15 unnamed Views as children of parent. - for i in range(15): - if i % 3 == 0: - unnamed_view = parent.createView("") - elif i % 3 == 1: - unnamed_view = parent.createViewScalar("", i * i) - else: - unnamed_view = parent.createViewString("", "foo") - if not unnamed_view.isApplied(): - unnamed_view.apply(pysidre.TypeID.INT_ID, i) - unnamed_view.allocate(pysidre.TypeID.INT_ID, i) - vdata = unnamed_view.getDataArray() # Returns numpy array - for j in range(i): - vdata[j] = j + 3 - - # Create Group not in list format, show that it can't create unnamed children. - not_list = root.createGroup("not_list", False) - dummy_group = not_list.createUnnamedGroup() - dummy_view = not_list.createView("") - assert not_list.isUsingMap() - assert not_list.getNumGroups() == 0 - assert not_list.getNumViews() == 0 - assert dummy_group is None - assert dummy_view is None - - # Access data from unnamed Groups held by parent. - scalars = set() - idx = parent.getFirstValidGroupIndex() - while pysidre.indexIsValid(idx): - unnamed_group = parent.getGroup(idx) - val_view = unnamed_group.getView("val") - val = val_view.getDataInt() - assert val >= 0 and val < 10 - scalars.add(val) - idx = parent.getNextValidGroupIndex(idx) - - assert parent.isUsingList() - assert len(scalars) == 10 - assert parent.hasGroup(6) - assert not parent.hasGroup(20) - - # Destroy five of the unnamed Groups held by parent. - idx = parent.getFirstValidGroupIndex() - while pysidre.indexIsValid(idx): - if idx % 2 == 1: - parent.destroyGroup(idx) - idx = parent.getNextValidGroupIndex(idx) - - # Add one more unnamed Group, so there should be six child Groups. - parent.createUnnamedGroup() - assert parent.getNumGroups() == 6 - - # Access data from the unnamed Views. - idx = parent.getFirstValidViewIndex() - while pysidre.indexIsValid(idx): - unnamed_view = parent.getView(idx) - if idx % 3 == 0: - assert unnamed_view.getTypeID() == pysidre.TypeID.INT32_ID - num_elems = unnamed_view.getNumElements() - assert num_elems == idx - vdata = unnamed_view.getDataArray() - for j in range(num_elems): - assert vdata[j] == j + 3 - elif idx % 3 == 1: - assert unnamed_view.isScalar() - val = unnamed_view.getDataInt() - assert val == idx * idx - else: - assert unnamed_view.isString() - vstr = unnamed_view.getString() - assert vstr == "foo" - idx = parent.getNextValidViewIndex(idx) - - root.destroyGroup("parent") + ds = pysidre.DataStore() + root = ds.getRoot() + + # parent is a Group in list format. + parent = root.createGroup("parent", True) + + # Create 10 unnamed Groups as children of parent. + for i in range(10): + unnamed_group = parent.createUnnamedGroup() + unnamed_group.createViewScalar("val", i) + + # Create 15 unnamed Views as children of parent. + for i in range(15): + if i % 3 == 0: + unnamed_view = parent.createView("") + elif i % 3 == 1: + unnamed_view = parent.createViewScalar("", i * i) + else: + unnamed_view = parent.createViewString("", "foo") + if not unnamed_view.isApplied(): + unnamed_view.apply(pysidre.TypeID.INT_ID, i) + unnamed_view.allocate(pysidre.TypeID.INT_ID, i) + vdata = unnamed_view.getDataArray() # Returns numpy array + for j in range(i): + vdata[j] = j + 3 + + # Create Group not in list format, show that it can't create unnamed children. + not_list = root.createGroup("not_list", False) + dummy_group = not_list.createUnnamedGroup() + dummy_view = not_list.createView("") + assert not_list.isUsingMap() + assert not_list.getNumGroups() == 0 + assert not_list.getNumViews() == 0 + assert dummy_group is None + assert dummy_view is None + + # Access data from unnamed Groups held by parent. + scalars = set() + idx = parent.getFirstValidGroupIndex() + while pysidre.indexIsValid(idx): + unnamed_group = parent.getGroup(idx) + val_view = unnamed_group.getView("val") + val = val_view.getDataInt() + assert val >= 0 and val < 10 + scalars.add(val) + idx = parent.getNextValidGroupIndex(idx) + + assert parent.isUsingList() + assert len(scalars) == 10 + assert parent.hasGroup(6) + assert not parent.hasGroup(20) + + # Destroy five of the unnamed Groups held by parent. + idx = parent.getFirstValidGroupIndex() + while pysidre.indexIsValid(idx): + if idx % 2 == 1: + parent.destroyGroup(idx) + idx = parent.getNextValidGroupIndex(idx) + + # Add one more unnamed Group, so there should be six child Groups. + parent.createUnnamedGroup() + assert parent.getNumGroups() == 6 + + # Access data from the unnamed Views. + idx = parent.getFirstValidViewIndex() + while pysidre.indexIsValid(idx): + unnamed_view = parent.getView(idx) + if idx % 3 == 0: + assert unnamed_view.getTypeID() == pysidre.TypeID.INT32_ID + num_elems = unnamed_view.getNumElements() + assert num_elems == idx + vdata = unnamed_view.getDataArray() + for j in range(num_elems): + assert vdata[j] == j + 3 + elif idx % 3 == 1: + assert unnamed_view.isScalar() + val = unnamed_view.getDataInt() + assert val == idx * idx + else: + assert unnamed_view.isString() + vstr = unnamed_view.getString() + assert vstr == "foo" + idx = parent.getNextValidViewIndex(idx) + + root.destroyGroup("parent") #------------------------------------------------------------------------------ # Verify results with various path arguments for items in list #------------------------------------------------------------------------------ def test_list_item_names(): - ds = pysidre.DataStore() - root = ds.getRoot() + ds = pysidre.DataStore() + root = ds.getRoot() - # Create a group that uses the list format. - list_test = root.createGroup("list_test", True) + # Create a group that uses the list format. + list_test = root.createGroup("list_test", True) - # It is recommended that all items held in a Group that uses the list - # format be unnamed, as the names are not useful to access those items - # from the parent Group. Nonetheless it is allowed, and this test - # verifies that the names are created as expected. + # It is recommended that all items held in a Group that uses the list + # format be unnamed, as the names are not useful to access those items + # from the parent Group. Nonetheless it is allowed, and this test + # verifies that the names are created as expected. - # Test a group created with createUnnamedGroup, the recommended way to - # create groups for a list. - unnamed_group = list_test.createUnnamedGroup() - assert unnamed_group.getName() == "" + # Test a group created with createUnnamedGroup, the recommended way to + # create groups for a list. + unnamed_group = list_test.createUnnamedGroup() + assert unnamed_group.getName() == "" - # Test groups created with empty string, a simple name, and a path. + # Test groups created with empty string, a simple name, and a path. - # The API says that groups cannot be created with an empty string argument, - # so None is returned for this one. - blank_group = list_test.createGroup("") + # The API says that groups cannot be created with an empty string argument, + # so None is returned for this one. + blank_group = list_test.createGroup("") - # A simple name with no path syntax will be assigned to the group. - named_group = list_test.createGroup("named") + # A simple name with no path syntax will be assigned to the group. + named_group = list_test.createGroup("named") - # With a path, the leading names are ignored and the final name is used. - path_group_a = list_test.createGroup("testing/path") - path_group_b = list_test.createGroup("testing/longer/path") - found_group_a = list_test.getGroup("testing/path") - found_group_b = list_test.getGroup("testing/longer/path") + # With a path, the leading names are ignored and the final name is used. + path_group_a = list_test.createGroup("testing/path") + path_group_b = list_test.createGroup("testing/longer/path") + found_group_a = list_test.getGroup("testing/path") + found_group_b = list_test.getGroup("testing/longer/path") - assert blank_group is None - assert named_group.getName() == "named" - assert path_group_a is None - assert path_group_b is None - assert found_group_a is None - assert found_group_b is None + assert blank_group is None + assert named_group.getName() == "named" + assert path_group_a is None + assert path_group_b is None + assert found_group_a is None + assert found_group_b is None - # Similar tests for views + # Similar tests for views - # An empty string is the recommended way to create an unnamed view for - # a list. - blank_view = list_test.createView("") + # An empty string is the recommended way to create an unnamed view for + # a list. + blank_view = list_test.createView("") - # A simple name with no path syntax will be assigned to the view. - named_view = list_test.createView("named") + # A simple name with no path syntax will be assigned to the view. + named_view = list_test.createView("named") - # With a path, the leading names are ignored and the final name is used. - path_view_a = list_test.createView("testing/path") - path_view_b = list_test.createView("testing/longer/path") - found_view_a = list_test.getView("testing/path") - found_view_b = list_test.getView("testing/longer/path") + # With a path, the leading names are ignored and the final name is used. + path_view_a = list_test.createView("testing/path") + path_view_b = list_test.createView("testing/longer/path") + found_view_a = list_test.getView("testing/path") + found_view_b = list_test.getView("testing/longer/path") - assert blank_view.getName() == "" - assert named_view.getName() == "named" - assert path_view_a is None - assert path_view_b is None - assert found_view_a is None - assert found_view_b is None + assert blank_view.getName() == "" + assert named_view.getName() == "named" + assert path_view_a is None + assert path_view_b is None + assert found_view_a is None + assert found_view_b is None - root.destroyGroup("list_test") + root.destroyGroup("list_test") #------------------------------------------------------------------------------ # Test Group's list format for holding contents of a vector of strings. #------------------------------------------------------------------------------ def test_string_list(): - # Round-trip test from Python list of strings to Group and back. - ds = pysidre.DataStore() - root = ds.getRoot() - - str_vec = [ - "This", - "is", - "a", - "vector", - "to", - "test", - "strings", - "in", - "sidre::Group's", - "list", - "format" - ] - - # my_strings is a Group in list format. - use_list_collection = True - my_strings = root.createGroup("my_strings", use_list_collection) - - # Put strings into the Group. - for s in str_vec: - # The first parameter will be ignored when creating a View in a Group - # that uses list collections, so we use the empty string - str_view = my_strings.createViewString("", s) - assert str_view is not None - assert str_view.isString() - - test_vec = [] - - # Get strings from the Group. - idx = my_strings.getFirstValidViewIndex() - while pysidre.indexIsValid(idx): - str_view = my_strings.getView(idx) - assert str_view is not None - assert str_view.isString() - vstr = str_view.getString() - test_vec.append(vstr) - idx = my_strings.getNextValidViewIndex(idx) - - assert str_vec == test_vec + # Round-trip test from Python list of strings to Group and back. + ds = pysidre.DataStore() + root = ds.getRoot() + + str_vec = [ + "This", "is", "a", "vector", "to", "test", "strings", "in", "sidre::Group's", "list", + "format" + ] + + # my_strings is a Group in list format. + use_list_collection = True + my_strings = root.createGroup("my_strings", use_list_collection) + + # Put strings into the Group. + for s in str_vec: + # The first parameter will be ignored when creating a View in a Group + # that uses list collections, so we use the empty string + str_view = my_strings.createViewString("", s) + assert str_view is not None + assert str_view.isString() + + test_vec = [] + + # Get strings from the Group. + idx = my_strings.getFirstValidViewIndex() + while pysidre.indexIsValid(idx): + str_view = my_strings.getView(idx) + assert str_view is not None + assert str_view.isString() + vstr = str_view.getString() + test_vec.append(vstr) + idx = my_strings.getNextValidViewIndex(idx) + + assert str_vec == test_vec #------------------------------------------------------------------------------ # Iterate Groups with getFirstValidGroupIndex, getNextValidGroupIndex #------------------------------------------------------------------------------ def test_iterate_groups(): - ds = pysidre.DataStore() - root = ds.getRoot() - - parent = root.createGroup("parent") - parent.createView("view1") - parent.createView("view2") - parent.createView("view3") - parent.createGroup("g1") - parent.createView("view4") - parent.createView("view5") - parent.createView("view6") - parent.createGroup("g2") - parent.createGroup("g3") - parent.createView("view7") - parent.createView("view8") - parent.createView("view9") - parent.createGroup("g4") - - groupcount = 0 - idx = parent.getFirstValidGroupIndex() - while pysidre.indexIsValid(idx): - groupcount += 1 - idx = parent.getNextValidGroupIndex(idx) - assert groupcount == 4 + ds = pysidre.DataStore() + root = ds.getRoot() + + parent = root.createGroup("parent") + parent.createView("view1") + parent.createView("view2") + parent.createView("view3") + parent.createGroup("g1") + parent.createView("view4") + parent.createView("view5") + parent.createView("view6") + parent.createGroup("g2") + parent.createGroup("g3") + parent.createView("view7") + parent.createView("view8") + parent.createView("view9") + parent.createGroup("g4") + + groupcount = 0 + idx = parent.getFirstValidGroupIndex() + while pysidre.indexIsValid(idx): + groupcount += 1 + idx = parent.getNextValidGroupIndex(idx) + assert groupcount == 4 #------------------------------------------------------------------------------ @@ -603,138 +594,138 @@ def test_iterate_groups(): #------------------------------------------------------------------------------ def test_iterate_groups_with_iterator(): - ds = pysidre.DataStore() - foo_group = ds.getRoot().createGroup("foo") - foo_group.createGroup("bar_group") - foo_group.createGroup("bar_group/child_1") - foo_group.createGroup("bar_group/child_2") + ds = pysidre.DataStore() + foo_group = ds.getRoot().createGroup("foo") + foo_group.createGroup("bar_group") + foo_group.createGroup("bar_group/child_1") + foo_group.createGroup("bar_group/child_2") - foo_group.createGroup("baz_group") - foo_group.createGroup("baz_group/child_1") - foo_group.createGroup("baz_group/child_2") - foo_group.createGroup("baz_group/child_3") + foo_group.createGroup("baz_group") + foo_group.createGroup("baz_group/child_1") + foo_group.createGroup("baz_group/child_2") + foo_group.createGroup("baz_group/child_3") - foo_group.createGroup("qux_group") - foo_group.createGroup("qux_group/child_1") + foo_group.createGroup("qux_group") + foo_group.createGroup("qux_group/child_1") - foo_group.createView("bar_view") - foo_group.createView("baz_view") - foo_group.createView("qux_view") - foo_group.createView("quux_view") + foo_group.createView("bar_view") + foo_group.createView("baz_view") + foo_group.createView("qux_view") + foo_group.createView("quux_view") - numExpGroups = 3 - numExpViews = 4 + numExpGroups = 3 + numExpViews = 4 - # iterate through groups and views of 'foo' using Python for-loop - nGroups = 0 - for group in foo_group.groups(): - assert group.getParent() == foo_group - assert group.getName().endswith("_group") - nGroups += 1 - assert nGroups == numExpGroups + # iterate through groups and views of 'foo' using Python for-loop + nGroups = 0 + for group in foo_group.groups(): + assert group.getParent() == foo_group + assert group.getName().endswith("_group") + nGroups += 1 + assert nGroups == numExpGroups - nViews = 0 - for view in foo_group.views(): - assert view.getOwningGroup() == foo_group - assert view.getName().endswith("_view") - nViews += 1 - assert nViews == numExpViews + nViews = 0 + for view in foo_group.views(): + assert view.getOwningGroup() == foo_group + assert view.getName().endswith("_view") + nViews += 1 + assert nViews == numExpViews #------------------------------------------------------------------------------ # Verify getFirstValidViewIndex() and getNextValidIndex() #------------------------------------------------------------------------------ def test_get_first_and_next_view_index(): - ds = pysidre.DataStore() - root = ds.getRoot() + ds = pysidre.DataStore() + root = ds.getRoot() - parent = root.createGroup("parent") - view1 = parent.createView("view1") - view2 = parent.createView("view2") + parent = root.createGroup("parent") + view1 = parent.createView("view1") + view2 = parent.createView("view2") - assert parent.getNumViews() == 2 + assert parent.getNumViews() == 2 - idx1 = parent.getFirstValidViewIndex() - idx2 = parent.getNextValidViewIndex(idx1) - idx3 = parent.getNextValidViewIndex(idx2) - assert idx1 == 0 - assert idx2 == 1 - assert idx3 == pysidre.InvalidIndex + idx1 = parent.getFirstValidViewIndex() + idx2 = parent.getNextValidViewIndex(idx1) + idx3 = parent.getNextValidViewIndex(idx2) + assert idx1 == 0 + assert idx2 == 1 + assert idx3 == pysidre.InvalidIndex - view1out = parent.getView(idx1) - view2out = parent.getView(idx2) - assert view1 == view1out - assert view2 == view2out + view1out = parent.getView(idx1) + view2out = parent.getView(idx2) + assert view1 == view1out + assert view2 == view2out - # Check error conditions - emptygrp = root.createGroup("emptyGroup") - badidx1 = emptygrp.getFirstValidViewIndex() - badidx2 = emptygrp.getNextValidViewIndex(badidx1) + # Check error conditions + emptygrp = root.createGroup("emptyGroup") + badidx1 = emptygrp.getFirstValidViewIndex() + badidx2 = emptygrp.getNextValidViewIndex(badidx1) - assert badidx1 == pysidre.InvalidIndex - assert badidx2 == pysidre.InvalidIndex + assert badidx1 == pysidre.InvalidIndex + assert badidx2 == pysidre.InvalidIndex #------------------------------------------------------------------------------ # Iterate Views with getFirstValidViewIndex, getNextValidViewIndex #------------------------------------------------------------------------------ def test_iterate_views(): - ds = pysidre.DataStore() - root = ds.getRoot() - - parent = root.createGroup("parent") - parent.createView("view1") - parent.createView("view2") - parent.createView("view3") - parent.createGroup("g1") - parent.createView("view4") - parent.createView("view5") - parent.createView("view6") - parent.createGroup("g2") - parent.createGroup("g3") - parent.createView("view7") - parent.createView("view8") - parent.createView("view9") - parent.createGroup("g4") - - viewcount = 0 - idx = parent.getFirstValidViewIndex() - while pysidre.indexIsValid(idx): - viewcount += 1 - idx = parent.getNextValidViewIndex(idx) - assert viewcount == 9 - - + ds = pysidre.DataStore() + root = ds.getRoot() + + parent = root.createGroup("parent") + parent.createView("view1") + parent.createView("view2") + parent.createView("view3") + parent.createGroup("g1") + parent.createView("view4") + parent.createView("view5") + parent.createView("view6") + parent.createGroup("g2") + parent.createGroup("g3") + parent.createView("view7") + parent.createView("view8") + parent.createView("view9") + parent.createGroup("g4") + + viewcount = 0 + idx = parent.getFirstValidViewIndex() + while pysidre.indexIsValid(idx): + viewcount += 1 + idx = parent.getNextValidViewIndex(idx) + assert viewcount == 9 + + #------------------------------------------------------------------------------ # Verify getGroupName() and getGroupIndex() #------------------------------------------------------------------------------ def test_get_group_name_index(): - ds = pysidre.DataStore() - root = ds.getRoot() + ds = pysidre.DataStore() + root = ds.getRoot() - parent = root.createGroup("parent") - grp1 = parent.createGroup("grp1") - grp2 = parent.createGroup("grp2") - assert parent.getNumGroups() == 2 + parent = root.createGroup("parent") + grp1 = parent.createGroup("grp1") + grp2 = parent.createGroup("grp2") + assert parent.getNumGroups() == 2 - idx1 = parent.getGroupIndex("grp1") - idx2 = parent.getGroupIndex("grp2") + idx1 = parent.getGroupIndex("grp1") + idx2 = parent.getGroupIndex("grp2") - name1 = parent.getGroupName(idx1) - name2 = parent.getGroupName(idx2) + name1 = parent.getGroupName(idx1) + name2 = parent.getGroupName(idx2) - assert name1 == "grp1" - assert grp1.getName() == name1 + assert name1 == "grp1" + assert grp1.getName() == name1 - assert name2 == "grp2" - assert grp2.getName() == name2 + assert name2 == "grp2" + assert grp2.getName() == name2 - idx3 = parent.getGroupIndex("grp3") - assert idx3 == pysidre.InvalidIndex + idx3 = parent.getGroupIndex("grp3") + assert idx3 == pysidre.InvalidIndex - name3 = parent.getGroupName(idx3) - assert name3 == "" - assert not pysidre.nameIsValid(name3) + name3 = parent.getGroupName(idx3) + assert name3 == "" + assert not pysidre.nameIsValid(name3) # ------------------------------------------------------------------------------ @@ -745,1144 +736,1142 @@ def test_get_group_name_index(): # hasView() # ------------------------------------------------------------------------------ def test_create_destroy_has_view(): - ds = pysidre.DataStore() - root = ds.getRoot() - group = root.createGroup("parent") - - view = group.createView("view") - assert group.getParent() == root - assert not view.hasBuffer() - assert group.hasView("view") - iview = group.getViewIndex("view") - assert iview == 0 - iview = view.getIndex() - assert iview == 0 - - # Try creating view again, should be a no-op (returns None) - assert group.createView("view") is None - - # Create another view to make sure destroyView only destroys one view - group.createView("viewfiller") - assert group.getNumViews() == 2 - iviewfiller = group.getViewIndex("viewfiller") - assert iviewfiller == 1 - - group.destroyView("view") - assert group.getNumViews() == 1 - # Check if index changed - assert iviewfiller == group.getViewIndex("viewfiller") - - # Destroy already destroyed view. Should be a no-op, not a failure - group.destroyView("view") - assert group.getNumViews() == 1 - assert not group.hasView("view") - - # Try API call that specifies specific type and length - group.createViewAndAllocate("viewWithLength1", pysidre.TypeID.INT32_ID, 50) - iview2 = group.getViewIndex("viewWithLength1") - assert iview == iview2 # reuse slot - - # Error condition check - try again with duplicate name, should be a no-op - assert group.createViewAndAllocate("viewWithLength1", pysidre.TypeID.FLOAT64_ID, 50) is None - group.destroyViewAndData("viewWithLength1") - assert not group.hasView("viewWithLength1") - - # Should not allow negative length - assert group.createViewAndAllocate("viewWithLengthBadLen", pysidre.TypeID.FLOAT64_ID, -1) is None - - # Try API call that specifies data type in another way - group.createViewAndAllocate("viewWithLength2", pysidre.TypeID.FLOAT64_ID, 50) - assert group.createViewAndAllocate("viewWithLength2", pysidre.TypeID.FLOAT64_ID, 50) is None - - # Destroy view and its buffer using index - indx = group.getFirstValidViewIndex() - buffer = group.getView(indx).getBuffer() - bindx = buffer.getIndex() - group.destroyViewAndData(indx) - # Buffer should be destroyed from datastore - assert ds.getBuffer(bindx) is None - - # Destroy view but not the buffer - view = group.createViewAndAllocate("viewWithLength2", pysidre.TypeID.INT_ID, 50) - buff = view.getBuffer() - group.destroyView("viewWithLength2") - assert buff.isAllocated() + ds = pysidre.DataStore() + root = ds.getRoot() + group = root.createGroup("parent") + + view = group.createView("view") + assert group.getParent() == root + assert not view.hasBuffer() + assert group.hasView("view") + iview = group.getViewIndex("view") + assert iview == 0 + iview = view.getIndex() + assert iview == 0 + + # Try creating view again, should be a no-op (returns None) + assert group.createView("view") is None + + # Create another view to make sure destroyView only destroys one view + group.createView("viewfiller") + assert group.getNumViews() == 2 + iviewfiller = group.getViewIndex("viewfiller") + assert iviewfiller == 1 + + group.destroyView("view") + assert group.getNumViews() == 1 + # Check if index changed + assert iviewfiller == group.getViewIndex("viewfiller") + + # Destroy already destroyed view. Should be a no-op, not a failure + group.destroyView("view") + assert group.getNumViews() == 1 + assert not group.hasView("view") + + # Try API call that specifies specific type and length + group.createViewAndAllocate("viewWithLength1", pysidre.TypeID.INT32_ID, 50) + iview2 = group.getViewIndex("viewWithLength1") + assert iview == iview2 # reuse slot + + # Error condition check - try again with duplicate name, should be a no-op + assert group.createViewAndAllocate("viewWithLength1", pysidre.TypeID.FLOAT64_ID, 50) is None + group.destroyViewAndData("viewWithLength1") + assert not group.hasView("viewWithLength1") + + # Should not allow negative length + assert group.createViewAndAllocate("viewWithLengthBadLen", pysidre.TypeID.FLOAT64_ID, + -1) is None + + # Try API call that specifies data type in another way + group.createViewAndAllocate("viewWithLength2", pysidre.TypeID.FLOAT64_ID, 50) + assert group.createViewAndAllocate("viewWithLength2", pysidre.TypeID.FLOAT64_ID, 50) is None + + # Destroy view and its buffer using index + indx = group.getFirstValidViewIndex() + buffer = group.getView(indx).getBuffer() + bindx = buffer.getIndex() + group.destroyViewAndData(indx) + # Buffer should be destroyed from datastore + assert ds.getBuffer(bindx) is None + + # Destroy view but not the buffer + view = group.createViewAndAllocate("viewWithLength2", pysidre.TypeID.INT_ID, 50) + buff = view.getBuffer() + group.destroyView("viewWithLength2") + assert buff.isAllocated() #------------------------------------------------------------------------------ # createViewAndAllocate() with zero-sized array #------------------------------------------------------------------------------ def test_create_zero_sized_view(): - ds = pysidre.DataStore() - root = ds.getRoot() + ds = pysidre.DataStore() + root = ds.getRoot() - zero_sized_view = root.createViewAndAllocate("foo", pysidre.TypeID.INT_ID, 0) - assert zero_sized_view.isDescribed() - assert zero_sized_view.isAllocated() + zero_sized_view = root.createViewAndAllocate("foo", pysidre.TypeID.INT_ID, 0) + assert zero_sized_view.isDescribed() + assert zero_sized_view.isAllocated() #------------------------------------------------------------------------------ # Verify createGroup(), destroyGroup(), hasGroup() #------------------------------------------------------------------------------ def test_create_destroy_has_group(): - ds = pysidre.DataStore() - root = ds.getRoot() + ds = pysidre.DataStore() + root = ds.getRoot() - grp = root.createGroup("grp") - assert grp.getParent() == root + grp = root.createGroup("grp") + assert grp.getParent() == root - assert root.hasGroup("grp") + assert root.hasGroup("grp") - root.destroyGroup("grp") - assert not root.hasGroup("grp") + root.destroyGroup("grp") + assert not root.hasGroup("grp") - grp2 = root.createGroup("grp2") - root.destroyGroup(root.getFirstValidGroupIndex()) + grp2 = root.createGroup("grp2") + root.destroyGroup(root.getFirstValidGroupIndex()) #------------------------------------------------------------------------------ # Test various destroy methods #------------------------------------------------------------------------------ def test_destroy_group_and_data(): - ds = pysidre.DataStore() - root = ds.getRoot() - group0 = root.createGroup("group0") - group1 = root.createGroup("group1") - child0 = group0.createGroup("child0") - child1 = group0.createGroup("child1") - child2 = group1.createGroup("child2") - child3 = group1.createGroup("child3") - child4 = group1.createGroup("child4") - - child0.createViewAndAllocate("intview", pysidre.TypeID.INT_ID, 15) - foo0 = child0.createGroup("foo") - child0.createGroup("empty") - child0.createViewScalar("sclview", 3.14159) - child0.createViewString("strview", "Hello world.") - foo0.createViewAndAllocate("fooview", pysidre.TypeID.FLOAT64_ID, 12) - - int0_view = child0.getView("intview") - int0_vals = int0_view.getDataArray() - for i in range(15): - int0_vals[i] = i - - fooview = foo0.getView("fooview") - flt0_vals = fooview.getDataArray() - for i in range(12): - flt0_vals[i] = float(-i) - - intbuf = int0_view.getBuffer() - fltbuf = fooview.getBuffer() - - # Store each Buffer's index for later testing. - int_idx = intbuf.getIndex() - flt_idx = fltbuf.getIndex() - - # Attach buffers to views in other children - child1.createView("intview", pysidre.TypeID.INT_ID, 15, intbuf) - foo1 = child1.createGroup("foo") - child1.createGroup("empty") - child1.createViewScalar("sclview", 3.14159) - child1.createViewString("strview", "Hello world.") - foo1.createView("fooview", pysidre.TypeID.FLOAT64_ID, 12, fltbuf) - - child2.createView("intview", pysidre.TypeID.INT_ID, 15, intbuf) - foo2 = child2.createGroup("foo") - child2.createGroup("empty") - child2.createViewScalar("sclview", 3.14159) - child2.createViewString("strview", "Hello world.") - foo2.createView("fooview", pysidre.TypeID.FLOAT64_ID, 12, fltbuf) - - child3.createView("intview", pysidre.TypeID.INT_ID, 15, intbuf) - foo3 = child3.createGroup("foo") - child3.createGroup("empty") - child3.createViewScalar("sclview", 3.14159) - child3.createViewString("strview", "Hello world.") - foo3.createView("fooview", pysidre.TypeID.FLOAT64_ID, 12, fltbuf) - - child4.createView("intview", pysidre.TypeID.INT_ID, 15, intbuf) - foo4 = child4.createGroup("foo") - child4.createGroup("empty") - child4.createViewScalar("sclview", 3.14159) - child4.createViewString("strview", "Hello world.") - foo4.createView("fooview", pysidre.TypeID.FLOAT64_ID, 12, fltbuf) - - # Beginning state: 2 Buffers, each attached to 5 Views. - assert ds.getNumBuffers() == 2 - assert intbuf.getNumViews() == 5 - assert fltbuf.getNumViews() == 5 - - # Destroy "child0/foo" by path. This destroys the View that created fltbuf. - assert child0.getNumGroups() == 2 - group0.destroyGroupAndData("child0/foo") - - # Verify that fltbuf now is attached to 4 Views and child0 has only one - # group "empty". - assert fltbuf.getNumViews() == 4 - assert child0.getNumGroups() == 1 - assert child0.hasGroup("empty") - - # Destroy child3 using index argument - idx3 = group1.getGroupIndex("child3") - group1.destroyGroupAndData(idx3) - - # intbuf and fltbuf both lose one attached View - assert intbuf.getNumViews() == 4 - assert fltbuf.getNumViews() == 3 - - # Verify Buffers' data can be accessed by other Views - int4_vals = child4.getView("intview").getDataArray() - for i in range(15): - assert int4_vals[i] == i - - flt4_vals = foo4.getView("fooview").getDataArray() - for i in range(12): - assert abs(flt4_vals[i] - float(-i)) < 1.0e-12 - - # Destroy Groups held by child1, removes "foo" and "empty" but leaves Views - assert child1.getNumGroups() == 2 - assert child1.getNumViews() == 3 - child1.destroyGroupsAndData() - assert child1.getNumGroups() == 0 - assert child1.getNumViews() == 3 - - # That removed one more View from fltbuf but left intbuf unchanged. - assert intbuf.getNumViews() == 4 - assert fltbuf.getNumViews() == 2 - - # Destroy the entire subtree of child4 - assert child4.getNumGroups() == 2 - assert child4.getNumViews() == 3 - child4.destroyGroupSubtreeAndData() - assert child4.getNumGroups() == 0 - assert child4.getNumViews() == 0 - - # Both buffers lost one more View - assert intbuf.getNumViews() == 3 - assert fltbuf.getNumViews() == 1 - - # The View at "group1/child2/foo/fooview" is the only View still attached to fltbuf - assert ds.getNumBuffers() == 2 - assert group1.hasView("child2/foo/fooview") - assert group1.getView("child2/foo/fooview").hasBuffer() - assert group1.getView("child2/foo/fooview").getBuffer() == fltbuf - - # Destroy entire subtree of group1. This detaches last View from fltbuf and destroys fltbuf - group1.destroyGroupSubtreeAndData() - assert ds.getNumBuffers() == 1 - assert ds.hasBuffer(int_idx) - assert not ds.hasBuffer(flt_idx) - assert group1.getNumViews() == 0 - assert group1.getNumGroups() == 0 - - # intbuf still attached to the "intview" Views in child0 and child1 - assert intbuf.getNumViews() == 2 - assert group0.getView("child0/intview").getBuffer() == intbuf - assert group0.getView("child1/intview").getBuffer() == intbuf - - # Destroy everything below root, remaining buffer will be destroyed - root.destroyGroupSubtreeAndData() - assert not ds.hasBuffer(int_idx) - assert ds.getNumBuffers() == 0 - assert root.getNumViews() == 0 - assert root.getNumGroups() == 0 + ds = pysidre.DataStore() + root = ds.getRoot() + group0 = root.createGroup("group0") + group1 = root.createGroup("group1") + child0 = group0.createGroup("child0") + child1 = group0.createGroup("child1") + child2 = group1.createGroup("child2") + child3 = group1.createGroup("child3") + child4 = group1.createGroup("child4") + + child0.createViewAndAllocate("intview", pysidre.TypeID.INT_ID, 15) + foo0 = child0.createGroup("foo") + child0.createGroup("empty") + child0.createViewScalar("sclview", 3.14159) + child0.createViewString("strview", "Hello world.") + foo0.createViewAndAllocate("fooview", pysidre.TypeID.FLOAT64_ID, 12) + + int0_view = child0.getView("intview") + int0_vals = int0_view.getDataArray() + for i in range(15): + int0_vals[i] = i + + fooview = foo0.getView("fooview") + flt0_vals = fooview.getDataArray() + for i in range(12): + flt0_vals[i] = float(-i) + + intbuf = int0_view.getBuffer() + fltbuf = fooview.getBuffer() + + # Store each Buffer's index for later testing. + int_idx = intbuf.getIndex() + flt_idx = fltbuf.getIndex() + + # Attach buffers to views in other children + child1.createView("intview", pysidre.TypeID.INT_ID, 15, intbuf) + foo1 = child1.createGroup("foo") + child1.createGroup("empty") + child1.createViewScalar("sclview", 3.14159) + child1.createViewString("strview", "Hello world.") + foo1.createView("fooview", pysidre.TypeID.FLOAT64_ID, 12, fltbuf) + + child2.createView("intview", pysidre.TypeID.INT_ID, 15, intbuf) + foo2 = child2.createGroup("foo") + child2.createGroup("empty") + child2.createViewScalar("sclview", 3.14159) + child2.createViewString("strview", "Hello world.") + foo2.createView("fooview", pysidre.TypeID.FLOAT64_ID, 12, fltbuf) + + child3.createView("intview", pysidre.TypeID.INT_ID, 15, intbuf) + foo3 = child3.createGroup("foo") + child3.createGroup("empty") + child3.createViewScalar("sclview", 3.14159) + child3.createViewString("strview", "Hello world.") + foo3.createView("fooview", pysidre.TypeID.FLOAT64_ID, 12, fltbuf) + + child4.createView("intview", pysidre.TypeID.INT_ID, 15, intbuf) + foo4 = child4.createGroup("foo") + child4.createGroup("empty") + child4.createViewScalar("sclview", 3.14159) + child4.createViewString("strview", "Hello world.") + foo4.createView("fooview", pysidre.TypeID.FLOAT64_ID, 12, fltbuf) + + # Beginning state: 2 Buffers, each attached to 5 Views. + assert ds.getNumBuffers() == 2 + assert intbuf.getNumViews() == 5 + assert fltbuf.getNumViews() == 5 + + # Destroy "child0/foo" by path. This destroys the View that created fltbuf. + assert child0.getNumGroups() == 2 + group0.destroyGroupAndData("child0/foo") + + # Verify that fltbuf now is attached to 4 Views and child0 has only one + # group "empty". + assert fltbuf.getNumViews() == 4 + assert child0.getNumGroups() == 1 + assert child0.hasGroup("empty") + + # Destroy child3 using index argument + idx3 = group1.getGroupIndex("child3") + group1.destroyGroupAndData(idx3) + + # intbuf and fltbuf both lose one attached View + assert intbuf.getNumViews() == 4 + assert fltbuf.getNumViews() == 3 + + # Verify Buffers' data can be accessed by other Views + int4_vals = child4.getView("intview").getDataArray() + for i in range(15): + assert int4_vals[i] == i + + flt4_vals = foo4.getView("fooview").getDataArray() + for i in range(12): + assert abs(flt4_vals[i] - float(-i)) < 1.0e-12 + + # Destroy Groups held by child1, removes "foo" and "empty" but leaves Views + assert child1.getNumGroups() == 2 + assert child1.getNumViews() == 3 + child1.destroyGroupsAndData() + assert child1.getNumGroups() == 0 + assert child1.getNumViews() == 3 + + # That removed one more View from fltbuf but left intbuf unchanged. + assert intbuf.getNumViews() == 4 + assert fltbuf.getNumViews() == 2 + + # Destroy the entire subtree of child4 + assert child4.getNumGroups() == 2 + assert child4.getNumViews() == 3 + child4.destroyGroupSubtreeAndData() + assert child4.getNumGroups() == 0 + assert child4.getNumViews() == 0 + + # Both buffers lost one more View + assert intbuf.getNumViews() == 3 + assert fltbuf.getNumViews() == 1 + + # The View at "group1/child2/foo/fooview" is the only View still attached to fltbuf + assert ds.getNumBuffers() == 2 + assert group1.hasView("child2/foo/fooview") + assert group1.getView("child2/foo/fooview").hasBuffer() + assert group1.getView("child2/foo/fooview").getBuffer() == fltbuf + + # Destroy entire subtree of group1. This detaches last View from fltbuf and destroys fltbuf + group1.destroyGroupSubtreeAndData() + assert ds.getNumBuffers() == 1 + assert ds.hasBuffer(int_idx) + assert not ds.hasBuffer(flt_idx) + assert group1.getNumViews() == 0 + assert group1.getNumGroups() == 0 + + # intbuf still attached to the "intview" Views in child0 and child1 + assert intbuf.getNumViews() == 2 + assert group0.getView("child0/intview").getBuffer() == intbuf + assert group0.getView("child1/intview").getBuffer() == intbuf + + # Destroy everything below root, remaining buffer will be destroyed + root.destroyGroupSubtreeAndData() + assert not ds.hasBuffer(int_idx) + assert ds.getNumBuffers() == 0 + assert root.getNumViews() == 0 + assert root.getNumGroups() == 0 def test_group_name_collisions(): - ds = pysidre.DataStore() - root = ds.getRoot() - flds = root.createGroup("fields") - flds.createView("a") + ds = pysidre.DataStore() + root = ds.getRoot() + flds = root.createGroup("fields") + flds.createView("a") - assert flds.hasChildView("a") + assert flds.hasChildView("a") - # Attempt to create duplicate group name - assert root.createGroup("fields") is None + # Attempt to create duplicate group name + assert root.createGroup("fields") is None - # Attempt to create duplicate view name - assert flds.createView("a") is None + # Attempt to create duplicate view name + assert flds.createView("a") is None - # Attempt to create a group named the same as an existing view - assert flds.createGroup("a") is None + # Attempt to create a group named the same as an existing view + assert flds.createGroup("a") is None - # Attempt to create a view named the same as an existing group - assert root.createView("fields") is None + # Attempt to create a view named the same as an existing group + assert root.createView("fields") is None - # Create groups with unusual names/paths - root.createGroup("here//is/path") - root.createGroup("éch≈o/Ωd") - root.createGroup("../group/..") + # Create groups with unusual names/paths + root.createGroup("here//is/path") + root.createGroup("éch≈o/Ωd") + root.createGroup("../group/..") - # Print all group names - idx = root.getFirstValidGroupIndex() - while pysidre.indexIsValid(idx): - print(root.getGroup(idx).getName()) - idx = root.getNextValidGroupIndex(idx) + # Print all group names + idx = root.getFirstValidGroupIndex() + while pysidre.indexIsValid(idx): + print(root.getGroup(idx).getName()) + idx = root.getNextValidGroupIndex(idx) def test_view_copy_move(): - ds = pysidre.DataStore() - root = ds.getRoot() - flds = root.createGroup("fields") - extdata = np.array([0] * 10) - - views = [None] * 6 - names = [None] * 6 - - # Create views in different states - views[0] = flds.createView("empty0") - views[1] = flds.createView("empty1", pysidre.TypeID.INT32_ID, 10) - views[2] = flds.createViewAndAllocate("buffer", pysidre.TypeID.INT32_ID, 10) - views[3] = flds.createView("external", pysidre.TypeID.INT32_ID, 10) - views[3].setExternalData(extdata) - views[4] = flds.createViewScalar("scalar", 25) - views[5] = flds.createViewString("string", "I am string") - - buffdata = flds.getView("buffer").getDataArray() - for i in range(10): - extdata[i] = i - buffdata[i] = i + 100 - - for i in range(6): - names[i] = views[i].getName() - assert flds.hasView(names[i]) - - # Test moving a view from flds to sub1 - sub1 = flds.createGroup("sub1") - - for i in range(6): - sub1.moveView(views[i]) - assert not flds.hasView(names[i]) - assert sub1.hasView(names[i]) - - # Moving to same group is a no-op - sub1.moveView(views[i]) - assert sub1.hasView(names[i]) - - sub2 = flds.createGroup("sub2") - - for i in range(6): - sub2.copyView(views[i]) - assert sub1.hasView(names[i]) - assert sub2.hasView(names[i]) - - # Check copies - view1 = sub1.getView("empty0") - view2 = sub2.getView("empty0") - assert view1 is not view2 - assert view2.isEmpty() - assert not view2.isDescribed() - assert not view2.isAllocated() - assert not view2.isApplied() - - view1 = sub1.getView("empty1") - view2 = sub2.getView("empty1") - assert view1 is not view2 - assert view2.isEmpty() - assert view2.isDescribed() - assert not view2.isAllocated() - assert not view2.isApplied() - - view1 = sub1.getView("buffer") - view2 = sub2.getView("buffer") - assert view1 is not view2 - assert view2.hasBuffer() - assert view2.isDescribed() - assert view2.isAllocated() - assert view2.isApplied() - assert view1.getBuffer() == view2.getBuffer() - assert view1.getBuffer().getNumViews() == 2 - - view1 = sub1.getView("external") - view2 = sub2.getView("external") - assert view1 is not view2 - assert view2.isExternal() - assert view2.isDescribed() - assert view2.isAllocated() - assert view2.isApplied() - assert view1.getDataInt() == view2.getDataInt() - - view1 = sub1.getView("scalar") - view2 = sub2.getView("scalar") - assert view1 is not view2 - assert view2.isScalar() - assert view2.isDescribed() - assert view2.isAllocated() - assert view2.isApplied() - assert view1.getDataInt() == view2.getDataInt() - - view1 = sub1.getView("string") - view2 = sub2.getView("string") - assert view1 is not view2 - assert view2.isString() - assert view2.isDescribed() - assert view2.isAllocated() - assert view2.isApplied() - svalue = view1.getString() - assert svalue == "I am string" + ds = pysidre.DataStore() + root = ds.getRoot() + flds = root.createGroup("fields") + extdata = np.array([0] * 10) + + views = [None] * 6 + names = [None] * 6 + + # Create views in different states + views[0] = flds.createView("empty0") + views[1] = flds.createView("empty1", pysidre.TypeID.INT32_ID, 10) + views[2] = flds.createViewAndAllocate("buffer", pysidre.TypeID.INT32_ID, 10) + views[3] = flds.createView("external", pysidre.TypeID.INT32_ID, 10) + views[3].setExternalData(extdata) + views[4] = flds.createViewScalar("scalar", 25) + views[5] = flds.createViewString("string", "I am string") + + buffdata = flds.getView("buffer").getDataArray() + for i in range(10): + extdata[i] = i + buffdata[i] = i + 100 + + for i in range(6): + names[i] = views[i].getName() + assert flds.hasView(names[i]) + + # Test moving a view from flds to sub1 + sub1 = flds.createGroup("sub1") + + for i in range(6): + sub1.moveView(views[i]) + assert not flds.hasView(names[i]) + assert sub1.hasView(names[i]) + + # Moving to same group is a no-op + sub1.moveView(views[i]) + assert sub1.hasView(names[i]) + + sub2 = flds.createGroup("sub2") + + for i in range(6): + sub2.copyView(views[i]) + assert sub1.hasView(names[i]) + assert sub2.hasView(names[i]) + + # Check copies + view1 = sub1.getView("empty0") + view2 = sub2.getView("empty0") + assert view1 is not view2 + assert view2.isEmpty() + assert not view2.isDescribed() + assert not view2.isAllocated() + assert not view2.isApplied() + + view1 = sub1.getView("empty1") + view2 = sub2.getView("empty1") + assert view1 is not view2 + assert view2.isEmpty() + assert view2.isDescribed() + assert not view2.isAllocated() + assert not view2.isApplied() + + view1 = sub1.getView("buffer") + view2 = sub2.getView("buffer") + assert view1 is not view2 + assert view2.hasBuffer() + assert view2.isDescribed() + assert view2.isAllocated() + assert view2.isApplied() + assert view1.getBuffer() == view2.getBuffer() + assert view1.getBuffer().getNumViews() == 2 + + view1 = sub1.getView("external") + view2 = sub2.getView("external") + assert view1 is not view2 + assert view2.isExternal() + assert view2.isDescribed() + assert view2.isAllocated() + assert view2.isApplied() + assert view1.getDataInt() == view2.getDataInt() + + view1 = sub1.getView("scalar") + view2 = sub2.getView("scalar") + assert view1 is not view2 + assert view2.isScalar() + assert view2.isDescribed() + assert view2.isAllocated() + assert view2.isApplied() + assert view1.getDataInt() == view2.getDataInt() + + view1 = sub1.getView("string") + view2 = sub2.getView("string") + assert view1 is not view2 + assert view2.isString() + assert view2.isDescribed() + assert view2.isAllocated() + assert view2.isApplied() + svalue = view1.getString() + assert svalue == "I am string" def test_groups_move_copy(): - ds = pysidre.DataStore() - root = ds.getRoot() - flds = root.createGroup("fields") - - ga = flds.createGroup("a") - gb = flds.createGroup("b") - gc = flds.createGroup("c") - - f0value = 100.0 - val = 101.0 - - bschild = gb.createGroup("childOfB") - - ga.createView("i0").setScalar(1) - gb.createView("f0").setScalar(f0value) - gc.createView("d0").setScalar(3000.0) - bschild.createView("val").setScalar(val) - - buffercount = ds.getNumBuffers() - - # Check that all sub groups exist - assert flds.hasGroup("a") - assert flds.hasGroup("b") - assert flds.hasGroup("c") - - # Move "b" to a child of "sub" - assert gb.getIndex() == 1 - assert gb.getParent() == flds - gsub = flds.createGroup("sub") - gb0 = gsub.moveGroup(gb) - - # gb0 is an alias to gb - assert gb == gb0 - assert gb.getIndex() == 0 - assert gb.getParent() == gsub - assert gb0.getNumGroups() == 1 - assert gb0.getGroup("childOfB") == bschild - assert bschild.getNumGroups() == 0 - assert buffercount == ds.getNumBuffers() - - assert gb0.getNumViews() == 1 - assert gb0.hasChildView("f0") - if gb0.hasChildView("f0"): - assert gb0.getView("f0").getDataFloat() == f0value - - assert bschild.getNumViews() == 1 - assert bschild.hasChildView("val") - if bschild.hasChildView("val"): - assert bschild.getView("val").getDataFloat() == val - - assert flds.getNumGroups() == 3 - assert flds.hasGroup("a") - assert flds.hasGroup("sub") - assert flds.hasGroup("c") - - assert flds.getGroup("sub").getGroup("b") == gb - - # Verify that we can copy a group into an empty group - containCopy = root.createGroup("containCopy") - theCopy = containCopy.copyGroup(flds) - assert theCopy.isEquivalentTo(flds) - assert containCopy.getNumGroups() == 1 - assert buffercount == ds.getNumBuffers() - - # Verify that we can copy a group when there is no name clash - anotherCopy = root.createGroup("anotherCopy") - anotherCopy.createGroup("futureSiblingGroup") - theOtherCopy = anotherCopy.copyGroup(flds) - assert anotherCopy.getNumGroups() == 2 - assert theOtherCopy.isEquivalentTo(flds) - assert buffercount == ds.getNumBuffers() - - # Verify that we cannot copy a group when there is a name clash - otherB = containCopy.createGroup("b") - otherB.createView("f1").setScalar(42.0) - otherB.createGroup("Q") - triedCopy = gsub.copyGroup(otherB) - assert triedCopy is None - assert gsub.getNumGroups() == 1 - assert gsub.hasChildGroup("b") - assert buffercount == ds.getNumBuffers() - - assert gb0.getNumGroups() == 1 - assert gb0.getGroup("childOfB") == bschild - assert gb0.getNumViews() == 1 - assert gb0.hasChildView("f0") - if gb0.hasChildView("f0"): - assert gb0.getView("f0").getDataFloat() == f0value + ds = pysidre.DataStore() + root = ds.getRoot() + flds = root.createGroup("fields") + + ga = flds.createGroup("a") + gb = flds.createGroup("b") + gc = flds.createGroup("c") + + f0value = 100.0 + val = 101.0 + + bschild = gb.createGroup("childOfB") + + ga.createView("i0").setScalar(1) + gb.createView("f0").setScalar(f0value) + gc.createView("d0").setScalar(3000.0) + bschild.createView("val").setScalar(val) + + buffercount = ds.getNumBuffers() + + # Check that all sub groups exist + assert flds.hasGroup("a") + assert flds.hasGroup("b") + assert flds.hasGroup("c") + + # Move "b" to a child of "sub" + assert gb.getIndex() == 1 + assert gb.getParent() == flds + gsub = flds.createGroup("sub") + gb0 = gsub.moveGroup(gb) + + # gb0 is an alias to gb + assert gb == gb0 + assert gb.getIndex() == 0 + assert gb.getParent() == gsub + assert gb0.getNumGroups() == 1 + assert gb0.getGroup("childOfB") == bschild + assert bschild.getNumGroups() == 0 + assert buffercount == ds.getNumBuffers() + + assert gb0.getNumViews() == 1 + assert gb0.hasChildView("f0") + if gb0.hasChildView("f0"): + assert gb0.getView("f0").getDataFloat() == f0value + + assert bschild.getNumViews() == 1 + assert bschild.hasChildView("val") + if bschild.hasChildView("val"): + assert bschild.getView("val").getDataFloat() == val + + assert flds.getNumGroups() == 3 + assert flds.hasGroup("a") + assert flds.hasGroup("sub") + assert flds.hasGroup("c") + + assert flds.getGroup("sub").getGroup("b") == gb + + # Verify that we can copy a group into an empty group + containCopy = root.createGroup("containCopy") + theCopy = containCopy.copyGroup(flds) + assert theCopy.isEquivalentTo(flds) + assert containCopy.getNumGroups() == 1 + assert buffercount == ds.getNumBuffers() + + # Verify that we can copy a group when there is no name clash + anotherCopy = root.createGroup("anotherCopy") + anotherCopy.createGroup("futureSiblingGroup") + theOtherCopy = anotherCopy.copyGroup(flds) + assert anotherCopy.getNumGroups() == 2 + assert theOtherCopy.isEquivalentTo(flds) + assert buffercount == ds.getNumBuffers() + + # Verify that we cannot copy a group when there is a name clash + otherB = containCopy.createGroup("b") + otherB.createView("f1").setScalar(42.0) + otherB.createGroup("Q") + triedCopy = gsub.copyGroup(otherB) + assert triedCopy is None + assert gsub.getNumGroups() == 1 + assert gsub.hasChildGroup("b") + assert buffercount == ds.getNumBuffers() + + assert gb0.getNumGroups() == 1 + assert gb0.getGroup("childOfB") == bschild + assert gb0.getNumViews() == 1 + assert gb0.hasChildView("f0") + if gb0.hasChildView("f0"): + assert gb0.getView("f0").getDataFloat() == f0value def test_group_deep_copy(): - ds = pysidre.DataStore() - root = ds.getRoot() - flds = root.createGroup("fields") - - ga = flds.createGroup("a") - gb = flds.createGroup("b") - - dval0 = 100.0 - dval1 = 301.0 - - ga.createView("i0").setScalar(1) - ga.createView("d0").setScalar(dval0) - gb.createView("d1").setScalar(dval1) - gb.createView("s0").setString("my string") - - # Check that all sub groups exist - assert flds.hasGroup("a") - assert flds.hasGroup("b") - - viewlen = 8 - ownsbuf = ga.createViewAndAllocate("ownsbuf", pysidre.TypeID.INT32_ID, viewlen) - int_vals = ownsbuf.getDataArray() - for i in range(viewlen): - int_vals[i] = i + 1 - - buflen = 24 - dbuff = ds.createBuffer() - dbuff.allocate(pysidre.TypeID.FLOAT64_ID, buflen) - buf_ptr = dbuff.getDataArray() - for i in range(buflen): - buf_ptr[i] = 2.0 * float(i) - - NUM_VIEWS = 4 - size = [5, 4, 10, 11] - stride = [3, 2, 2, 1] - offset = [2, 9, 0, 10] - names = ["viewa", "viewb", "viewc", "viewd"] - - for i in range(NUM_VIEWS): - ga.createView(names[i], dbuff).apply(size[i], offset[i], stride[i]) - - extlen = 30 - ext_array = np.array([-1.0 * float(i) for i in range(extlen)]) - - for i in range(NUM_VIEWS): - gb.createView(names[i], ext_array).apply(pysidre.TypeID.FLOAT64_ID, size[i], offset[i], stride[i]) - - deep_copy = root.createGroup("deep_copy") - deep_copy.deepCopyGroup(flds) - - assert deep_copy.hasGroup("fields/a") - assert deep_copy.hasGroup("fields/b") - - copy_ga = deep_copy.getGroup("fields/a") - copy_gb = deep_copy.getGroup("fields/b") - - io_val = copy_ga.getView("i0").getDataInt() - assert io_val == 1 - assert abs(copy_ga.getView("d0").getDataFloat() - dval0) < 1.0e-12 - assert abs(copy_gb.getView("d1").getDataFloat() - dval1) < 1.0e-12 - assert copy_gb.getView("s0").getString() == "my string" - - for i in range(NUM_VIEWS): - assert copy_ga.hasView(names[i]) - copy_view = copy_ga.getView(names[i]) - assert copy_view.hasBuffer() - - # The deep copy creates a compact buffer in the copied View, associated only with that View. - buffer = copy_view.getBuffer() - assert buffer.getNumViews() == 1 - assert buffer.getNumElements() == size[i] - assert copy_view.getOffset() == 0 - assert copy_view.getStride() == 1 - - fdata = copy_view.getDataArray() - for j in range(size[i]): - assert abs(fdata[j] - 2.0 * (offset[i] + j * stride[i])) < 1.0e-12 - - for i in range(NUM_VIEWS): - assert copy_gb.hasView(names[i]) - copy_view = copy_gb.getView(names[i]) - assert copy_view.hasBuffer() - - # The deep copy creates a compact buffer in the copied View, associated only with that View. - buffer = copy_view.getBuffer() - assert buffer.getNumViews() == 1 - assert buffer.getNumElements() == size[i] - assert copy_view.getOffset() == 0 - assert copy_view.getStride() == 1 - - fdata = copy_view.getDataArray() - for j in range(size[i]): - assert abs(fdata[j] - (-1.0 * (offset[i] + j * stride[i]))) < 1.0e-12 + ds = pysidre.DataStore() + root = ds.getRoot() + flds = root.createGroup("fields") + + ga = flds.createGroup("a") + gb = flds.createGroup("b") + + dval0 = 100.0 + dval1 = 301.0 + + ga.createView("i0").setScalar(1) + ga.createView("d0").setScalar(dval0) + gb.createView("d1").setScalar(dval1) + gb.createView("s0").setString("my string") + + # Check that all sub groups exist + assert flds.hasGroup("a") + assert flds.hasGroup("b") + + viewlen = 8 + ownsbuf = ga.createViewAndAllocate("ownsbuf", pysidre.TypeID.INT32_ID, viewlen) + int_vals = ownsbuf.getDataArray() + for i in range(viewlen): + int_vals[i] = i + 1 + + buflen = 24 + dbuff = ds.createBuffer() + dbuff.allocate(pysidre.TypeID.FLOAT64_ID, buflen) + buf_ptr = dbuff.getDataArray() + for i in range(buflen): + buf_ptr[i] = 2.0 * float(i) + + NUM_VIEWS = 4 + size = [5, 4, 10, 11] + stride = [3, 2, 2, 1] + offset = [2, 9, 0, 10] + names = ["viewa", "viewb", "viewc", "viewd"] + + for i in range(NUM_VIEWS): + ga.createView(names[i], dbuff).apply(size[i], offset[i], stride[i]) + + extlen = 30 + ext_array = np.array([-1.0 * float(i) for i in range(extlen)]) + + for i in range(NUM_VIEWS): + gb.createView(names[i], ext_array).apply(pysidre.TypeID.FLOAT64_ID, size[i], offset[i], + stride[i]) + + deep_copy = root.createGroup("deep_copy") + deep_copy.deepCopyGroup(flds) + + assert deep_copy.hasGroup("fields/a") + assert deep_copy.hasGroup("fields/b") + + copy_ga = deep_copy.getGroup("fields/a") + copy_gb = deep_copy.getGroup("fields/b") + + io_val = copy_ga.getView("i0").getDataInt() + assert io_val == 1 + assert abs(copy_ga.getView("d0").getDataFloat() - dval0) < 1.0e-12 + assert abs(copy_gb.getView("d1").getDataFloat() - dval1) < 1.0e-12 + assert copy_gb.getView("s0").getString() == "my string" + + for i in range(NUM_VIEWS): + assert copy_ga.hasView(names[i]) + copy_view = copy_ga.getView(names[i]) + assert copy_view.hasBuffer() + + # The deep copy creates a compact buffer in the copied View, associated only with that View. + buffer = copy_view.getBuffer() + assert buffer.getNumViews() == 1 + assert buffer.getNumElements() == size[i] + assert copy_view.getOffset() == 0 + assert copy_view.getStride() == 1 + + fdata = copy_view.getDataArray() + for j in range(size[i]): + assert abs(fdata[j] - 2.0 * (offset[i] + j * stride[i])) < 1.0e-12 + + for i in range(NUM_VIEWS): + assert copy_gb.hasView(names[i]) + copy_view = copy_gb.getView(names[i]) + assert copy_view.hasBuffer() + + # The deep copy creates a compact buffer in the copied View, associated only with that View. + buffer = copy_view.getBuffer() + assert buffer.getNumViews() == 1 + assert buffer.getNumElements() == size[i] + assert copy_view.getOffset() == 0 + assert copy_view.getStride() == 1 + + fdata = copy_view.getDataArray() + for j in range(size[i]): + assert abs(fdata[j] - (-1.0 * (offset[i] + j * stride[i]))) < 1.0e-12 def test_create_destroy_view_and_buffer2(): - ds = pysidre.DataStore() - root = ds.getRoot() - grp = root.createGroup("grp") + ds = pysidre.DataStore() + root = ds.getRoot() + grp = root.createGroup("grp") - viewName1 = "viewBuffer1" - viewName2 = "viewBuffer2" + viewName1 = "viewBuffer1" + viewName2 = "viewBuffer2" - view1 = grp.createViewAndAllocate(viewName1, pysidre.TypeID.INT_ID, 1) - view2 = grp.createViewAndAllocate(viewName2, pysidre.TypeID.INT_ID, 1) + view1 = grp.createViewAndAllocate(viewName1, pysidre.TypeID.INT_ID, 1) + view2 = grp.createViewAndAllocate(viewName2, pysidre.TypeID.INT_ID, 1) - assert grp.hasView(viewName1) - assert grp.getView(viewName1) == view1 + assert grp.hasView(viewName1) + assert grp.getView(viewName1) == view1 - assert grp.hasView(viewName2) - assert grp.getView(viewName2) == view2 + assert grp.hasView(viewName2) + assert grp.getView(viewName2) == view2 - bufferId1 = view1.getBuffer().getIndex() + bufferId1 = view1.getBuffer().getIndex() - grp.destroyViewAndData(viewName1) + grp.destroyViewAndData(viewName1) - assert not grp.hasView(viewName1) - assert ds.getNumBuffers() == 1 + assert not grp.hasView(viewName1) + assert ds.getNumBuffers() == 1 - buffer1 = ds.getBuffer(bufferId1) - assert buffer1 is None + buffer1 = ds.getBuffer(bufferId1) + assert buffer1 is None - view3 = grp.createView("viewBuffer3") - grp.destroyViewsAndData() - # should be no-op - grp.destroyViewsAndData() + view3 = grp.createView("viewBuffer3") + grp.destroyViewsAndData() + # should be no-op + grp.destroyViewsAndData() def test_create_destroy_alloc_view_and_buffer(): - ds = pysidre.DataStore() - root = ds.getRoot() - grp = root.createGroup("grp") + ds = pysidre.DataStore() + root = ds.getRoot() + grp = root.createGroup("grp") - viewName1 = "viewBuffer1" - viewName2 = "viewBuffer2" + viewName1 = "viewBuffer1" + viewName2 = "viewBuffer2" - # Use create + alloc convenience methods - # This one is the DataType method - view1 = grp.createViewAndAllocate(viewName1, pysidre.TypeID.INT_ID, 10) + # Use create + alloc convenience methods + # This one is the DataType method + view1 = grp.createViewAndAllocate(viewName1, pysidre.TypeID.INT_ID, 10) - assert grp.hasChildView(viewName1) - assert grp.getView(viewName1) == view1 + assert grp.hasChildView(viewName1) + assert grp.getView(viewName1) == view1 - v1_vals = view1.getDataArray() - for i in range(10): - v1_vals[i] = i + v1_vals = view1.getDataArray() + for i in range(10): + v1_vals[i] = i - assert view1.getNumElements() == 10 - assert view1.getTotalBytes() == 10 * 4 # Assuming int is 4 bytes + assert view1.getNumElements() == 10 + assert view1.getTotalBytes() == 10 * 4 # Assuming int is 4 bytes - grp.destroyViewAndData(viewName1) + grp.destroyViewAndData(viewName1) def test_create_view_of_buffer_with_schema(): - ds = pysidre.DataStore() - root = ds.getRoot() + ds = pysidre.DataStore() + root = ds.getRoot() - # Use create + alloc convenience methods - base = root.createViewAndAllocate("base", pysidre.TypeID.INT_ID, 10) - base_vals = base.getDataArray() - for i in range(10): - if i < 5: - base_vals[i] = 10 - else: - base_vals[i] = 20 + # Use create + alloc convenience methods + base = root.createViewAndAllocate("base", pysidre.TypeID.INT_ID, 10) + base_vals = base.getDataArray() + for i in range(10): + if i < 5: + base_vals[i] = 10 + else: + base_vals[i] = 20 - base_buff = base.getBuffer() + base_buff = base.getBuffer() - # Create two views into this buffer - # View for the first 5 values - sub_a = root.createView("sub_a", base_buff) - sub_a.apply(pysidre.TypeID.INT_ID, 5) + # Create two views into this buffer + # View for the first 5 values + sub_a = root.createView("sub_a", base_buff) + sub_a.apply(pysidre.TypeID.INT_ID, 5) - sub_a_vals = sub_a.getDataArray() - for i in range(5): - assert sub_a_vals[i] == 10 + sub_a_vals = sub_a.getDataArray() + for i in range(5): + assert sub_a_vals[i] == 10 def test_create_destroy_view_and_data(): - ds = pysidre.DataStore() - root = ds.getRoot() - grp = root.createGroup("grp") + ds = pysidre.DataStore() + root = ds.getRoot() + grp = root.createGroup("grp") - view_name1 = "viewBuffer1" - view_name2 = "viewBuffer2" + view_name1 = "viewBuffer1" + view_name2 = "viewBuffer2" - view1 = grp.createViewAndAllocate(view_name1, pysidre.TypeID.INT32_ID, 1) - view2 = grp.createViewAndAllocate(view_name2, pysidre.TypeID.INT32_ID, 1) + view1 = grp.createViewAndAllocate(view_name1, pysidre.TypeID.INT32_ID, 1) + view2 = grp.createViewAndAllocate(view_name2, pysidre.TypeID.INT32_ID, 1) - assert grp.hasView(view_name1) - assert grp.getView(view_name1) == view1 + assert grp.hasView(view_name1) + assert grp.getView(view_name1) == view1 - assert grp.hasView(view_name2) - assert grp.getView(view_name2) == view2 + assert grp.hasView(view_name2) + assert grp.getView(view_name2) == view2 - tmpbuf = view1.getBuffer() - bufferid1 = tmpbuf.getIndex() + tmpbuf = view1.getBuffer() + bufferid1 = tmpbuf.getIndex() - grp.destroyViewAndData(view_name1) - - assert not grp.hasView(view_name1) - assert ds.getNumBuffers() == 1 + grp.destroyViewAndData(view_name1) + assert not grp.hasView(view_name1) + assert ds.getNumBuffers() == 1 def test_create_destroy_alloc_view_and_data(): - ds = pysidre.DataStore() - root = ds.getRoot() - grp = root.createGroup("grp") + ds = pysidre.DataStore() + root = ds.getRoot() + grp = root.createGroup("grp") - view_name1 = "viewBuffer1" - view_name2 = "viewBuffer2" + view_name1 = "viewBuffer1" + view_name2 = "viewBuffer2" - # Use create + alloc convenience methods - # this one is the DataType & method - view1 = grp.createViewAndAllocate(view_name1, pysidre.TypeID.INT32_ID, 10) - assert grp.hasView(view_name1) - assert grp.getView(view_name1) == view1 + # Use create + alloc convenience methods + # this one is the DataType & method + view1 = grp.createViewAndAllocate(view_name1, pysidre.TypeID.INT32_ID, 10) + assert grp.hasView(view_name1) + assert grp.getView(view_name1) == view1 - # TODO getData, need numpy array implementation - v1_vals = view1.getDataArray() + # TODO getData, need numpy array implementation + v1_vals = view1.getDataArray() - for i in range(10): - v1_vals[i] = i + for i in range(10): + v1_vals[i] = i - assert view1.getNumElements() == 10 - grp.destroyViewAndData(view_name1) + assert view1.getNumElements() == 10 + grp.destroyViewAndData(view_name1) def test_create_view_of_buffer_with_datatype(): - ds = pysidre.DataStore() - root = ds.getRoot() + ds = pysidre.DataStore() + root = ds.getRoot() - # Use create + alloc convenience methods - # this one is the DataType & method - base = root.createViewAndAllocate("base", pysidre.TypeID.INT32_ID, 10) - base_vals = base.getDataArray() + # Use create + alloc convenience methods + # this one is the DataType & method + base = root.createViewAndAllocate("base", pysidre.TypeID.INT32_ID, 10) + base_vals = base.getDataArray() - base_vals[0:5] = 10 - base_vals[5:10] = 20 + base_vals[0:5] = 10 + base_vals[5:10] = 20 - base_buff = base.getBuffer() + base_buff = base.getBuffer() - # Create view into this buffer - sub_a = root.createView("sub_a", pysidre.TypeID.INT32_ID, 10, base_buff) + # Create view into this buffer + sub_a = root.createView("sub_a", pysidre.TypeID.INT32_ID, 10, base_buff) - sub_a_vals = root.getView("sub_a").getDataArray() + sub_a_vals = root.getView("sub_a").getDataArray() - for i in range(5): - assert sub_a_vals[i] == 10 - for i in range(5,10): - assert sub_a_vals[i] == 20 + for i in range(5): + assert sub_a_vals[i] == 10 + for i in range(5, 10): + assert sub_a_vals[i] == 20 def test_save_restore_empty_datastore(): - file_path_base = "py_sidre_empty_datastore_" - ds1 = pysidre.DataStore() - root1 = ds1.getRoot() - - for i in range(NPROTOCOLS): - file_path = file_path_base + PROTOCOLS[i] - root1.save(file_path, PROTOCOLS[i]) - - for i in range(NPROTOCOLS): - if PROTOCOLS[i] != "sidre_hdf5": - continue - file_path = file_path_base + PROTOCOLS[i] - - ds2 = pysidre.DataStore() - root2 = ds2.getRoot() - - root2.load(file_path, PROTOCOLS[i]) - - assert ds2.getNumBuffers() == 0 - assert root2.getNumGroups() == 0 - assert root2.getNumViews() == 0 - - -def test_save_restore_scalars_and_strings(): - file_path_base = "py_sidre_save_scalars_and_strings_" - ds1 = pysidre.DataStore() - root1 = ds1.getRoot() - - view = root1.createViewScalar("i0", 1) - view = root1.createViewScalar("f0", 1.0) - view = root1.createViewScalar("d0", 10.0) - view = root1.createViewString("s0", "I am a string") - - for i in range(NPROTOCOLS): - file_path = file_path_base + PROTOCOLS[i] - root1.save(file_path, PROTOCOLS[i]) - - for i in range(NPROTOCOLS): - if PROTOCOLS[i] != "sidre_hdf5": - continue - file_path = file_path_base + PROTOCOLS[i] - - ds2 = pysidre.DataStore() - root2 = ds2.getRoot() + file_path_base = "py_sidre_empty_datastore_" + ds1 = pysidre.DataStore() + root1 = ds1.getRoot() - root2.load(file_path, PROTOCOLS[i]) + for i in range(NPROTOCOLS): + file_path = file_path_base + PROTOCOLS[i] + root1.save(file_path, PROTOCOLS[i]) - assert root1.isEquivalentTo(root2) + for i in range(NPROTOCOLS): + if PROTOCOLS[i] != "sidre_hdf5": + continue + file_path = file_path_base + PROTOCOLS[i] - view = root2.getView("i0") - i0 = view.getDataInt() - assert i0 == 1 + ds2 = pysidre.DataStore() + root2 = ds2.getRoot() - view = root2.getView("f0") - f0 = view.getDataFloat() - assert f0 == 1.0 + root2.load(file_path, PROTOCOLS[i]) - view = root2.getView("d0") - d0 = view.getDataFloat() - assert d0 == 10.0 + assert ds2.getNumBuffers() == 0 + assert root2.getNumGroups() == 0 + assert root2.getNumViews() == 0 - view = root2.getView("s0") - s0 = view.getString() - assert s0 == "I am a string" +def test_save_restore_scalars_and_strings(): + file_path_base = "py_sidre_save_scalars_and_strings_" + ds1 = pysidre.DataStore() + root1 = ds1.getRoot() -def test_save_restore_external_data(): - file_path_base = "py_sidre_save_external_" - - nfoo = 10 - foo1 = np.array(range(nfoo)) - - # dtype is necessary, or garbage conversion from float64 --> int64 takes place - foo2 = np.zeros(10, dtype = int) - foo3 = np.empty(0) - foo4 = np.array([i+1 for i in range(10)]) - - shape = np.array([10,2]) - int2d1 = np.column_stack((foo1, foo1 + nfoo)) - int2d2 = np.zeros((10,2), dtype = int) - - ds1 = pysidre.DataStore() - root1 = ds1.getRoot() - - root1.createView("external_array", pysidre.TypeID.INT64_ID, nfoo, foo1) - root1.createView("empty_array", pysidre.TypeID.INT64_ID, 0, foo3) - root1.createView("external_undescribed").setExternalData(foo4) - root1.createViewWithShape("int2d", pysidre.TypeID.INT64_ID, 2, shape, int2d1) - - for protocol in PROTOCOLS: - file_path = file_path_base + protocol - assert root1.save(file_path, protocol) == True - - # Now load back in - for protocol in PROTOCOLS: - # Only restore sidre_hdf5 protocol - if protocol != "sidre_hdf5": - continue - file_path = file_path_base + protocol - - ds2 = pysidre.DataStore() - root2 = ds2.getRoot() + view = root1.createViewScalar("i0", 1) + view = root1.createViewScalar("f0", 1.0) + view = root1.createViewScalar("d0", 10.0) + view = root1.createViewString("s0", "I am a string") - assert root2.load(file_path, protocol) == True + for i in range(NPROTOCOLS): + file_path = file_path_base + PROTOCOLS[i] + root1.save(file_path, PROTOCOLS[i]) - # Load has the set type and size of the view. - # Now set the external address before calling load_external - view1 = root2.getView("external_array") - assert view1.isExternal() == True, "external_array is external" - assert view1.isDescribed() == True, "external_array is described" - assert view1.getTypeID() == pysidre.TypeID.INT64_ID, "external_array get TypeId" - assert view1.getNumElements() == nfoo, "external_array get num elements" - view1.setExternalData(foo2) + for i in range(NPROTOCOLS): + if PROTOCOLS[i] != "sidre_hdf5": + continue + file_path = file_path_base + PROTOCOLS[i] - view2 = root2.getView("empty_array") - assert view2.isExternal() == True, "empty_array is external" - assert view2.isDescribed() == True, "empty_array is described" - assert view2.getTypeID() == pysidre.TypeID.INT64_ID, "empty_array get TypeId" - view2.setExternalData(foo3) + ds2 = pysidre.DataStore() + root2 = ds2.getRoot() - view3 = root2.getView("external_undescribed") - assert view3.isEmpty() == True, "external_undescribed is empty" - assert view3.isDescribed() == False, "external_undescribed is undescribed" + root2.load(file_path, PROTOCOLS[i]) - extents = np.zeros(7) - view4 = root2.getView("int2d") - assert view4.isExternal() == True, "int2d is external" - assert view4.isDescribed() == True, "int2d is described" - assert view4.getTypeID() == pysidre.TypeID.INT64_ID, "int2d get TypeId" - assert view4.getNumElements() == nfoo * 2, "int2d get num elements" - assert view4.getNumDimensions() == 2, "int2d get num dimensions" + assert root1.isEquivalentTo(root2) - rank, extents = view4.getShape(7, extents) - assert rank == 2, "int2d rank" - assert extents[0] == nfoo - assert extents[1] == 2 - view4.setExternalData(int2d2) + view = root2.getView("i0") + i0 = view.getDataInt() + assert i0 == 1 - # Read external data into views - assert root2.loadExternalData(file_path) == True + view = root2.getView("f0") + f0 = view.getDataFloat() + assert f0 == 1.0 - # Check loaded data - assert np.array_equal(foo1,foo2), "compare foo1 foo2" + view = root2.getView("d0") + d0 = view.getDataFloat() + assert d0 == 10.0 - assert np.array_equal(view1.getDataArray(), foo2) - assert np.array_equal(view2.getDataArray(), foo3) - assert np.array_equal(view4.getDataArray(), int2d2) + view = root2.getView("s0") + s0 = view.getString() + assert s0 == "I am a string" - assert np.array_equal(int2d1,int2d2) +def test_save_restore_external_data(): + file_path_base = "py_sidre_save_external_" + + nfoo = 10 + foo1 = np.array(range(nfoo)) + + # dtype is necessary, or garbage conversion from float64 --> int64 takes place + foo2 = np.zeros(10, dtype=int) + foo3 = np.empty(0) + foo4 = np.array([i + 1 for i in range(10)]) + + shape = np.array([10, 2]) + int2d1 = np.column_stack((foo1, foo1 + nfoo)) + int2d2 = np.zeros((10, 2), dtype=int) + + ds1 = pysidre.DataStore() + root1 = ds1.getRoot() + + root1.createView("external_array", pysidre.TypeID.INT64_ID, nfoo, foo1) + root1.createView("empty_array", pysidre.TypeID.INT64_ID, 0, foo3) + root1.createView("external_undescribed").setExternalData(foo4) + root1.createViewWithShape("int2d", pysidre.TypeID.INT64_ID, 2, shape, int2d1) + + for protocol in PROTOCOLS: + file_path = file_path_base + protocol + assert root1.save(file_path, protocol) == True + + # Now load back in + for protocol in PROTOCOLS: + # Only restore sidre_hdf5 protocol + if protocol != "sidre_hdf5": + continue + file_path = file_path_base + protocol + + ds2 = pysidre.DataStore() + root2 = ds2.getRoot() + + assert root2.load(file_path, protocol) == True + + # Load has the set type and size of the view. + # Now set the external address before calling load_external + view1 = root2.getView("external_array") + assert view1.isExternal() == True, "external_array is external" + assert view1.isDescribed() == True, "external_array is described" + assert view1.getTypeID() == pysidre.TypeID.INT64_ID, "external_array get TypeId" + assert view1.getNumElements() == nfoo, "external_array get num elements" + view1.setExternalData(foo2) + + view2 = root2.getView("empty_array") + assert view2.isExternal() == True, "empty_array is external" + assert view2.isDescribed() == True, "empty_array is described" + assert view2.getTypeID() == pysidre.TypeID.INT64_ID, "empty_array get TypeId" + view2.setExternalData(foo3) + + view3 = root2.getView("external_undescribed") + assert view3.isEmpty() == True, "external_undescribed is empty" + assert view3.isDescribed() == False, "external_undescribed is undescribed" + + extents = np.zeros(7) + view4 = root2.getView("int2d") + assert view4.isExternal() == True, "int2d is external" + assert view4.isDescribed() == True, "int2d is described" + assert view4.getTypeID() == pysidre.TypeID.INT64_ID, "int2d get TypeId" + assert view4.getNumElements() == nfoo * 2, "int2d get num elements" + assert view4.getNumDimensions() == 2, "int2d get num dimensions" + + rank, extents = view4.getShape(7, extents) + assert rank == 2, "int2d rank" + assert extents[0] == nfoo + assert extents[1] == 2 + view4.setExternalData(int2d2) + + # Read external data into views + assert root2.loadExternalData(file_path) == True + + # Check loaded data + assert np.array_equal(foo1, foo2), "compare foo1 foo2" + + assert np.array_equal(view1.getDataArray(), foo2) + assert np.array_equal(view2.getDataArray(), foo3) + assert np.array_equal(view4.getDataArray(), int2d2) + + assert np.array_equal(int2d1, int2d2) def test_save_restore_other(): - file_path_base = "py_sidre_empty_other_" - ndata = 10 - - ds1 = pysidre.DataStore() - root1 = ds1.getRoot() - - shape1 = np.array([ndata, 2]) - view1 = root1.createView("empty_view") - view2 = root1.createView("empty_described", pysidre.TypeID.INT32_ID, ndata) - view3 = root1.createViewWithShape("empty_shape", pysidre.TypeID.INT32_ID, 2, shape1) - view4 = root1.createViewWithShapeAndAllocate("buffer_shape", pysidre.TypeID.INT32_ID, 2, shape1) - - for protocol in PROTOCOLS: - file_path = file_path_base + protocol - assert root1.save(file_path, protocol) == True - - # Now load back in - for protocol in PROTOCOLS: - # Only restore sidre_hdf5 protocol - if protocol != "sidre_hdf5": - continue - - file_path = file_path_base + protocol - - ds2 = pysidre.DataStore() - root2 = ds2.getRoot() - - root2.load(file_path, protocol) - - view1 = root2.getView("empty_view") - assert view1.isEmpty() == True, "empty_view is empty" - assert view1.isDescribed() == False, "empty_view is described" - - view2 = root2.getView("empty_described") - assert view2.isEmpty() == True, "empty_described is empty" - assert view2.isDescribed() == True, "empty_described is described" - assert view2.getTypeID() == pysidre.TypeID.INT32_ID, "empty_described get TypeID" - assert view2.getNumElements() == ndata, "empty_described get num elements" - - view3 = root2.getView("empty_shape") - assert view3.isEmpty() == True, "empty_shape is empty" - assert view3.isDescribed() == True, "empty_shape is described" - assert view3.getTypeID() == pysidre.TypeID.INT32_ID, "empty_shape get TypeID" - assert view3.getNumElements() == ndata * 2, "empty_shape get num elements" - shape2 = np.zeros(7) - rank, shape2 = view3.getShape(7, shape2) - assert rank == 2, "empty_shape rank" - assert shape2[0] == ndata and shape2[1] == 2, "empty_shape get shape" - - view4 = root2.getView("buffer_shape") - assert view4.hasBuffer() == True, "buffer_shape has buffer" - assert view4.isDescribed() == True, "buffer_shape is described" - assert view4.getTypeID() == pysidre.TypeID.INT32_ID, "buffer_shape get TypeID" - assert view4.getNumElements() == ndata * 2, "buffer_shape get num elements" - shape2 = np.zeros(7) - rank, shape2 = view4.getShape(7, shape2) - assert rank == 2, "buffer_shape rank" - assert shape2[0] == ndata and shape2[1] == 2, "buffer_shape get shape" - + file_path_base = "py_sidre_empty_other_" + ndata = 10 + + ds1 = pysidre.DataStore() + root1 = ds1.getRoot() + + shape1 = np.array([ndata, 2]) + view1 = root1.createView("empty_view") + view2 = root1.createView("empty_described", pysidre.TypeID.INT32_ID, ndata) + view3 = root1.createViewWithShape("empty_shape", pysidre.TypeID.INT32_ID, 2, shape1) + view4 = root1.createViewWithShapeAndAllocate("buffer_shape", pysidre.TypeID.INT32_ID, 2, shape1) + + for protocol in PROTOCOLS: + file_path = file_path_base + protocol + assert root1.save(file_path, protocol) == True + + # Now load back in + for protocol in PROTOCOLS: + # Only restore sidre_hdf5 protocol + if protocol != "sidre_hdf5": + continue + + file_path = file_path_base + protocol + + ds2 = pysidre.DataStore() + root2 = ds2.getRoot() + + root2.load(file_path, protocol) + + view1 = root2.getView("empty_view") + assert view1.isEmpty() == True, "empty_view is empty" + assert view1.isDescribed() == False, "empty_view is described" + + view2 = root2.getView("empty_described") + assert view2.isEmpty() == True, "empty_described is empty" + assert view2.isDescribed() == True, "empty_described is described" + assert view2.getTypeID() == pysidre.TypeID.INT32_ID, "empty_described get TypeID" + assert view2.getNumElements() == ndata, "empty_described get num elements" + + view3 = root2.getView("empty_shape") + assert view3.isEmpty() == True, "empty_shape is empty" + assert view3.isDescribed() == True, "empty_shape is described" + assert view3.getTypeID() == pysidre.TypeID.INT32_ID, "empty_shape get TypeID" + assert view3.getNumElements() == ndata * 2, "empty_shape get num elements" + shape2 = np.zeros(7) + rank, shape2 = view3.getShape(7, shape2) + assert rank == 2, "empty_shape rank" + assert shape2[0] == ndata and shape2[1] == 2, "empty_shape get shape" + + view4 = root2.getView("buffer_shape") + assert view4.hasBuffer() == True, "buffer_shape has buffer" + assert view4.isDescribed() == True, "buffer_shape is described" + assert view4.getTypeID() == pysidre.TypeID.INT32_ID, "buffer_shape get TypeID" + assert view4.getNumElements() == ndata * 2, "buffer_shape get num elements" + shape2 = np.zeros(7) + rank, shape2 = view4.getShape(7, shape2) + assert rank == 2, "buffer_shape rank" + assert shape2[0] == ndata and shape2[1] == 2, "buffer_shape get shape" def test_rename_group(): - ds = pysidre.DataStore() - root = ds.getRoot() - child1 = root.createGroup("g_a") - child2 = root.createGroup("g_b") - child3 = root.createGroup("g_c") - - # Rename should not change the index - assert child1.getIndex() == 0 - success = child1.rename("g_r") - assert success - assert child1.getName() == "g_r" - assert child1.getIndex() == 0 - assert root.hasGroup("g_r") - assert not root.hasGroup("g_a") - - # Try to rename to path - success = child2.rename("fields/g_s") - assert not success - assert child2.getName() == "g_b" - - # Try to rename to existing group name - success = child3.rename("g_b") - assert not success - assert child3.getName() == "g_c" - - # Rename root group - assert not pysidre.indexIsValid(root.getIndex()) - assert root.getParent() == root - assert root.getName() == "" - root.rename("newroot") - assert not pysidre.indexIsValid(root.getIndex()) - assert root.getParent() == root - assert root.getName() == "newroot" + ds = pysidre.DataStore() + root = ds.getRoot() + child1 = root.createGroup("g_a") + child2 = root.createGroup("g_b") + child3 = root.createGroup("g_c") + + # Rename should not change the index + assert child1.getIndex() == 0 + success = child1.rename("g_r") + assert success + assert child1.getName() == "g_r" + assert child1.getIndex() == 0 + assert root.hasGroup("g_r") + assert not root.hasGroup("g_a") + + # Try to rename to path + success = child2.rename("fields/g_s") + assert not success + assert child2.getName() == "g_b" + + # Try to rename to existing group name + success = child3.rename("g_b") + assert not success + assert child3.getName() == "g_c" + + # Rename root group + assert not pysidre.indexIsValid(root.getIndex()) + assert root.getParent() == root + assert root.getName() == "" + root.rename("newroot") + assert not pysidre.indexIsValid(root.getIndex()) + assert root.getParent() == root + assert root.getName() == "newroot" # Fortran comment - redo these, the C++ tests were heavily rewritten def test_save_restore_simple(): - file_path = "py_out_sidre_group_save_restore_simple" - ds = pysidre.DataStore() - root = ds.getRoot() - flds = root.createGroup("fields") + file_path = "py_out_sidre_group_save_restore_simple" + ds = pysidre.DataStore() + root = ds.getRoot() + flds = root.createGroup("fields") - ga = flds.createGroup("a") + ga = flds.createGroup("a") - i0_view = ga.createViewScalar("i0", 1) + i0_view = ga.createViewScalar("i0", 1) - assert root.hasGroup("fields") == True - assert flds.hasGroup("a") == True - assert ga.hasView("i0") == True + assert root.hasGroup("fields") == True + assert flds.hasGroup("a") == True + assert ga.hasView("i0") == True - root.save(file_path, "sidre_conduit_json") + root.save(file_path, "sidre_conduit_json") - ds2 = pysidre.DataStore() - root2 = ds2.getRoot() + ds2 = pysidre.DataStore() + root2 = ds2.getRoot() - root2.load(file_path, "sidre_conduit_json") + root2.load(file_path, "sidre_conduit_json") - flds = root2.getGroup("fields") - assert flds.hasGroup("a") == True - ga = flds.getGroup("a") - i0_view = ga.getView("i0") - assert i0_view.getDataInt() == 1 + flds = root2.getGroup("fields") + assert flds.hasGroup("a") == True + ga = flds.getGroup("a") + i0_view = ga.getView("i0") + assert i0_view.getDataInt() == 1 # Fortran comment - redo these, the C++ tests were heavily rewritten def test_save_restore_complex(): - file_path = "py_out_sidre_group_save_restore_complex" + file_path = "py_out_sidre_group_save_restore_complex" - ds = pysidre.DataStore() - root = ds.getRoot() - flds = root.createGroup("fields") + ds = pysidre.DataStore() + root = ds.getRoot() + flds = root.createGroup("fields") - ga = flds.createGroup("a") - gb = flds.createGroup("b") - gc = flds.createGroup("c") + ga = flds.createGroup("a") + gb = flds.createGroup("b") + gc = flds.createGroup("c") - ga.createViewScalar("i0", 1) - gb.createViewScalar("f0", 100.0) - gc.createViewScalar("d0", 3000.0) + ga.createViewScalar("i0", 1) + gb.createViewScalar("f0", 100.0) + gc.createViewScalar("d0", 3000.0) - # Check that all sub groups exist - assert flds.hasGroup("a") == True - assert flds.hasGroup("b") == True - assert flds.hasGroup("c") == True + # Check that all sub groups exist + assert flds.hasGroup("a") == True + assert flds.hasGroup("b") == True + assert flds.hasGroup("c") == True - root.save(file_path, "sidre_conduit_json") + root.save(file_path, "sidre_conduit_json") - ds2 = pysidre.DataStore() - root2 = ds2.getRoot() + ds2 = pysidre.DataStore() + root2 = ds2.getRoot() - root2.load(file_path, "sidre_conduit_json") + root2.load(file_path, "sidre_conduit_json") - flds = root2.getGroup("fields") + flds = root2.getGroup("fields") - # Check that all sub groups exist - assert flds.hasGroup("a") == True - assert flds.hasGroup("b") == True - assert flds.hasGroup("c") == True + # Check that all sub groups exist + assert flds.hasGroup("a") == True + assert flds.hasGroup("b") == True + assert flds.hasGroup("c") == True - ga = flds.getGroup("a") - gb = flds.getGroup("b") - gc = flds.getGroup("c") + ga = flds.getGroup("a") + gb = flds.getGroup("b") + gc = flds.getGroup("c") - i0_view = ga.getView("i0") - f0_view = gb.getView("f0") - d0_view = gc.getView("d0") + i0_view = ga.getView("i0") + f0_view = gb.getView("f0") + d0_view = gc.getView("d0") - assert i0_view.getDataInt() == 1 - assert f0_view.getDataFloat() == 100.0 - assert d0_view.getDataFloat() == 3000.0 + assert i0_view.getDataInt() == 1 + assert f0_view.getDataFloat() == 100.0 + assert d0_view.getDataFloat() == 3000.0 # Fortran - for some reason not part of main program def test_save_load_preserve_contents(): - file_path_base0 = "py_sidre_save_preserve_contents_tree0_" - file_path_base1 = "py_sidre_save_preserve_contents_tree1_" - - ds = pysidre.DataStore() - root = ds.getRoot() - tree0 = root.createGroup("tree0") + file_path_base0 = "py_sidre_save_preserve_contents_tree0_" + file_path_base1 = "py_sidre_save_preserve_contents_tree1_" - ga = tree0.createGroup("a") - gb = tree0.createGroup("b") - gc = tree0.createGroup("c") + ds = pysidre.DataStore() + root = ds.getRoot() + tree0 = root.createGroup("tree0") - i0_view = ga.createViewScalar("i0", 100) - f0_view = ga.createViewScalar("f0", 3000.0) - s0_view = gb.createViewString("s0", "foo") - i10_view = gc.createViewAndAllocate("int10", pysidre.TypeID.INT32_ID, 10) + ga = tree0.createGroup("a") + gb = tree0.createGroup("b") + gc = tree0.createGroup("c") - v1_vals = i10_view.getDataArray() - for i in range(10): - v1_vals[i] = i + i0_view = ga.createViewScalar("i0", 100) + f0_view = ga.createViewScalar("f0", 3000.0) + s0_view = gb.createViewString("s0", "foo") + i10_view = gc.createViewAndAllocate("int10", pysidre.TypeID.INT32_ID, 10) - for protocol in PROTOCOLS: - # Only restore sidre_hdf5 protocol - if protocol != "sidre_hdf5": - continue + v1_vals = i10_view.getDataArray() + for i in range(10): + v1_vals[i] = i - file_path0 = file_path_base0 + protocol - tree0.save(file_path0, protocol) + for protocol in PROTOCOLS: + # Only restore sidre_hdf5 protocol + if protocol != "sidre_hdf5": + continue - tree1 = root.createGroup("tree1") + file_path0 = file_path_base0 + protocol + tree0.save(file_path0, protocol) - gx = tree1.createGroup("x") - gy = tree1.createGroup("y") - gz = tree1.createGroup("z") + tree1 = root.createGroup("tree1") - i20_view = gx.createViewAndAllocate("int20", pysidre.TypeID.INT32_ID, 20) - v2_vals = i20_view.getDataArray() - for i in range(20): - v2_vals[i] = 2 * i + gx = tree1.createGroup("x") + gy = tree1.createGroup("y") + gz = tree1.createGroup("z") - i1_view = gy.createViewScalar("i1", 400) - f1_view = gz.createViewScalar("f1", 17.0) + i20_view = gx.createViewAndAllocate("int20", pysidre.TypeID.INT32_ID, 20) + v2_vals = i20_view.getDataArray() + for i in range(20): + v2_vals[i] = 2 * i - file_path1 = file_path_base1 + protocol - assert tree1.save(file_path1, protocol) + i1_view = gy.createViewScalar("i1", 400) + f1_view = gz.createViewScalar("f1", 17.0) - dsload = pysidre.DataStore() - ldroot = dsload.getRoot() + file_path1 = file_path_base1 + protocol + assert tree1.save(file_path1, protocol) - ldtree0 = ldroot.createGroup("tree0") - ldtree0.load(file_path0, protocol) - ldtree0.load(file_path1, protocol, True) - ldtree0.rename("tree1") + dsload = pysidre.DataStore() + ldroot = dsload.getRoot() + ldtree0 = ldroot.createGroup("tree0") + ldtree0.load(file_path0, protocol) + ldtree0.load(file_path1, protocol, True) + ldtree0.rename("tree1") - i0_view = ldroot.getView("tree1/a/i0") - i0 = i0_view.getDataInt() - assert i0 == 100 + i0_view = ldroot.getView("tree1/a/i0") + i0 = i0_view.getDataInt() + assert i0 == 100 - f0_view = ldroot.getView("tree1/a/f0") - f0 = f0_view.getDataFloat() - assert f0 == 3000.0 + f0_view = ldroot.getView("tree1/a/f0") + f0 = f0_view.getDataFloat() + assert f0 == 3000.0 - s0_view = ldroot.getView("tree1/b/s0") - s0 = s0_view.getString() - assert s0 == "foo" + s0_view = ldroot.getView("tree1/b/s0") + s0 = s0_view.getString() + assert s0 == "foo" - i1_view = ldroot.getView("tree1/y/i1") - i1 = i1_view.getDataInt() - assert i1 == 400 + i1_view = ldroot.getView("tree1/y/i1") + i1 = i1_view.getDataInt() + assert i1 == 400 - f1_view = ldroot.getView("tree1/z/f1") - f1 = f1_view.getDataFloat() - assert f1 == 17.0 + f1_view = ldroot.getView("tree1/z/f1") + f1 = f1_view.getDataFloat() + assert f1 == 17.0 - i10_view = ldroot.getView("tree1/c/int10") - i20_view = ldroot.getView("tree1/x/int20") + i10_view = ldroot.getView("tree1/c/int10") + i20_view = ldroot.getView("tree1/x/int20") - v1_vals = i10_view.getDataArray() - v2_vals = i20_view.getDataArray() + v1_vals = i10_view.getDataArray() + v2_vals = i20_view.getDataArray() - for i in range(10): - assert v1_vals[i] == i + for i in range(10): + assert v1_vals[i] == i - for i in range(20): - assert v2_vals[i] == 2 * i + for i in range(20): + assert v2_vals[i] == 2 * i - # Delete the group so it is ready to use by the next protocol - root.destroyGroup("tree1") + # Delete the group so it is ready to use by the next protocol + root.destroyGroup("tree1") diff --git a/src/axom/sidre/tests/sidre_smoke_Py.py b/src/axom/sidre/tests/sidre_smoke_Py.py index 9d245806a1..78bc39a943 100644 --- a/src/axom/sidre/tests/sidre_smoke_Py.py +++ b/src/axom/sidre/tests/sidre_smoke_Py.py @@ -5,21 +5,31 @@ # SPDX-License-Identifier: (BSD-3-Clause) import pysidre +from conduit import Node + # Python automatically calls destructor during garbage collection def test_create_datastore(): - ds = pysidre.DataStore() - assert True + ds = pysidre.DataStore() + assert True + def test_valid_invalid(): - ds = pysidre.DataStore() + ds = pysidre.DataStore() + + idx = 3 + assert idx != pysidre.InvalidIndex + + name = "foo" + assert pysidre.nameIsValid(name) - idx = 3 - assert idx != pysidre.InvalidIndex + root = ds.getRoot() + assert root.getGroupName(idx) == pysidre.InvalidName + assert root.getGroupIndex(name) == pysidre.InvalidIndex - name = "foo" - assert pysidre.nameIsValid(name) - root = ds.getRoot() - assert root.getGroupName(idx) == pysidre.InvalidName - assert root.getGroupIndex(name) == pysidre.InvalidIndex \ No newline at end of file +def test_conduit_in_sidre_smoke(): + # make sure we can import conduit module + n = Node() + n["field"] = 100 + assert n["field"] == 100 diff --git a/src/axom/sidre/tests/sidre_view_Py.py b/src/axom/sidre/tests/sidre_view_Py.py index a123250166..19c08ccec4 100644 --- a/src/axom/sidre/tests/sidre_view_Py.py +++ b/src/axom/sidre/tests/sidre_view_Py.py @@ -17,136 +17,139 @@ STRINGVIEW = 5 NOTYPE = 6 + # Helper function to get state def get_state(view): - if view.isEmpty(): - return EMPTYVIEW - elif view.hasBuffer(): - return BUFFERVIEW - elif view.isExternal(): - return EXTERNALVIEW - elif view.isScalar(): - return SCALARVIEW - elif view.isString(): - return STRINGVIEW - else: - return NOTYPE + if view.isEmpty(): + return EMPTYVIEW + elif view.hasBuffer(): + return BUFFERVIEW + elif view.isExternal(): + return EXTERNALVIEW + elif view.isScalar(): + return SCALARVIEW + elif view.isString(): + return STRINGVIEW + else: + return NOTYPE # Helper function to check values def check_view_values(view, state, is_described, is_allocated, is_applied, length): - dims = np.array([0,0]) + dims = np.array([0, 0]) + + name = view.getName() + assert get_state(view) == state + assert view.isDescribed() == is_described, f"{name} is described" + assert view.isAllocated() == is_allocated, f"{name} is allocated" + assert view.isApplied() == is_applied, f"{name} is applied" + assert view.getNumElements() == length, f"{name} getNumElements" - name = view.getName() - assert get_state(view) == state - assert view.isDescribed() == is_described, f"{name} is described" - assert view.isAllocated() == is_allocated, f"{name} is allocated" - assert view.isApplied() == is_applied, f"{name} is applied" - assert view.getNumElements() == length, f"{name} getNumElements" + if view.isDescribed(): + assert view.getNumDimensions() == 1, f"{name} getNumDimensions" - if view.isDescribed(): - assert view.getNumDimensions() == 1, f"{name} getNumDimensions" - - ndims, dims = view.getShape(1, dims) - assert ndims == 1, f"{name} getShape" - assert dims[0] == length, f"{name} dims[0]" + ndims, dims = view.getShape(1, dims) + assert ndims == 1, f"{name} getShape" + assert dims[0] == length, f"{name} dims[0]" def test_create_views(): - ds = pysidre.DataStore() - root = ds.getRoot() + ds = pysidre.DataStore() + root = ds.getRoot() - dv_0 = root.createViewAndAllocate("field0", pysidre.TypeID.INT_ID, 1) - dv_1 = root.createViewAndAllocate("field1", pysidre.TypeID.INT_ID, 1) + dv_0 = root.createViewAndAllocate("field0", pysidre.TypeID.INT_ID, 1) + dv_1 = root.createViewAndAllocate("field1", pysidre.TypeID.INT_ID, 1) - db_0 = dv_0.getBuffer() - db_1 = dv_1.getBuffer() + db_0 = dv_0.getBuffer() + db_1 = dv_1.getBuffer() - assert db_0.getIndex() == 0 - assert db_1.getIndex() == 1 + assert db_0.getIndex() == 0 + assert db_1.getIndex() == 1 def test_get_path_name(): - ds = pysidre.DataStore() - root = ds.getRoot() + ds = pysidre.DataStore() + root = ds.getRoot() - v1 = root.createView("test/a/b/v1") - v2 = root.createView("test/v2") - v3 = root.createView("v3") + v1 = root.createView("test/a/b/v1") + v2 = root.createView("test/v2") + v3 = root.createView("v3") - assert v1.getName() == "v1" - assert v1.getPath() == "test/a/b" - assert v1.getPathName() == "test/a/b/v1" + assert v1.getName() == "v1" + assert v1.getPath() == "test/a/b" + assert v1.getPathName() == "test/a/b/v1" - assert v2.getName() == "v2" - assert v2.getPath() == "test" - assert v2.getPathName() == "test/v2" + assert v2.getName() == "v2" + assert v2.getPath() == "test" + assert v2.getPathName() == "test/v2" - assert v3.getName() == "v3" - assert v3.getPath() == "" - assert v3.getPathName() == "v3" + assert v3.getName() == "v3" + assert v3.getPath() == "" + assert v3.getPathName() == "v3" def test_create_view_from_path(): - ds = pysidre.DataStore() - root = ds.getRoot() + ds = pysidre.DataStore() + root = ds.getRoot() - baz = root.createView("foo/bar/baz") - assert root.hasGroup("foo") - assert root.getGroup("foo").hasGroup("bar") + baz = root.createView("foo/bar/baz") + assert root.hasGroup("foo") + assert root.getGroup("foo").hasGroup("bar") - bar = root.getGroup("foo").getGroup("bar") - assert bar.hasView("baz") - assert bar.getView("baz") == baz + bar = root.getGroup("foo").getGroup("bar") + assert bar.hasView("baz") + assert bar.getView("baz") == baz def test_scalar_view(): - # Inner helper function - def check_scalar_values(view, state, is_described, is_allocated, is_applied, typeID, length): - dims = np.array([0,0]) - - name = view.getName() - assert get_state(view) == state - assert view.isDescribed() == is_described, f"{name} is described" - assert view.isAllocated() == is_allocated, f"{name} is allocated" - assert view.isApplied() == is_applied, f"{name} is applied" - - assert view.getTypeID() == typeID, f"{name} getTypeID" - assert view.getNumElements() == length, f"{name} getNumElements" - assert view.getNumDimensions() == 1, f"{name} getNumDimensions" - - ndims, dims = view.getShape(1, dims) - assert ndims == 1, f"{name} getShape" - assert dims[0] == length, f"{name} dims[0]" - - ds = pysidre.DataStore() - root = ds.getRoot() - - i1 = 1 - i0view = root.createView("i0") - i0view.setScalar(i1) - check_scalar_values(i0view, SCALARVIEW, True, True, True, pysidre.TypeID.INT32_ID, 1) - i2 = i0view.getDataInt() - assert i1 == i2 - - i1 = 2 - i1view = root.createViewScalar("i1", i1) - check_scalar_values(i1view, SCALARVIEW, True, True, True, pysidre.TypeID.INT32_ID, 1) - i2 = i1view.getDataInt() - assert i1 == i2 - - s1 = "i am a string" - s0view = root.createView("s0") - s0view.setString(s1) - check_scalar_values(s0view, STRINGVIEW, True, True, True, pysidre.TypeID.CHAR8_STR_ID, len(s1) + 1) - s2 = s0view.getString() - assert s1 == s2 - - s1 = "i too am a string" - s1view = root.createViewString("s1", s1) - check_scalar_values(s1view, STRINGVIEW, True, True, True, pysidre.TypeID.CHAR8_STR_ID, len(s1) + 1) - s2 = s1view.getString() - assert s1 == s2 + # Inner helper function + def check_scalar_values(view, state, is_described, is_allocated, is_applied, typeID, length): + dims = np.array([0, 0]) + + name = view.getName() + assert get_state(view) == state + assert view.isDescribed() == is_described, f"{name} is described" + assert view.isAllocated() == is_allocated, f"{name} is allocated" + assert view.isApplied() == is_applied, f"{name} is applied" + + assert view.getTypeID() == typeID, f"{name} getTypeID" + assert view.getNumElements() == length, f"{name} getNumElements" + assert view.getNumDimensions() == 1, f"{name} getNumDimensions" + + ndims, dims = view.getShape(1, dims) + assert ndims == 1, f"{name} getShape" + assert dims[0] == length, f"{name} dims[0]" + + ds = pysidre.DataStore() + root = ds.getRoot() + + i1 = 1 + i0view = root.createView("i0") + i0view.setScalar(i1) + check_scalar_values(i0view, SCALARVIEW, True, True, True, pysidre.TypeID.INT32_ID, 1) + i2 = i0view.getDataInt() + assert i1 == i2 + + i1 = 2 + i1view = root.createViewScalar("i1", i1) + check_scalar_values(i1view, SCALARVIEW, True, True, True, pysidre.TypeID.INT32_ID, 1) + i2 = i1view.getDataInt() + assert i1 == i2 + + s1 = "i am a string" + s0view = root.createView("s0") + s0view.setString(s1) + check_scalar_values(s0view, STRINGVIEW, True, True, True, pysidre.TypeID.CHAR8_STR_ID, + len(s1) + 1) + s2 = s0view.getString() + assert s1 == s2 + + s1 = "i too am a string" + s1view = root.createViewString("s1", s1) + check_scalar_values(s1view, STRINGVIEW, True, True, True, pysidre.TypeID.CHAR8_STR_ID, + len(s1) + 1) + s2 = s1view.getString() + assert s1 == s2 # Test functions that are commented out in Fortran's "main" method, but unimplemented. @@ -156,407 +159,404 @@ def check_scalar_values(view, state, is_described, is_allocated, is_applied, typ #def test_alloc_and_dealloc_multiview(): + def test_int_buffer_from_view(): - elem_count = 10 - ds = pysidre.DataStore() - root = ds.getRoot() + elem_count = 10 + ds = pysidre.DataStore() + root = ds.getRoot() - dv = root.createViewAndAllocate("u0", pysidre.TypeID.INT32_ID, elem_count) - data = dv.getDataArray() + dv = root.createViewAndAllocate("u0", pysidre.TypeID.INT32_ID, elem_count) + data = dv.getDataArray() - for i in range(elem_count): - data[i] = i * i + for i in range(elem_count): + data[i] = i * i - dv.print() + dv.print() - assert dv.getNumElements() == elem_count - assert dv.getTotalBytes() == NUM_BYTES_INT_32 * elem_count + assert dv.getNumElements() == elem_count + assert dv.getTotalBytes() == NUM_BYTES_INT_32 * elem_count def test_int_array_multi_view(): - ds = pysidre.DataStore() - root = ds.getRoot() - dbuff = ds.createBuffer(pysidre.TypeID.INT32_ID, 10) + ds = pysidre.DataStore() + root = ds.getRoot() + dbuff = ds.createBuffer(pysidre.TypeID.INT32_ID, 10) - dbuff.allocate() - data = dbuff.getDataArray() + dbuff.allocate() + data = dbuff.getDataArray() - for i in range(10): - data[i] = i + for i in range(10): + data[i] = i - dbuff.print() + dbuff.print() - dv_e = root.createView("even", dbuff) - dv_o = root.createView("odd", dbuff) - assert dbuff.getNumViews() == 2, f"{dbuff.getNumViews()} == 2" + dv_e = root.createView("even", dbuff) + dv_o = root.createView("odd", dbuff) + assert dbuff.getNumViews() == 2, f"{dbuff.getNumViews()} == 2" - # NOTE - The data/data ptr here is different from C++ implementation. - # Buffer representations are the same. - # "even" - # C++ : [0,1,2,3,4,5,6,7,8,9] - # python: [0,2,4,6,8] - # "odd" - # C++ : [1,2,3,4,5,6,7,8,9, ] - # python: [1,3,5,7,9] + # NOTE - The data/data ptr here is different from C++ implementation. + # Buffer representations are the same. + # "even" + # C++ : [0,1,2,3,4,5,6,7,8,9] + # python: [0,2,4,6,8] + # "odd" + # C++ : [1,2,3,4,5,6,7,8,9, ] + # python: [1,3,5,7,9] - dv_e.apply(5,0,2) - dv_e.print() - data_e = dv_e.getDataArray() + dv_e.apply(5, 0, 2) + dv_e.print() + data_e = dv_e.getDataArray() - dv_o.apply(5,1,2) - dv_o.print() - data_o = dv_o.getDataArray() + dv_o.apply(5, 1, 2) + dv_o.print() + data_o = dv_o.getDataArray() - for i in range(5): - assert data_e[i] % 2 == 0 - assert data_o[i] % 2 == 1 + for i in range(5): + assert data_e[i] % 2 == 0 + assert data_o[i] % 2 == 1 def test_init_int_array_multi_view(): - ds = pysidre.DataStore() - root = ds.getRoot() + ds = pysidre.DataStore() + root = ds.getRoot() - dbuff = ds.createBuffer() - dbuff.allocate(pysidre.TypeID.INT32_ID, 10) + dbuff = ds.createBuffer() + dbuff.allocate(pysidre.TypeID.INT32_ID, 10) - data = dbuff.getDataArray() - for i in range(10): - data[i] = i - dbuff.print() + data = dbuff.getDataArray() + for i in range(10): + data[i] = i + dbuff.print() - dv_e = root.createView("even", dbuff) - dv_o = root.createView("odd", dbuff) - assert dbuff.getNumViews() == 2, f"{dbuff.getNumViews()} == 2" + dv_e = root.createView("even", dbuff) + dv_o = root.createView("odd", dbuff) + assert dbuff.getNumViews() == 2, f"{dbuff.getNumViews()} == 2" - # NOTE - The data/data ptr here is different from C++ implementation. - # Buffer representations are the same. - # "even" - # C++ : [0,1,2,3,4,5,6,7,8,9] - # python: [0,2,4,6,8] - # "odd" - # C++ : [1,2,3,4,5,6,7,8,9, ] - # python: [1,3,5,7,9] + # NOTE - The data/data ptr here is different from C++ implementation. + # Buffer representations are the same. + # "even" + # C++ : [0,1,2,3,4,5,6,7,8,9] + # python: [0,2,4,6,8] + # "odd" + # C++ : [1,2,3,4,5,6,7,8,9, ] + # python: [1,3,5,7,9] - dv_e.apply(5,0,2) - dv_e.print() - data_e = dv_e.getDataArray() + dv_e.apply(5, 0, 2) + dv_e.print() + data_e = dv_e.getDataArray() - dv_o.apply(5,1,2) - dv_o.print() - data_o = dv_o.getDataArray() - - for i in range(5): - assert data_e[i] % 2 == 0 - assert data_o[i] % 2 == 1 + dv_o.apply(5, 1, 2) + dv_o.print() + data_o = dv_o.getDataArray() + for i in range(5): + assert data_e[i] % 2 == 0 + assert data_o[i] % 2 == 1 def test_int_array_depth_view(): - ds = pysidre.DataStore() - depth_nelems = 10 - total_nelems = 4 * depth_nelems + ds = pysidre.DataStore() + depth_nelems = 10 + total_nelems = 4 * depth_nelems - dbuff = ds.createBuffer(pysidre.TypeID.INT32_ID, total_nelems) + dbuff = ds.createBuffer(pysidre.TypeID.INT32_ID, total_nelems) - # Get access to our root data Group - root = ds.getRoot() + # Get access to our root data Group + root = ds.getRoot() - # Allocate buffer to hold data for 4 "depth" views - dbuff.allocate() + # Allocate buffer to hold data for 4 "depth" views + dbuff.allocate() - data = dbuff.getDataArray() + data = dbuff.getDataArray() - for i in range(total_nelems): - data[i] = i / depth_nelems + for i in range(total_nelems): + data[i] = i / depth_nelems - dbuff.print() - assert dbuff.getNumElements() == 4 * depth_nelems + dbuff.print() + assert dbuff.getNumElements() == 4 * depth_nelems - # Create 4 "depth" views and apply offsets into buffer - view0 = root.createView("depth_view_0", dbuff) - view0.apply(depth_nelems, 0 * depth_nelems) + # Create 4 "depth" views and apply offsets into buffer + view0 = root.createView("depth_view_0", dbuff) + view0.apply(depth_nelems, 0 * depth_nelems) - view1 = root.createView("depth_view_1", dbuff) - view1.apply(depth_nelems, 1 * depth_nelems) + view1 = root.createView("depth_view_1", dbuff) + view1.apply(depth_nelems, 1 * depth_nelems) - view2 = root.createView("depth_view_2", dbuff) - view2.apply(depth_nelems, 2 * depth_nelems) + view2 = root.createView("depth_view_2", dbuff) + view2.apply(depth_nelems, 2 * depth_nelems) - view3 = root.createView("depth_view_3", dbuff) - view3.apply(depth_nelems, 3 * depth_nelems) + view3 = root.createView("depth_view_3", dbuff) + view3.apply(depth_nelems, 3 * depth_nelems) - assert dbuff.getNumViews() == 4 + assert dbuff.getNumViews() == 4 - view0.print() - view1.print() - view2.print() - view3.print() + view0.print() + view1.print() + view2.print() + view3.print() - # Check values in depth views - data = view0.getDataArray() - assert np.all(data == 0) + # Check values in depth views + data = view0.getDataArray() + assert np.all(data == 0) - data = view1.getDataArray() - assert np.all(data == 1) + data = view1.getDataArray() + assert np.all(data == 1) - data = view2.getDataArray() - assert np.all(data == 2) + data = view2.getDataArray() + assert np.all(data == 2) - data = view3.getDataArray() - assert np.all(data == 3) + data = view3.getDataArray() + assert np.all(data == 3) def test_int_array_view_attach_buffer(): - # Create our main data store - ds = pysidre.DataStore() - - # Get access to our root data Group - root = ds.getRoot() + # Create our main data store + ds = pysidre.DataStore() - field_nelems = 10 + # Get access to our root data Group + root = ds.getRoot() - # Create 2 "field" views with type and # elems - elem_count = 0 - field0 = root.createView("field0", pysidre.TypeID.INT32_ID, field_nelems) - elem_count = elem_count + field0.getNumElements() - print(f"elem_count field0 {elem_count}") - field1 = root.createView("field1", pysidre.TypeID.INT32_ID, field_nelems) - elem_count = elem_count + field1.getNumElements() - print(f"elem_count field1 {elem_count}") + field_nelems = 10 - assert elem_count == 2 * field_nelems + # Create 2 "field" views with type and # elems + elem_count = 0 + field0 = root.createView("field0", pysidre.TypeID.INT32_ID, field_nelems) + elem_count = elem_count + field0.getNumElements() + print(f"elem_count field0 {elem_count}") + field1 = root.createView("field1", pysidre.TypeID.INT32_ID, field_nelems) + elem_count = elem_count + field1.getNumElements() + print(f"elem_count field1 {elem_count}") - # Create buffer to hold data for all fields and allocate - dbuff = ds.createBuffer(pysidre.TypeID.INT32_ID, elem_count) - dbuff.allocate() + assert elem_count == 2 * field_nelems - assert dbuff.getNumElements() == elem_count + # Create buffer to hold data for all fields and allocate + dbuff = ds.createBuffer(pysidre.TypeID.INT32_ID, elem_count) + dbuff.allocate() - # Initialize buffer data for testing below - data = dbuff.getDataArray() - for i in range(elem_count): - data[i] = i / field_nelems + assert dbuff.getNumElements() == elem_count - dbuff.print() + # Initialize buffer data for testing below + data = dbuff.getDataArray() + for i in range(elem_count): + data[i] = i / field_nelems - # Attach field views to buffer and apply offsets into buffer - offset0 = 0 * field_nelems - field0.attachBuffer(dbuff) - field0.apply(field_nelems, offset0) + dbuff.print() - offset1 = 1 * field_nelems - field1.attachBuffer(dbuff) - field1.apply(field_nelems, offset1) + # Attach field views to buffer and apply offsets into buffer + offset0 = 0 * field_nelems + field0.attachBuffer(dbuff) + field0.apply(field_nelems, offset0) - assert dbuff.getNumViews() == 2 + offset1 = 1 * field_nelems + field1.attachBuffer(dbuff) + field1.apply(field_nelems, offset1) - # Print field views... - field0.print() - field1.print() + assert dbuff.getNumViews() == 2 - # Check values in field views - data = field0.getDataArray() - assert np.size(data) == field_nelems - assert np.all(data == 0) - assert field0.getOffset() == offset0 + # Print field views... + field0.print() + field1.print() - data = field1.getDataArray() - assert np.size(data) == field_nelems - assert np.all(data == 1) - assert field1.getOffset() == offset1 + # Check values in field views + data = field0.getDataArray() + assert np.size(data) == field_nelems + assert np.all(data == 0) + assert field0.getOffset() == offset0 + data = field1.getDataArray() + assert np.size(data) == field_nelems + assert np.all(data == 1) + assert field1.getOffset() == offset1 def test_int_array_offset_stride(): - # create our main data store - ds = pysidre.DataStore() - - # get access to our root data Group - root = ds.getRoot() - - field_nelems = 20 - field0 = root.createViewAndAllocate("field0", pysidre.TypeID.DOUBLE_ID, field_nelems) - assert field0.getNumElements() == field_nelems - assert field0.getBytesPerElement() == NUM_BYTES_DOUBLE - assert field0.getTotalBytes() == NUM_BYTES_DOUBLE * field_nelems - assert field0.getOffset() == 0 - assert field0.getStride() == 1 - - dbuff = field0.getBuffer() - - # Initialize buffer data for testing below - data = dbuff.getDataArray() - - for i in range(field_nelems): - data[i] = (i+1) * 1.001 - - dbuff.print() - - # Create two more views into field0's buffer and test stride and offset - v1_nelems = 3 - v1_stride = 3 - v1_offset = 2 - view1 = root.createView("offset_stride1", dbuff) - view1.apply(v1_nelems, v1_offset, v1_stride) - data1 = view1.getDataArray() - - v2_nelems = 3 - v2_stride = 3 - v2_offset = 3 - view2 = root.createView("offset_stride2", dbuff) - view2.apply(v2_nelems, v2_offset, v2_stride) - data2 = view2.getDataArray() - - v3_nelems = 5 - v3_stride = 1 - v3_offset = 12 - view3 = root.createView("offset_stride3", dbuff) - view3.apply(v3_nelems, v3_offset, v3_stride) - data3 = view3.getDataArray() - - assert view1.getNumElements() == v1_nelems - assert view1.getBytesPerElement() == NUM_BYTES_DOUBLE - assert view1.getOffset() == v1_offset - assert view1.getStride() == v1_stride - assert view1.getTotalBytes() == NUM_BYTES_DOUBLE * (1 + (v1_stride * (v1_nelems - 1))) - assert data1[0] == data[v1_offset] - - assert view2.getNumElements() == v2_nelems - assert view2.getBytesPerElement() == NUM_BYTES_DOUBLE - assert view2.getOffset() == v2_offset - assert view2.getStride() == v2_stride - assert view2.getTotalBytes() == NUM_BYTES_DOUBLE * (1 + (v2_stride * (v2_nelems - 1))) - assert data2[0] == data[v2_offset] - - assert view3.getNumElements() == v3_nelems - assert view3.getBytesPerElement() == NUM_BYTES_DOUBLE - assert view3.getOffset() == v3_offset - assert view3.getStride() == v3_stride - assert view3.getTotalBytes() == NUM_BYTES_DOUBLE * (1 + (v3_stride * (v3_nelems - 1))) - assert data3[0] == data[v3_offset] - - # Test stride and offset against other types of views - other = root.createGroup("other") - view1 = other.createView("key_empty") - assert view1.getOffset() == 0 - assert view1.getStride() == 1 - assert view1.getNumElements() == 0 - assert view1.getBytesPerElement() == 0 - - # Opaque - not described - view1 = other.createView("key_opaque", data) - assert view1.getOffset() == 0 - assert view1.getStride() == 1 - assert view1.getNumElements() == 0 - assert view1.getBytesPerElement() == 0 - assert view1.getTotalBytes() == 0 - - view1 = other.createViewString("key_str", "val_str") - assert view1.getOffset() == 0 - assert view1.getStride() == 1 - assert view1.getBytesPerElement() == 1 - - view1 = other.createViewScalar("key_int", 5) - int_data = view1.getDataInt() - assert int_data == 5 - assert view1.getOffset() == 0 - assert view1.getStride() == 1 - assert view1.getNumElements() == 1 - assert view1.getBytesPerElement() == NUM_BYTES_INT_32 - assert view1.getTotalBytes() == NUM_BYTES_INT_32 + # create our main data store + ds = pysidre.DataStore() + + # get access to our root data Group + root = ds.getRoot() + + field_nelems = 20 + field0 = root.createViewAndAllocate("field0", pysidre.TypeID.DOUBLE_ID, field_nelems) + assert field0.getNumElements() == field_nelems + assert field0.getBytesPerElement() == NUM_BYTES_DOUBLE + assert field0.getTotalBytes() == NUM_BYTES_DOUBLE * field_nelems + assert field0.getOffset() == 0 + assert field0.getStride() == 1 + + dbuff = field0.getBuffer() + + # Initialize buffer data for testing below + data = dbuff.getDataArray() + + for i in range(field_nelems): + data[i] = (i + 1) * 1.001 + + dbuff.print() + + # Create two more views into field0's buffer and test stride and offset + v1_nelems = 3 + v1_stride = 3 + v1_offset = 2 + view1 = root.createView("offset_stride1", dbuff) + view1.apply(v1_nelems, v1_offset, v1_stride) + data1 = view1.getDataArray() + + v2_nelems = 3 + v2_stride = 3 + v2_offset = 3 + view2 = root.createView("offset_stride2", dbuff) + view2.apply(v2_nelems, v2_offset, v2_stride) + data2 = view2.getDataArray() + + v3_nelems = 5 + v3_stride = 1 + v3_offset = 12 + view3 = root.createView("offset_stride3", dbuff) + view3.apply(v3_nelems, v3_offset, v3_stride) + data3 = view3.getDataArray() + + assert view1.getNumElements() == v1_nelems + assert view1.getBytesPerElement() == NUM_BYTES_DOUBLE + assert view1.getOffset() == v1_offset + assert view1.getStride() == v1_stride + assert view1.getTotalBytes() == NUM_BYTES_DOUBLE * (1 + (v1_stride * (v1_nelems - 1))) + assert data1[0] == data[v1_offset] + + assert view2.getNumElements() == v2_nelems + assert view2.getBytesPerElement() == NUM_BYTES_DOUBLE + assert view2.getOffset() == v2_offset + assert view2.getStride() == v2_stride + assert view2.getTotalBytes() == NUM_BYTES_DOUBLE * (1 + (v2_stride * (v2_nelems - 1))) + assert data2[0] == data[v2_offset] + + assert view3.getNumElements() == v3_nelems + assert view3.getBytesPerElement() == NUM_BYTES_DOUBLE + assert view3.getOffset() == v3_offset + assert view3.getStride() == v3_stride + assert view3.getTotalBytes() == NUM_BYTES_DOUBLE * (1 + (v3_stride * (v3_nelems - 1))) + assert data3[0] == data[v3_offset] + + # Test stride and offset against other types of views + other = root.createGroup("other") + view1 = other.createView("key_empty") + assert view1.getOffset() == 0 + assert view1.getStride() == 1 + assert view1.getNumElements() == 0 + assert view1.getBytesPerElement() == 0 + + # Opaque - not described + view1 = other.createView("key_opaque", data) + assert view1.getOffset() == 0 + assert view1.getStride() == 1 + assert view1.getNumElements() == 0 + assert view1.getBytesPerElement() == 0 + assert view1.getTotalBytes() == 0 + + view1 = other.createViewString("key_str", "val_str") + assert view1.getOffset() == 0 + assert view1.getStride() == 1 + assert view1.getBytesPerElement() == 1 + + view1 = other.createViewScalar("key_int", 5) + int_data = view1.getDataInt() + assert int_data == 5 + assert view1.getOffset() == 0 + assert view1.getStride() == 1 + assert view1.getNumElements() == 1 + assert view1.getBytesPerElement() == NUM_BYTES_INT_32 + assert view1.getTotalBytes() == NUM_BYTES_INT_32 def test_int_array_multi_view_resize(): - # This example creates a 4 * 10 buffer of ints, - # and 4 views that point the 4 sections of 10 ints - - # We then create a new buffer to support 4*12 ints - # and 4 views that point into them - - # after this we use the old buffers to copy the values - # into the new views - - # Create our main data store - ds = pysidre.DataStore() - - # Get access to our root data Group - root = ds.getRoot() - - # Create a group to hold the "old" or data we want to copy - r_old = root.createGroup("r_old") - - # Create a view to hold the base buffer and allocate - # we will create 4 sub views of this array - base_old = r_old.createViewAndAllocate("base_data", pysidre.TypeID.INT32_ID, 40) - - - # Init the buff with values that align with the 4 subsections - data = base_old.getDataArray() - data[0:10] = 1 - data[10:20] = 2 - data[20:30] = 3 - data[30:40] = 4 - - # Setup our 4 views - buff_old = base_old.getBuffer() - r0_old = r_old.createView("r0", buff_old) - r1_old = r_old.createView("r1", buff_old) - r2_old = r_old.createView("r2", buff_old) - r3_old = r_old.createView("r3", buff_old) - - # Each view is offset by 10 - offset = 0 - r0_old.apply(10, offset) - offset += 10 - r1_old.apply(10, offset) - offset += 10 - r2_old.apply(10, offset) - offset += 10 - r3_old.apply(10, offset) - - # Check that our views actually point to the expected data - r0_old_data = r0_old.getDataArray() - r1_old_data = r1_old.getDataArray() - r2_old_data = r2_old.getDataArray() - r3_old_data = r3_old.getDataArray() - - for i in range(10): - assert r0_old_data[i] == 1 - assert r1_old_data[i] == 2 - assert r2_old_data[i] == 3 - assert r3_old_data[i] == 4 - - # Create a group to hold the "new" or data we want to copy into - r_new = root.createGroup("r_new") - - # Create a view to hold the base buffer - base_new = r_new.createView("base_data") - base_new.allocate(pysidre.TypeID.INT32_ID, 48) - base_new_data = base_new.getDataArray() - for i in range(48): - base_new_data[i] = 0 - - buff_new = base_new.getBuffer() - buff_new.print() - - # Create the 4 sub views of this array - r0_new = r_new.createView("r0", buff_new) - r1_new = r_new.createView("r1", buff_new) - r2_new = r_new.createView("r2", buff_new) - r3_new = r_new.createView("r3", buff_new) - - # Apply views to r0, r1, r2, r3 - # Each view is offset by 12 - offset = 0 - r0_new.apply(12, offset) - offset += 12 - r1_new.apply(12, offset) - offset += 12 - r2_new.apply(12, offset) - offset += 12 - r3_new.apply(12, offset) - - """ + # This example creates a 4 * 10 buffer of ints, + # and 4 views that point the 4 sections of 10 ints + + # We then create a new buffer to support 4*12 ints + # and 4 views that point into them + + # after this we use the old buffers to copy the values + # into the new views + + # Create our main data store + ds = pysidre.DataStore() + + # Get access to our root data Group + root = ds.getRoot() + + # Create a group to hold the "old" or data we want to copy + r_old = root.createGroup("r_old") + + # Create a view to hold the base buffer and allocate + # we will create 4 sub views of this array + base_old = r_old.createViewAndAllocate("base_data", pysidre.TypeID.INT32_ID, 40) + + # Init the buff with values that align with the 4 subsections + data = base_old.getDataArray() + data[0:10] = 1 + data[10:20] = 2 + data[20:30] = 3 + data[30:40] = 4 + + # Setup our 4 views + buff_old = base_old.getBuffer() + r0_old = r_old.createView("r0", buff_old) + r1_old = r_old.createView("r1", buff_old) + r2_old = r_old.createView("r2", buff_old) + r3_old = r_old.createView("r3", buff_old) + + # Each view is offset by 10 + offset = 0 + r0_old.apply(10, offset) + offset += 10 + r1_old.apply(10, offset) + offset += 10 + r2_old.apply(10, offset) + offset += 10 + r3_old.apply(10, offset) + + # Check that our views actually point to the expected data + r0_old_data = r0_old.getDataArray() + r1_old_data = r1_old.getDataArray() + r2_old_data = r2_old.getDataArray() + r3_old_data = r3_old.getDataArray() + + for i in range(10): + assert r0_old_data[i] == 1 + assert r1_old_data[i] == 2 + assert r2_old_data[i] == 3 + assert r3_old_data[i] == 4 + + # Create a group to hold the "new" or data we want to copy into + r_new = root.createGroup("r_new") + + # Create a view to hold the base buffer + base_new = r_new.createView("base_data") + base_new.allocate(pysidre.TypeID.INT32_ID, 48) + base_new_data = base_new.getDataArray() + for i in range(48): + base_new_data[i] = 0 + + buff_new = base_new.getBuffer() + buff_new.print() + + # Create the 4 sub views of this array + r0_new = r_new.createView("r0", buff_new) + r1_new = r_new.createView("r1", buff_new) + r2_new = r_new.createView("r2", buff_new) + r3_new = r_new.createView("r3", buff_new) + + # Apply views to r0, r1, r2, r3 + # Each view is offset by 12 + offset = 0 + r0_new.apply(12, offset) + offset += 12 + r1_new.apply(12, offset) + offset += 12 + r2_new.apply(12, offset) + offset += 12 + r3_new.apply(12, offset) + """ # Note - this requires getNode() (Conduit Node) ! update r2 as an example first call buff_new%print() @@ -592,151 +592,148 @@ def test_int_array_multi_view_resize(): def test_int_array_realloc(): - # Create our main data store - ds = pysidre.DataStore() + # Create our main data store + ds = pysidre.DataStore() - # Get access to our root data Group - root = ds.getRoot() + # Get access to our root data Group + root = ds.getRoot() - a1 = root.createViewAndAllocate("a1", pysidre.TypeID.DOUBLE_ID, 5) - a2 = root.createViewAndAllocate("a2", pysidre.TypeID.DOUBLE_ID, 5) + a1 = root.createViewAndAllocate("a1", pysidre.TypeID.DOUBLE_ID, 5) + a2 = root.createViewAndAllocate("a2", pysidre.TypeID.DOUBLE_ID, 5) - a1_data = a1.getDataArray() - a2_data = a2.getDataArray() + a1_data = a1.getDataArray() + a2_data = a2.getDataArray() - assert np.size(a1_data) == 5 - assert np.size(a2_data) == 5 + assert np.size(a1_data) == 5 + assert np.size(a2_data) == 5 - a1_data[0:5] = 5.0 - a2_data[0:5] = -5.0 + a1_data[0:5] = 5.0 + a2_data[0:5] = -5.0 - a1.reallocate(10) - a2.reallocate(15) + a1.reallocate(10) + a2.reallocate(15) - a1_data = a1.getDataArray() - a2_data = a2.getDataArray() + a1_data = a1.getDataArray() + a2_data = a2.getDataArray() - assert np.size(a1_data) == 10 - assert np.size(a2_data) == 15 + assert np.size(a1_data) == 10 + assert np.size(a2_data) == 15 - assert np.all(a1_data[0:5] == 5.0) - assert np.all(a2_data[0:5] == -5.0) + assert np.all(a1_data[0:5] == 5.0) + assert np.all(a2_data[0:5] == -5.0) - a1_data[5:10] = 10.0 - a2_data[5:10] = -10.0 - a2_data[10:15] = -15.0 + a1_data[5:10] = 10.0 + a2_data[5:10] = -10.0 + a2_data[10:15] = -15.0 - assert np.all(a1_data[5:10] == 10.0) - assert np.all(a2_data[5:10] == -10.0) - assert np.all(a2_data[10:15] == -15.0) + assert np.all(a1_data[5:10] == 10.0) + assert np.all(a2_data[5:10] == -10.0) + assert np.all(a2_data[10:15] == -15.0) - ds.print() + ds.print() def test_simple_opaque(): - # Create our main data store - ds = pysidre.DataStore() + # Create our main data store + ds = pysidre.DataStore() - # Get access to our root data Group - root = ds.getRoot() + # Get access to our root data Group + root = ds.getRoot() - src_data = np.array([42]) - opq_view = root.createView("my_opaque", src_data) + src_data = np.array([42]) + opq_view = root.createView("my_opaque", src_data) - # External data is held in the view, not buffer - assert ds.getNumBuffers() == 0 + # External data is held in the view, not buffer + assert ds.getNumBuffers() == 0 - assert opq_view.isExternal() == True - assert opq_view.isApplied() == False - assert opq_view.isOpaque() == True - assert opq_view.getTypeID() == pysidre.TypeID.NO_TYPE_ID + assert opq_view.isExternal() == True + assert opq_view.isApplied() == False + assert opq_view.isOpaque() == True + assert opq_view.getTypeID() == pysidre.TypeID.NO_TYPE_ID - # Apply type to get data - opq_view.apply(pysidre.TypeID.INT32_ID, 1) - opq_data = opq_view.getDataArray() - assert opq_data[0] == 42 + # Apply type to get data + opq_view.apply(pysidre.TypeID.INT32_ID, 1) + opq_data = opq_view.getDataArray() + assert opq_data[0] == 42 - ds.print() + ds.print() def test_clear_view(): - BLEN = 10 - ds = pysidre.DataStore() - root = ds.getRoot() - - # Create an empty view - view = root.createView("v_empty") - check_view_values(view, EMPTYVIEW, False, False, False, 0) - view.clear() - check_view_values(view, EMPTYVIEW, False, False, False, 0) - - # Describe an empty view - view = root.createView("v_described", pysidre.TypeID.INT32_ID, BLEN) - check_view_values(view, EMPTYVIEW, True, False, False, BLEN) - view.clear() - check_view_values(view, EMPTYVIEW, False, False, False, 0) - - # Scalar view - view = root.createViewScalar("v_scalar", 1) - check_view_values(view, SCALARVIEW, True, True, True, 1) - view.clear() - check_view_values(view, EMPTYVIEW, False, False, False, 0) - - # String view - view = root.createViewString("v_string", "string-test") - view.clear() - check_view_values(view, EMPTYVIEW, False, False, False, 0) - - # Allocated view, Buffer will be released - nbuf = ds.getNumBuffers() - view = root.createViewAndAllocate("v_allocated", pysidre.TypeID.INT32_ID, BLEN) - check_view_values(view, BUFFERVIEW, True, True, True, BLEN) - view.clear() - check_view_values(view, EMPTYVIEW, False, False, False, 0) - assert ds.getNumBuffers() == nbuf - - # Undescribed buffer - nbuf = ds.getNumBuffers() - dbuff = ds.createBuffer() - view = root.createView("v_undescribed_buffer", dbuff) - check_view_values(view, BUFFERVIEW, False, False, False, 0) - view.clear() - check_view_values(view, EMPTYVIEW, False, False, False, 0) - assert ds.getNumBuffers() == nbuf - - # Explicit buffer attached to two views - dbuff = ds.createBuffer() - dbuff.allocate(pysidre.TypeID.INT32_ID, BLEN) - nbuf = ds.getNumBuffers() - assert dbuff.getNumViews() == 0 - - vother = root.createView("v_other", pysidre.TypeID.INT32_ID, BLEN) - view = root.createView("v_buffer", pysidre.TypeID.INT32_ID, BLEN) - vother.attachBuffer(dbuff) - assert dbuff.getNumViews() == 1 - view.attachBuffer(dbuff) - assert dbuff.getNumViews() == 2 - - check_view_values(view, BUFFERVIEW, True, True, True, BLEN) - view.clear() - check_view_values(view, EMPTYVIEW, False, False, False, 0) - - assert ds.getNumBuffers() == nbuf - assert dbuff.getNumViews() == 1 - - # External View - ext_data = np.array(BLEN) - view = root.createView("v_external", pysidre.TypeID.INT32_ID, BLEN, ext_data) - check_view_values(view, EXTERNALVIEW, True, True, True, BLEN) - view.clear() - check_view_values(view, EMPTYVIEW, False, False, False, 0) - - - # Opaque view - ext_data = np.array(BLEN) - view = root.createView("v_opaque", ext_data) - check_view_values(view, EXTERNALVIEW, False, True, False, 0) - view.clear() - check_view_values(view, EMPTYVIEW, False, False, False, 0) - - + BLEN = 10 + ds = pysidre.DataStore() + root = ds.getRoot() + + # Create an empty view + view = root.createView("v_empty") + check_view_values(view, EMPTYVIEW, False, False, False, 0) + view.clear() + check_view_values(view, EMPTYVIEW, False, False, False, 0) + + # Describe an empty view + view = root.createView("v_described", pysidre.TypeID.INT32_ID, BLEN) + check_view_values(view, EMPTYVIEW, True, False, False, BLEN) + view.clear() + check_view_values(view, EMPTYVIEW, False, False, False, 0) + + # Scalar view + view = root.createViewScalar("v_scalar", 1) + check_view_values(view, SCALARVIEW, True, True, True, 1) + view.clear() + check_view_values(view, EMPTYVIEW, False, False, False, 0) + + # String view + view = root.createViewString("v_string", "string-test") + view.clear() + check_view_values(view, EMPTYVIEW, False, False, False, 0) + + # Allocated view, Buffer will be released + nbuf = ds.getNumBuffers() + view = root.createViewAndAllocate("v_allocated", pysidre.TypeID.INT32_ID, BLEN) + check_view_values(view, BUFFERVIEW, True, True, True, BLEN) + view.clear() + check_view_values(view, EMPTYVIEW, False, False, False, 0) + assert ds.getNumBuffers() == nbuf + + # Undescribed buffer + nbuf = ds.getNumBuffers() + dbuff = ds.createBuffer() + view = root.createView("v_undescribed_buffer", dbuff) + check_view_values(view, BUFFERVIEW, False, False, False, 0) + view.clear() + check_view_values(view, EMPTYVIEW, False, False, False, 0) + assert ds.getNumBuffers() == nbuf + + # Explicit buffer attached to two views + dbuff = ds.createBuffer() + dbuff.allocate(pysidre.TypeID.INT32_ID, BLEN) + nbuf = ds.getNumBuffers() + assert dbuff.getNumViews() == 0 + + vother = root.createView("v_other", pysidre.TypeID.INT32_ID, BLEN) + view = root.createView("v_buffer", pysidre.TypeID.INT32_ID, BLEN) + vother.attachBuffer(dbuff) + assert dbuff.getNumViews() == 1 + view.attachBuffer(dbuff) + assert dbuff.getNumViews() == 2 + + check_view_values(view, BUFFERVIEW, True, True, True, BLEN) + view.clear() + check_view_values(view, EMPTYVIEW, False, False, False, 0) + + assert ds.getNumBuffers() == nbuf + assert dbuff.getNumViews() == 1 + + # External View + ext_data = np.array(BLEN) + view = root.createView("v_external", pysidre.TypeID.INT32_ID, BLEN, ext_data) + check_view_values(view, EXTERNALVIEW, True, True, True, BLEN) + view.clear() + check_view_values(view, EMPTYVIEW, False, False, False, 0) + + # Opaque view + ext_data = np.array(BLEN) + view = root.createView("v_opaque", ext_data) + check_view_values(view, EXTERNALVIEW, False, True, False, 0) + view.clear() + check_view_values(view, EMPTYVIEW, False, False, False, 0) diff --git a/src/axom/sina/tests/test_fortran_integration.py b/src/axom/sina/tests/test_fortran_integration.py index db5e2f7184..8d3ac99d09 100644 --- a/src/axom/sina/tests/test_fortran_integration.py +++ b/src/axom/sina/tests/test_fortran_integration.py @@ -8,7 +8,6 @@ import sys import random - if (config.AXOM_USE_HDF5): import h5py @@ -16,11 +15,14 @@ def parse_args(): """Helper function to obtain the binary directory path of Axom from CLI""" parser = argparse.ArgumentParser(description="Unit test arguments") - parser.add_argument("-bd", "--binary-dir", type=str, + parser.add_argument("-bd", + "--binary-dir", + type=str, help="Path to the binary directory for Axom") # Add other arguments as needed return parser.parse_args() + # JSON Tests: Will always run @@ -42,9 +44,9 @@ def setUpClass(cls): os.chdir(cls.binary_dir) - if not os.path.exists(os.path.join( - cls.binary_dir, "examples/sina_fortran_ex")): - p = subprocess.Popen(["make", "sina_fortran_ex"], stdout=subprocess.PIPE, + if not os.path.exists(os.path.join(cls.binary_dir, "examples/sina_fortran_ex")): + p = subprocess.Popen(["make", "sina_fortran_ex"], + stdout=subprocess.PIPE, stderr=subprocess.PIPE) o, e = p.communicate() if p.returncode != 0: @@ -59,10 +61,7 @@ def setUp(self): """ Invoke example Fortran application to dump a sina file """ seed = f"sina_dump_{random.randint(1,10000)}" cmd = [os.path.join(self.binary_dir, "examples/sina_fortran_ex"), seed] - p = subprocess.Popen( - cmd, - stderr=subprocess.PIPE, - stdout=subprocess.PIPE) + p = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE) o, e = p.communicate() self.assertEqual(p.returncode, 0) self.dump_file = f"{seed}.json" @@ -75,8 +74,7 @@ def test_file_validity(self): """ Make sure the files we're importing follow the Sina schema. """ try: import jsonschema - schema_file = os.path.join( - self.binary_dir, "tests", "sina_schema.json") + schema_file = os.path.join(self.binary_dir, "tests", "sina_schema.json") with io.open(schema_file, "r", encoding="utf-8") as schema: schema = json.load(schema) @@ -102,22 +100,13 @@ def test_validate_contents_of_records_json(self): self.assertEqual("custom_type", record2["type"]) # Test the files - self.assertEqual( - list( - record["files"].keys()), [ - "/path/to/my/file/my_other_file.txt", "/path/to/my/file/my_file.txt"]) - self.assertEqual( - record["files"]["/path/to/my/file/my_other_file.txt"]["mimetype"], - "png") - self.assertEqual( - record["files"]["/path/to/my/file/my_file.txt"]["mimetype"], - "txt") + self.assertEqual(list(record["files"].keys()), + ["/path/to/my/file/my_other_file.txt", "/path/to/my/file/my_file.txt"]) + self.assertEqual(record["files"]["/path/to/my/file/my_other_file.txt"]["mimetype"], "png") + self.assertEqual(record["files"]["/path/to/my/file/my_file.txt"]["mimetype"], "txt") # Test the files - self.assertEqual(list(record2["files"].keys()), [ - "/path/to/my/file/my_file.txt"]) - self.assertEqual( - record2["files"]["/path/to/my/file/my_file.txt"]["mimetype"], - "txt") + self.assertEqual(list(record2["files"].keys()), ["/path/to/my/file/my_file.txt"]) + self.assertEqual(record2["files"]["/path/to/my/file/my_file.txt"]["mimetype"], "txt") # Test the signed variants self.assertEqual("A", record["data"]["char"]["value"]) @@ -141,17 +130,11 @@ def test_validate_contents_of_records_json(self): self.assertEqual("kg", record["data"]["u_long"]["units"]) self.assertEqual(1.23456704616547, record["data"]["u_real"]["value"]) self.assertEqual("kg", record["data"]["u_real"]["units"]) - self.assertEqual( - 0.810000002384186, - record["data"]["u_double"]["value"]) + self.assertEqual(0.810000002384186, record["data"]["u_double"]["value"]) self.assertEqual("kg", record["data"]["u_double"]["units"]) - self.assertEqual( - 0.810000002384186, - record["data"]["u_double_w_tag"]["value"]) + self.assertEqual(0.810000002384186, record["data"]["u_double_w_tag"]["value"]) self.assertEqual("kg", record["data"]["u_double_w_tag"]["units"]) - self.assertEqual( - ["new_fancy_tag"], - record["data"]["u_double_w_tag"]["tags"]) + self.assertEqual(["new_fancy_tag"], record["data"]["u_double_w_tag"]["tags"]) # Test the curves nums = range(1, 21) @@ -160,35 +143,41 @@ def test_validate_contents_of_records_json(self): int_arr = [i * 3 for i in nums] long_arr = [i * 4 for i in nums] curveset = "my_curveset" - self.assertEqual(list(record["curve_sets"][curveset]['independent'].keys()), - sorted(['my_indep_curve_double', 'my_indep_curve_real', - 'my_indep_curve_int', 'my_indep_curve_long'])) - self.assertEqual(list(record2["curve_sets"]["my_other_curveset"]['independent'].keys()), - sorted(['my_indep_curve_double', 'my_indep_curve_real', - 'my_indep_curve_int', 'my_indep_curve_long'], reverse=True)) - self.assertEqual(list(record["curve_sets"][curveset]['dependent'].keys()), - sorted(['my_dep_curve_double', 'my_dep_curve_double_2', - 'my_dep_curve_real', 'my_dep_curve_int', - 'my_dep_curve_long'])) + self.assertEqual( + list(record["curve_sets"][curveset]['independent'].keys()), + sorted([ + 'my_indep_curve_double', 'my_indep_curve_real', 'my_indep_curve_int', + 'my_indep_curve_long' + ])) + self.assertEqual( + list(record2["curve_sets"]["my_other_curveset"]['independent'].keys()), + sorted([ + 'my_indep_curve_double', 'my_indep_curve_real', 'my_indep_curve_int', + 'my_indep_curve_long' + ], + reverse=True)) + self.assertEqual( + list(record["curve_sets"][curveset]['dependent'].keys()), + sorted([ + 'my_dep_curve_double', 'my_dep_curve_double_2', 'my_dep_curve_real', + 'my_dep_curve_int', 'my_dep_curve_long' + ])) for kind, loc in (("indep", "independent"), ("dep", "dependent")): - for val_type, target in ( - ("real", real_arr), ("double", double_arr), ("int", int_arr), ("long", long_arr)): + for val_type, target in (("real", real_arr), ("double", double_arr), ("int", int_arr), + ("long", long_arr)): name = "my_{}_curve_{}".format(kind, val_type) - self.assertEqual( - target, record["curve_sets"][curveset][loc][name]["value"]) + self.assertEqual(target, record["curve_sets"][curveset][loc][name]["value"]) if val_type == "double": - self.assertEqual( - target, record2["curve_sets"]["my_other_curveset"][loc][name]["value"]) + self.assertEqual(target, + record2["curve_sets"]["my_other_curveset"][loc][name]["value"]) double_2_name = "my_dep_curve_double_2" - self.assertEqual( - double_arr, - record["curve_sets"][curveset]["dependent"][double_2_name]["value"]) + self.assertEqual(double_arr, + record["curve_sets"][curveset]["dependent"][double_2_name]["value"]) # HDF5 Test -@unittest.skipUnless(config.AXOM_USE_HDF5, - "Requires h5py for HDF5-dependent tests") +@unittest.skipUnless(config.AXOM_USE_HDF5, "Requires h5py for HDF5-dependent tests") class TestFortranExampleIntegrationHDF5(unittest.TestCase): @classmethod @@ -207,8 +196,7 @@ def setUpClass(cls): os.chdir(cls.binary_dir) - if not os.path.exists(os.path.join( - cls.binary_dir, "examples/sina_fortran_ex")): + if not os.path.exists(os.path.join(cls.binary_dir, "examples/sina_fortran_ex")): subprocess.run(["make", "sina_fortran_ex"]) os.chdir(cwd) @@ -217,10 +205,7 @@ def setUp(self): """ Invoke example Fortran application to dump a sina file """ seed = f"sina_dump_{random.randint(1,10000)}" cmd = [os.path.join(self.binary_dir, "examples/sina_fortran_ex"), seed] - p = subprocess.Popen( - cmd, - stderr=subprocess.PIPE, - stdout=subprocess.PIPE) + p = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE) o, e = p.communicate() self.assertEqual(p.returncode, 0) self.dump_file = f"{seed}.hdf5" @@ -239,8 +224,8 @@ def extract_hdf5_value(self, value): # If the value is a list or tuple of bytes, join them into a single # bytes object and decode. - if isinstance(value, (list, tuple)) and value and all( - isinstance(item, bytes) for item in value): + if isinstance(value, + (list, tuple)) and value and all(isinstance(item, bytes) for item in value): joined = b"".join(value) return joined.decode("utf-8").strip("\0").strip() @@ -267,22 +252,10 @@ def test_validate_contents_of_records_hdf5(self): record3 = f["records"]["2"] # Validate metadata - self.assertEqual( - "my_rec_id", - self.extract_hdf5_value( - record["id"])) - self.assertEqual( - "fortran_code_output", - self.extract_hdf5_value( - record["type"])) - self.assertEqual( - "custom_type", - self.extract_hdf5_value( - record2["type"])) - self.assertEqual( - "fortran_test", - self.extract_hdf5_value( - record3["type"])) + self.assertEqual("my_rec_id", self.extract_hdf5_value(record["id"])) + self.assertEqual("fortran_code_output", self.extract_hdf5_value(record["type"])) + self.assertEqual("custom_type", self.extract_hdf5_value(record2["type"])) + self.assertEqual("fortran_test", self.extract_hdf5_value(record3["type"])) # Validate Files files_group = record["files"] @@ -290,88 +263,44 @@ def test_validate_contents_of_records_hdf5(self): "__SINA_SLASHREPLACE__path__SINA_SLASHREPLACE__to__SINA_SLASHREPLACE__my__SINA_SLASHREPLACE__file__SINA_SLASHREPLACE__my_other_file.txt", "__SINA_SLASHREPLACE__path__SINA_SLASHREPLACE__to__SINA_SLASHREPLACE__my__SINA_SLASHREPLACE__file__SINA_SLASHREPLACE__my_file.txt" ] + self.assertEqual(sorted(list(files_group.keys())), sorted(expected_file_keys)) + self.assertEqual( + self.extract_hdf5_value(files_group[ + "__SINA_SLASHREPLACE__path__SINA_SLASHREPLACE__to__SINA_SLASHREPLACE__my__SINA_SLASHREPLACE__file__SINA_SLASHREPLACE__my_other_file.txt"] + ["mimetype"]), "png") self.assertEqual( - sorted( - list( - files_group.keys())), - sorted(expected_file_keys)) - self.assertEqual(self.extract_hdf5_value( - files_group["__SINA_SLASHREPLACE__path__SINA_SLASHREPLACE__to__SINA_SLASHREPLACE__my__SINA_SLASHREPLACE__file__SINA_SLASHREPLACE__my_other_file.txt"]["mimetype"]), - "png") - self.assertEqual(self.extract_hdf5_value( - files_group["__SINA_SLASHREPLACE__path__SINA_SLASHREPLACE__to__SINA_SLASHREPLACE__my__SINA_SLASHREPLACE__file__SINA_SLASHREPLACE__my_file.txt"]["mimetype"]), - "txt") + self.extract_hdf5_value(files_group[ + "__SINA_SLASHREPLACE__path__SINA_SLASHREPLACE__to__SINA_SLASHREPLACE__my__SINA_SLASHREPLACE__file__SINA_SLASHREPLACE__my_file.txt"] + ["mimetype"]), "txt") # Validate Data data_group = record["data"] - self.assertEqual( - self.extract_hdf5_value( - data_group["char"]["value"]), "A") - self.assertEqual( - self.extract_hdf5_value( - data_group["int"]["value"]), 10) - self.assertEqual( - self.extract_hdf5_value( - data_group["logical"]["value"]), 0) - self.assertEqual( - self.extract_hdf5_value( - data_group["long"]["value"]), - 1000000000.0) - self.assertAlmostEqual( - self.extract_hdf5_value( - data_group["real"]["value"]), - 1.23456704616547) - self.assertAlmostEqual( - self.extract_hdf5_value( - data_group["double"]["value"]), - 0.810000002384186) - - self.assertEqual( - self.extract_hdf5_value( - data_group["u_char"]["value"]), "A") - self.assertEqual( - self.extract_hdf5_value( - data_group["u_char"]["units"]), "kg") - self.assertEqual( - self.extract_hdf5_value( - data_group["u_int"]["value"]), 10) - self.assertEqual( - self.extract_hdf5_value( - data_group["u_int"]["units"]), "kg") - self.assertEqual( - self.extract_hdf5_value( - data_group["u_logical"]["value"]), 1.0) - self.assertEqual( - self.extract_hdf5_value( - data_group["u_logical"]["units"]), "kg") - self.assertEqual( - self.extract_hdf5_value( - data_group["u_long"]["value"]), - 1000000000.0) - self.assertEqual( - self.extract_hdf5_value( - data_group["u_long"]["units"]), "kg") - self.assertAlmostEqual( - self.extract_hdf5_value( - data_group["u_real"]["value"]), - 1.23456704616547) - self.assertEqual( - self.extract_hdf5_value( - data_group["u_real"]["units"]), "kg") - self.assertAlmostEqual( - self.extract_hdf5_value( - data_group["u_double"]["value"]), - 0.810000002384186) - self.assertEqual( - self.extract_hdf5_value( - data_group["u_double"]["units"]), "kg") - self.assertAlmostEqual( - self.extract_hdf5_value( - data_group["u_double_w_tag"]["value"]), - 0.810000002384186) - self.assertEqual( - self.extract_hdf5_value( - data_group["u_double_w_tag"]["units"]), "kg") + self.assertEqual(self.extract_hdf5_value(data_group["char"]["value"]), "A") + self.assertEqual(self.extract_hdf5_value(data_group["int"]["value"]), 10) + self.assertEqual(self.extract_hdf5_value(data_group["logical"]["value"]), 0) + self.assertEqual(self.extract_hdf5_value(data_group["long"]["value"]), 1000000000.0) + self.assertAlmostEqual(self.extract_hdf5_value(data_group["real"]["value"]), + 1.23456704616547) + self.assertAlmostEqual(self.extract_hdf5_value(data_group["double"]["value"]), + 0.810000002384186) + + self.assertEqual(self.extract_hdf5_value(data_group["u_char"]["value"]), "A") + self.assertEqual(self.extract_hdf5_value(data_group["u_char"]["units"]), "kg") + self.assertEqual(self.extract_hdf5_value(data_group["u_int"]["value"]), 10) + self.assertEqual(self.extract_hdf5_value(data_group["u_int"]["units"]), "kg") + self.assertEqual(self.extract_hdf5_value(data_group["u_logical"]["value"]), 1.0) + self.assertEqual(self.extract_hdf5_value(data_group["u_logical"]["units"]), "kg") + self.assertEqual(self.extract_hdf5_value(data_group["u_long"]["value"]), 1000000000.0) + self.assertEqual(self.extract_hdf5_value(data_group["u_long"]["units"]), "kg") + self.assertAlmostEqual(self.extract_hdf5_value(data_group["u_real"]["value"]), + 1.23456704616547) + self.assertEqual(self.extract_hdf5_value(data_group["u_real"]["units"]), "kg") + self.assertAlmostEqual(self.extract_hdf5_value(data_group["u_double"]["value"]), + 0.810000002384186) + self.assertEqual(self.extract_hdf5_value(data_group["u_double"]["units"]), "kg") + self.assertAlmostEqual(self.extract_hdf5_value(data_group["u_double_w_tag"]["value"]), + 0.810000002384186) + self.assertEqual(self.extract_hdf5_value(data_group["u_double_w_tag"]["units"]), "kg") tags_value = data_group["u_double_w_tag"]["tags"] if isinstance(tags_value, h5py.Group): @@ -386,15 +315,12 @@ def test_validate_contents_of_records_hdf5(self): # Validate order set on record self.assertEqual( - list( - record2["curve_sets"]["my_other_curveset"]["independent"].keys()), - sorted( - [ - 'my_indep_curve_double', - 'my_indep_curve_real', - 'my_indep_curve_int', - 'my_indep_curve_long'], - reverse=True)) + list(record2["curve_sets"]["my_other_curveset"]["independent"].keys()), + sorted([ + 'my_indep_curve_double', 'my_indep_curve_real', 'my_indep_curve_int', + 'my_indep_curve_long' + ], + reverse=True)) curveset_group = record["curve_sets"]["my_curveset"] independent_group = curveset_group["independent"] dependent_group = curveset_group["dependent"] @@ -405,47 +331,52 @@ def test_validate_contents_of_records_hdf5(self): int_arr = [i * 3 for i in nums] long_arr = [i * 4 for i in nums] - self.assertEqual(list(curveset_group['independent'].keys()), - sorted(['my_indep_curve_double', 'my_indep_curve_real', 'my_indep_curve_int', 'my_indep_curve_long'])) - self.assertEqual(list(curveset_group['dependent'].keys()), - sorted(['my_dep_curve_double', 'my_dep_curve_double_2', 'my_dep_curve_real', 'my_dep_curve_int', 'my_dep_curve_long'])) - for kind, grp in (("indep", independent_group), - ("dep", dependent_group)): - for val_type, target in (("real", real_arr), - ("double", double_arr), - ("int", int_arr), - ("long", long_arr)): + self.assertEqual( + list(curveset_group['independent'].keys()), + sorted([ + 'my_indep_curve_double', 'my_indep_curve_real', 'my_indep_curve_int', + 'my_indep_curve_long' + ])) + self.assertEqual( + list(curveset_group['dependent'].keys()), + sorted([ + 'my_dep_curve_double', 'my_dep_curve_double_2', 'my_dep_curve_real', + 'my_dep_curve_int', 'my_dep_curve_long' + ])) + for kind, grp in (("indep", independent_group), ("dep", dependent_group)): + for val_type, target in (("real", real_arr), ("double", double_arr), + ("int", int_arr), ("long", long_arr)): curve_name = f"my_{kind}_curve_{val_type}" self.assertIn(curve_name, grp) - curve_val = self.extract_hdf5_value( - grp[curve_name]["value"]) + curve_val = self.extract_hdf5_value(grp[curve_name]["value"]) self.assertEqual(len(curve_val), len(target)) self.assertEqual(curve_val, target) # Let's check group2 as well if val_type == "double": curve_val = self.extract_hdf5_value( - record2["curve_sets"]["my_other_curveset"]["independent"]["my_indep_curve_double"]["value"]) + record2["curve_sets"]["my_other_curveset"]["independent"] + ["my_indep_curve_double"]["value"]) self.assertEqual(len(curve_val), len(target)) self.assertEqual(curve_val, target) curve_val = self.extract_hdf5_value( - record3["curve_sets"]["my_other_curveset"]["independent"]["my_indep_curve_double"]["value"]) + record3["curve_sets"]["my_other_curveset"]["independent"] + ["my_indep_curve_double"]["value"]) self.assertEqual(len(curve_val), 2 * len(target)) double_2_name = "my_dep_curve_double_2" self.assertIn(double_2_name, dependent_group) - curve_double_2 = self.extract_hdf5_value( - dependent_group[double_2_name]["value"]) + curve_double_2 = self.extract_hdf5_value(dependent_group[double_2_name]["value"]) self.assertEqual(curve_double_2, double_arr) if __name__ == "__main__": # Doing the below instead of unittest.main() so that we can print to stdout suite = unittest.TestSuite() - suite.addTests(unittest.defaultTestLoader.loadTestsFromTestCase( - TestFortranExampleIntegrationJSON)) + suite.addTests( + unittest.defaultTestLoader.loadTestsFromTestCase(TestFortranExampleIntegrationJSON)) if config.AXOM_USE_HDF5: - suite.addTests(unittest.defaultTestLoader.loadTestsFromTestCase( - TestFortranExampleIntegrationHDF5)) + suite.addTests( + unittest.defaultTestLoader.loadTestsFromTestCase(TestFortranExampleIntegrationHDF5)) runner = unittest.TextTestRunner(buffer=False) results = runner.run(suite) if not results.wasSuccessful(): diff --git a/src/axom/slic/tests/slic_macros.cpp b/src/axom/slic/tests/slic_macros.cpp index a020b6c8b9..747390f538 100644 --- a/src/axom/slic/tests/slic_macros.cpp +++ b/src/axom/slic/tests/slic_macros.cpp @@ -341,7 +341,7 @@ TEST(slic_macros, test_debug_macros) //------------------------------------------------------------------------------ TEST(slic_macros, test_assert_macros) { - int expected_line_number; + [[maybe_unused]] int expected_line_number; EXPECT_TRUE(slic::internal::is_stream_empty()); constexpr int val = 42; @@ -384,7 +384,7 @@ TEST(slic_macros, test_assert_macros) //------------------------------------------------------------------------------ TEST(slic_macros, test_check_macros) { - int expected_line_number; + [[maybe_unused]] int expected_line_number; EXPECT_TRUE(slic::internal::is_stream_empty()); constexpr int val = 42; diff --git a/src/axom/slic/tests/slic_macros_parallel.cpp b/src/axom/slic/tests/slic_macros_parallel.cpp index aa51833b81..a716895940 100644 --- a/src/axom/slic/tests/slic_macros_parallel.cpp +++ b/src/axom/slic/tests/slic_macros_parallel.cpp @@ -1216,7 +1216,7 @@ TEST_P(SlicMacrosParallel, test_abort_warning_macros) //------------------------------------------------------------------------------ TEST_P(SlicMacrosParallel, test_assert_macros) { - int expected_line_number; + [[maybe_unused]] int expected_line_number; slic::internal::clear_streams(); EXPECT_TRUE(slic::internal::are_all_streams_empty()); @@ -1288,7 +1288,7 @@ TEST_P(SlicMacrosParallel, test_assert_macros) // ------------------------------------------------------------------------------ TEST_P(SlicMacrosParallel, test_check_macros) { - int expected_line_number; + [[maybe_unused]] int expected_line_number; EXPECT_TRUE(slic::internal::are_all_streams_empty()); diff --git a/src/axom/spin/internal/linear_bvh/bvh_traverse.hpp b/src/axom/spin/internal/linear_bvh/bvh_traverse.hpp index 327520e00c..0efbc0eaff 100644 --- a/src/axom/spin/internal/linear_bvh/bvh_traverse.hpp +++ b/src/axom/spin/internal/linear_bvh/bvh_traverse.hpp @@ -12,12 +12,54 @@ #include "axom/core/Types.hpp" // for axom types #include "axom/slic.hpp" // for SLIC macros +#include // For template magic +#include + namespace axom { namespace spin { namespace internal { +/*! + * \brief Checks if provided InBinCheck can accept a third positional argument representing the + * index of `bvhBox` in the traverser's internal node list. + * + * This is necessary because typical usage of a BVH traverser requires no access to the internal + * node layout as implemented in LinearBVH, requiring a two-argument InBin predicate. + * However, `LinearBVHTraverser::reduce_tree` returns an array of values that are associated with + * each node, and a three-argument InBin predicate allows indexing into this array in the check. + * + * \sa quest::fast_approximate_winding_number + */ +template +AXOM_HOST_DEVICE inline bool invoke_InBinCheck(InBinCheck&& B, + PointType&& p, + BoxType&& bvhBox, + IndexType&& node_idx) +{ + // Case 1: InBinCheck is invokable as B( p, bvhBox, node_idx ) + if constexpr(std::is_invocable_v) + { + return std::forward(B)(std::forward(p), + std::forward(bvhBox), + std::forward(node_idx)); + } + // Case 2: InBinCheck is invokable as B( p, bvhBox ), which is more common + else if constexpr(std::is_invocable_v) + { + return std::forward(B)(std::forward(p), std::forward(bvhBox)); + } + // Case 3: Neither works + else + { + static_assert(std::is_invocable_v || + std::is_invocable_v, + "InBinCheck must be callable as B(p, bvhBox, node_idx) or B(p, bvhBox)"); + return false; + } +} + namespace linear_bvh { /*! @@ -93,8 +135,10 @@ AXOM_HOST_DEVICE inline void bvh_traverse( { BBoxType left_bin = inner_nodes[current_node + 0]; BBoxType right_bin = inner_nodes[current_node + 1]; - const bool in_left = left_bin.isValid() ? B(p, left_bin) : false; - const bool in_right = right_bin.isValid() ? B(p, right_bin) : false; + const bool in_left = + left_bin.isValid() ? invoke_InBinCheck(B, p, left_bin, current_node + 0) : false; + const bool in_right = + right_bin.isValid() ? invoke_InBinCheck(B, p, right_bin, current_node + 1) : false; std::int32_t l_child = inner_node_children[current_node + 0]; std::int32_t r_child = inner_node_children[current_node + 1]; bool swap = Comp(left_bin, right_bin, p); diff --git a/src/axom/spin/policy/LinearBVH.hpp b/src/axom/spin/policy/LinearBVH.hpp index d792d6944e..9c270953b6 100644 --- a/src/axom/spin/policy/LinearBVH.hpp +++ b/src/axom/spin/policy/LinearBVH.hpp @@ -38,18 +38,27 @@ namespace policy namespace lbvh = internal::linear_bvh; /* - * \brief Interface for traversing a BVH tree. + * \brief Interface for a BVH tree through a traversal operation (which + * searches a tree based on a user-provided predicate) or a reduce + * operation (which calculates a value at each node by adding its children). * * \brief Traverse a tree to perform user-specified actions at the * leaves, while limiting the search to branches satisfying a * user-provided predicate. - * - * To initiate traversals, use \a traverse_tree. It requires + * + * To initiate traversals, use \a traverse_tree. It requires * -# an action functor to call at the leaves, * -# a predicate functor to decide whether to descend a branch and * -# some data to pass to the functors + * + * \brief Reduce a tree by invoking a user-specified leaf action at + * each leaf node, then iterating up the tree so the value at each node + * is a sum of the value for its children. + * + * To initiate reductions, use \a reduce_tree. It requires + * -# an action functor to call at the leaves, * - * Both functors should only access memory that's available to the + * All functors should only access memory that's available to the * execution space. For example, GPU execution should access only * device and unified memory. * @@ -71,7 +80,9 @@ class LinearBVHTraverser { } template - AXOM_HOST_DEVICE void traverse_tree(const PointType& p, LeafAction&& lf, Predicate&& predicate) const + AXOM_HOST_DEVICE void traverse_tree(const PointType& p, + LeafAction&& leaf_action, + Predicate&& predicate) const { auto traversePref = [](const BoxType& l, const BoxType& r, const PointType& p) { double sqDistL = primal::squared_distance(p, l.getCentroid()); @@ -82,16 +93,24 @@ class LinearBVHTraverser return sqDistL > sqDistR; }; - lbvh::bvh_traverse(m_inner_nodes, m_inner_node_children, m_leaf_nodes, p, predicate, lf, traversePref); + lbvh::bvh_traverse(m_inner_nodes, + m_inner_node_children, + m_leaf_nodes, + p, + predicate, + leaf_action, + traversePref); } /* - * Functors \a lf and \a predicate should access only memory compatible + * Functors \a leaf_action and \a predicate should access only memory compatible * with the execution space. For example, GPU execution should access * only device and unified memory. */ template - AXOM_HOST_DEVICE void traverse_tree(const Primitive& p, LeafAction&& lf, Predicate&& predicate) const + AXOM_HOST_DEVICE void traverse_tree(const Primitive& p, + LeafAction&& leaf_action, + Predicate&& predicate) const { auto noTraversePref = [](const BoxType& l, const BoxType& r, const Primitive& p) { AXOM_UNUSED_VAR(l); @@ -100,10 +119,98 @@ class LinearBVHTraverser return false; }; - lbvh::bvh_traverse(m_inner_nodes, m_inner_node_children, m_leaf_nodes, p, predicate, lf, noTraversePref); + lbvh::bvh_traverse(m_inner_nodes, + m_inner_node_children, + m_leaf_nodes, + p, + predicate, + leaf_action, + noTraversePref); + } + + /*! + * \brief Iterate over the tree, invoking the leaf action at each leaf node to + * produce a value and then iterate back up the tree, combining nodes + * using a "+" reduction. Return the Array that contains values for + * all tree nodes. + * + * \param leaf_action The function to invoke on a leaf node to make its data. + * \param allocatorID The allocator to use to allocate array data. + * + * \return An Array that contains the reduced data for all nodes in the BVH. + */ + template + axom::Array reduce_tree(LeafAction&& leaf_action, + int allocatorID = axom::getDefaultAllocatorID()) const + { + // Make a field over all of the nodes (the return field). + axom::Array reducedField(m_inner_nodes.size(), m_inner_nodes.size(), allocatorID); + + if constexpr(std::is_same_v) + { + reduce_recursion(std::forward(leaf_action), reducedField.view(), 0); + reduce_recursion(std::forward(leaf_action), reducedField.view(), 1); + } + else + { + // Do it in 2 stages. + + // Make a field for just the leaf data. Compute it in parallel. + axom::Array leafField(m_leaf_nodes.size(), m_leaf_nodes.size(), allocatorID); + auto leafFieldView = leafField.view(); + const std::int32_t* leaf_nodes_data = m_leaf_nodes.data(); + axom::for_all(m_leaf_nodes.size(), [&](axom::IndexType currentNode) { + const auto idx = leaf_nodes_data[currentNode]; + leafFieldView[idx] = leaf_action(static_cast(currentNode), leaf_nodes_data); + }); + + // Return the precomputed values in the reduction. + auto returnLeafValue = + AXOM_LAMBDA(std::int32_t currentNode, const std::int32_t* leafNodes)->ValueType + { + const auto idx = leafNodes[currentNode]; + return leafFieldView[idx]; + }; + + // TODO: Replace this with GPU-compatible code. + reduce_recursion(returnLeafValue, reducedField.view(), 0); + reduce_recursion(returnLeafValue, reducedField.view(), 1); + } + + return reducedField; } private: + /*! + * \brief This is a helper method used in reduce_tree. + * + * \param leaf_action The function to invoke on a leaf node to make its data. + * \param node_data The view that contains the traversal order for leaf nodes. + * \param current_node The current node. + */ + template + void reduce_recursion(LeafAction&& leaf_action, + axom::ArrayView node_data, + std::int32_t current_node) const + { + auto child_index = m_inner_node_children[current_node]; + + // Check if node is a leaf + if(child_index < 0) + { + node_data[current_node] = leaf_action(-child_index - 1, m_leaf_nodes.data()); + + return; + } + + // Populate children + reduce_recursion(std::forward(leaf_action), node_data, child_index + 0); + reduce_recursion(std::forward(leaf_action), node_data, child_index + 1); + + // Sum to get value for current node + node_data[current_node] = node_data[child_index + 0] + node_data[child_index + 1]; + } + axom::ArrayView m_inner_nodes; // BVH bins including leafs axom::ArrayView m_inner_node_children; axom::ArrayView m_leaf_nodes; // leaf data diff --git a/src/axom/spin/tests/spin_bvh.cpp b/src/axom/spin/tests/spin_bvh.cpp index 236f39510d..bb459c9bdf 100644 --- a/src/axom/spin/tests/spin_bvh.cpp +++ b/src/axom/spin/tests/spin_bvh.cpp @@ -1554,6 +1554,89 @@ void check_0_or_1_bbox_2d() bvh_compute_point_distances_2d(bvh2, src_pts, query_pts, true); } +//------------------------------------------------------------------------------ +/*! + * \brief Tests LinearBVHTraverser::reduce_tree by reducing across BVH of points + * a field that counts how many points are contained in each node. + * + * For a BVH with N leaves, LinearBVH stores 2*(N-1) "node slots" in its + * internal representation. Exactly N of those slots correspond to leaf nodes. + * When each leaf contributes 1, internal nodes must reduce to a value > 1. + */ +template +void check_reduce_tree_point_counts_2d() +{ + constexpr int NDIMS = 2; + + using BVHType = spin::BVH; + using BoxType = typename BVHType::BoxType; + using PointType = typename BVHType::PointType; + using CountType = axom::IndexType; + + const int hostAllocatorID = axom::execution_space::allocatorID(); + const int execAllocatorID = axom::execution_space::allocatorID(); + + // Build a deterministic set of distinct points. + constexpr axom::IndexType NX = 8; + constexpr axom::IndexType NY = 8; + constexpr axom::IndexType NPTS = NX * NY; + + axom::Array bboxes(NPTS, NPTS, hostAllocatorID); + axom::IndexType idx = 0; + for(axom::IndexType j = 0; j < NY; ++j) + { + for(axom::IndexType i = 0; i < NX; ++i, ++idx) + { + const auto x = static_cast(i) + static_cast(0.25); + const auto y = static_cast(j) + static_cast(0.75); + bboxes[idx] = BoxType(PointType {x, y}); + } + } + EXPECT_EQ(idx, NPTS); + + // Copy boxes to the execution space allocator and build the BVH. + axom::Array bboxes_exec(bboxes, execAllocatorID); + BVHType bvh; + bvh.setScaleFactor(1.0); + bvh.initialize(bboxes_exec.view(), NPTS); + + // Reduce the BVH into a field that counts points per node. + const auto traverser = bvh.getTraverser(); + auto leafToOne = AXOM_LAMBDA(std::int32_t, const std::int32_t*)->CountType + { + return static_cast(1); + }; + + axom::Array counts = + traverser.template reduce_tree(leafToOne, hostAllocatorID); + + // For a BVH with N leaves, LinearBVH stores 2*(N-1) node slots. + ASSERT_EQ(counts.size(), static_cast(2 * (NPTS - 1))); + + // The implicit root's children live at indices 0 and 1. + ASSERT_EQ(counts[0] + counts[1], NPTS); + + // Each node should have a count between 1 and N, and a power of 2 + axom::IndexType nleaf_nodes = 0; + for(axom::IndexType n = 0; n < counts.size(); ++n) + { + EXPECT_GE(counts[n], 1); + EXPECT_LE(counts[n], NPTS); + + if(counts[n] == 1) + { + ++nleaf_nodes; + } + else + { + EXPECT_EQ(counts[n] % 2, 0); + } + } + + // There should be exactly N leaf nodes. + EXPECT_EQ(nleaf_nodes, NPTS); +} + } /* end unnamed namespace */ //------------------------------------------------------------------------------ @@ -1670,6 +1753,13 @@ TEST(spin_bvh, single_bbox_sequential) check_0_or_1_bbox_2d(); } +//------------------------------------------------------------------------------ +TEST(spin_bvh, reduce_tree_point_counts_sequential) +{ + check_reduce_tree_point_counts_2d(); + check_reduce_tree_point_counts_2d(); +} + //------------------------------------------------------------------------------ #if defined(AXOM_USE_OPENMP) && defined(AXOM_USE_RAJA) @@ -1759,6 +1849,13 @@ TEST(spin_bvh, single_bbox_omp) check_0_or_1_bbox_2d(); } +//------------------------------------------------------------------------------ +TEST(spin_bvh, reduce_tree_point_counts_omp) +{ + check_reduce_tree_point_counts_2d(); + check_reduce_tree_point_counts_2d(); +} + #endif //------------------------------------------------------------------------------ diff --git a/src/cmake/AxomMacros.cmake b/src/cmake/AxomMacros.cmake index b6026fe110..192277fed0 100644 --- a/src/cmake/AxomMacros.cmake +++ b/src/cmake/AxomMacros.cmake @@ -34,7 +34,7 @@ macro(axom_add_code_checks) set(_base_dirs "axom" "examples" "thirdparty/tests" "tools") set(_ext_expressions "*.cpp" "*.hpp" "*.inl" "*.cxx" "*.hxx" "*.cc" "*.c" "*.h" "*.hh" - "*.F" "*.f" "*.f90" "*.F90") + "*.F" "*.f" "*.f90" "*.F90" "*.py") set(_glob_expressions) foreach(_exp ${_ext_expressions}) @@ -59,10 +59,11 @@ macro(axom_add_code_checks) blt_add_code_checks(PREFIX axom SOURCES ${_sources} CLANGFORMAT_CFG_FILE ${PROJECT_SOURCE_DIR}/.clang-format + YAPF_CFG_FILE ${PROJECT_SOURCE_DIR}/.style.yapf CPPCHECK_FLAGS --enable=all --inconclusive) # Set FOLDER property for code check targets - foreach(_suffix clangformat_check clangformat_style clang_tidy_check clang_tidy_style) + foreach(_suffix clangformat_check clangformat_style clang_tidy_check clang_tidy_style yapf_check yapf_style) set(_tgt ${arg_PREFIX}_${_suffix}) if(TARGET ${_tgt}) set_target_properties(${_tgt} PROPERTIES FOLDER "axom/code_checks") @@ -564,3 +565,50 @@ macro(axom_configure_file _source _target) execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different ${_tmp_target} ${_target}) execute_process(COMMAND ${CMAKE_COMMAND} -E remove ${_tmp_target}) endmacro(axom_configure_file) + +##------------------------------------------------------------------------------ +## axom_add_python_test(NAME [name] +## SOURCE [source] +## OUTPUT_DIR [dir]) +## +## Wrapper around add_test() that handles functionality +## that Axom applies to all python tests. +##------------------------------------------------------------------------------ +macro(axom_add_python_test) + + set(options) + set(singleValueArgs NAME SOURCE OUTPUT_DIR) + set(multiValueArgs) + + # Parse the arguments to the macro + cmake_parse_arguments(arg + "${options}" "${singleValueArgs}" "${multiValueArgs}" ${ARGN}) + + # Copy python test file to build + axom_configure_file ("${arg_SOURCE}" + "${arg_OUTPUT_DIR}/${arg_SOURCE}" COPYONLY) + + # Run unit test with pytest ("python3 -m pytest"). + # Use convenience script that has + # pytest, pysidre, and conduit added to PYTHONPATH. + # "-p no:cacheprovider" disables caching. + add_test (NAME ${arg_NAME} + COMMAND ${PROJECT_BINARY_DIR}/bin/run_python_with_axom.sh -m pytest -s -p no:cacheprovider ${arg_OUTPUT_DIR}/${arg_SOURCE} + ) + +endmacro(axom_add_python_test) + +##------------------------------------------------------------------------------ +## axom_force_release_for_target +## +## This macro forces a target to be compiled in Release mode by adding compiler +## optimization flags. +##------------------------------------------------------------------------------ +macro(axom_force_release_for_target tgt) + if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + target_compile_options(${tgt} PRIVATE /O2) + else() + target_compile_options(${tgt} PRIVATE -O3 -g0) + endif() + target_compile_definitions(${tgt} PRIVATE NDEBUG) +endmacro(axom_force_release_for_target) diff --git a/src/cmake/AxomVersion.cmake b/src/cmake/AxomVersion.cmake index 5fde962a1b..a92594402c 100644 --- a/src/cmake/AxomVersion.cmake +++ b/src/cmake/AxomVersion.cmake @@ -10,7 +10,7 @@ # otherwise, the hard-coded values will go in to the config. #------------------------------------------------------------------------------ set(AXOM_VERSION_MAJOR 0) -set(AXOM_VERSION_MINOR 13) +set(AXOM_VERSION_MINOR 14) set(AXOM_VERSION_PATCH 0) string(CONCAT AXOM_VERSION_FULL "v${AXOM_VERSION_MAJOR}" diff --git a/src/cmake/thirdparty/SetupAxomThirdParty.cmake b/src/cmake/thirdparty/SetupAxomThirdParty.cmake index 7c06f67823..e063779f94 100644 --- a/src/cmake/thirdparty/SetupAxomThirdParty.cmake +++ b/src/cmake/thirdparty/SetupAxomThirdParty.cmake @@ -311,19 +311,55 @@ if(EXISTS ${Python_EXECUTABLE}) message(STATUS "Python include dir: ${Python_INCLUDE_DIRS}") message(STATUS "Python library: ${Python_LIBRARIES}") - # Check for nanobind package + # Check for just nanobind package execute_process( - COMMAND "${Python_EXECUTABLE}" -c "import nanobind" - RESULT_VARIABLE NANOBIND_IMPORT_CODE - OUTPUT_QUIET + COMMAND "${CMAKE_COMMAND}" -E env + "PYTHONPATH=$ENV{PYTHONPATH}:${PY_NANOBIND_DIR}" + "${Python_EXECUTABLE}" -c "import nanobind" + RESULT_VARIABLE NANOBIND_IMPORT_CODE + OUTPUT_QUIET ) # Get nanobind root directory if(NANOBIND_IMPORT_CODE EQUAL 0) execute_process( - COMMAND "${Python_EXECUTABLE}" -m nanobind --cmake_dir - OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE nanobind_ROOT) + COMMAND "${CMAKE_COMMAND}" -E env + "PYTHONPATH=$ENV{PYTHONPATH}:${PY_NANOBIND_DIR}" + "${Python_EXECUTABLE}" -m nanobind --cmake_dir + OUTPUT_VARIABLE nanobind_ROOT + OUTPUT_STRIP_TRAILING_WHITESPACE + ) endif() + + # Check if python environment potentially contains all + # required dependencies + execute_process( + COMMAND "${CMAKE_COMMAND}" -E env + "${Python_EXECUTABLE}" -c "import nanobind, conduit, numpy, pytest" + RESULT_VARIABLE PY_ENV_IMPORT_CODE + OUTPUT_QUIET + ERROR_QUIET + ) +endif() + +# If python environment does not contain required modules, check if +# library installation paths were provided instead. +if((NOT PY_ENV_IMPORT_CODE EQUAL 0) + AND + nanobind_ROOT + AND + (NOT PY_NANOBIND_DIR + OR NOT CONDUIT_PYTHON_MODULE_DIR + OR NOT PY_NUMPY_DIR + OR NOT PY_PYTEST_DIR + OR NOT PY_PLUGGY_DIR + OR NOT PY_INICONFIG_DIR)) + message(FATAL_ERROR + "Axom's python extensions require nanobind, numpy, pytest, and conduit." + "\nThe python library installation paths " + "(and pytest's dependencies pluggy and iniconfig) " + "can be specified with CMake variables: " + "PY_NANOBIND_DIR, CONDUIT_PYTHON_MODULE_DIR, PY_NUMPY_DIR, PY_PYTEST_DIR, PY_PLUGGY_DIR, PY_INICONFIG_DIR ") endif() # "cannot allocate memory in static TLS block" on blueos with cuda and/or clang. diff --git a/src/docs/dependencies.dot b/src/docs/dependencies.dot index 9ae90f2992..33af56b39c 100644 --- a/src/docs/dependencies.dot +++ b/src/docs/dependencies.dot @@ -4,7 +4,7 @@ digraph dependencies { {inlet klee mint primal quest slam spin sidre} -> {slic core}; mint -> slam mint -> sidre [style="dashed"]; - mir -> {bump slic core slam primal}; + mir -> {bump sidre slic core slam primal}; multimat -> {slic slam}; spin -> {slam primal}; sina -> {core}; @@ -13,5 +13,5 @@ digraph dependencies { lumberjack -> core; inlet -> {sidre primal}; klee -> {sidre primal inlet}; - bump -> {core slic spin primal}; + bump -> {core sidre slic spin primal}; } diff --git a/src/docs/sphinx/dev_guide/release.rst b/src/docs/sphinx/dev_guide/release.rst index fd361f6fa0..59cc385336 100644 --- a/src/docs/sphinx/dev_guide/release.rst +++ b/src/docs/sphinx/dev_guide/release.rst @@ -175,6 +175,8 @@ the history. After merging, the release candidate branch can be deleted. extra files to put in the `data` directory only if you want to run certain Axom tests. +#. Click the checkbox at the bottom of the page that says "Set as the latest release". + #. Publish the release. This will create a tag at the tip of the main branch and add corresponding entry in the `Releases section `_ diff --git a/src/docs/sphinx/dev_guide/updating_tpls.rst b/src/docs/sphinx/dev_guide/updating_tpls.rst index 711d6fe9ef..f5990a8142 100644 --- a/src/docs/sphinx/dev_guide/updating_tpls.rst +++ b/src/docs/sphinx/dev_guide/updating_tpls.rst @@ -271,7 +271,7 @@ script to change the version number and any patches that need to be applied. The will clone the fmt library and attempt to apply existing patches and update them, if possible. If patches cannot be applied, then you will need to update them. This is best done by commenting out the "apply_patches" step and steps that follow it. Run the script to clone -the fmt repository. Next, make the same edits found in the various "*.patch" files to the +the fmt repository. Next, make the same edits found in the various "\*.patch" files to the files in the current directory. After editing a file, make a new patch: ``patch -u fmt/include/fmt/format.h format.h > format.h.patch`` (be sure to edit the filenames). Repeat this process until all of the relevant patches are updated. Note that newer versions diff --git a/src/examples/shaping_tutorial/lesson_04/visit_plot_circle.py b/src/examples/shaping_tutorial/lesson_04/visit_plot_circle.py index 53bf770215..247bf758d3 100644 --- a/src/examples/shaping_tutorial/lesson_04/visit_plot_circle.py +++ b/src/examples/shaping_tutorial/lesson_04/visit_plot_circle.py @@ -12,7 +12,7 @@ fb = GetPlotOptions() fb.SetMultiColor(0, (244, 204, 153, 255)) # void fb.SetMultiColor(1, (128, 128, 128, 255)) # steel -fb.SetMultiColor(2, (0, 0, 255, 255)) # free +fb.SetMultiColor(2, (0, 0, 255, 255)) # free SetPlotOptions(fb) mrc = MultiresControlAttributes() mrc.resolution = 10 @@ -72,8 +72,8 @@ # Turn off some annotations. annot = GetAnnotationAttributes() annot.databaseInfoFlag = 0 -annot.backgroundColor = (255,255,255,255) -annot.foregroundColor = (0,0,0,255) +annot.backgroundColor = (255, 255, 255, 255) +annot.foregroundColor = (0, 0, 0, 255) annot.backgroundMode = annot.Solid annot.userInfoFlag = 0 SetAnnotationAttributes(annot) diff --git a/src/examples/shaping_tutorial/lesson_04/visit_plot_ice_cream.py b/src/examples/shaping_tutorial/lesson_04/visit_plot_ice_cream.py index 21a9b739e5..f3b56844de 100644 --- a/src/examples/shaping_tutorial/lesson_04/visit_plot_ice_cream.py +++ b/src/examples/shaping_tutorial/lesson_04/visit_plot_ice_cream.py @@ -11,9 +11,9 @@ AddOperator("MultiresControl", 0) fb = GetPlotOptions() fb.SetMultiColor(0, (255, 254, 246, 255)) # air -fb.SetMultiColor(1, (170, 103, 89, 255)) # batter +fb.SetMultiColor(1, (170, 103, 89, 255)) # batter fb.SetMultiColor(2, (255, 153, 204, 255)) # icecream -fb.SetMultiColor(3, (255, 0, 0, 255)) # sprinkles +fb.SetMultiColor(3, (255, 0, 0, 255)) # sprinkles fb.SetMultiColor(4, (255, 255, 255, 255)) # free SetPlotOptions(fb) @@ -29,8 +29,8 @@ # Set the annotations. annot = GetAnnotationAttributes() annot.databaseInfoFlag = 0 -annot.backgroundColor = (255,255,255,255) -annot.foregroundColor = (0,0,0,255) +annot.backgroundColor = (255, 255, 255, 255) +annot.foregroundColor = (0, 0, 0, 255) annot.backgroundMode = annot.Solid annot.userInfoFlag = 0 SetAnnotationAttributes(annot) diff --git a/src/examples/using-with-blt/CMakeLists.txt b/src/examples/using-with-blt/CMakeLists.txt index cfe8d46fcc..6fb0884d9f 100644 --- a/src/examples/using-with-blt/CMakeLists.txt +++ b/src/examples/using-with-blt/CMakeLists.txt @@ -64,6 +64,10 @@ if(ENABLE_HIP) set(example_depends ${example_depends} blt::hip) endif () +if(ENABLE_CUDA) + set(example_depends ${example_depends} blt::cuda) +endif () + blt_add_executable(NAME example SOURCES example.cpp DEPENDS_ON ${example_depends}) diff --git a/src/examples/using-with-cmake/CMakeLists.txt b/src/examples/using-with-cmake/CMakeLists.txt index 9fd30d2ae0..85fb26aa3a 100644 --- a/src/examples/using-with-cmake/CMakeLists.txt +++ b/src/examples/using-with-cmake/CMakeLists.txt @@ -74,6 +74,11 @@ if (ENABLE_HIP) set_source_files_properties(example.cpp PROPERTIES LANGUAGE HIP) endif() +# Compile as CUDA source if enabled +if (ENABLE_CUDA) + set_source_files_properties(example.cpp PROPERTIES LANGUAGE CUDA) +endif() + # setup the axom include path target_include_directories(example PRIVATE ${AXOM_INCLUDE_DIRS}) diff --git a/src/examples/using-with-cmake/host-config.cmake.in b/src/examples/using-with-cmake/host-config.cmake.in index 055e3a577f..aafda9484f 100644 --- a/src/examples/using-with-cmake/host-config.cmake.in +++ b/src/examples/using-with-cmake/host-config.cmake.in @@ -49,6 +49,7 @@ endif() set(ENABLE_HIP @ENABLE_HIP@ CACHE BOOL "") if(ENABLE_HIP) + set(CMAKE_PREFIX_PATH "@ROCM_PATH@" CACHE STRING "") set(CMAKE_HIP_COMPILER "@CMAKE_HIP_COMPILER@" CACHE PATH "") set(ROCM_PATH "@ROCM_PATH@" CACHE PATH "") set(ROCM_ROOT_DIR "@ROCM_ROOT_DIR@" CACHE PATH "") diff --git a/src/index.rst b/src/index.rst index fa4f090bde..60995d9126 100644 --- a/src/index.rst +++ b/src/index.rst @@ -129,7 +129,7 @@ Component Level Dependencies Axom has the following inter-component dependencies: - Core has no dependencies and the other components depend on Core -- Bump depends on Slic and Primal. +- Bump depends on Sidre, Slic, Spin, and Primal. - Slic optionally depends on Lumberjack - Slam, Spin, Primal, Mint, Quest, and Sidre depend on Slic - Mint depends on Slam, and optionally Sidre diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt index 4e5e717666..dd44524aa9 100644 --- a/src/tools/CMakeLists.txt +++ b/src/tools/CMakeLists.txt @@ -208,10 +208,10 @@ if(NANOBIND_FOUND) unset(_PYEXT_DIR) - # Add unit test to check script + # Add smoke test to check script if(AXOM_ENABLE_TESTS AND AXOM_ENABLE_SIDRE) axom_add_test( NAME run_python_with_axom_build - COMMAND ${PROJECT_BINARY_DIR}/bin/run_python_with_axom.sh -c "import pysidre") + COMMAND ${PROJECT_BINARY_DIR}/bin/run_python_with_axom.sh -c "import pysidre, nanobind, conduit, numpy, pytest") endif() endif() diff --git a/src/tools/gen-multidom-structured-mesh.py b/src/tools/gen-multidom-structured-mesh.py index 3f649b0139..b41dc79f3a 100755 --- a/src/tools/gen-multidom-structured-mesh.py +++ b/src/tools/gen-multidom-structured-mesh.py @@ -4,42 +4,50 @@ # Write a simple multidomain structured blueprint mesh for testing. # This script requires a conduit installation configured with python3 and hdf5. -# Make sure PYTHONPATH includes /path/to/conduit/install/python-modules +# Make sure PYTHONPATH includes /path/to/conduit/install/python-modules, +# or use Axom's convenience script /path/to/axom_build_dir/bin/run_python_with_axom.sh +# that includes Conduit in PYTHONPATH. try: - import conduit - import conduit.blueprint - import conduit.relay + import conduit + import conduit.blueprint + import conduit.relay except ModuleNotFoundError as e: - print(f'{e}\nMake sure your PYTHONPATH includes /path/to/conduit/install/python-modules\nConduit must be configured with python and hdf5.') - exit(-1) + print( + f'{e}\nMake sure your PYTHONPATH includes /path/to/conduit/install/python-modules\nConduit must be configured with python and hdf5.\nAlternatively, you can use the convenience script\n/path/to/axom_build_dir/bin/run_python_with_axom.sh\nthat includes Conduit in PYTHONPATH.' + ) + exit(-1) import numpy as np + def i_c(s): - '''Convert comma-separated string to list of integers.''' - return list(map(int, s.split(','))) + '''Convert comma-separated string to list of integers.''' + return list(map(int, s.split(','))) + def f_c(s): - '''Convert comma-separated string to list of floating point numbers.''' - return list(map(float, s.split(','))) + '''Convert comma-separated string to list of floating point numbers.''' + return list(map(float, s.split(','))) + from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter + ps = ArgumentParser(description='Write a blueprint strided-unstructured mesh.', formatter_class=ArgumentDefaultsHelpFormatter) ps.add_argument('--useList', action='store_true', help='Put domains in a list instead of a map') -ps.add_argument('-ml', type=f_c, default=(0.,0.), help='Mesh lower coordinates') -ps.add_argument('-mu', type=f_c, default=(1.,1.), help='Mesh upper coordinates') -ps.add_argument('-ms', type=i_c, default=(3,3), help='Logical size of mesh (cells)') -ps.add_argument('-dc', type=i_c, default=(1,1), help='Domain counts in each index direction') +ps.add_argument('-ml', type=f_c, default=(0., 0.), help='Mesh lower coordinates') +ps.add_argument('-mu', type=f_c, default=(1., 1.), help='Mesh upper coordinates') +ps.add_argument('-ms', type=i_c, default=(3, 3), help='Logical size of mesh (cells)') +ps.add_argument('-dc', type=i_c, default=(1, 1), help='Domain counts in each index direction') ps.add_argument('-o', '--output', type=str, default='mdmesh', help='Output file base name') ps.add_argument('--strided', action='store_true', help='Use strided_structured (has ghosts)') ps.add_argument('-v', '--verbose', action='store_true', help='Print additional info') -opts,unkn = ps.parse_known_args() -if(opts.verbose): print(opts, unkn) -if(unkn): - print("Unrecognized arguments:", *unkn) - quit(1) +opts, unkn = ps.parse_known_args() +if (opts.verbose): print(opts, unkn) +if (unkn): + print("Unrecognized arguments:", *unkn) + quit(1) dim = len(opts.dc) @@ -47,69 +55,71 @@ def f_c(s): or len(opts.ms) != dim \ or len(opts.ml) != dim \ or len(opts.mu) != dim: - raise RuntimeError('dc, ms, ml and mu options must have the same dimensions (2 or 3)') + raise RuntimeError('dc, ms, ml and mu options must have the same dimensions (2 or 3)') # Must have enough cells for requested partitioning. goodDc = [opts.ms[i] >= opts.dc[i] for i in range(dim)] if sum(goodDc) < dim: - raise RuntimeError(f'ms ({opts.ms}) must be >= dc ({opts.dc}) in all directions.') + raise RuntimeError(f'ms ({opts.ms}) must be >= dc ({opts.dc}) in all directions.') # Number of phony nodes on left and right sides, for strided option if opts.strided: - npnl, npnr = 2, 1 + npnl, npnr = 2, 1 else: - npnl, npnr = 0, 0 + npnl, npnr = 0, 0 + def scale_structured_domain(n, startCoord, endCoord): - '''This function scales and shifts a blueprint structured domain after + '''This function scales and shifts a blueprint structured domain after it has been created. There's no way to specify the physical extent of a domain using conduit.blueprint.mesh.examples methods, as far as I can tell. ''' - #print(f'Rescaling to {startCoord} -> {endCoord}') - - ndim = n['coordsets/coords/values'].number_of_children() - - domLens = n['topologies/mesh/elements/dims'] - dirs = 'ij' if ndim == 2 else 'ijk' - domLens = [ domLens[d] for d in dirs ] - domLens = np.array(domLens) - domPhysicalSize = np.array(endCoord) - np.array(startCoord) - #print(f'domLens={domLens} domPhysicalSize={domPhysicalSize}') - assert(n['topologies/mesh/type'] == 'structured') - assert(len(startCoord) >= ndim) - assert(len(domPhysicalSize) >= ndim) - - coordArrayLens = domLens + 1 + npnl + npnr - #print(f'coordArrayLens={coordArrayLens}') - - xyz = 'xyz' - for d in range(ndim): - coords = n['coordsets/coords/values'][d] - coords = np.reshape(coords, np.flip(coordArrayLens)) - - # realCoords excludes the ghost layers. - if ndim == 2: - if npnr == 0: - realCoords = coords[npnl:, npnl:] - else: - realCoords = coords[npnl:-npnr, npnl:-npnr] - else: - if npnr == 0: - realCoords = coords[npnl:, npnl:, npnl:] - else: - realCoords = coords[npnl:-npnr, npnl:-npnr, npnl:-npnr] - - minC, maxC = np.amin(realCoords), np.amax(realCoords) - curRange = maxC - minC - shift = startCoord[d] - minC - scale = domPhysicalSize[d]/curRange - coords = (coords - minC) * domPhysicalSize[d]/curRange + startCoord[d] - n['coordsets/coords/values'][xyz[d]] = coords + #print(f'Rescaling to {startCoord} -> {endCoord}') + + ndim = n['coordsets/coords/values'].number_of_children() + + domLens = n['topologies/mesh/elements/dims'] + dirs = 'ij' if ndim == 2 else 'ijk' + domLens = [domLens[d] for d in dirs] + domLens = np.array(domLens) + domPhysicalSize = np.array(endCoord) - np.array(startCoord) + #print(f'domLens={domLens} domPhysicalSize={domPhysicalSize}') + assert (n['topologies/mesh/type'] == 'structured') + assert (len(startCoord) >= ndim) + assert (len(domPhysicalSize) >= ndim) + + coordArrayLens = domLens + 1 + npnl + npnr + #print(f'coordArrayLens={coordArrayLens}') + + xyz = 'xyz' + for d in range(ndim): + coords = n['coordsets/coords/values'][d] + coords = np.reshape(coords, np.flip(coordArrayLens)) + + # realCoords excludes the ghost layers. + if ndim == 2: + if npnr == 0: + realCoords = coords[npnl:, npnl:] + else: + realCoords = coords[npnl:-npnr, npnl:-npnr] + else: + if npnr == 0: + realCoords = coords[npnl:, npnl:, npnl:] + else: + realCoords = coords[npnl:-npnr, npnl:-npnr, npnl:-npnr] + + minC, maxC = np.amin(realCoords), np.amax(realCoords) + curRange = maxC - minC + shift = startCoord[d] - minC + scale = domPhysicalSize[d] / curRange + coords = (coords - minC) * domPhysicalSize[d] / curRange + startCoord[d] + n['coordsets/coords/values'][xyz[d]] = coords + domType = 'structured' -domCounts = opts.dc if dim == 3 else (*opts.dc, 1) # domCounts must be length 3, even for 2D. +domCounts = opts.dc if dim == 3 else (*opts.dc, 1) # domCounts must be length 3, even for 2D. meshSize = opts.ms meshLower = opts.ml meshUpper = opts.mu @@ -120,71 +130,74 @@ def scale_structured_domain(n, startCoord, endCoord): meshLower = np.array(meshLower) meshUpper = np.array(meshUpper) -domPhysicalSize = (meshUpper - meshLower)/domCounts[:dim] -cellPhysicalSize = (meshUpper - meshLower)/meshSize +domPhysicalSize = (meshUpper - meshLower) / domCounts[:dim] +cellPhysicalSize = (meshUpper - meshLower) / meshSize -domSize = meshSize//domCounts[:dim] +domSize = meshSize // domCounts[:dim] domSizeRem = meshSize % domCounts[:dim] if opts.verbose: - print(f'meshSize={meshSize} cells, domCounts={domCounts[0:dim]}' - f' domSize={domSize} domSizeRem={domSizeRem}') + print(f'meshSize={meshSize} cells, domCounts={domCounts[0:dim]}' + f' domSize={domSize} domSizeRem={domSizeRem}') + def domain_index_begin(di, dj, dk=None): - '''Compute first cell index of the domain with multi-dimensional index (di, dj, dk).''' - ds = (di, dj) if dim == 2 else (di, dj, dk) - idx = np.array(ds) - std = domSize * ds - extra = np.where( idx < domSizeRem[:dim], idx, domSizeRem[:dim] ) - begin = std + extra - return begin + '''Compute first cell index of the domain with multi-dimensional index (di, dj, dk).''' + ds = (di, dj) if dim == 2 else (di, dj, dk) + idx = np.array(ds) + std = domSize * ds + extra = np.where(idx < domSizeRem[:dim], idx, domSizeRem[:dim]) + begin = std + extra + return begin + mdMesh = conduit.Node() for dk in range(domCounts[2]): - for dj in range(domCounts[1]): - for di in range(domCounts[0]): - if opts.useList: - dom = mdMesh.append() - else: - domName = f'domain_{di:1d}_{dj:1d}' - if len(opts.dc) == 3: domName += f'_{dk:1d}' - dom = mdMesh[domName] - - cellStart = domain_index_begin(di, dj, dk) - cellEnd = domain_index_begin(di+1, dj+1, dk+1 if dim == 3 else 0) - pointCounts = cellEnd - cellStart + 1 - #print(f'cellStart={cellStart} cellEnd={cellEnd} pointCounts={pointCounts}') - - elemExtents = (cellEnd - cellStart) + (npnl + npnr + 1) - vertExtents = np.array(pointCounts) + (npnl + npnr) - elemOffset = np.full(dim, npnl) - vertOffset = np.full(dim, npnl) - #print(f'\n{domName}: {cellStart} -> {cellEnd}') - - pointCounts3 = pointCounts if len(pointCounts) == 3 else (*pointCounts, 0) - if opts.strided: - desc = conduit.Node() - desc['vertex_data/shape'].set(vertExtents) - desc['vertex_data/origin'].set(vertOffset) - desc['element_data/shape'].set(elemExtents) - desc['element_data/origin'].set(elemOffset) - #print(f'\ndesc({di},{dj},{dk}):', end=''); print(desc) - conduit.blueprint.mesh.examples.strided_structured(desc, *pointCounts3, dom) - if dom.has_child("state"): dom.remove_child("state") - else: - conduit.blueprint.mesh.examples.basic(domType, *pointCounts3, dom) - - domLower = meshLower[:dim] + cellStart * cellPhysicalSize[:dim] - domUpper = meshLower[:dim] + cellEnd * cellPhysicalSize[:dim] - scale_structured_domain(dom, domLower, domUpper) - # if opts.verbose: print(f'Domain [{di},{dj},{dk}]: {dom}') + for dj in range(domCounts[1]): + for di in range(domCounts[0]): + if opts.useList: + dom = mdMesh.append() + else: + domName = f'domain_{di:1d}_{dj:1d}' + if len(opts.dc) == 3: domName += f'_{dk:1d}' + dom = mdMesh[domName] + + cellStart = domain_index_begin(di, dj, dk) + cellEnd = domain_index_begin(di + 1, dj + 1, dk + 1 if dim == 3 else 0) + pointCounts = cellEnd - cellStart + 1 + #print(f'cellStart={cellStart} cellEnd={cellEnd} pointCounts={pointCounts}') + + elemExtents = (cellEnd - cellStart) + (npnl + npnr + 1) + vertExtents = np.array(pointCounts) + (npnl + npnr) + elemOffset = np.full(dim, npnl) + vertOffset = np.full(dim, npnl) + #print(f'\n{domName}: {cellStart} -> {cellEnd}') + + pointCounts3 = pointCounts if len(pointCounts) == 3 else (*pointCounts, 0) + if opts.strided: + desc = conduit.Node() + desc['vertex_data/shape'].set(vertExtents) + desc['vertex_data/origin'].set(vertOffset) + desc['element_data/shape'].set(elemExtents) + desc['element_data/origin'].set(elemOffset) + #print(f'\ndesc({di},{dj},{dk}):', end=''); print(desc) + conduit.blueprint.mesh.examples.strided_structured(desc, *pointCounts3, dom) + if dom.has_child("state"): dom.remove_child("state") + else: + conduit.blueprint.mesh.examples.basic(domType, *pointCounts3, dom) + + domLower = meshLower[:dim] + cellStart * cellPhysicalSize[:dim] + domUpper = meshLower[:dim] + cellEnd * cellPhysicalSize[:dim] + scale_structured_domain(dom, domLower, domUpper) + # if opts.verbose: print(f'Domain [{di},{dj},{dk}]: {dom}') if opts.verbose: - print('mdMesh:'); print(mdMesh) + print('mdMesh:') + print(mdMesh) info = conduit.Node() if not conduit.blueprint.mesh.verify(mdMesh, info): - print("Mesh failed blueprint verification. Info:") - print(info) + print("Mesh failed blueprint verification. Info:") + print(info) conduit.relay.io.blueprint.save_mesh(mdMesh, opts.output, "hdf5") print(f'Wrote mesh {opts.output}') diff --git a/src/tools/run_python_with_axom.sh.in b/src/tools/run_python_with_axom.sh.in index def85ceff8..152e406ecc 100755 --- a/src/tools/run_python_with_axom.sh.in +++ b/src/tools/run_python_with_axom.sh.in @@ -10,4 +10,4 @@ ## Convenience script that runs python interpreter with Axom extension(s) in ## the PYTHONPATH. ##----------------------------------------------------------------------------- -env PYTHONPATH=$PYTHONPATH:@_PYEXT_DIR@ @Python_EXECUTABLE@ "$@" +env PYTHONPATH=@_PYEXT_DIR@:@CONDUIT_PYTHON_MODULE_DIR@:@PY_NANOBIND_DIR@:@PY_NUMPY_DIR@:@PY_PYTEST_DIR@:@PY_PLUGGY_DIR@:@PY_INICONFIG_DIR@:$PYTHONPATH @Python_EXECUTABLE@ "$@" diff --git a/src/tools/svg2contours/svg2contours.py b/src/tools/svg2contours/svg2contours.py index 241c1fa9b7..31ab1a8c0d 100755 --- a/src/tools/svg2contours/svg2contours.py +++ b/src/tools/svg2contours/svg2contours.py @@ -6,7 +6,6 @@ # files for dates and other details. # # SPDX-License-Identifier: (BSD-3-Clause) - """ file: svg2contours.py @@ -17,6 +16,7 @@ import sys import os +import json from svgpathtools import ( Document, Path, @@ -35,6 +35,51 @@ import argparse +def parse_viewbox(view_box: str): + """Parse an SVG viewBox attribute string. + + Returns a 4-tuple (min_x, min_y, width, height) as floats, or None if + view_box is not provided or is invalid. + """ + + if not view_box: + return None + + # SVG spec allows whitespace and/or comma separators. + parts = [p for p in re.split(r"[,\s]+", view_box.strip()) if p] + if len(parts) != 4: + return None + + try: + return tuple(map(float, parts)) + except Exception: + return None + + +def parse_svg_length(length: str): + """Parse an SVG length attribute and return its numeric value as a float. + + If the value is missing or expressed as a percentage, returns None. + Units (e.g. 'mm', 'px') are ignored and the leading numeric portion is used. + """ + + if not length: + return None + + length = length.strip() + if length.endswith("%"): + return None + + match = re.search(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?", length) + if not match: + return None + + try: + return float(match.group(0)) + except Exception: + return None + + def get_root_transform(doc: Document): """Create transform to convert 2D coordinate system from y pointing down to y pointing up""" @@ -48,26 +93,18 @@ def get_root_transform(doc: Document): tf = np.identity(3) # Prefer viewBox since it defines the internal user-coordinate system used by path data. - if viewBox: - try: - # SVG spec allows whitespace and/or comma separators. - parts = [p for p in re.split(r"[,\s]+", viewBox.strip()) if p] - if len(parts) == 4: - _, min_y, _, vb_height = map(float, parts) - tf[1, 1] = -1 - tf[1, 2] = 2.0 * min_y + vb_height - return tf - except Exception: - pass + parsed_viewbox = parse_viewbox(viewBox) + if parsed_viewbox is not None: + _, min_y, _, vb_height = parsed_viewbox + tf[1, 1] = -1 + tf[1, 2] = 2.0 * min_y + vb_height + return tf # Fallback to root height attribute when viewBox is unavailable/invalid. - if height and not height.endswith("%"): - match = re.search(r"[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?", height.strip()) - if match: - height_number = float(match.group(0)) - - tf[1, 1] = -1 - tf[1, 2] = height_number + height_number = parse_svg_length(height) + if height_number is not None: + tf[1, 1] = -1 + tf[1, 2] = height_number # Last-resort fallback: flip about y=0 when we cannot infer a reference height. if tf[1, 1] == 1: @@ -209,7 +246,7 @@ def dist_to_ellipse(center, radius, angle, pt): rot = np.exp(-1j * np.radians(angle)) transformed_pt = rot * complex(pt.real - cx, pt.imag - cy) - return transformed_pt.real**2 / rx**2 + transformed_pt.imag**2 / ry**2 - 1 + return transformed_pt.real ** 2 / rx ** 2 + transformed_pt.imag ** 2 / ry ** 2 - 1 class MFEMData: @@ -239,30 +276,30 @@ def add_cubic_bezier(self, cubic, weights, attrib): self.knots.append("3 4 0 0 0 0 1 1 1 1") self.wgts_ends.append(f"{weights[0]} {weights[3]}") self.wgts_ints.append(f"{weights[2]} {weights[1]}") - self.dof_ends.append(" ".join(map(str, [cubic.start.real, cubic.start.imag, cubic.end.real, cubic.end.imag]))) - self.dof_ints.append( - " ".join(map(str, [cubic.control2.real, cubic.control2.imag, cubic.control1.real, cubic.control1.imag])) - ) + self.dof_ends.append(" ".join( + map(str, [cubic.start.real, cubic.start.imag, cubic.end.real, cubic.end.imag]))) + self.dof_ints.append(" ".join( + map(str, [ + cubic.control2.real, cubic.control2.imag, cubic.control1.real, cubic.control1.imag + ]))) def write_file(self, filename): mfem_file = [] - mfem_file.extend( - [ - "MFEM NURBS mesh v1.0", - "", - "# MFEM Geometry Types (see fem/geom.hpp):", - "#", - "# SEGMENT = 1 | SQUARE = 3 | CUBE = 5", - "#", - "# element: 1 ", - "# edge: 0 1 <-- idx increases by one each time", - "# knotvector: [knots]; sizeof(knots) is 1+order+num_ctrl_pts", - "# weights: array of weights corresponding to the NURBS element", - "# FES: list of control points; vertex control points at top, then interior control points", - "", - ] - ) + mfem_file.extend([ + "MFEM NURBS mesh v1.0", + "", + "# MFEM Geometry Types (see fem/geom.hpp):", + "#", + "# SEGMENT = 1 | SQUARE = 3 | CUBE = 5", + "#", + "# element: 1 ", + "# edge: 0 1 <-- idx increases by one each time", + "# knotvector: [knots]; sizeof(knots) is 1+order+num_ctrl_pts", + "# weights: array of weights corresponding to the NURBS element", + "# FES: list of control points; vertex control points at top, then interior control points", + "", + ]) mfem_file.extend(["dimension", "1", ""]) @@ -278,26 +315,51 @@ def write_file(self, filename): mfem_file.extend(["weights", "\n".join(self.wgts_ends), "\n".join(self.wgts_ints), ""]) - mfem_file.extend( - [ - "FiniteElementSpace", - "FiniteElementCollection: NURBS", - "VDim: 2", - "Ordering: 1", - "", - "\n".join(self.dof_ends), - "\n".join(self.dof_ints), - "", - ] - ) + mfem_file.extend([ + "FiniteElementSpace", + "FiniteElementCollection: NURBS", + "VDim: 2", + "Ordering: 1", + "", + "\n".join(self.dof_ends), + "\n".join(self.dof_ints), + "", + ]) with open(filename, mode="w") as f: f.write("\n".join(mfem_file)) +def compute_svg_path_stats(paths): + stats = { + "paths_total": len(paths), + "curves_order_1": 0, + "curves_order_2": 0, + "curves_order_3": 0, + "elliptical_arcs": 0, + "unknown_segments": 0, + } + + for p in paths: + for seg in p: + if isinstance(seg, Line): + stats["curves_order_1"] += 1 + elif isinstance(seg, QuadraticBezier): + stats["curves_order_2"] += 1 + elif isinstance(seg, CubicBezier): + stats["curves_order_3"] += 1 + elif isinstance(seg, Arc): + stats["elliptical_arcs"] += 1 + else: + stats["unknown_segments"] += 1 + + return stats + + def parse_args(): - parser = argparse.ArgumentParser(description="svg2contours: Convert the curves in an SVG to MFEM NURBS mesh") + parser = argparse.ArgumentParser( + description="svg2contours: Convert the curves in an SVG to MFEM NURBS mesh") parser.add_argument( "-i", @@ -317,12 +379,29 @@ def parse_args(): ) parser.add_argument( - "-r", "--reverse", dest="reverse_paths", default=False, action="store_true", - help="reverses paths (can be helpful during coordinate system transformation from y-axis pointing down to up)" + "--stats", + dest="statsfile", + default=None, + help="Optional output JSON file with SVG curve statistics (use '-' for stdout)", ) parser.add_argument( - "-v", "--verbose", dest="verbose", default=False, action="store_true", help="verbose output flag" + "-r", + "--reverse", + dest="reverse_paths", + default=False, + action="store_true", + help= + "reverses paths (can be helpful during coordinate system transformation from y-axis pointing down to up)", + ) + + parser.add_argument( + "-v", + "--verbose", + dest="verbose", + default=False, + action="store_true", + help="verbose output flag", ) opts = parser.parse_args() @@ -350,6 +429,40 @@ def main(): coordinate_transform = get_root_transform(doc) + ## Optionally, generate a json file w/ stats about the number of curves/paths + stats_file = opts.get("statsfile", None) + if stats_file: + stats = compute_svg_path_stats(paths) + stats["input_svg"] = os.path.relpath(input_file, os.getcwd()) + + root_attr = doc.tree.getroot().attrib + parsed_viewbox = parse_viewbox(root_attr.get("viewBox", None)) + if parsed_viewbox is not None: + min_x, min_y, vb_width, vb_height = parsed_viewbox + stats["bounding_box"] = { + "min_x": min_x, + "min_y": min_y, + "max_x": min_x + vb_width, + "max_y": min_y + vb_height, + } + else: + width_number = parse_svg_length(root_attr.get("width", None)) + height_number = parse_svg_length(root_attr.get("height", None)) + if width_number is not None and height_number is not None: + stats["bounding_box"] = { + "min_x": 0.0, + "min_y": 0.0, + "max_x": width_number, + "max_y": height_number, + } + + stats_json = json.dumps(stats, indent=2, sort_keys=True) + if stats_file == "-": + print(stats_json) + else: + with open(stats_file, mode="w", encoding="utf-8") as f: + f.write(stats_json + "\n") + ## Process SVG paths if verbose: print("SVG paths: \n", paths) @@ -392,7 +505,9 @@ def main(): output_file = opts["outputfile"] mfem_data.write_file(output_file) - print(f"Wrote '{output_file}' with {mfem_data.vert_cnt} vertices and NURBS {mfem_data.elem_cnt} elements") + print( + f"Wrote '{output_file}' with {mfem_data.vert_cnt} vertices and NURBS {mfem_data.elem_cnt} elements" + ) if __name__ == "__main__":