Compare commits
117
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b86fb5308a | ||
|
|
4463d921f6 | ||
|
|
20c657559d | ||
|
|
7a999efb0d | ||
|
|
442ac18b65 | ||
|
|
5097a44411 | ||
|
|
e84fef4191 | ||
|
|
64ef39bbe6 | ||
|
|
ec39b3509c | ||
|
|
399d8e1e9b | ||
|
|
10dbed9658 | ||
|
|
f09a062c04 | ||
|
|
0c97d6f375 | ||
|
|
aed9c8ef4a | ||
|
|
e4e85e28ef | ||
|
|
fff973f192 | ||
|
|
775f06c43b | ||
|
|
18ff1d8289 | ||
|
|
5a0962c674 | ||
|
|
0d999709e6 | ||
|
|
c2649eb998 | ||
|
|
a1ce49fb57 | ||
|
|
f58cfc8170 | ||
|
|
6c837d2954 | ||
|
|
5b37c3b595 | ||
|
|
e49f9f7988 | ||
|
|
7c36b55628 | ||
|
|
faa73ef554 | ||
|
|
ecb6b06aa0 | ||
|
|
af4649a088 | ||
|
|
a9f58f3982 | ||
|
|
6de6675783 | ||
|
|
085ee02a29 | ||
|
|
9a124335a7 | ||
|
|
91d5e490aa | ||
|
|
dd931b2584 | ||
|
|
8a42ea2834 | ||
|
|
24e5d5fc0a | ||
|
|
6722dd7a70 | ||
|
|
cb862cbfa1 | ||
|
|
f7445844ba | ||
|
|
672e2a442b | ||
|
|
416536eb9d | ||
|
|
f557e348da | ||
|
|
881598e5da | ||
|
|
564b7ab4ec | ||
|
|
3f2f925400 | ||
|
|
463e34dc7f | ||
|
|
9a456b908e | ||
|
|
616839388a | ||
|
|
2fda3db982 | ||
|
|
4823a33a6a | ||
|
|
a96319e0be | ||
|
|
5f4283f512 | ||
|
|
8735d28561 | ||
|
|
a10c7a943b | ||
|
|
96eff4684f | ||
|
|
b6255fc825 | ||
|
|
18d27f6ffb | ||
|
|
7bfb57ef17 | ||
|
|
ab394d795e | ||
|
|
cad9cc4c82 | ||
|
|
4dc741ca48 | ||
|
|
918eb114d3 | ||
|
|
3341acf0f7 | ||
|
|
287cb24d0a | ||
|
|
70370b6241 | ||
|
|
ea291fb157 | ||
|
|
fce4ae7bb0 | ||
|
|
ef44f047aa | ||
|
|
ae002f7369 | ||
|
|
e4cd3f9e18 | ||
|
|
abdcf82d70 | ||
|
|
ad93d526b7 | ||
|
|
87c1a5cb77 | ||
|
|
89ad250940 | ||
|
|
d5dec97d23 | ||
|
|
2d401bcb74 | ||
|
|
4f383f4b19 | ||
|
|
7f35ecb8f5 | ||
|
|
9e4d9799dc | ||
|
|
ac4e558164 | ||
|
|
691cd8a687 | ||
|
|
cdc327a511 | ||
|
|
0d2e8f93e6 | ||
|
|
47c9ad2e34 | ||
|
|
ed862050b2 | ||
|
|
3c6c1eb634 | ||
|
|
22851a9463 | ||
|
|
38df8156b9 | ||
|
|
542467fd6a | ||
|
|
5986542e3d | ||
|
|
5163313285 | ||
|
|
2201f3354a | ||
|
|
f5b03af9d6 | ||
|
|
80c7823ac7 | ||
|
|
a443f003bb | ||
|
|
1730b05078 | ||
|
|
8a522f5e7d | ||
|
|
fcbd105b82 | ||
|
|
b82dcf1387 | ||
|
|
d3471aef59 | ||
|
|
822555df0b | ||
|
|
4626d65ac1 | ||
|
|
38a80ea0e4 | ||
|
|
590f954d6f | ||
|
|
bc5fc2b0f3 | ||
|
|
0f78d8aa5c | ||
|
|
3f98aa1cfb | ||
|
|
feecd75ff3 | ||
|
|
248bdcc149 | ||
|
|
e4e354834d | ||
|
|
d64a6d6255 | ||
|
|
510387a605 | ||
|
|
e99b2a8410 | ||
|
|
6608111315 | ||
|
|
b7253275fc |
@@ -25,7 +25,7 @@ runs:
|
||||
steps:
|
||||
- uses: ./.github/actions/sanitize/config
|
||||
|
||||
- uses: actions/cache@v4
|
||||
- uses: actions/cache@v5
|
||||
if: ${{env.DEBUG == 'true'}}
|
||||
id: debug
|
||||
with:
|
||||
|
||||
@@ -36,7 +36,7 @@ runs:
|
||||
steps:
|
||||
- uses: ./.github/actions/sanitize/config
|
||||
|
||||
- uses: actions/cache@v4
|
||||
- uses: actions/cache@v5
|
||||
if: ${{env.DEBUG == 'true' && inputs.cache-skip != 'true'}}
|
||||
id: debug
|
||||
with:
|
||||
|
||||
@@ -23,7 +23,7 @@ inputs:
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- uses: actions/cache/restore@v4 # Cache for LLVM libcxx
|
||||
- uses: actions/cache/restore@v5 # Cache for LLVM libcxx
|
||||
with:
|
||||
path: ${{env.LLVM_DIR}}
|
||||
fail-on-cache-miss: true
|
||||
@@ -32,14 +32,14 @@ runs:
|
||||
- uses: ./.github/actions/sanitize/mpi
|
||||
if: ${{inputs.par == 'true'}}
|
||||
|
||||
- uses: actions/cache/restore@v4 # Cache for Hypre
|
||||
- uses: actions/cache/restore@v5 # Cache for Hypre
|
||||
if: ${{inputs.par == 'true'}}
|
||||
with:
|
||||
path: ${{env.HYPRE_DIR}}
|
||||
fail-on-cache-miss: true
|
||||
key: ${{runner.os}}-ompi-build-${{env.HYPRE_DIR}}-int32-fp64-v2.5
|
||||
|
||||
- uses: actions/cache/restore@v4 # Cache for Metis
|
||||
- uses: actions/cache/restore@v5 # Cache for Metis
|
||||
if: ${{inputs.par == 'true'}}
|
||||
with:
|
||||
path: ${{env.METIS_DIR}}
|
||||
@@ -51,13 +51,13 @@ runs:
|
||||
run: ln -s -f ${{env.HYPRE_DIR}} hypre && ln -s -f ${{env.METIS_DIR}} metis-4.0
|
||||
shell: bash
|
||||
|
||||
- uses: actions/cache/restore@v4 # Cache for LSAN suppression file
|
||||
- uses: actions/cache/restore@v5 # Cache for LSAN suppression file
|
||||
with:
|
||||
path: ${{env.LSAN_DIR}}
|
||||
fail-on-cache-miss: true
|
||||
key: build-lsan-suppression-file
|
||||
|
||||
- uses: actions/checkout@v4 # Checkout the repository
|
||||
- uses: actions/checkout@v6 # Checkout the repository
|
||||
with:
|
||||
path: mfem
|
||||
# ref: ${{env.BRANCH}}
|
||||
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
remove-docker-images: 'true'
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
# It's easier to reference named variables than indexes of the matrix
|
||||
- name: Set Environment
|
||||
|
||||
@@ -153,7 +153,7 @@ jobs:
|
||||
# /home/runner/work/mfem/mfem/mfem
|
||||
# Note: Done now to access "install-hypre" and "install-metis" actions.
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
path: ${{ env.MFEM_TOP_DIR }}
|
||||
# Fetch the complete history for codecov to access commits ID
|
||||
@@ -225,7 +225,7 @@ jobs:
|
||||
- name: cache hypre
|
||||
id: hypre-cache
|
||||
if: matrix.mpi == 'par'
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ${{ env.HYPRE_TOP_DIR }}
|
||||
key: ${{ runner.os }}-ompi-build-${{ env.HYPRE_TOP_DIR }}-${{ matrix.hypre-target }}-${{ matrix.precision }}-v2.5
|
||||
@@ -255,7 +255,7 @@ jobs:
|
||||
- name: cache metis
|
||||
id: metis-cache
|
||||
if: matrix.mpi == 'par' && matrix.os != 'windows-latest'
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ${{ env.METIS_TOP_DIR }}
|
||||
key: ${{ runner.os }}-build-${{ env.METIS_TOP_DIR }}-v2.5
|
||||
@@ -270,7 +270,7 @@ jobs:
|
||||
- name: cache vcpkg (Windows)
|
||||
id: vcpkg-cache
|
||||
if: matrix.os == 'windows-latest'
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: vcpkg_cache
|
||||
key: ${{ runner.os }}-${{ matrix.mpi }}-vcpkg-v1
|
||||
@@ -295,7 +295,8 @@ jobs:
|
||||
export HOMEBREW_NO_INSTALL_CLEANUP=1
|
||||
brew update
|
||||
brew install enzyme
|
||||
ENZYME_LLVM=$(brew info enzyme | sed -n 's/^Required:.*\(llvm[^ ]*\).*/\1/p')
|
||||
ENZYME_LLVM=$(brew info enzyme | sed -n 's/^Required.*:.*\(llvm[^ ]*\).*/\1/p')
|
||||
echo "ENZYME_LLVM=$ENZYME_LLVM"
|
||||
LLVM_PREFIX=$(brew --prefix $ENZYME_LLVM)
|
||||
echo "LLVM_PREFIX=$LLVM_PREFIX" >> $GITHUB_ENV
|
||||
echo "OMPI_CC=$LLVM_PREFIX/bin/clang" >> $GITHUB_ENV
|
||||
|
||||
@@ -40,11 +40,11 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v4
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -57,7 +57,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
uses: github/codeql-action/autobuild@v4
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
@@ -70,4 +70,4 @@ jobs:
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v4
|
||||
|
||||
@@ -39,7 +39,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: checkout MFEM
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
path: mfem
|
||||
|
||||
@@ -50,7 +50,7 @@ jobs:
|
||||
|
||||
- name: Cache Hypre Install
|
||||
id: hypre-cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ${{ env.HYPRE_TOP_DIR }}
|
||||
key: ${{ runner.os }}-ompi-build-${{ env.HYPRE_TOP_DIR }}-v2.5
|
||||
@@ -65,7 +65,7 @@ jobs:
|
||||
|
||||
- name: Cache Metis Install
|
||||
id: metis-cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ${{ env.METIS_TOP_DIR }}
|
||||
key: ${{ runner.os }}-build-${{ env.METIS_TOP_DIR }}-v2.5
|
||||
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
github.event.pull_request.head.repo.full_name != github.repository)
|
||||
steps:
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: copyright check
|
||||
id: copyright
|
||||
@@ -93,7 +93,7 @@ jobs:
|
||||
github.event.pull_request.head.repo.full_name != github.repository)
|
||||
steps:
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: get astyle
|
||||
run: |
|
||||
@@ -110,7 +110,7 @@ jobs:
|
||||
github.event.pull_request.head.repo.full_name != github.repository)
|
||||
steps:
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: get doxygen and graphviz
|
||||
run: |
|
||||
@@ -135,7 +135,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
||||
@@ -17,11 +17,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: 2.19.0
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
- uses: ./.github/actions/sanitize/config
|
||||
- name: Cache
|
||||
id: cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ${{env.HYPRE_DIR}}
|
||||
key: ${{runner.os}}-ompi-build-${{env.HYPRE_DIR}}-int32-fp64-v2.5
|
||||
|
||||
@@ -27,13 +27,13 @@ jobs:
|
||||
llvm_use_sanitizer: "Undefined"
|
||||
name: ${{matrix.sanitizer}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
- uses: ./.github/actions/sanitize/config
|
||||
with:
|
||||
NO_FLAGS: true
|
||||
- name: Cache
|
||||
id: cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ${{env.LLVM_DIR}}
|
||||
key: build-libcxx-${{env.LLVM_VER}}-${{matrix.sanitizer}}
|
||||
|
||||
@@ -17,11 +17,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: lsan.supp
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
- uses: ./.github/actions/sanitize/config
|
||||
- name: Cache
|
||||
id: cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ${{env.LSAN_DIR}}
|
||||
key: build-lsan-suppression-file
|
||||
|
||||
@@ -17,11 +17,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: 4.0.3
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
- uses: ./.github/actions/sanitize/config
|
||||
- name: Cache
|
||||
id: cache
|
||||
uses: actions/cache@v4
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: ${{env.METIS_DIR}}
|
||||
key: ${{runner.os}}-build-${{env.METIS_DIR}}-v2.5
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
- uses: ./.github/actions/sanitize/mfem
|
||||
with:
|
||||
par: ${{inputs.par}}
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
env:
|
||||
ex: ${{inputs.par && 'ex1p' || 'ex1'}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
- uses: ./.github/actions/sanitize/restore
|
||||
id: restore
|
||||
with:
|
||||
@@ -58,7 +58,7 @@ jobs:
|
||||
env:
|
||||
exclude: ${{inputs.par && '-E "_ser"' || ''}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
- uses: ./.github/actions/sanitize/restore
|
||||
id: restore
|
||||
with:
|
||||
@@ -82,7 +82,7 @@ jobs:
|
||||
env:
|
||||
exclude: ${{inputs.par && '-E "_ser"' || ''}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
- uses: ./.github/actions/sanitize/restore
|
||||
id: restore
|
||||
with:
|
||||
@@ -107,7 +107,7 @@ jobs:
|
||||
run: ${{inputs.par && '-R "_cpu_np"' || ''}}
|
||||
exclude: ${{inputs.par && '"unit_tests|debug"' || '"^unit_tests$|debug"'}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
- uses: ./.github/actions/sanitize/restore
|
||||
id: restore
|
||||
with:
|
||||
@@ -131,7 +131,7 @@ jobs:
|
||||
env:
|
||||
unit_tests: ${{inputs.par && 'punit_tests' || 'unit_tests'}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
- uses: ./.github/actions/sanitize/restore
|
||||
id: restore
|
||||
with:
|
||||
@@ -165,7 +165,7 @@ jobs:
|
||||
unit_tests: ${{inputs.par && 'punit_tests' || 'unit_tests'}}
|
||||
np: ${{inputs.par && '_np=2' || ''}}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
- uses: ./.github/actions/sanitize/restore
|
||||
id: restore
|
||||
with:
|
||||
|
||||
@@ -8,6 +8,21 @@
|
||||
https://mfem.org
|
||||
|
||||
|
||||
Version 4.10 (development)
|
||||
==========================
|
||||
|
||||
Discretization improvements
|
||||
---------------------------
|
||||
- Replaced legacy simplex quadrature rules with symmetric positive-weight
|
||||
rules for triangles (orders 0-25) and tetrahedra (orders 0-20). These
|
||||
rules guarantee all-positive weights and interior quadrature points,
|
||||
improving numerical stability. Higher orders fall back to Grundmann-Moller.
|
||||
Triangle rules: Witherden & Vincent, Comput. Math. Appl. 69(10):1232-1241,
|
||||
2015.
|
||||
Tet rules (d=1-13): Witherden & Vincent (ibid).
|
||||
Tet rules (d=14-20): Chuluunbaatar et al., Comput. Math. Appl. 124:89-97,
|
||||
2022.
|
||||
|
||||
Version 4.9.1 (development)
|
||||
===========================
|
||||
|
||||
@@ -30,6 +45,11 @@ New and updated examples and miniapps
|
||||
- Electromagnetics/lorentz miniapp has been updated to leverage the ParticleSet
|
||||
capability.
|
||||
|
||||
Miscellaneous
|
||||
-------------
|
||||
- Removes the SidreDataCollection class from MFEM in favor of the
|
||||
MFEMSidreDataCollection class in the Axom library (https://github.com/llnl/axom).
|
||||
|
||||
|
||||
Version 4.9, released on Dec 11, 2025
|
||||
=====================================
|
||||
|
||||
+2
-9
@@ -75,12 +75,10 @@ set(XSDK_ENABLE_Fortran OFF)
|
||||
|
||||
# Check if we need to enable C or Fortran.
|
||||
if (MFEM_USE_CONDUIT OR
|
||||
MFEM_USE_SIDRE OR
|
||||
MFEM_USE_PETSC)
|
||||
# This seems to be needed by:
|
||||
# * find_package(BLAS REQUIRED) and
|
||||
# * find_package(HDF5 REQUIRED) needed, in turn, by:
|
||||
# - find_package(AXOM REQUIRED)
|
||||
# * find_package(HDF5 REQUIRED) and
|
||||
# * find_package(PETSc REQUIRED)
|
||||
set(XSDK_ENABLE_C ON)
|
||||
endif()
|
||||
@@ -478,11 +476,6 @@ if (MFEM_USE_FMS)
|
||||
find_package(FMS REQUIRED fms)
|
||||
endif()
|
||||
|
||||
# Axom/Sidre
|
||||
if (MFEM_USE_SIDRE)
|
||||
find_package(Axom REQUIRED Axom)
|
||||
endif()
|
||||
|
||||
# PUMI
|
||||
if (MFEM_USE_PUMI)
|
||||
# If PUMI_DIR was specified, only link to that directory,
|
||||
@@ -629,7 +622,7 @@ find_package(Threads REQUIRED)
|
||||
# integers, the METIS header (with 32-bit indices, as used by mfem) needs to
|
||||
# be before SuiteSparse.
|
||||
set(MFEM_TPLS OPENMP HYPRE LAPACK BLAS SuperLUDist STRUMPACK METIS SuiteSparse
|
||||
SUNDIALS PETSC SLEPC MUMPS AXOM FMS CONDUIT Ginkgo GNUTLS GSLIB HDF5
|
||||
SUNDIALS PETSC SLEPC MUMPS FMS CONDUIT Ginkgo GNUTLS GSLIB HDF5
|
||||
NETCDF MPFR PUMI HIOP POSIXCLOCKS MFEMBacktrace ZLIB OCCA CEED RAJA UMPIRE
|
||||
ADIOS2 MKL_CPARDISO MKL_PARDISO AMGX MAGMA CUSPARSE CUBLAS CALIPER CODIPACK
|
||||
BENCHMARK PARELAG TRIBOL MPI_CXX HIP HIPBLAS HIPSPARSE MOONOLITH BLITZ
|
||||
|
||||
@@ -452,13 +452,6 @@ MFEM_USE_MPFR = YES/NO
|
||||
quadrature rules. When enabled, this option uses the MPFR_* library options,
|
||||
see below.
|
||||
|
||||
MFEM_USE_SIDRE = YES/NO
|
||||
Sidre is a component of LLNL's axom project, https://github.com/LLNL/axom,
|
||||
that provides an HDF5-based file format for visualization or restart
|
||||
capability following the Conduit (https://github.com/LLNL/conduit) mesh
|
||||
blueprint specification. When enabled, this option requires installation of
|
||||
HDF5 (see also MFEM_USE_NETCDF), Conduit and LLNL's axom project.
|
||||
|
||||
MFEM_USE_SIMD = YES/NO
|
||||
Enables the high performance templated classes to use architecture dependent
|
||||
SIMD intrinsics instead of the generic implementation of class AutoSIMD in
|
||||
@@ -778,14 +771,6 @@ The specific libraries and their options are:
|
||||
Options: SLEPC_OPT, SLEPC_LIB.
|
||||
Versions: SLEPc >= 3.8.0.
|
||||
|
||||
- Sidre (optional), part of LLNL's axom project, used when MFEM_USE_SIDRE = YES.
|
||||
Starting with MFEM v4.1, Axom version 0.3.1 or later is required.
|
||||
URL: https://github.com/LLNL/axom
|
||||
https://github.com/LLNL/conduit (Conduit)
|
||||
https://support.hdfgroup.org/HDF5 (HDF5)
|
||||
Options: SIDRE_OPT, SIDRE_LIB.
|
||||
Versions: Axom >= 0.3.1.
|
||||
|
||||
- Conduit (optional), used when MFEM_USE_CONDUIT = YES. Conduit Mesh Blueprint
|
||||
support requires Conduit >= v0.3.1 and VisIt >= v2.13.1 to read the output.
|
||||
URL: https://github.com/LLNL/conduit (Conduit)
|
||||
@@ -1069,7 +1054,6 @@ MFEM_USE_OCCA
|
||||
MFEM_USE_CEED
|
||||
MFEM_USE_RAJA
|
||||
MFEM_USE_UMPIRE
|
||||
MFEM_USE_SIDRE
|
||||
MFEM_USE_MOONOLITH
|
||||
MFEM_USE_CALIPER
|
||||
MFEM_USE_FMS
|
||||
@@ -1133,7 +1117,6 @@ The CMake build system adds auto-detection for the following packages/libraries:
|
||||
- OCCA
|
||||
- RAJA
|
||||
- UMPIRE
|
||||
- AXOM - Used when MFEM_USE_SIDRE is enabled
|
||||
- MOONOLITH
|
||||
- CALIPER
|
||||
- FMS
|
||||
|
||||
@@ -248,10 +248,6 @@ IF (DEFINED TPL_ENABLE_MPFR)
|
||||
SET(MFEM_USE_MPFR ${TPL_ENABLE_MPFR} CACHE BOOL "Enable MPFR usage." FORCE)
|
||||
ENDIF()
|
||||
|
||||
IF (DEFINED TPL_ENABLE_SIDRE)
|
||||
SET(MFEM_USE_SIDRE ${TPL_ENABLE_SIDRE} CACHE BOOL "Enable Axom/Sidre usage" FORCE)
|
||||
ENDIF()
|
||||
|
||||
IF (DEFINED TPL_ENABLE_FMS)
|
||||
SET(MFEM_USE_FMS ${TPL_ENABLE_FMS} CACHE BOOL "Enable FMS usage" FORCE)
|
||||
ENDIF()
|
||||
|
||||
@@ -46,7 +46,6 @@ set(MFEM_USE_NETCDF @MFEM_USE_NETCDF@)
|
||||
set(MFEM_USE_PETSC @MFEM_USE_PETSC@)
|
||||
set(MFEM_USE_SLEPC @MFEM_USE_SLEPC@)
|
||||
set(MFEM_USE_MPFR @MFEM_USE_MPFR@)
|
||||
set(MFEM_USE_SIDRE @MFEM_USE_SIDRE@)
|
||||
set(MFEM_USE_FMS @MFEM_USE_FMS@)
|
||||
set(MFEM_USE_CONDUIT @MFEM_USE_CONDUIT@)
|
||||
set(MFEM_USE_PUMI @MFEM_USE_PUMI@)
|
||||
|
||||
@@ -120,9 +120,6 @@
|
||||
// Enable secure socket streams based on the GNUTLS library.
|
||||
#cmakedefine MFEM_USE_GNUTLS
|
||||
|
||||
// Enable Sidre support.
|
||||
#cmakedefine MFEM_USE_SIDRE
|
||||
|
||||
// Enable the use of SIMD in the high performance templated classes.
|
||||
#cmakedefine MFEM_USE_SIMD
|
||||
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
# Defines the following variables:
|
||||
# - ADIAK_FOUND
|
||||
# - ADIAK_LIBRARIES
|
||||
# - ADIAK_INCLUDE_DIRS
|
||||
|
||||
include(MfemCmakeUtilities)
|
||||
|
||||
mfem_find_package(Adiak ADIAK ADIAK_DIR
|
||||
"include" "adiak.h"
|
||||
"lib" "adiak"
|
||||
"Paths to headers required by Adiak."
|
||||
"Libraries required by Adiak.")
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
# - AXOM_FOUND
|
||||
# - AXOM_LIBRARIES
|
||||
# - AXOM_INCLUDE_DIRS
|
||||
#
|
||||
# MFEM itself does not depend on Axom, however Tribol does. This module exists
|
||||
# to support MFEM's Tribol integration (e.g. the contact miniapp).
|
||||
|
||||
include(MfemCmakeUtilities)
|
||||
# Note: components are enabled based on the find_package() parameters.
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
# LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability visit https://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
# CONTRIBUTING.md for details.
|
||||
|
||||
# Defines the following variables:
|
||||
# - CAMP_FOUND
|
||||
# - CAMP_LIBRARIES
|
||||
# - CAMP_INCLUDE_DIRS
|
||||
|
||||
include(MfemCmakeUtilities)
|
||||
|
||||
mfem_find_package(CAMP CAMP CAMP_DIR
|
||||
"include" "camp/camp.hpp"
|
||||
"lib" "camp"
|
||||
"Paths to headers required by CAMP."
|
||||
"Libraries required by CAMP.")
|
||||
|
||||
# RAJA commonly lists "camp" in INTERFACE_LINK_LIBRARIES. If there is no CMake
|
||||
# target named "camp", CMake treats it as a bare library name (-lcamp).
|
||||
if (CAMP_FOUND AND NOT TARGET camp)
|
||||
list(GET CAMP_LIBRARIES 0 _camp_lib0)
|
||||
add_library(camp UNKNOWN IMPORTED)
|
||||
set_target_properties(camp PROPERTIES
|
||||
IMPORTED_LOCATION "${_camp_lib0}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${CAMP_INCLUDE_DIRS}")
|
||||
set(CAMP_LIBRARIES "camp" CACHE STRING "CAMP imported target." FORCE)
|
||||
unset(_camp_lib0)
|
||||
endif()
|
||||
|
||||
@@ -21,6 +21,21 @@ mfem_find_package(Caliper CALIPER CALIPER_DIR
|
||||
"Paths to headers required by Caliper."
|
||||
"Libraries required by Caliper.")
|
||||
|
||||
# Some downstream CMake packages (notably RAJA) may list "caliper" in their
|
||||
# INTERFACE_LINK_LIBRARIES. If there is no CMake target named "caliper", CMake
|
||||
# treats it as a bare library name and will pass -lcaliper to the linker.
|
||||
# Create a minimal imported target when we only located the library by path.
|
||||
if (CALIPER_FOUND AND NOT TARGET caliper)
|
||||
list(GET CALIPER_LIBRARIES 0 _caliper_lib0)
|
||||
add_library(caliper UNKNOWN IMPORTED)
|
||||
set_target_properties(caliper PROPERTIES
|
||||
IMPORTED_LOCATION "${_caliper_lib0}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${CALIPER_INCLUDE_DIRS}")
|
||||
# Prefer linking via the target.
|
||||
set(CALIPER_LIBRARIES "caliper" CACHE STRING "Caliper imported target." FORCE)
|
||||
unset(_caliper_lib0)
|
||||
endif()
|
||||
|
||||
# Append adiak path/lib if the user provided ADIAK_DIR
|
||||
if(ADIAK_DIR AND EXISTS ${ADIAK_DIR})
|
||||
find_package(adiak NO_DEFAULT_PATH REQUIRED PATHS ${ADIAK_DIR}/lib/cmake/adiak ${ADIAK_DIR})
|
||||
|
||||
@@ -878,7 +878,7 @@ function(mfem_export_mk_files)
|
||||
MFEM_USE_SUITESPARSE MFEM_USE_SUPERLU MFEM_USE_SUPERLU5 MFEM_USE_MUMPS
|
||||
MFEM_USE_STRUMPACK MFEM_USE_GINKGO MFEM_USE_AMGX MFEM_USE_MAGMA
|
||||
MFEM_USE_GNUTLS MFEM_USE_NETCDF MFEM_USE_PETSC MFEM_USE_SLEPC
|
||||
MFEM_USE_MPFR MFEM_USE_SIDRE MFEM_USE_FMS MFEM_USE_CONDUIT MFEM_USE_PUMI
|
||||
MFEM_USE_MPFR MFEM_USE_FMS MFEM_USE_CONDUIT MFEM_USE_PUMI
|
||||
MFEM_USE_HIOP MFEM_USE_GSLIB MFEM_USE_CUDA MFEM_USE_HIP MFEM_USE_RAJA
|
||||
MFEM_USE_OCCA MFEM_USE_CEED MFEM_USE_CALIPER MFEM_USE_UMPIRE MFEM_USE_SIMD
|
||||
MFEM_USE_ADIOS2 MFEM_USE_MKL_CPARDISO MFEM_USE_MKL_PARDISO
|
||||
|
||||
@@ -120,9 +120,6 @@
|
||||
// Enable secure socket streams based on the GNUTLS library.
|
||||
// #define MFEM_USE_GNUTLS
|
||||
|
||||
// Enable Sidre support.
|
||||
// #define MFEM_USE_SIDRE
|
||||
|
||||
// Enable the use of SIMD in the high performance templated classes.
|
||||
// #define MFEM_USE_SIMD
|
||||
|
||||
|
||||
@@ -45,7 +45,6 @@ MFEM_USE_NETCDF = @MFEM_USE_NETCDF@
|
||||
MFEM_USE_PETSC = @MFEM_USE_PETSC@
|
||||
MFEM_USE_SLEPC = @MFEM_USE_SLEPC@
|
||||
MFEM_USE_MPFR = @MFEM_USE_MPFR@
|
||||
MFEM_USE_SIDRE = @MFEM_USE_SIDRE@
|
||||
MFEM_USE_FMS = @MFEM_USE_FMS@
|
||||
MFEM_USE_CONDUIT = @MFEM_USE_CONDUIT@
|
||||
MFEM_USE_PUMI = @MFEM_USE_PUMI@
|
||||
|
||||
+9
-14
@@ -48,7 +48,6 @@ option(MFEM_USE_NETCDF "Enable NETCDF usage" OFF)
|
||||
option(MFEM_USE_PETSC "Enable PETSc support." OFF)
|
||||
option(MFEM_USE_SLEPC "Enable SLEPc support." OFF)
|
||||
option(MFEM_USE_MPFR "Enable MPFR usage." OFF)
|
||||
option(MFEM_USE_SIDRE "Enable Axom/Sidre usage" OFF)
|
||||
option(MFEM_USE_FMS "Enable FMS usage" OFF)
|
||||
option(MFEM_USE_CONDUIT "Enable Conduit usage" OFF)
|
||||
option(MFEM_USE_PUMI "Enable PUMI" OFF)
|
||||
@@ -224,17 +223,8 @@ set(FMS_DIR "${MFEM_DIR}/../fms" CACHE PATH
|
||||
set(CONDUIT_DIR "${MFEM_DIR}/../conduit" CACHE PATH
|
||||
"Path to the Conduit library.")
|
||||
|
||||
set(AXOM_DIR "${MFEM_DIR}/../axom" CACHE PATH "Path to the Axom library.")
|
||||
# May need to add "Boost" as requirement.
|
||||
if (MFEM_USE_SIDRE)
|
||||
if (MFEM_USE_MPI)
|
||||
set(Axom_REQUIRED_PACKAGES "Conduit/blueprint/blueprint_mpi/relay/relay_mpi" CACHE STRING
|
||||
"Additional packages required by Axom.")
|
||||
elseif()
|
||||
set(Axom_REQUIRED_PACKAGES "Conduit/blueprint/relay" CACHE STRING
|
||||
"Additional packages required by Axom.")
|
||||
endif()
|
||||
endif()
|
||||
set(AXOM_DIR "${MFEM_DIR}/../axom" CACHE PATH
|
||||
"Path to the Axom library (required by Tribol for the contact mini-app).")
|
||||
|
||||
set(PUMI_DIR "${MFEM_DIR}/../pumi-2.1.0" CACHE STRING
|
||||
"Directory where PUMI is installed")
|
||||
@@ -252,6 +242,7 @@ set(MKL_PARDISO_DIR "" CACHE STRING "MKL installation path.")
|
||||
|
||||
set(OCCA_DIR "${MFEM_DIR}/../occa" CACHE PATH "Path to OCCA")
|
||||
set(RAJA_DIR "${MFEM_DIR}/../raja" CACHE PATH "Path to RAJA")
|
||||
set(CAMP_DIR "${MFEM_DIR}/../camp" CACHE PATH "Path to CAMP (required by RAJA/Umpire)")
|
||||
set(CEED_DIR "${MFEM_DIR}/../libCEED" CACHE PATH "Path to libCEED")
|
||||
set(UMPIRE_DIR "${MFEM_DIR}/../umpire" CACHE PATH "Path to Umpire")
|
||||
set(CALIPER_DIR "${MFEM_DIR}/../caliper" CACHE PATH "Path to Caliper")
|
||||
@@ -272,8 +263,12 @@ set(PARELAG_LIBRARIES "${PARELAG_DIR}/build/src/libParELAG.a" CACHE STRING
|
||||
"The ParELAG library.")
|
||||
|
||||
set(TRIBOL_DIR "${MFEM_DIR}/../tribol" CACHE PATH "Path to Tribol")
|
||||
set(Tribol_REQUIRED_PACKAGES "Axom/core/mint/slam/slic" CACHE STRING
|
||||
"Additional packages required by Tribol")
|
||||
# Tribol requires Axom. Many Tribol builds also enable optional TPLs like
|
||||
# RAJA/UMPIRE/Caliper, and may pull additional Axom components (e.g. quest,
|
||||
# lumberjack) via its exported targets.
|
||||
set(Tribol_REQUIRED_PACKAGES
|
||||
"REQUIRED:;Axom/core/primal/mint/slam/slic/quest/lumberjack;OPTIONAL:;Adiak;CAMP;RAJA;UMPIRE;Caliper"
|
||||
CACHE STRING "Additional packages required by Tribol")
|
||||
|
||||
set(ENZYME_DIR "${MFEM_DIR}/../enzyme" CACHE PATH "Path to Enzyme")
|
||||
|
||||
|
||||
+78
-15
@@ -162,7 +162,6 @@ MFEM_USE_NETCDF = NO
|
||||
MFEM_USE_PETSC = NO
|
||||
MFEM_USE_SLEPC = NO
|
||||
MFEM_USE_MPFR = NO
|
||||
MFEM_USE_SIDRE = NO
|
||||
MFEM_USE_FMS = NO
|
||||
MFEM_USE_CONDUIT = NO
|
||||
MFEM_USE_PUMI = NO
|
||||
@@ -249,6 +248,15 @@ endif
|
||||
|
||||
# METIS library configuration
|
||||
ifeq ($(MFEM_USE_SUPERLU)$(MFEM_USE_STRUMPACK)$(MFEM_USE_MUMPS),NONONO)
|
||||
# MFEM_USE_METIS_5: when the user supplies METIS_DIR, try to auto-detect
|
||||
# METIS 5 installs that follow the common <prefix>/{include,lib,lib64} layout.
|
||||
ifeq ($(MFEM_USE_METIS_5),NO)
|
||||
ifneq ($(wildcard $(METIS_DIR)/include/metis.h),)
|
||||
ifneq ($(wildcard $(METIS_DIR)/lib/libmetis.* $(METIS_DIR)/lib64/libmetis.*),)
|
||||
MFEM_USE_METIS_5 = YES
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
ifeq ($(MFEM_USE_METIS_5),NO)
|
||||
METIS_DIR = @MFEM_DIR@/../metis-4.0
|
||||
METIS_OPT =
|
||||
@@ -487,17 +495,6 @@ ifneq (,$(wildcard $(CONDUIT_HDF5_HEADER)))
|
||||
-lhdf5 $(ZLIB_LIB)
|
||||
endif
|
||||
|
||||
# Sidre and required libraries configuration
|
||||
# Be sure to check the HDF5_DIR (set above) is correct
|
||||
SIDRE_DIR = @MFEM_DIR@/../axom
|
||||
SIDRE_OPT = -I$(SIDRE_DIR)/include -I$(CONDUIT_DIR)/include/conduit\
|
||||
-I$(HDF5_DIR)/include
|
||||
SIDRE_LIB = \
|
||||
$(XLINKER)-rpath,$(SIDRE_DIR)/lib -L$(SIDRE_DIR)/lib \
|
||||
$(XLINKER)-rpath,$(CONDUIT_DIR)/lib -L$(CONDUIT_DIR)/lib \
|
||||
$(XLINKER)-rpath,$(HDF5_DIR)/lib -L$(HDF5_DIR)/lib \
|
||||
-laxom -lconduit -lconduit_relay -lconduit_blueprint -lhdf5 $(ZLIB_LIB) -ldl
|
||||
|
||||
# PUMI
|
||||
# Note that PUMI_DIR is needed -- it is used to check for gmi_sim.h
|
||||
PUMI_DIR = @MFEM_DIR@/../pumi-2.1.0
|
||||
@@ -579,7 +576,13 @@ ifdef CUB_DIR
|
||||
RAJA_OPT += -I$(CUB_DIR)
|
||||
endif
|
||||
|
||||
# CAMP library configuration (required by RAJA/Umpire for most installs)
|
||||
CAMP_LIB = -lcamp
|
||||
# If the common sibling layout exists, use it as a default (handles versioned
|
||||
# directories like camp-<hash>).
|
||||
ifneq ($(wildcard $(RAJA_DIR)/../camp*/include/camp/camp.hpp),)
|
||||
CAMP_DIR ?= $(patsubst %/include/camp/camp.hpp,%,$(firstword $(wildcard $(RAJA_DIR)/../camp*/include/camp/camp.hpp)))
|
||||
endif
|
||||
ifdef CAMP_DIR
|
||||
RAJA_OPT += -I$(CAMP_DIR)/include
|
||||
CAMP_LIB = $(XLINKER)-rpath,$(CAMP_DIR)/lib -L$(CAMP_DIR)/lib -lcamp
|
||||
@@ -589,7 +592,12 @@ RAJA_LIB = $(XLINKER)-rpath,$(RAJA_DIR)/lib -L$(RAJA_DIR)/lib -lRAJA $(CAMP_LIB)
|
||||
# UMPIRE library configuration
|
||||
UMPIRE_DIR = @MFEM_DIR@/../umpire
|
||||
UMPIRE_OPT = -I$(UMPIRE_DIR)/include $(if $(CAMP_DIR), -I$(CAMP_DIR)/include)
|
||||
UMPIRE_LIB = -L$(UMPIRE_DIR)/lib -L$(UMPIRE_DIR)/lib64 -lumpire $(CAMP_LIB)
|
||||
UMPIRE_LIB = -L$(UMPIRE_DIR)/lib -L$(UMPIRE_DIR)/lib64 -lumpire $(CAMP_LIB) -lpthread
|
||||
# If the common sibling layout exists, use it as a default (handles versioned
|
||||
# directories like fmt-<hash>).
|
||||
ifneq ($(wildcard $(UMPIRE_DIR)/../fmt*/include/fmt/format.h),)
|
||||
FMT_DIR ?= $(patsubst %/include/fmt/format.h,%,$(firstword $(wildcard $(UMPIRE_DIR)/../fmt*/include/fmt/format.h)))
|
||||
endif
|
||||
ifdef FMT_DIR
|
||||
UMPIRE_OPT += -I$(FMT_DIR)/include
|
||||
UMPIRE_LIB += -L$(FMT_DIR)/lib -L$(FMT_DIR)/lib64 -lfmt
|
||||
@@ -621,8 +629,63 @@ PARELAG_LIB = -L$(PARELAG_DIR)/build/src -lParELAG
|
||||
AXOM_DIR = @MFEM_DIR@/../axom
|
||||
TRIBOL_DIR = @MFEM_DIR@/../tribol
|
||||
TRIBOL_OPT = -I$(TRIBOL_DIR)/include -I$(AXOM_DIR)/include
|
||||
TRIBOL_LIB = -L$(TRIBOL_DIR)/lib -ltribol -lredecomp -L$(AXOM_DIR)/lib -laxom_mint\
|
||||
-laxom_slam -laxom_slic -laxom_core
|
||||
# Tribol may be built with optional dependencies (e.g. RAJA/UMPIRE/CALIPER).
|
||||
# Add those options only when the corresponding headers/libraries exist.
|
||||
ifneq ($(wildcard $(RAJA_DIR)/include/RAJA/RAJA.hpp),)
|
||||
TRIBOL_OPT += $(RAJA_OPT)
|
||||
endif
|
||||
ifneq ($(wildcard $(UMPIRE_DIR)/include/umpire/Umpire.hpp),)
|
||||
TRIBOL_OPT += $(UMPIRE_OPT)
|
||||
endif
|
||||
ifneq ($(wildcard $(CALIPER_DIR)/include/caliper/cali.h),)
|
||||
TRIBOL_OPT += $(CALIPER_OPT)
|
||||
endif
|
||||
|
||||
TRIBOL_LIB = -L$(TRIBOL_DIR)/lib -L$(TRIBOL_DIR)/lib64
|
||||
ifneq ($(wildcard $(TRIBOL_DIR)/lib/libtribol.* $(TRIBOL_DIR)/lib64/libtribol.*),)
|
||||
TRIBOL_LIB += -ltribol
|
||||
endif
|
||||
ifneq ($(wildcard $(TRIBOL_DIR)/lib/libtribol_shared.* $(TRIBOL_DIR)/lib64/libtribol_shared.*),)
|
||||
TRIBOL_LIB += -ltribol_shared
|
||||
endif
|
||||
ifneq ($(wildcard $(TRIBOL_DIR)/lib/libredecomp.* $(TRIBOL_DIR)/lib64/libredecomp.*),)
|
||||
TRIBOL_LIB += -lredecomp
|
||||
endif
|
||||
|
||||
TRIBOL_LIB += -L$(AXOM_DIR)/lib -L$(AXOM_DIR)/lib64
|
||||
ifneq ($(wildcard $(AXOM_DIR)/lib/libaxom_quest.* $(AXOM_DIR)/lib64/libaxom_quest.*),)
|
||||
TRIBOL_LIB += -laxom_quest
|
||||
endif
|
||||
ifneq ($(wildcard $(AXOM_DIR)/lib/libaxom_mint.* $(AXOM_DIR)/lib64/libaxom_mint.*),)
|
||||
TRIBOL_LIB += -laxom_mint
|
||||
endif
|
||||
ifneq ($(wildcard $(AXOM_DIR)/lib/libaxom_slam.* $(AXOM_DIR)/lib64/libaxom_slam.*),)
|
||||
TRIBOL_LIB += -laxom_slam
|
||||
endif
|
||||
ifneq ($(wildcard $(AXOM_DIR)/lib/libaxom_slic.* $(AXOM_DIR)/lib64/libaxom_slic.*),)
|
||||
TRIBOL_LIB += -laxom_slic
|
||||
endif
|
||||
ifneq ($(wildcard $(AXOM_DIR)/lib/libaxom_lumberjack.* $(AXOM_DIR)/lib64/libaxom_lumberjack.*),)
|
||||
TRIBOL_LIB += -laxom_lumberjack
|
||||
endif
|
||||
ifneq ($(wildcard $(AXOM_DIR)/lib/libaxom_core.* $(AXOM_DIR)/lib64/libaxom_core.*),)
|
||||
TRIBOL_LIB += -laxom_core
|
||||
endif
|
||||
|
||||
# Add common optional Tribol TPLs when their libraries are present.
|
||||
ifneq ($(wildcard $(ADIAK_DIR)/lib/libadiak.* $(ADIAK_DIR)/lib64/libadiak.*),)
|
||||
TRIBOL_LIB += $(XLINKER)-rpath,$(ADIAK_DIR)/lib64 $(XLINKER)-rpath,$(ADIAK_DIR)/lib \
|
||||
-L$(ADIAK_DIR)/lib64 -L$(ADIAK_DIR)/lib -ladiak -ldl
|
||||
endif
|
||||
ifneq ($(wildcard $(UMPIRE_DIR)/lib/libumpire.* $(UMPIRE_DIR)/lib64/libumpire.*),)
|
||||
TRIBOL_LIB += $(UMPIRE_LIB)
|
||||
endif
|
||||
ifneq ($(wildcard $(RAJA_DIR)/lib/libRAJA.* $(RAJA_DIR)/lib64/libRAJA.*),)
|
||||
TRIBOL_LIB += $(RAJA_LIB)
|
||||
endif
|
||||
ifneq ($(wildcard $(CALIPER_DIR)/lib/libcaliper.* $(CALIPER_DIR)/lib64/libcaliper.*),)
|
||||
TRIBOL_LIB += $(CALIPER_LIB)
|
||||
endif
|
||||
|
||||
# Enzyme configuration
|
||||
ENZYME_DIR = @MFEM_DIR@/../enzyme
|
||||
|
||||
+2
-2
@@ -5,9 +5,9 @@
|
||||
// Sample runs:
|
||||
// mpirun -np 4 ex12p -m ../data/beam-tri.mesh
|
||||
// mpirun -np 4 ex12p -m ../data/beam-quad.mesh
|
||||
// mpirun -np 4 ex12p -m ../data/beam-tet.mesh -s 462 -n 10 -o 2 -elast
|
||||
// mpirun -np 4 ex12p -m ../data/beam-tet.mesh -s 464 -n 10 -o 2 -elast
|
||||
// mpirun -np 4 ex12p -m ../data/beam-hex.mesh -s 3878
|
||||
// mpirun -np 4 ex12p -m ../data/beam-wedge.mesh -s 81
|
||||
// mpirun -np 4 ex12p -m ../data/beam-wedge.mesh -s 82
|
||||
// mpirun -np 4 ex12p -m ../data/beam-tri.mesh -s 3877 -o 2 -sys
|
||||
// mpirun -np 4 ex12p -m ../data/beam-quad.mesh -s 4544 -n 6 -o 3 -elast
|
||||
// mpirun -np 4 ex12p -m ../data/beam-quad-nurbs.mesh
|
||||
|
||||
+27
-9
@@ -302,15 +302,21 @@ int main(int argc, char *argv[])
|
||||
char vishost[] = "localhost";
|
||||
int visport = 19916;
|
||||
socketstream sol_sock_r(vishost, visport);
|
||||
socketstream sol_sock_i(vishost, visport);
|
||||
sol_sock_r << "parallel " << num_procs << " " << myid << "\n";
|
||||
sol_sock_i << "parallel " << num_procs << " " << myid << "\n";
|
||||
sol_sock_r.precision(8);
|
||||
sol_sock_i.precision(8);
|
||||
sol_sock_r << "solution\n" << *pmesh << u_exact->real()
|
||||
<< "window_title 'Exact: Real Part'" << flush;
|
||||
// Make sure all ranks have sent their real solution before initiating
|
||||
// another set of GLVis connections (one from each rank):
|
||||
MPI_Barrier(pmesh->GetComm());
|
||||
socketstream sol_sock_i(vishost, visport);
|
||||
sol_sock_i << "parallel " << num_procs << " " << myid << "\n";
|
||||
sol_sock_i.precision(8);
|
||||
sol_sock_i << "solution\n" << *pmesh << u_exact->imag()
|
||||
<< "window_title 'Exact: Imaginary Part'" << flush;
|
||||
// Make sure all ranks have sent their imaginary solution before initiating
|
||||
// another set of GLVis connections (one from each rank):
|
||||
MPI_Barrier(pmesh->GetComm());
|
||||
}
|
||||
|
||||
// 11. Set up the parallel sesquilinear form a(.,.) on the finite element
|
||||
@@ -534,15 +540,21 @@ int main(int argc, char *argv[])
|
||||
char vishost[] = "localhost";
|
||||
int visport = 19916;
|
||||
socketstream sol_sock_r(vishost, visport);
|
||||
socketstream sol_sock_i(vishost, visport);
|
||||
sol_sock_r << "parallel " << num_procs << " " << myid << "\n";
|
||||
sol_sock_i << "parallel " << num_procs << " " << myid << "\n";
|
||||
sol_sock_r.precision(8);
|
||||
sol_sock_i.precision(8);
|
||||
sol_sock_r << "solution\n" << *pmesh << u.real()
|
||||
<< "window_title 'Solution: Real Part'" << flush;
|
||||
// Make sure all ranks have sent their real solution before initiating
|
||||
// another set of GLVis connections (one from each rank):
|
||||
MPI_Barrier(pmesh->GetComm());
|
||||
socketstream sol_sock_i(vishost, visport);
|
||||
sol_sock_i << "parallel " << num_procs << " " << myid << "\n";
|
||||
sol_sock_i.precision(8);
|
||||
sol_sock_i << "solution\n" << *pmesh << u.imag()
|
||||
<< "window_title 'Solution: Imaginary Part'" << flush;
|
||||
// Make sure all ranks have sent their imaginary solution before initiating
|
||||
// another set of GLVis connections (one from each rank):
|
||||
MPI_Barrier(pmesh->GetComm());
|
||||
}
|
||||
if (visualization && exact_sol)
|
||||
{
|
||||
@@ -551,15 +563,21 @@ int main(int argc, char *argv[])
|
||||
char vishost[] = "localhost";
|
||||
int visport = 19916;
|
||||
socketstream sol_sock_r(vishost, visport);
|
||||
socketstream sol_sock_i(vishost, visport);
|
||||
sol_sock_r << "parallel " << num_procs << " " << myid << "\n";
|
||||
sol_sock_i << "parallel " << num_procs << " " << myid << "\n";
|
||||
sol_sock_r.precision(8);
|
||||
sol_sock_i.precision(8);
|
||||
sol_sock_r << "solution\n" << *pmesh << u_exact->real()
|
||||
<< "window_title 'Error: Real Part'" << flush;
|
||||
// Make sure all ranks have sent their real solution before initiating
|
||||
// another set of GLVis connections (one from each rank):
|
||||
MPI_Barrier(pmesh->GetComm());
|
||||
socketstream sol_sock_i(vishost, visport);
|
||||
sol_sock_i << "parallel " << num_procs << " " << myid << "\n";
|
||||
sol_sock_i.precision(8);
|
||||
sol_sock_i << "solution\n" << *pmesh << u_exact->imag()
|
||||
<< "window_title 'Error: Imaginary Part'" << flush;
|
||||
// Make sure all ranks have sent their imaginary solution before initiating
|
||||
// another set of GLVis connections (one from each rank):
|
||||
MPI_Barrier(pmesh->GetComm());
|
||||
}
|
||||
if (visualization)
|
||||
{
|
||||
|
||||
+6
-4
@@ -433,16 +433,18 @@ int main(int argc, char *argv[])
|
||||
u.ProjectCoefficient(*u0);
|
||||
|
||||
// Create data collection for solution output: either VisItDataCollection for
|
||||
// ascii data files, or SidreDataCollection for binary data files.
|
||||
// ascii data files, or ConduitDataCollection for binary data files.
|
||||
DataCollection *dc = NULL;
|
||||
if (visit)
|
||||
{
|
||||
if (binary)
|
||||
{
|
||||
#ifdef MFEM_USE_SIDRE
|
||||
dc = new SidreDataCollection("Example41", &mesh);
|
||||
#ifdef MFEM_USE_CONDUIT
|
||||
auto conduit_dc = new ConduitDataCollection("Example41", &mesh);
|
||||
conduit_dc->SetProtocol("hdf5");
|
||||
dc = conduit_dc;
|
||||
#else
|
||||
MFEM_ABORT("Must build with MFEM_USE_SIDRE=YES for binary output.");
|
||||
MFEM_ABORT("Must build with MFEM_USE_CONDUIT=YES for binary output.");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
||||
+5
-3
@@ -518,10 +518,12 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
if (binary)
|
||||
{
|
||||
#ifdef MFEM_USE_SIDRE
|
||||
dc = new SidreDataCollection("Example41-Parallel", pmesh);
|
||||
#ifdef MFEM_USE_CONDUIT
|
||||
auto conduit_dc = new ConduitDataCollection("Example41-Parallel", pmesh);
|
||||
conduit_dc->SetProtocol("hdf5");
|
||||
dc = conduit_dc;
|
||||
#else
|
||||
MFEM_ABORT("Must build with MFEM_USE_SIDRE=YES for binary output.");
|
||||
MFEM_ABORT("Must build with MFEM_USE_CONDUIT=YES for binary output.");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
||||
+6
-4
@@ -305,16 +305,18 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// Create data collection for solution output: either VisItDataCollection for
|
||||
// ascii data files, or SidreDataCollection for binary data files.
|
||||
// ascii data files, or ConduitDataCollection for binary data files.
|
||||
DataCollection *dc = NULL;
|
||||
if (visit)
|
||||
{
|
||||
if (binary)
|
||||
{
|
||||
#ifdef MFEM_USE_SIDRE
|
||||
dc = new SidreDataCollection("Example9", &mesh);
|
||||
#ifdef MFEM_USE_CONDUIT
|
||||
auto conduit_dc = new ConduitDataCollection("Example9", &mesh);
|
||||
conduit_dc->SetProtocol("hdf5");
|
||||
dc = conduit_dc;
|
||||
#else
|
||||
MFEM_ABORT("Must build with MFEM_USE_SIDRE=YES for binary output.");
|
||||
MFEM_ABORT("Must build with MFEM_USE_CONDUIT=YES for binary output.");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
||||
+6
-4
@@ -441,16 +441,18 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// Create data collection for solution output: either VisItDataCollection for
|
||||
// ascii data files, or SidreDataCollection for binary data files.
|
||||
// ascii data files, or ConduitDataCollection for binary data files.
|
||||
DataCollection *dc = NULL;
|
||||
if (visit)
|
||||
{
|
||||
if (binary)
|
||||
{
|
||||
#ifdef MFEM_USE_SIDRE
|
||||
dc = new SidreDataCollection("Example9-Parallel", pmesh);
|
||||
#ifdef MFEM_USE_CONDUIT
|
||||
auto conduit_dc = new ConduitDataCollection("Example9-Parallel", pmesh);
|
||||
conduit_dc->SetProtocol("hdf5");
|
||||
dc = conduit_dc;
|
||||
#else
|
||||
MFEM_ABORT("Must build with MFEM_USE_SIDRE=YES for binary output.");
|
||||
MFEM_ABORT("Must build with MFEM_USE_CONDUIT=YES for binary output.");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
||||
@@ -354,16 +354,18 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// Create data collection for solution output: either VisItDataCollection for
|
||||
// ascii data files, or SidreDataCollection for binary data files.
|
||||
// ascii data files, or ConduitDataCollection for binary data files.
|
||||
DataCollection *dc = NULL;
|
||||
if (visit)
|
||||
{
|
||||
if (binary)
|
||||
{
|
||||
#ifdef MFEM_USE_SIDRE
|
||||
dc = new SidreDataCollection("Example9", mesh);
|
||||
#ifdef MFEM_USE_CONDUIT
|
||||
auto conduit_dc = new ConduitDataCollection("Example9", mesh);
|
||||
conduit_dc->SetProtocol("hdf5");
|
||||
dc = conduit_dc;
|
||||
#else
|
||||
MFEM_ABORT("Must build with MFEM_USE_SIDRE=YES for binary output.");
|
||||
MFEM_ABORT("Must build with MFEM_USE_CONDUIT=YES for binary output.");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
||||
@@ -414,16 +414,18 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// Create data collection for solution output: either VisItDataCollection for
|
||||
// ascii data files, or SidreDataCollection for binary data files.
|
||||
// ascii data files, or ConduitDataCollection for binary data files.
|
||||
DataCollection *dc = NULL;
|
||||
if (visit)
|
||||
{
|
||||
if (binary)
|
||||
{
|
||||
#ifdef MFEM_USE_SIDRE
|
||||
dc = new SidreDataCollection("Example9-Parallel", pmesh);
|
||||
#ifdef MFEM_USE_CONDUIT
|
||||
auto conduit_dc = new ConduitDataCollection("Example9-Parallel", pmesh);
|
||||
conduit_dc->SetProtocol("hdf5");
|
||||
dc = conduit_dc;
|
||||
#else
|
||||
MFEM_ABORT("Must build with MFEM_USE_SIDRE=YES for binary output.");
|
||||
MFEM_ABORT("Must build with MFEM_USE_CONDUIT=YES for binary output.");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
||||
@@ -368,16 +368,18 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// Create data collection for solution output: either VisItDataCollection for
|
||||
// ascii data files, or SidreDataCollection for binary data files.
|
||||
// ascii data files, or ConduitDataCollection for binary data files.
|
||||
DataCollection *dc = NULL;
|
||||
if (visit)
|
||||
{
|
||||
if (binary)
|
||||
{
|
||||
#ifdef MFEM_USE_SIDRE
|
||||
dc = new SidreDataCollection("Example9-Parallel", pmesh);
|
||||
#ifdef MFEM_USE_CONDUIT
|
||||
auto conduit_dc = new ConduitDataCollection("Example9-Parallel", pmesh);
|
||||
conduit_dc->SetProtocol("hdf5");
|
||||
dc = conduit_dc;
|
||||
#else
|
||||
MFEM_ABORT("Must build with MFEM_USE_SIDRE=YES for binary output.");
|
||||
MFEM_ABORT("Must build with MFEM_USE_CONDUIT=YES for binary output.");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
||||
@@ -316,16 +316,18 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// Create data collection for solution output: either VisItDataCollection for
|
||||
// ascii data files, or SidreDataCollection for binary data files.
|
||||
// ascii data files, or ConduitDataCollection for binary data files.
|
||||
DataCollection *dc = NULL;
|
||||
if (visit)
|
||||
{
|
||||
if (binary)
|
||||
{
|
||||
#ifdef MFEM_USE_SIDRE
|
||||
dc = new SidreDataCollection("Example9", &mesh);
|
||||
#ifdef MFEM_USE_CONDUIT
|
||||
auto conduit_dc = new ConduitDataCollection("Example9", &mesh);
|
||||
conduit_dc->SetProtocol("hdf5");
|
||||
dc = conduit_dc;
|
||||
#else
|
||||
MFEM_ABORT("Must build with MFEM_USE_SIDRE=YES for binary output.");
|
||||
MFEM_ABORT("Must build with MFEM_USE_CONDUIT=YES for binary output.");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
||||
@@ -453,16 +453,18 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// Create data collection for solution output: either VisItDataCollection for
|
||||
// ascii data files, or SidreDataCollection for binary data files.
|
||||
// ascii data files, or ConduitDataCollection for binary data files.
|
||||
DataCollection *dc = NULL;
|
||||
if (visit)
|
||||
{
|
||||
if (binary)
|
||||
{
|
||||
#ifdef MFEM_USE_SIDRE
|
||||
dc = new SidreDataCollection("Example9-Parallel", pmesh);
|
||||
#ifdef MFEM_USE_CONDUIT
|
||||
auto conduit_dc = new ConduitDataCollection("Example9-Parallel", pmesh);
|
||||
conduit_dc->SetProtocol("hdf5");
|
||||
dc = conduit_dc;
|
||||
#else
|
||||
MFEM_ABORT("Must build with MFEM_USE_SIDRE=YES for binary output.");
|
||||
MFEM_ABORT("Must build with MFEM_USE_CONDUIT=YES for binary output.");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
|
||||
@@ -312,11 +312,6 @@ set(HDRS
|
||||
particleset.hpp
|
||||
)
|
||||
|
||||
if (MFEM_USE_SIDRE)
|
||||
list(APPEND SRCS sidredatacollection.cpp)
|
||||
list(APPEND HDRS sidredatacollection.hpp)
|
||||
endif()
|
||||
|
||||
if (MFEM_USE_CONDUIT)
|
||||
list(APPEND SRCS conduitdatacollection.cpp)
|
||||
list(APPEND HDRS conduitdatacollection.hpp)
|
||||
|
||||
@@ -729,7 +729,8 @@ void BilinearForm::Assemble(int skip_zeros)
|
||||
tr = mesh -> GetBdrFaceTransformations (i);
|
||||
if (tr != NULL)
|
||||
{
|
||||
fes -> GetElementVDofs (tr -> Elem1No, vdofs);
|
||||
mfem::DofTransformation doftrans;
|
||||
fes -> GetElementVDofs (tr -> Elem1No, vdofs, doftrans);
|
||||
fe1 = fes -> GetFE (tr -> Elem1No);
|
||||
// The fe2 object is really a dummy and not used on the boundaries,
|
||||
// but we can't dereference a NULL pointer, and we don't want to
|
||||
@@ -743,6 +744,7 @@ void BilinearForm::Assemble(int skip_zeros)
|
||||
|
||||
boundary_face_integs[k] -> AssembleFaceMatrix (*fe1, *fe2, *tr,
|
||||
elemmat);
|
||||
doftrans.TransformDual(elemmat);
|
||||
mat -> AddSubMatrix (vdofs, vdofs, elemmat, skip_zeros);
|
||||
}
|
||||
}
|
||||
@@ -1723,6 +1725,7 @@ void MixedBilinearForm::Assemble(int skip_zeros)
|
||||
}
|
||||
}
|
||||
|
||||
DofTransformation dom_dof_trans, ran_dof_trans;
|
||||
for (int i = 0; i < trial_fes -> GetNBE(); i++)
|
||||
{
|
||||
const int bdr_attr = mesh->GetBdrAttribute(i);
|
||||
@@ -1731,8 +1734,8 @@ void MixedBilinearForm::Assemble(int skip_zeros)
|
||||
ftr = mesh -> GetBdrFaceTransformations (i);
|
||||
if (ftr != NULL)
|
||||
{
|
||||
trial_fes->GetElementVDofs(ftr->Elem1No, trial_vdofs);
|
||||
test_fes->GetElementVDofs(ftr->Elem1No, test_vdofs);
|
||||
trial_fes->GetElementVDofs(ftr->Elem1No, trial_vdofs, dom_dof_trans);
|
||||
test_fes->GetElementVDofs(ftr->Elem1No, test_vdofs, ran_dof_trans);
|
||||
trial_fe1 = trial_fes->GetFE(ftr->Elem1No);
|
||||
test_fe1 = test_fes->GetFE(ftr->Elem1No);
|
||||
// The test_fe2 object is really a dummy and not used on the
|
||||
@@ -1748,6 +1751,7 @@ void MixedBilinearForm::Assemble(int skip_zeros)
|
||||
boundary_face_integs[k]->AssembleFaceMatrix(*trial_fe1, *test_fe1, *trial_fe2,
|
||||
*test_fe2,
|
||||
*ftr, elemmat);
|
||||
TransformDual(ran_dof_trans, dom_dof_trans, elemmat);
|
||||
mat->AddSubMatrix(test_vdofs, trial_vdofs, elemmat, skip_zeros);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -2710,7 +2710,7 @@ public:
|
||||
|
||||
|
||||
/** Integrator for $(-Q u, \nabla v)$ for Nedelec ($u$) and $H^1$ ($v$) elements.
|
||||
This is equivalent to a weak divergence of the $H(curl$ basis functions. */
|
||||
This is equivalent to a weak divergence of the $H(curl)$ basis functions. */
|
||||
class VectorFEWeakDivergenceIntegrator: public BilinearFormIntegrator
|
||||
{
|
||||
protected:
|
||||
|
||||
@@ -1453,8 +1453,6 @@ ConduitDataCollection::LoadMeshAndFields(int domain_id,
|
||||
std::string
|
||||
ConduitDataCollection::ElementTypeToShapeName(Element::Type element_type)
|
||||
{
|
||||
// Adapted from SidreDataCollection
|
||||
|
||||
// Note -- the mapping from Element::Type to string is based on
|
||||
// enum Element::Type { POINT, SEGMENT, TRIANGLE, QUADRILATERAL,
|
||||
// TETRAHEDRON, HEXAHEDRON };
|
||||
|
||||
@@ -34,10 +34,10 @@ namespace mfem
|
||||
- HDF5 library, https://support.hdfgroup.org/HDF5
|
||||
|
||||
@note The ConduitDataCollection only wraps the mfem objects to save them and
|
||||
creates them on load, Conduit does not own any of the data. The
|
||||
SidreDataCollection provides more features, for example the
|
||||
SidreDataCollection allocates and will own the data backing the mfem objects
|
||||
in the data collection.
|
||||
creates them on load, Conduit does not own any of the data.
|
||||
The MFEMSidreDataCollection in the Axom package (https://github.com/LLNL/axom)
|
||||
derives from mfem::DataCollection and provides more features, for example
|
||||
it allocates and will own the data backing the mfem objects in the data collection.
|
||||
|
||||
This class also provides public static methods that convert between MFEM
|
||||
Meshes and GridFunctions and Conduit Mesh Blueprint descriptions.
|
||||
|
||||
+3
-3
@@ -349,7 +349,7 @@ public:
|
||||
vector-valued finite elements, which is also the width of the
|
||||
DenseMatrix argument in
|
||||
CalcPhysVShape(ElementTransformation &Trans, DenseMatrix &shape). */
|
||||
int GetPhysRangeDim(int /* space_dim */) const { return vdim; }
|
||||
virtual int GetPhysRangeDim(int /* space_dim */) const { return vdim; }
|
||||
|
||||
/** Returns the dimension of the curl for vector-valued finite elements,
|
||||
which is also the width of the DenseMatrix argument in
|
||||
@@ -360,7 +360,7 @@ public:
|
||||
finite elements, which is also the width of the DenseMatrix argument in
|
||||
CalcPhysCurlShape(ElementTransformation &Trans, DenseMatrix &curl_shape).
|
||||
*/
|
||||
int GetPhysCurlDim(int /* space_dim */) const { return cdim; }
|
||||
virtual int GetPhysCurlDim(int /* space_dim */) const { return cdim; }
|
||||
|
||||
/// Returns the Geometry::Type of the reference element.
|
||||
Geometry::Type GetGeomType() const { return geom_type; }
|
||||
@@ -1017,7 +1017,7 @@ public:
|
||||
VectorFiniteElement(int D, Geometry::Type G, int Do, int O, int M,
|
||||
int F = FunctionSpace::Pk);
|
||||
|
||||
int GetPhysRangeDim(int space_dim) const { return space_dim; }
|
||||
int GetPhysRangeDim(int space_dim) const override { return space_dim; }
|
||||
};
|
||||
|
||||
/// @brief Class for computing 1D special polynomials and their associated basis
|
||||
|
||||
+4
-4
@@ -663,8 +663,8 @@ public:
|
||||
const int cb_type = BasisType::GaussLobatto,
|
||||
const int ob_type = BasisType::GaussLegendre);
|
||||
|
||||
int GetPhysRangeDim(int space_dim) const { return 2; }
|
||||
int GetPhysCurlDim(int space_dim) const { return 1; }
|
||||
int GetPhysRangeDim(int space_dim) const override { return 2; }
|
||||
int GetPhysCurlDim(int space_dim) const override { return 1; }
|
||||
|
||||
void CalcVShape(const IntegrationPoint &ip,
|
||||
DenseMatrix &shape) const override;
|
||||
@@ -708,8 +708,8 @@ private:
|
||||
DenseMatrix &I) const;
|
||||
|
||||
public:
|
||||
int GetPhysRangeDim(int space_dim) const { return 3; }
|
||||
int GetPhysCurlDim(int space_dim) const { return 3; }
|
||||
int GetPhysRangeDim(int space_dim) const override { return 3; }
|
||||
int GetPhysCurlDim(int space_dim) const override { return 3; }
|
||||
|
||||
using FiniteElement::CalcVShape;
|
||||
using FiniteElement::CalcPhysCurlShape;
|
||||
|
||||
+4
-4
@@ -510,8 +510,8 @@ public:
|
||||
RT_R2D_SegmentElement(const int p,
|
||||
const int ob_type = BasisType::GaussLegendre);
|
||||
|
||||
int GetPhysRangeDim(int space_dim) const { return 2; }
|
||||
int GetPhysCurlDim(int space_dim) const { return 0; }
|
||||
int GetPhysRangeDim(int space_dim) const override { return 2; }
|
||||
int GetPhysCurlDim(int space_dim) const override { return 0; }
|
||||
|
||||
void CalcVShape(const IntegrationPoint &ip,
|
||||
DenseMatrix &shape) const override;
|
||||
@@ -550,8 +550,8 @@ private:
|
||||
DenseMatrix &I) const;
|
||||
|
||||
public:
|
||||
int GetPhysRangeDim(int space_dim) const { return 3; }
|
||||
int GetPhysCurlDim(int space_dim) const { return 0; }
|
||||
int GetPhysRangeDim(int space_dim) const override { return 3; }
|
||||
int GetPhysCurlDim(int space_dim) const override { return 0; }
|
||||
|
||||
using FiniteElement::CalcVShape;
|
||||
|
||||
|
||||
@@ -62,10 +62,6 @@
|
||||
#include "pnonlinearform.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef MFEM_USE_SIDRE
|
||||
#include "sidredatacollection.hpp"
|
||||
#endif
|
||||
|
||||
#ifdef MFEM_USE_CONDUIT
|
||||
#include "conduitdatacollection.hpp"
|
||||
#endif
|
||||
|
||||
@@ -3934,6 +3934,16 @@ const FiniteElement *FiniteElementSpace::GetBE(int i) const
|
||||
return BE;
|
||||
}
|
||||
|
||||
const FiniteElement *FiniteElementSpace::GetTypicalBE() const
|
||||
{
|
||||
if (mesh->GetNBE() > 0) { return GetBE(0); }
|
||||
|
||||
Geometry::Type geom = mesh->GetTypicalFaceGeometry();
|
||||
const FiniteElement *be = fec->FiniteElementForGeometry(geom);
|
||||
MFEM_VERIFY(be != nullptr, "Could not determine a typical BE!");
|
||||
return be;
|
||||
}
|
||||
|
||||
const FiniteElement *FiniteElementSpace::GetFaceElement(int i) const
|
||||
{
|
||||
MFEM_VERIFY(!IsVariableOrder(), "not implemented");
|
||||
@@ -3964,6 +3974,11 @@ const FiniteElement *FiniteElementSpace::GetFaceElement(int i) const
|
||||
return fe;
|
||||
}
|
||||
|
||||
const FiniteElement *FiniteElementSpace::GetTypicalFaceElement() const
|
||||
{
|
||||
return fec->FiniteElementForGeometry(mesh->GetTypicalFaceGeometry());
|
||||
}
|
||||
|
||||
const FiniteElement *FiniteElementSpace::GetEdgeElement(int i,
|
||||
int variant) const
|
||||
{
|
||||
|
||||
+13
-1
@@ -839,7 +839,7 @@ public:
|
||||
Note: For vector-valued elements, the results pads up the range dimension
|
||||
to the spatial dimension. E.g., consider a stack of 5 vector-valued
|
||||
elements each representing 2D vectors, living in a 3 dimensional space.
|
||||
Then this fucntion would give 15, not 10.
|
||||
Then this function would give 15, not 10.
|
||||
*/
|
||||
int GetVectorDim() const;
|
||||
|
||||
@@ -1323,12 +1323,24 @@ public:
|
||||
associated with i'th boundary face in the mesh object. */
|
||||
const FiniteElement *GetBE(int i) const;
|
||||
|
||||
/// @brief Return a "typical" boundary element.
|
||||
///
|
||||
/// This can be used in situations where the local mesh partition may be
|
||||
/// empty.
|
||||
const FiniteElement *GetTypicalBE() const;
|
||||
|
||||
/** @brief Returns pointer to the FiniteElement in the FiniteElementCollection
|
||||
associated with i'th face in the mesh object. Faces in this case refer
|
||||
to the MESHDIM-1 primitive so in 2D they are segments and in 1D they are
|
||||
points.*/
|
||||
const FiniteElement *GetFaceElement(int i) const;
|
||||
|
||||
/// @brief Return a "typical" face element.
|
||||
///
|
||||
/// This can be used in situations where the local mesh partition may be
|
||||
/// empty.
|
||||
const FiniteElement *GetTypicalFaceElement() const;
|
||||
|
||||
/** @brief Returns pointer to the FiniteElement in the FiniteElementCollection
|
||||
associated with i'th edge in the mesh object. */
|
||||
const FiniteElement *GetEdgeElement(int i, int variant = 0) const;
|
||||
|
||||
+75
-65
@@ -345,27 +345,6 @@ void GridFunction::ComputeFlux(BilinearFormIntegrator &blfi,
|
||||
}
|
||||
}
|
||||
|
||||
int GridFunction::VectorDim() const
|
||||
{
|
||||
const FiniteElement *fe = fes->GetTypicalFE();
|
||||
if (!fe || fe->GetRangeType() == FiniteElement::SCALAR)
|
||||
{
|
||||
return fes->GetVDim();
|
||||
}
|
||||
return fes->GetVDim()*std::max(fes->GetMesh()->SpaceDimension(),
|
||||
fe->GetRangeDim());
|
||||
}
|
||||
|
||||
int GridFunction::CurlDim() const
|
||||
{
|
||||
const FiniteElement *fe = fes->GetTypicalFE();
|
||||
if (!fe || fe->GetRangeType() == FiniteElement::SCALAR)
|
||||
{
|
||||
return 2 * fes->GetMesh()->SpaceDimension() - 3;
|
||||
}
|
||||
return fes->GetVDim()*fe->GetCurlDim();
|
||||
}
|
||||
|
||||
void GridFunction::GetTrueDofs(Vector &tv) const
|
||||
{
|
||||
const SparseMatrix *R = fes->GetRestrictionMatrix();
|
||||
@@ -2050,6 +2029,18 @@ void GridFunction::AccumulateAndCountBdrValues(
|
||||
Coefficient *coeff[], VectorCoefficient *vcoeff, const Array<int> &attr,
|
||||
Array<int> &values_counter)
|
||||
{
|
||||
if (vcoeff)
|
||||
{
|
||||
MFEM_VERIFY(fes->GetVDim() == vcoeff->GetVDim(),
|
||||
"vcoeff vdim != fes VDim");
|
||||
MFEM_VERIFY(fes->GetTypicalBE()->GetMapType() == FiniteElement::VALUE &&
|
||||
fes->GetTypicalBE()->GetRangeType() ==
|
||||
FiniteElement::SCALAR,
|
||||
"Can only call ProjectBdrCoefficient on scalar value-type "
|
||||
"boundary elements. "
|
||||
"Did you intended to call ProjectBdrCoefficientNormal or "
|
||||
"ProjectBdrCoefficientTangent for vector finite elements?");
|
||||
}
|
||||
Array<int> vdofs;
|
||||
Vector vc;
|
||||
|
||||
@@ -2202,6 +2193,9 @@ void GridFunction::AccumulateAndCountBdrTangentValues(
|
||||
VectorCoefficient &vcoeff, const Array<int> &bdr_attr,
|
||||
Array<int> &values_counter)
|
||||
{
|
||||
MFEM_VERIFY(fes->GetTypicalBE()->GetPhysRangeDim(
|
||||
fes->GetMesh()->SpaceDimension()) == vcoeff.GetVDim(),
|
||||
"vcoeff vdim != PhysRangeDim");
|
||||
const FiniteElement *fe;
|
||||
ElementTransformation *T;
|
||||
Array<int> dofs;
|
||||
@@ -2355,6 +2349,9 @@ void GridFunction::ProjectDeltaCoefficient(DeltaCoefficient &delta_coeff,
|
||||
|
||||
void GridFunction::ProjectCoefficient(Coefficient &coeff, ProjectType type)
|
||||
{
|
||||
MFEM_VERIFY(
|
||||
VectorDim() == 1,
|
||||
"Cannot project scalar Coefficient onto vector GridFunction");
|
||||
DeltaCoefficient *delta_c = dynamic_cast<DeltaCoefficient *>(&coeff);
|
||||
DofTransformation doftrans;
|
||||
Array<int> vdofs;
|
||||
@@ -2630,6 +2627,7 @@ void GridFunction::ProjectCoefficient(
|
||||
void GridFunction::ProjectCoefficient(VectorCoefficient &vcoeff,
|
||||
ProjectType type)
|
||||
{
|
||||
MFEM_VERIFY(VectorDim() == vcoeff.GetVDim(), "vcoeff vdim != VectorDim()");
|
||||
Array<int> vdofs;
|
||||
Vector vals;
|
||||
DofTransformation doftrans;
|
||||
@@ -2945,6 +2943,7 @@ void GridFunction::ProjectCoefficientElementL2(VectorCoefficient &vcoeff)
|
||||
void GridFunction::ProjectCoefficient(
|
||||
VectorCoefficient &vcoeff, Array<int> &dofs)
|
||||
{
|
||||
MFEM_VERIFY(VectorDim() == vcoeff.GetVDim(), "vcoeff vdim != VectorDim()");
|
||||
int el = -1;
|
||||
ElementTransformation *T = NULL;
|
||||
const FiniteElement *fe = NULL;
|
||||
@@ -2974,6 +2973,7 @@ void GridFunction::ProjectCoefficient(
|
||||
|
||||
void GridFunction::ProjectCoefficient(VectorCoefficient &vcoeff, int attribute)
|
||||
{
|
||||
MFEM_VERIFY(VectorDim() == vcoeff.GetVDim(), "vcoeff vdim != VectorDim()");
|
||||
int i;
|
||||
Array<int> vdofs;
|
||||
Vector vals;
|
||||
@@ -3033,6 +3033,7 @@ void GridFunction::ProjectCoefficient(Coefficient *coeff[])
|
||||
void GridFunction::ProjectDiscCoefficient(VectorCoefficient &coeff,
|
||||
Array<int> &dof_attr)
|
||||
{
|
||||
MFEM_VERIFY(VectorDim() == coeff.GetVDim(), "coeff vdim != VectorDim()");
|
||||
Array<int> vdofs;
|
||||
Vector vals;
|
||||
|
||||
@@ -3064,6 +3065,7 @@ void GridFunction::ProjectDiscCoefficient(VectorCoefficient &coeff,
|
||||
|
||||
void GridFunction::ProjectDiscCoefficient(VectorCoefficient &coeff)
|
||||
{
|
||||
MFEM_VERIFY(VectorDim() == coeff.GetVDim(), "coeff vdim != VectorDim()");
|
||||
Array<int> dof_attr;
|
||||
ProjectDiscCoefficient(coeff, dof_attr);
|
||||
}
|
||||
@@ -3073,6 +3075,10 @@ void GridFunction::ProjectDiscCoefficient(Coefficient &coeff, AvgType type)
|
||||
// Harmonic (x1 ... xn) = [ (1/x1 + ... + 1/xn) / n ]^-1.
|
||||
// Arithmetic(x1 ... xn) = (x1 + ... + xn) / n.
|
||||
|
||||
MFEM_VERIFY(
|
||||
VectorDim() == 1,
|
||||
"Cannot project a scalar coefficient onto a vector GridFunction");
|
||||
|
||||
Array<int> zones_per_vdof;
|
||||
AccumulateAndCountZones(coeff, type, zones_per_vdof);
|
||||
|
||||
@@ -3082,6 +3088,7 @@ void GridFunction::ProjectDiscCoefficient(Coefficient &coeff, AvgType type)
|
||||
void GridFunction::ProjectDiscCoefficient(VectorCoefficient &coeff,
|
||||
AvgType type)
|
||||
{
|
||||
MFEM_VERIFY(VectorDim() == coeff.GetVDim(), "coeff vdim != VectorDim()");
|
||||
Array<int> zones_per_vdof;
|
||||
AccumulateAndCountZones(coeff, type, zones_per_vdof);
|
||||
|
||||
@@ -3137,52 +3144,33 @@ void GridFunction::ProjectBdrCoefficient(Coefficient *coeff[],
|
||||
}
|
||||
|
||||
void GridFunction::ProjectBdrCoefficientNormal(
|
||||
VectorCoefficient &vcoeff, const Array<int> &bdr_attr)
|
||||
Coefficient *coeff, VectorCoefficient *vcoeff, const Array<int> &bdr_attr)
|
||||
{
|
||||
#if 0
|
||||
// implementation for the case when the face dofs are integrals of the
|
||||
// normal component.
|
||||
const FiniteElement *fe;
|
||||
ElementTransformation *T;
|
||||
Array<int> dofs;
|
||||
int dim = vcoeff.GetVDim();
|
||||
Vector vc(dim), nor(dim), lvec, shape;
|
||||
|
||||
for (int i = 0; i < fes->GetNBE(); i++)
|
||||
MFEM_VERIFY(fes->GetVDim() == 1, "fespace VDim != 1");
|
||||
MFEM_VERIFY(fes->GetTypicalBE()->GetRangeType() == FiniteElement::SCALAR &&
|
||||
fes->GetTypicalBE()->GetMapType() == FiniteElement::INTEGRAL,
|
||||
"Not an RT FE space!");
|
||||
if (vcoeff)
|
||||
{
|
||||
if (bdr_attr[fes->GetBdrAttribute(i)-1] == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
fe = fes->GetBE(i);
|
||||
T = fes->GetBdrElementTransformation(i);
|
||||
int intorder = 2*fe->GetOrder(); // !!!
|
||||
const IntegrationRule &ir = IntRules.Get(fe->GetGeomType(), intorder);
|
||||
int nd = fe->GetDof();
|
||||
lvec.SetSize(nd);
|
||||
shape.SetSize(nd);
|
||||
lvec = 0.0;
|
||||
for (int j = 0; j < ir.GetNPoints(); j++)
|
||||
{
|
||||
const IntegrationPoint &ip = ir.IntPoint(j);
|
||||
T->SetIntPoint(&ip);
|
||||
vcoeff.Eval(vc, *T, ip);
|
||||
CalcOrtho(T->Jacobian(), nor);
|
||||
fe->CalcShape(ip, shape);
|
||||
lvec.Add(ip.weight * (vc * nor), shape);
|
||||
}
|
||||
fes->GetBdrElementDofs(i, dofs);
|
||||
SetSubVector(dofs, lvec);
|
||||
MFEM_VERIFY(vcoeff->GetVDim() == fes->GetMesh()->SpaceDimension(),
|
||||
"vcoeff vdim (" << vcoeff->GetVDim()
|
||||
<< ") != SpaceDimension ("
|
||||
<< fes->GetMesh()->SpaceDimension() << ")");
|
||||
}
|
||||
#else
|
||||
|
||||
// implementation for the case when the face dofs are scaled point
|
||||
// values of the normal component.
|
||||
const FiniteElement *fe;
|
||||
ElementTransformation *T;
|
||||
Array<int> dofs;
|
||||
int dim = vcoeff.GetVDim();
|
||||
Vector vc(dim), nor(dim), lvec;
|
||||
Vector vc, nor, lvec;
|
||||
DofTransformation doftrans;
|
||||
if (vcoeff)
|
||||
{
|
||||
const int dim = vcoeff->GetVDim();
|
||||
vc.SetSize(dim);
|
||||
nor.SetSize(dim);
|
||||
}
|
||||
|
||||
for (int i = 0; i < fes->GetNBE(); i++)
|
||||
{
|
||||
@@ -3198,15 +3186,22 @@ void GridFunction::ProjectBdrCoefficientNormal(
|
||||
{
|
||||
const IntegrationPoint &ip = ir.IntPoint(j);
|
||||
T->SetIntPoint(&ip);
|
||||
vcoeff.Eval(vc, *T, ip);
|
||||
CalcOrtho(T->Jacobian(), nor);
|
||||
lvec(j) = (vc * nor);
|
||||
if (coeff)
|
||||
{
|
||||
const real_t c = coeff->Eval(*T, ip);
|
||||
lvec(j) = c * T->Weight();
|
||||
}
|
||||
else if (vcoeff)
|
||||
{
|
||||
vcoeff->Eval(vc, *T, ip);
|
||||
CalcOrtho(T->Jacobian(), nor);
|
||||
lvec(j) = (vc * nor);
|
||||
}
|
||||
}
|
||||
fes->GetBdrElementDofs(i, dofs, doftrans);
|
||||
doftrans.TransformPrimal(lvec);
|
||||
SetSubVector(dofs, lvec);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void GridFunction::ProjectBdrCoefficientTangent(
|
||||
@@ -5007,6 +5002,14 @@ real_t ExtrudeCoefficient::Eval(ElementTransformation &T,
|
||||
return sol_in.Eval(*T_in, ip);
|
||||
}
|
||||
|
||||
void VectorExtrudeCoefficient::Eval(Vector &v, ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
ElementTransformation *T_in =
|
||||
mesh_in->GetElementTransformation(T.ElementNo / n);
|
||||
T_in->SetIntPoint(&ip);
|
||||
sol_in.Eval(v, *T_in, ip);
|
||||
}
|
||||
|
||||
GridFunction *Extrude1DGridFunction(Mesh *mesh, Mesh *mesh2d,
|
||||
GridFunction *sol, const int ny)
|
||||
@@ -5057,10 +5060,17 @@ GridFunction *Extrude1DGridFunction(Mesh *mesh, Mesh *mesh2d,
|
||||
return NULL;
|
||||
}
|
||||
FiniteElementSpace *solfes2d;
|
||||
// assuming sol is scalar
|
||||
solfes2d = new FiniteElementSpace(mesh2d, solfec2d);
|
||||
const int vdim = sol->FESpace()->GetVDim();
|
||||
solfes2d = new FiniteElementSpace(mesh2d, solfec2d, vdim);
|
||||
sol2d = new GridFunction(solfes2d);
|
||||
sol2d->MakeOwner(solfec2d);
|
||||
if (vdim > 1)
|
||||
{
|
||||
VectorGridFunctionCoefficient vcsol(sol);
|
||||
VectorExtrudeCoefficient vc2d(mesh, vcsol, ny);
|
||||
sol2d->ProjectCoefficient(vc2d);
|
||||
}
|
||||
else
|
||||
{
|
||||
GridFunctionCoefficient csol(sol);
|
||||
ExtrudeCoefficient c2d(mesh, csol, ny);
|
||||
@@ -5758,4 +5768,4 @@ std::pair<real_t, real_t> GridFunction::EstimateFunctionMaximum(
|
||||
return std::make_pair(global_max_lower, global_max_upper);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+69
-13
@@ -150,11 +150,13 @@ public:
|
||||
|
||||
FiniteElementCollection *OwnFEC() { return fec_owned; }
|
||||
|
||||
/// Shortcut for calling FiniteElementSpace::GetVectorDim() on the underlying #fes
|
||||
int VectorDim() const;
|
||||
/** @brief Shortcut for calling FiniteElementSpace::GetVectorDim() on the
|
||||
underlying #fes */
|
||||
int VectorDim() const { return fes->GetVectorDim(); }
|
||||
|
||||
/// Shortcut for calling FiniteElementSpace::GetCurlDim() on the underlying #fes
|
||||
int CurlDim() const;
|
||||
/** @brief Shortcut for calling FiniteElementSpace::GetCurlDim() on the
|
||||
underlying #fes */
|
||||
int CurlDim() const { return fes->GetCurlDim(); }
|
||||
|
||||
/// Read only access to the (optional) internal true-dof Vector.
|
||||
const Vector &GetTrueVector() const
|
||||
@@ -532,6 +534,9 @@ public:
|
||||
std::unique_ptr<GridFunction> ProlongateToMaxOrder() const;
|
||||
|
||||
protected:
|
||||
void ProjectBdrCoefficientNormal(Coefficient *coeff, VectorCoefficient *vcoeff,
|
||||
const Array<int> &attr);
|
||||
|
||||
/** @brief Accumulates (depending on @a type) the values of @a coeff at all
|
||||
shared vdofs and counts in how many zones each vdof appears. */
|
||||
void AccumulateAndCountZones(Coefficient &coeff, AvgType type,
|
||||
@@ -656,15 +661,26 @@ public:
|
||||
virtual void ProjectBdrCoefficient(Coefficient *coeff[],
|
||||
const Array<int> &attr);
|
||||
|
||||
/** Project the normal component of the given VectorCoefficient on
|
||||
the boundary. Only boundary attributes that are marked in
|
||||
'bdr_attr' are projected. Assumes RT-type VectorFE GridFunction. */
|
||||
/** @brief Project the normal component of the given VectorCoefficient on
|
||||
the boundary. */
|
||||
/** Only boundary attributes that are marked in @a bdr_attr are
|
||||
projected. Assumes RT-type vector finite element GridFunction. */
|
||||
void ProjectBdrCoefficientNormal(VectorCoefficient &vcoeff,
|
||||
const Array<int> &bdr_attr);
|
||||
const Array<int> &bdr_attr)
|
||||
{ ProjectBdrCoefficientNormal(NULL, &vcoeff, bdr_attr); }
|
||||
|
||||
/** @brief Project the given Coefficient in the normal direction on the
|
||||
boundary. */
|
||||
/** Only boundary attributes that are marked in @a bdr_attr are projected.
|
||||
Assumes RT-type vector finite element GridFunction. */
|
||||
void ProjectBdrCoefficientNormal(Coefficient &coeff,
|
||||
const Array<int> &bdr_attr)
|
||||
{ ProjectBdrCoefficientNormal(&coeff, NULL, bdr_attr); }
|
||||
|
||||
/** @brief Project the tangential components of the given VectorCoefficient
|
||||
on the boundary. Only boundary attributes that are marked in @a bdr_attr
|
||||
are projected. Assumes ND-type VectorFE GridFunction. */
|
||||
on the boundary. */
|
||||
/** Only boundary attributes that are marked in @a bdr_attr
|
||||
are projected. Assumes ND-type vector finite element GridFunction. */
|
||||
virtual void ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff,
|
||||
const Array<int> &bdr_attr);
|
||||
|
||||
@@ -1914,7 +1930,7 @@ real_t ComputeElementLpDistance(real_t p, int i,
|
||||
GridFunction& gf1, GridFunction& gf2);
|
||||
|
||||
|
||||
/// Class used for extruding scalar GridFunctions
|
||||
/// Class used for extruding a scalar coefficient
|
||||
class ExtrudeCoefficient : public Coefficient
|
||||
{
|
||||
private:
|
||||
@@ -1922,13 +1938,53 @@ private:
|
||||
Mesh *mesh_in;
|
||||
Coefficient &sol_in;
|
||||
public:
|
||||
/// Constructs an instance of VectorExtrudeCoefficient
|
||||
/**
|
||||
* @param m 1D mesh
|
||||
* @param s 1D vector coefficient
|
||||
* @param n_ number of transverse elements of the extruded mesh
|
||||
*/
|
||||
ExtrudeCoefficient(Mesh *m, Coefficient &s, int n_)
|
||||
: n(n_), mesh_in(m), sol_in(s) { }
|
||||
: n(n_), mesh_in(m), sol_in(s)
|
||||
{ MFEM_VERIFY(n > 0, "Number of transverse elements must be positive!"); }
|
||||
|
||||
real_t Eval(ElementTransformation &T, const IntegrationPoint &ip) override;
|
||||
|
||||
virtual ~ExtrudeCoefficient() { }
|
||||
};
|
||||
|
||||
/// Extrude a scalar 1D GridFunction, after extruding the mesh with Extrude1D.
|
||||
/// Class used for extruding a vector coefficient
|
||||
class VectorExtrudeCoefficient : public VectorCoefficient
|
||||
{
|
||||
private:
|
||||
int n;
|
||||
Mesh *mesh_in;
|
||||
VectorCoefficient &sol_in;
|
||||
public:
|
||||
/// Constructs an instance of VectorExtrudeCoefficient
|
||||
/**
|
||||
* @param m 1D mesh
|
||||
* @param s 1D vector coefficient
|
||||
* @param n_ number of transverse elements of the extruded mesh
|
||||
*/
|
||||
VectorExtrudeCoefficient(Mesh *m, VectorCoefficient &s, int n_)
|
||||
: VectorCoefficient(s.GetVDim()), n(n_), mesh_in(m), sol_in(s)
|
||||
{ MFEM_VERIFY(n > 0, "Number of transverse elements must be positive!"); }
|
||||
|
||||
void Eval(Vector &v, ElementTransformation &T,
|
||||
const IntegrationPoint &ip) override;
|
||||
using VectorCoefficient::Eval;
|
||||
|
||||
virtual ~VectorExtrudeCoefficient() { }
|
||||
};
|
||||
|
||||
/// Extrude a 1D GridFunction, after extruding the mesh with Extrude1D()
|
||||
/**
|
||||
* @param mesh 1D mesh
|
||||
* @param mesh2d extruded mesh
|
||||
* @param sol grid function
|
||||
* @param ny number of transverse elements of the extruded mesh
|
||||
*/
|
||||
GridFunction *Extrude1DGridFunction(Mesh *mesh, Mesh *mesh2d,
|
||||
GridFunction *sol, const int ny);
|
||||
|
||||
|
||||
@@ -197,15 +197,21 @@ static void EAHdivAssemble3D(const int NE,
|
||||
// Assemble (one row per thread)
|
||||
MFEM_FOREACH_THREAD(idx_i, x, NDOF)
|
||||
{
|
||||
// NOTE: due to an llvm backend bug, usage of the modulus operator
|
||||
// has been removed from this foreach section.
|
||||
const int ic = idx_i / NDOF_C;
|
||||
const int idx_ii = idx_i % NDOF_C;
|
||||
const int idx_ii = idx_i - ic * NDOF_C; // idx_i % NDOF_C
|
||||
|
||||
const int nx_i = (ic == 0) ? D1D : D1D-1;
|
||||
const int ny_i = (ic == 1) ? D1D : D1D-1;
|
||||
|
||||
const int ix = idx_ii % nx_i;
|
||||
const int iy = (idx_ii / nx_i) % ny_i;
|
||||
const int iz = (idx_ii / nx_i) / ny_i;
|
||||
const int qx_i = idx_ii / nx_i;
|
||||
const int ix = idx_ii - qx_i * nx_i; // idx_ii % nx_i
|
||||
|
||||
const int qy_i = qx_i / ny_i;
|
||||
const int iy = qx_i - qy_i * ny_i; // (idx_ii / nx_i) % ny_i
|
||||
|
||||
const int iz = qy_i; // (idx_ii / nx_i) / ny_i
|
||||
|
||||
const real_t (&Bi1)[MQ1][MD1] = (ic == 0) ? r_Bc : r_Bo;
|
||||
const real_t (&Bi2)[MQ1][MD1] = (ic == 1) ? r_Bc : r_Bo;
|
||||
@@ -214,14 +220,18 @@ static void EAHdivAssemble3D(const int NE,
|
||||
for (int idx_j = 0; idx_j < NDOF; ++idx_j)
|
||||
{
|
||||
const int jc = idx_j / NDOF_C;
|
||||
const int idx_jj = idx_j % NDOF_C;
|
||||
const int idx_jj = idx_j - jc * NDOF_C; // idx_j % NDOF_C
|
||||
|
||||
const int nx_j = (jc == 0) ? D1D : D1D-1;
|
||||
const int ny_j = (jc == 1) ? D1D : D1D-1;
|
||||
|
||||
const int jx = idx_jj % nx_j;
|
||||
const int jy = (idx_jj / nx_j) % ny_j;
|
||||
const int jz = (idx_jj / nx_j) / ny_j;
|
||||
const int qx_j = idx_jj / nx_j;
|
||||
const int jx = idx_jj - qx_j * nx_j; // idx_jj % nx_j
|
||||
|
||||
const int qy_j = qx_j / ny_j;
|
||||
const int jy = qx_j - qy_j * ny_j; // (idx_jj / nx_j) % ny_j
|
||||
|
||||
const int jz = qy_j; // (idx_jj / nx_j) / ny_j
|
||||
|
||||
const real_t (&Bj1)[MQ1][MD1] = (jc == 0) ? r_Bc : r_Bo;
|
||||
const real_t (&Bj2)[MQ1][MD1] = (jc == 1) ? r_Bc : r_Bo;
|
||||
|
||||
+811
-327
File diff suppressed because it is too large
Load Diff
+30
-27
@@ -125,18 +125,6 @@ private:
|
||||
void AddTriPoints3b(const int off, const real_t b, const real_t weight)
|
||||
{ AddTriPoints3(off, (1. - b)/2., b, weight); }
|
||||
|
||||
void AddTriPoints3R(const int off, const real_t a, const real_t b,
|
||||
const real_t c, const real_t weight)
|
||||
{
|
||||
IntPoint(off + 0).Set2w(a, b, weight);
|
||||
IntPoint(off + 1).Set2w(c, a, weight);
|
||||
IntPoint(off + 2).Set2w(b, c, weight);
|
||||
}
|
||||
|
||||
void AddTriPoints3R(const int off, const real_t a, const real_t b,
|
||||
const real_t weight)
|
||||
{ AddTriPoints3R(off, a, b, 1. - a - b, weight); }
|
||||
|
||||
void AddTriPoints6(const int off, const real_t a, const real_t b,
|
||||
const real_t c, const real_t weight)
|
||||
{
|
||||
@@ -183,14 +171,6 @@ private:
|
||||
AddTetPoints3(off + 1, a, 1. - 3.*a, weight);
|
||||
}
|
||||
|
||||
// given b, add the permutations of (a,a,a,b), where 3*a + b = 1
|
||||
void AddTetPoints4b(const int off, const real_t b, const real_t weight)
|
||||
{
|
||||
const real_t a = (1. - b)/3.;
|
||||
IntPoint(off).Set(a, a, a, weight);
|
||||
AddTetPoints3(off + 1, a, b, weight);
|
||||
}
|
||||
|
||||
// add the permutations of (a,a,b,b), 2*(a + b) = 1
|
||||
void AddTetPoints6(const int off, const real_t a, const real_t weight)
|
||||
{
|
||||
@@ -209,14 +189,37 @@ private:
|
||||
AddTetPoints6(off + 6, a, bc, cb, weight);
|
||||
}
|
||||
|
||||
// given (b,c), add the permutations of (a,a,b,c), 2*a + b + c = 1
|
||||
void AddTetPoints12bc(const int off, const real_t b, const real_t c,
|
||||
const real_t weight)
|
||||
// add all 24 permutations of (a,b,c,d) where a+b+c+d = 1, all distinct
|
||||
void AddTetPoints24(const int off, const real_t a, const real_t b,
|
||||
const real_t c, const real_t weight)
|
||||
{
|
||||
const real_t a = (1. - b - c)/2.;
|
||||
AddTetPoints3(off, a, b, weight);
|
||||
AddTetPoints3(off + 3, a, c, weight);
|
||||
AddTetPoints6(off + 6, a, b, c, weight);
|
||||
const real_t d = 1. - a - b - c;
|
||||
// all 24 permutations of 4 distinct barycentric coordinates
|
||||
// permuting which coordinate goes to x, y, z (4th is 1-x-y-z)
|
||||
IntPoint(off + 0).Set(a, b, c, weight);
|
||||
IntPoint(off + 1).Set(a, b, d, weight);
|
||||
IntPoint(off + 2).Set(a, c, b, weight);
|
||||
IntPoint(off + 3).Set(a, c, d, weight);
|
||||
IntPoint(off + 4).Set(a, d, b, weight);
|
||||
IntPoint(off + 5).Set(a, d, c, weight);
|
||||
IntPoint(off + 6).Set(b, a, c, weight);
|
||||
IntPoint(off + 7).Set(b, a, d, weight);
|
||||
IntPoint(off + 8).Set(b, c, a, weight);
|
||||
IntPoint(off + 9).Set(b, c, d, weight);
|
||||
IntPoint(off + 10).Set(b, d, a, weight);
|
||||
IntPoint(off + 11).Set(b, d, c, weight);
|
||||
IntPoint(off + 12).Set(c, a, b, weight);
|
||||
IntPoint(off + 13).Set(c, a, d, weight);
|
||||
IntPoint(off + 14).Set(c, b, a, weight);
|
||||
IntPoint(off + 15).Set(c, b, d, weight);
|
||||
IntPoint(off + 16).Set(c, d, a, weight);
|
||||
IntPoint(off + 17).Set(c, d, b, weight);
|
||||
IntPoint(off + 18).Set(d, a, b, weight);
|
||||
IntPoint(off + 19).Set(d, a, c, weight);
|
||||
IntPoint(off + 20).Set(d, b, a, weight);
|
||||
IntPoint(off + 21).Set(d, b, c, weight);
|
||||
IntPoint(off + 22).Set(d, c, a, weight);
|
||||
IntPoint(off + 23).Set(d, c, b, weight);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
+3
-1
@@ -297,7 +297,8 @@ void LinearForm::Assemble()
|
||||
tr = mesh->GetBdrFaceTransformations(i);
|
||||
if (tr != NULL)
|
||||
{
|
||||
fes -> GetElementVDofs (tr -> Elem1No, vdofs);
|
||||
mfem::DofTransformation doftrans;
|
||||
fes -> GetElementVDofs (tr -> Elem1No, vdofs, doftrans);
|
||||
for (int k = 0; k < boundary_face_integs.Size(); k++)
|
||||
{
|
||||
if (boundary_face_integs_marker[k] &&
|
||||
@@ -307,6 +308,7 @@ void LinearForm::Assemble()
|
||||
boundary_face_integs[k]->
|
||||
AssembleRHSElementVect(*fes->GetFE(tr->Elem1No),
|
||||
*tr, elemvect);
|
||||
doftrans.TransformDual(elemvect);
|
||||
AddElementVector (vdofs, elemvect);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -545,6 +545,8 @@ void ParGridFunction::GetElementDofValues(int el, Vector &dof_vals) const
|
||||
|
||||
void ParGridFunction::ProjectCoefficient(Coefficient &coeff, ProjectType type)
|
||||
{
|
||||
MFEM_VERIFY(VectorDim() == 1,
|
||||
"Cannot project scalar coefficient onto vector ParGridFunction");
|
||||
DeltaCoefficient *delta_c = dynamic_cast<DeltaCoefficient *>(&coeff);
|
||||
|
||||
if (delta_c == NULL)
|
||||
@@ -717,6 +719,7 @@ void ParGridFunction::ProjectCoefficientElementL2(VectorCoefficient &vcoeff)
|
||||
|
||||
void ParGridFunction::ProjectDiscCoefficient(VectorCoefficient &coeff)
|
||||
{
|
||||
MFEM_VERIFY(VectorDim() == coeff.GetVDim(), "coeff vdim != VectorDim()");
|
||||
// local maximal element attribute for each dof
|
||||
Array<int> ldof_attr;
|
||||
|
||||
@@ -761,6 +764,9 @@ void ParGridFunction::ProjectDiscCoefficient(VectorCoefficient &coeff)
|
||||
|
||||
void ParGridFunction::ProjectDiscCoefficient(Coefficient &coeff, AvgType type)
|
||||
{
|
||||
MFEM_VERIFY(
|
||||
VectorDim() == 1,
|
||||
"Cannot project scalar coefficient onto a vector ParGridFunction");
|
||||
// Harmonic (x1 ... xn) = [ (1/x1 + ... + 1/xn) / n ]^-1.
|
||||
// Arithmetic(x1 ... xn) = (x1 + ... + xn) / n.
|
||||
|
||||
@@ -786,6 +792,8 @@ void ParGridFunction::ProjectDiscCoefficient(VectorCoefficient &vcoeff,
|
||||
// Harmonic (x1 ... xn) = [ (1/x1 + ... + 1/xn) / n ]^-1.
|
||||
// Arithmetic(x1 ... xn) = (x1 + ... + xn) / n.
|
||||
|
||||
MFEM_VERIFY(VectorDim() == vcoeff.GetVDim(), "vcoeff vdim != VectorDim()");
|
||||
|
||||
// Number of zones that contain a given dof.
|
||||
Array<int> zones_per_vdof;
|
||||
AccumulateAndCountZones(vcoeff, type, zones_per_vdof);
|
||||
@@ -858,6 +866,12 @@ void ParGridFunction::ProjectBdrCoefficient(
|
||||
#endif
|
||||
}
|
||||
|
||||
void ParGridFunction::ProjectBdrCoefficient(VectorCoefficient &vcoeff,
|
||||
const Array<int> &attr)
|
||||
{
|
||||
ProjectBdrCoefficient(NULL, &vcoeff, attr);
|
||||
}
|
||||
|
||||
void ParGridFunction::ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff,
|
||||
const Array<int> &bdr_attr)
|
||||
{
|
||||
|
||||
+1
-2
@@ -280,8 +280,7 @@ public:
|
||||
using GridFunction::ProjectBdrCoefficient;
|
||||
|
||||
void ProjectBdrCoefficient(VectorCoefficient &vcoeff,
|
||||
const Array<int> &attr) override
|
||||
{ ProjectBdrCoefficient(NULL, &vcoeff, attr); }
|
||||
const Array<int> &attr) override;
|
||||
|
||||
void ProjectBdrCoefficient(Coefficient *coeff[],
|
||||
const Array<int> &attr) override
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,539 +0,0 @@
|
||||
// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
// LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
//
|
||||
// This file is part of the MFEM library. For more information and source code
|
||||
// availability visit https://mfem.org.
|
||||
//
|
||||
// MFEM is free software; you can redistribute it and/or modify it under the
|
||||
// terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
// CONTRIBUTING.md for details.
|
||||
|
||||
#ifndef MFEM_SIDREDATACOLLECTION
|
||||
#define MFEM_SIDREDATACOLLECTION
|
||||
|
||||
#include "../config/config.hpp"
|
||||
|
||||
#ifdef MFEM_USE_SIDRE
|
||||
|
||||
#include "datacollection.hpp"
|
||||
|
||||
// Ignore warnings from the axom/sidre header (GCC + Clang versions)
|
||||
#ifdef MFEM_HAVE_GCC_PRAGMA_DIAGNOSTIC
|
||||
# pragma GCC diagnostic push
|
||||
# if defined(__clang__)
|
||||
# pragma GCC diagnostic ignored "-Wextra-semi"
|
||||
# else // real GCC?
|
||||
# pragma GCC diagnostic ignored "-Wpedantic"
|
||||
# endif
|
||||
#endif
|
||||
#include <axom/sidre.hpp>
|
||||
#ifdef MFEM_HAVE_GCC_PRAGMA_DIAGNOSTIC
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
/** @brief Data collection with Sidre routines following the Conduit mesh
|
||||
blueprint specification. */
|
||||
/** SidreDataCollection provides an HDF5-based file format for visualization or
|
||||
restart capability. This functionality is aimed primarily at customers of
|
||||
LLNL's axom project that run problems at extreme scales.
|
||||
|
||||
For more information, see:
|
||||
- Sidre component of LLNL's axom project (to be open-sourced), http://goo.gl/cZyJdn
|
||||
- LLNL conduit/blueprint library, https://github.com/LLNL/conduit
|
||||
- HDF5 library, https://support.hdfgroup.org/HDF5
|
||||
|
||||
The layout created in the Sidre DataStore is: (`"──"` denote groups,
|
||||
`"─•"` denote views, `"─>"` denote links, i.e. shallow-copy view)
|
||||
|
||||
<root>
|
||||
├── <collection-name>_global (global group)
|
||||
│ └── blueprint_index
|
||||
│ └── <collection-name> (bp_index group)
|
||||
│ ├── state
|
||||
│ │ ├─• cycle
|
||||
│ │ ├─• time
|
||||
│ │ └─• number_of_domains = <mesh-mpi-comm-size>
|
||||
│ ├── coordsets
|
||||
│ │ └── coords
|
||||
│ │ ├─• path = "<bp-path>/coordsets/coords"
|
||||
│ │ ├─• type ─> <bp-grp>/coordsets/coords/type = "explicit"
|
||||
│ │ └─• coord_system = "x"|"xy"|"xyz"
|
||||
│ ├── topologies
|
||||
│ │ ├── mesh
|
||||
│ │ │ ├─• path = "<bp-path>/topologies/mesh"
|
||||
│ │ │ ├─• type ─> <bp-grp>/topologies/mesh/type = "unstructured"
|
||||
│ │ │ ├─• coordset ─> <bp-grp>/topologies/mesh/coordset = "coords"
|
||||
│ │ │ ├─• grid_function ─> <bp-grp>/topologies/mesh/grid_function = "<nodes-field-name>"
|
||||
│ │ │ └─• boundary_topology ─> <bp-grp>/topologies/mesh/boundary_topology = "boundary"
|
||||
│ │ └── boundary
|
||||
│ │ ├─• path = "<bp-path>/topologies/mesh"
|
||||
│ │ ├─• type ─> <bp-grp>/topologies/boundary/type = "unstructured"
|
||||
│ │ └─• coordset ─> <bp-grp>/topologies/boundary/coordset = "coords"
|
||||
│ └── fields
|
||||
│ ├── mesh_material_attribute
|
||||
│ │ ├─• path = "<bp-path>/fields/mesh_material_attribute"
|
||||
│ │ ├─• association ─> <bp-grp>/fields/mesh_material_attribute/association = "element"
|
||||
│ │ ├─• topology ─> <bp-grp>/fields/mesh_material_attribute/topology = "mesh"
|
||||
│ │ └─• number_of_components = 1
|
||||
│ ├── boundary_material_attribute
|
||||
│ │ ├─• path = "<bp-path>/fields/boundary_material_attribute"
|
||||
│ │ ├─• association ─> <bp-grp>/fields/boundary_material_attribute/association = "element"
|
||||
│ │ ├─• topology ─> <bp-grp>/fields/boundary_material_attribute/topology = "boundary"
|
||||
│ │ └─• number_of_components = 1
|
||||
│ ├── grid-function-1
|
||||
│ │ ├─• path = "<bp-path>/fields/grid-function-1"
|
||||
│ │ ├─• basis ─> <bp-grp>/fields/grid-function-1/basis = "<fe-coll-name>"
|
||||
│ │ ├─• topology ─> <bp-grp>/fields/grid-function-1/topology = "mesh"
|
||||
│ │ └─• number_of_components = gf1->VectorDim()
|
||||
│ ├── grid-function-2
|
||||
│ │ ├─• path = "<bp-path>/fields/grid-function-2"
|
||||
│ │ ├─• basis ─> <bp-grp>/fields/grid-function-2/basis = "<fe-coll-name>"
|
||||
│ │ ├─• topology ─> <bp-grp>/fields/grid-function-2/topology = "mesh"
|
||||
│ │ └─• number_of_components = gf2->VectorDim()
|
||||
│ ├── ...
|
||||
│ ...
|
||||
└── <collection-name> (domain group)
|
||||
├── blueprint (blueprint group)
|
||||
│ ├── state
|
||||
│ │ ├─• cycle
|
||||
│ │ ├─• time
|
||||
│ │ ├─• domain = <mesh-mpi-rank>
|
||||
│ │ └─• time_step
|
||||
│ ├── coordsets
|
||||
│ │ └── coords
|
||||
│ │ ├─• type = "explicit"
|
||||
│ │ └── values
|
||||
│ │ ├─• x = view in <vertex-coords-buffer>/<ext-double-data>
|
||||
│ │ ├─• y = view in <vertex-coords-buffer>/<ext-double-data>
|
||||
│ │ └─• z = view in <vertex-coords-buffer>/<ext-double-data>
|
||||
│ ├── topologies
|
||||
│ │ ├── mesh
|
||||
│ │ │ ├─• type = "unstructured"
|
||||
│ │ │ ├── elements
|
||||
│ │ │ │ ├─• shape = "points"|"lines"|...
|
||||
│ │ │ │ └─• connectivity = <vert-idx-array>
|
||||
│ │ │ ├─• coordset = "coords"
|
||||
│ │ │ ├─• grid_function = "<nodes-field-name>"
|
||||
│ │ │ └─• boundary_topology = "boundary"
|
||||
│ │ └── boundary
|
||||
│ │ ├─• type = "unstructured"
|
||||
│ │ ├── elements
|
||||
│ │ │ ├─• shape = "points"|"lines"|...
|
||||
│ │ │ └─• connectivity = <vert-idx-array>
|
||||
│ │ └─• coordset = "coords"
|
||||
│ └── fields
|
||||
│ ├── mesh_material_attribute
|
||||
│ │ ├─• association = "element"
|
||||
│ │ ├─• topology = "mesh"
|
||||
│ │ └─• values = <attr-array>
|
||||
│ ├── boundary_material_attribute
|
||||
│ │ ├─• association = "element"
|
||||
│ │ ├─• topology = "boundary"
|
||||
│ │ └─• values = <attr-array>
|
||||
│ ├── grid-function-1 (name can include path)
|
||||
│ │ ├─• basis = "<fe-coll-name>"
|
||||
│ │ ├─• topology = "mesh"
|
||||
│ │ └─• values = <ext-double-array>/<named-buffer> (vdim == 1)
|
||||
│ ├── grid-function-2 (name can include path)
|
||||
│ │ ├─• basis = "<fe-coll-name>"
|
||||
│ │ ├─• topology = "mesh"
|
||||
│ │ └── values (vdim > 1)
|
||||
│ │ ├─• x0 = view into <ext-double-array>/<named-buffer>
|
||||
│ │ ├─• x1 = view into <ext-double-array>/<named-buffer>
|
||||
│ │ └─• x2 = view into <ext-double-array>/<named-buffer>
|
||||
│ ├── ...
|
||||
│ ...
|
||||
└── named_buffers (named_buffers group)
|
||||
├─• vertex_coords = <double-array>
|
||||
├─• grid-function-1 = <double-array>
|
||||
├─• grid-function-2 = <double-array>
|
||||
...
|
||||
|
||||
@note blueprint_index is used both in serial and in parallel. In parallel,
|
||||
only rank 0 will add entries to the blueprint index.
|
||||
|
||||
@note QuadratureFunction%s (q-fields) are not supported.
|
||||
|
||||
@note SidreDataCollection does not manage the FiniteElementSpace%s and
|
||||
FiniteElementCollection%s associated with registered GridFunction%s.
|
||||
Therefore, field registration is left to the user of SidreDataCollection and
|
||||
there are no methods that automatically register GridFunction%s using just
|
||||
the content of the Sidre DataStore. Such capabilities can be implemented in
|
||||
a derived class, adding any desired object management routines.
|
||||
|
||||
@warning This class is still _experimental_, meaning that in future
|
||||
releases, it may not be backward compatible, and the output files generated
|
||||
by the current version may become unreadable.
|
||||
*/
|
||||
class SidreDataCollection : public DataCollection
|
||||
{
|
||||
public:
|
||||
typedef NamedFieldsMap< Array<int> > AttributeFieldMap;
|
||||
AttributeFieldMap attr_map;
|
||||
|
||||
public:
|
||||
|
||||
/// Constructor that allocates and initializes a Sidre DataStore.
|
||||
/**
|
||||
@param[in] collection_name Name of the collection used as a file name
|
||||
when saving
|
||||
@param[in] the_mesh Mesh shared by all grid functions in the
|
||||
collection (can be NULL)
|
||||
@param[in] owns_mesh_data Does the SidreDC own the mesh vertices?
|
||||
|
||||
With this constructor, the SidreDataCollection owns the allocated Sidre
|
||||
DataStore.
|
||||
*/
|
||||
SidreDataCollection(const std::string& collection_name,
|
||||
Mesh *the_mesh = NULL,
|
||||
bool owns_mesh_data = false);
|
||||
|
||||
/// Constructor that links to an external Sidre DataStore.
|
||||
/** Specifically, the global and domain groups can be at arbitrary paths.
|
||||
|
||||
@param[in] collection_name Name of the collection used as a file name
|
||||
when saving
|
||||
@param[in] bp_index_grp Pointer to the blueprint index group in the
|
||||
datastore, see the above schematic
|
||||
@param[in] domain_grp Pointer to the domain group in the datastore,
|
||||
see the above schematic
|
||||
@param[in] owns_mesh_data Does the SidreDC own the mesh vertices?
|
||||
|
||||
With this constructor, the SidreDataCollection does not own the Sidre
|
||||
DataStore.
|
||||
@note No mesh or fields are read from the given Groups. The mesh has
|
||||
to be set with SetMesh() and fields registered with RegisterField().
|
||||
*/
|
||||
SidreDataCollection(const std::string& collection_name,
|
||||
axom::sidre::Group * bp_index_grp,
|
||||
axom::sidre::Group * domain_grp,
|
||||
bool owns_mesh_data = false);
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
/// Associate an MPI communicator with the collection.
|
||||
/** If no mesh was associated with the collection, this method should be
|
||||
called before using any of the Load() methods to read parallel data. */
|
||||
void SetComm(MPI_Comm comm);
|
||||
#endif
|
||||
|
||||
/// Register a GridFunction in the Sidre DataStore.
|
||||
/** This method is a shortcut for the call
|
||||
`RegisterField(field_name, gf, field_name, 0)`.
|
||||
*/
|
||||
virtual void RegisterField(const std::string &field_name, GridFunction *gf)
|
||||
{
|
||||
RegisterField(field_name, gf, field_name, 0);
|
||||
}
|
||||
|
||||
/// Register a GridFunction in the Sidre DataStore.
|
||||
/** The registration procedure is as follows:
|
||||
- if (@a gf's data is NULL), allocate named buffer with the name
|
||||
@a buffer_name with size _offset + gf->FESpace()->GetVSize()_ and use
|
||||
its data (plus the given @a offset) to set @a gf's data;
|
||||
- else, if (DataStore has a named buffer @a buffer_name), replace @a gf's
|
||||
data array with that named buffer plus the given @a offset;
|
||||
- else, use @a gf's data as external data associated with @a field_name
|
||||
in the DataStore;
|
||||
- register @a field_name in #field_map.
|
||||
|
||||
Both the @a field_name and @a buffer_name can contain a path prefix.
|
||||
@note If @a field_name or @a buffer_name is empty, the method does
|
||||
nothing.
|
||||
@note If the GridFunction pointer @a gf or it's FiniteElementSpace
|
||||
pointer are NULL, the method does nothing.
|
||||
*/
|
||||
void RegisterField(const std::string &field_name, GridFunction *gf,
|
||||
const std::string &buffer_name,
|
||||
axom::sidre::IndexType offset);
|
||||
|
||||
/// Registers an attribute field in the Sidre DataStore
|
||||
/** The registration process is similar to that of RegisterField()
|
||||
The attribute field is associated with the elements of the mesh
|
||||
when @a is_bdry is false, and with the boundary elements, when
|
||||
@a is_bdry is true.
|
||||
@sa RegisterField() */
|
||||
void RegisterAttributeField(const std::string& name, bool is_bdry);
|
||||
void DeregisterAttributeField(const std::string& name);
|
||||
|
||||
/** Returns a pointer to the attribute field associated with
|
||||
@a field_name, or NULL when there is no associated field */
|
||||
Array<int>* GetAttributeField(const std::string& field_name) const
|
||||
{ return attr_map.Get(field_name); }
|
||||
|
||||
/** Checks if there is an attribute field associated with @a field_name */
|
||||
bool HasAttributeField(const std::string& field_name) const
|
||||
{ return attr_map.Has(field_name); }
|
||||
|
||||
/** Checks if any rank in the mesh has boundary elements */
|
||||
bool HasBoundaryMesh() const;
|
||||
|
||||
/// Set the name of the mesh nodes field.
|
||||
/** This name will be used by SetMesh() to register the mesh nodes, if not
|
||||
already registered. Also, this method should be called if the mesh nodes
|
||||
GridFunction was or will be registered directly by the user. The default
|
||||
value for the name is "mesh_nodes". */
|
||||
void SetMeshNodesName(const std::string &nodes_name)
|
||||
{
|
||||
if (!nodes_name.empty()) { m_meshNodesGFName = nodes_name; }
|
||||
}
|
||||
|
||||
/// De-register @a field_name from the SidreDataCollection.
|
||||
/** The field is removed from the #field_map and the DataStore, including
|
||||
deleting it from the named_buffers group, if allocated. */
|
||||
virtual void DeregisterField(const std::string& field_name);
|
||||
|
||||
/// Delete all owned data.
|
||||
virtual ~SidreDataCollection();
|
||||
|
||||
/// Set/change the mesh associated with the collection
|
||||
/** Uses the field name "mesh_nodes" or the value set by SetMeshNodesName()
|
||||
to register the mesh nodes GridFunction, if the mesh uses nodes. */
|
||||
virtual void SetMesh(Mesh *new_mesh);
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
/// Set/change the mesh associated with the collection
|
||||
/** Uses the field name "mesh_nodes" or the value set by SetMeshNodesName()
|
||||
to register the mesh nodes GridFunction, if the mesh uses nodes. */
|
||||
virtual void SetMesh(MPI_Comm comm, Mesh *new_mesh);
|
||||
#endif
|
||||
|
||||
/// Reset the domain and global datastore group pointers.
|
||||
/** These are set in the constructor, but if a host code changes the
|
||||
datastore contents ( such as wiping out the datastore and loading in new
|
||||
contents from a file, i.e. a restart ) these pointers will need to be
|
||||
reset to valid groups in the datastore.
|
||||
@sa Load(const std::string &path, const std::string &protocol).
|
||||
*/
|
||||
void SetGroupPointers(axom::sidre::Group * global_grp,
|
||||
axom::sidre::Group * domain_grp);
|
||||
|
||||
axom::sidre::Group * GetBPGroup() { return m_bp_grp; }
|
||||
axom::sidre::Group * GetBPIndexGroup() { return m_bp_index_grp; }
|
||||
|
||||
/// Prepare the DataStore for writing
|
||||
virtual void PrepareToSave();
|
||||
|
||||
/// Save the collection to file.
|
||||
/** This method calls `Save(collection_name, "sidre_hdf5")`. */
|
||||
virtual void Save();
|
||||
|
||||
/// Save the collection to @a filename.
|
||||
/** The collection path prefix is prepended to the @a filename and the
|
||||
current cycle is appended, if cycle >= 0. */
|
||||
void Save(const std::string& filename, const std::string& protocol);
|
||||
|
||||
/// Load the Sidre DataStore from file.
|
||||
/** No mesh or fields are read from the loaded DataStore.
|
||||
|
||||
If the data collection created the datastore, it knows the layout of
|
||||
where the domain and global groups are, and can restore them after the
|
||||
Load().
|
||||
|
||||
If, however, the data collection does not own the datastore (e.g. it did
|
||||
not create the datastore), the host code must reset these pointers after
|
||||
the load operation, using SetGroupPointers(), and also reset the state
|
||||
variables, using UpdateStateFromDS().
|
||||
*/
|
||||
void Load(const std::string& path, const std::string& protocol);
|
||||
|
||||
/// Load SidreDataCollection from file.
|
||||
/** The used file path is based on the current prefix path, collection name,
|
||||
and the given @a cycle_. The protocol is "sidre_hdf5".
|
||||
@sa Load(const std::string &path, const std::string &protocol).
|
||||
*/
|
||||
virtual void Load(int cycle_ = 0)
|
||||
{
|
||||
SetCycle(cycle_);
|
||||
Load(get_file_path(name), "sidre_hdf5");
|
||||
}
|
||||
|
||||
/// Load external data after registering externally owned fields.
|
||||
void LoadExternalData(const std::string& path);
|
||||
|
||||
/** @brief Updates the DataCollection's cycle, time, and time-step variables
|
||||
with the values from the data store. */
|
||||
void UpdateStateFromDS();
|
||||
|
||||
/** @brief Updates the data store's cycle, time, and time-step variables with
|
||||
the values from the SidreDataCollection. */
|
||||
void UpdateStateToDS();
|
||||
|
||||
/** @name Methods for named buffer access and manipulation. */
|
||||
///@{
|
||||
|
||||
/** @brief Get a pointer to the sidre::View holding the named buffer for
|
||||
@a buffer_name. */
|
||||
/** If such named buffer is not allocated, the method returns NULL.
|
||||
@note To access the underlying pointer, use View::getData().
|
||||
@note To query the size of the buffer, use View::getNumElements().
|
||||
*/
|
||||
axom::sidre::View *
|
||||
GetNamedBuffer(const std::string& buffer_name) const
|
||||
{
|
||||
return named_buffers_grp()->hasView(buffer_name)
|
||||
? named_buffers_grp()->getView(buffer_name)
|
||||
: NULL;
|
||||
}
|
||||
|
||||
/// Return newly allocated or existing named buffer for @a buffer_name.
|
||||
/** The buffer is stored in the named_buffers group. If the currently
|
||||
allocated buffer size is smaller than @a sz, then the buffer is
|
||||
reallocated with size @a sz, destroying its contents.
|
||||
@note To access the underlying pointer, use View::getData().
|
||||
*/
|
||||
axom::sidre::View *
|
||||
AllocNamedBuffer(const std::string& buffer_name,
|
||||
axom::sidre::IndexType sz,
|
||||
axom::sidre::TypeID type =
|
||||
axom::sidre::DOUBLE_ID);
|
||||
|
||||
/// Deallocate the named buffer @a buffer_name.
|
||||
void FreeNamedBuffer(const std::string& buffer_name)
|
||||
{ named_buffers_grp()->destroyViewAndData(buffer_name); }
|
||||
|
||||
///@}
|
||||
|
||||
private:
|
||||
// Used if the Sidre data collection is providing the datastore itself.
|
||||
const bool m_owns_datastore;
|
||||
|
||||
// TODO - Need to evaluate if this bool member can be combined with own_data
|
||||
// in parent data collection class. m_owns_mesh_data indicates whether the
|
||||
// Sidre dc owns the mesh element data and node positions gf. The DC base
|
||||
// class own_data indicates if the dc owns the mesh object pointer itself and
|
||||
// GF objects. Can we use one flag and just have DC own all objects vs none?
|
||||
const bool m_owns_mesh_data;
|
||||
|
||||
// Name to be used for registering the mesh nodes in the SidreDataCollection.
|
||||
// This name is used by SetMesh() and can be overwritten by the method
|
||||
// SetMeshNodesName().
|
||||
// Default value: "mesh_nodes".
|
||||
std::string m_meshNodesGFName;
|
||||
|
||||
// If the data collection owns the datastore, it will store a pointer to it.
|
||||
// Otherwise, this pointer is NULL.
|
||||
axom::sidre::DataStore * m_datastore_ptr;
|
||||
|
||||
protected:
|
||||
axom::sidre::Group *named_buffers_grp() const;
|
||||
|
||||
axom::sidre::View *
|
||||
alloc_view(axom::sidre::Group *grp,
|
||||
const std::string &view_name);
|
||||
|
||||
axom::sidre::View *
|
||||
alloc_view(axom::sidre::Group *grp,
|
||||
const std::string &view_name,
|
||||
const axom::sidre::DataType &dtype);
|
||||
|
||||
axom::sidre::Group *
|
||||
alloc_group(axom::sidre::Group *grp,
|
||||
const std::string &group_name);
|
||||
|
||||
// return the filename based on prefix_path, collection name and cycle.
|
||||
std::string get_file_path(const std::string &filename) const;
|
||||
|
||||
private:
|
||||
// If the data collection does not own the datastore, it will need pointers
|
||||
// to the blueprint and blueprint index group to use.
|
||||
axom::sidre::Group * m_bp_grp;
|
||||
axom::sidre::Group * m_bp_index_grp;
|
||||
|
||||
// This is stored for convenience.
|
||||
axom::sidre::Group * m_named_bufs_grp;
|
||||
|
||||
// Private helper functions
|
||||
|
||||
void RegisterFieldInBPIndex(const std::string& field_name,
|
||||
GridFunction *gf);
|
||||
void DeregisterFieldInBPIndex(const std::string & field_name);
|
||||
|
||||
void RegisterAttributeFieldInBPIndex(const std::string& attr_name);
|
||||
void DeregisterAttributeFieldInBPIndex(const std::string& attr_name);
|
||||
|
||||
/** @brief Return a string with the conduit blueprint name for the given
|
||||
Element::Type. */
|
||||
std::string getElementName( Element::Type elementEnum );
|
||||
|
||||
/**
|
||||
* \brief A private helper function to set up the views associated with the
|
||||
data of a scalar valued grid function in the blueprint style.
|
||||
* \pre gf is not null
|
||||
* \note This function is expected to be called by RegisterField()
|
||||
* \note Handles cases where hierarchy is already set up,
|
||||
* where the data was allocated by this data collection
|
||||
* and where the grid function data is external to Sidre
|
||||
*/
|
||||
void addScalarBasedGridFunction(const std::string& field_name,
|
||||
GridFunction* gf,
|
||||
const std::string &buffer_name,
|
||||
axom::sidre::IndexType offset);
|
||||
|
||||
/**
|
||||
* \brief A private helper function to set up the views associated with the
|
||||
data of a vector valued grid function in the blueprint style.
|
||||
* \pre gf is not null
|
||||
* \note This function is expected to be called by RegisterField()
|
||||
* \note Handles cases where hierarchy is already set up,
|
||||
* where the data was allocated by this data collection
|
||||
* and where the grid function data is external to Sidre
|
||||
*/
|
||||
void addVectorBasedGridFunction(const std::string& field_name,
|
||||
GridFunction* gf,
|
||||
const std::string &buffer_name,
|
||||
axom::sidre::IndexType offset);
|
||||
|
||||
/** @brief A private helper function to set up the Views associated with
|
||||
attribute field named @a field_name */
|
||||
void addIntegerAttributeField(const std::string& field_name, bool is_bdry);
|
||||
|
||||
/// Sets up the four main mesh blueprint groups.
|
||||
/**
|
||||
* \param hasBP Indicates whether the blueprint has already been set up.
|
||||
*/
|
||||
void createMeshBlueprintStubs(bool hasBP);
|
||||
|
||||
/// Sets up the mesh blueprint 'state' group.
|
||||
/**
|
||||
* \param hasBP Indicates whether the blueprint has already been set up.
|
||||
*/
|
||||
void createMeshBlueprintState(bool hasBP);
|
||||
|
||||
/// Sets up the mesh blueprint 'coordsets' group.
|
||||
/**
|
||||
* \param hasBP Indicates whether the blueprint has already been set up.
|
||||
*/
|
||||
void createMeshBlueprintCoordset(bool hasBP);
|
||||
|
||||
/// Sets up the mesh blueprint 'topologies' group.
|
||||
/**
|
||||
* This method is called from SetMesh().
|
||||
* \param hasBP Indicates whether the blueprint has already been set up.
|
||||
* \param mesh_name The name of the topology.
|
||||
* \note Valid values for @a mesh_name are "mesh" and "boundary" and the
|
||||
former has to be created with this method before the latter.
|
||||
*/
|
||||
void createMeshBlueprintTopologies(bool hasBP, const std::string& mesh_name);
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
/// Sets up the mesh blueprint 'adjacencies' group.
|
||||
/**
|
||||
* \param hasBP Indicates whether the blueprint has already been set up.
|
||||
* \note Only valid when using parallel meshes
|
||||
*/
|
||||
void createMeshBlueprintAdjacencies(bool hasBP);
|
||||
#endif
|
||||
|
||||
/// Verifies that the contents of the mesh blueprint data is valid.
|
||||
void verifyMeshBlueprint();
|
||||
};
|
||||
|
||||
} // end namespace mfem
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -278,9 +278,18 @@ void ArraysByName<T>::Load(std::istream &in)
|
||||
q1 = ArrayLine.find(' ');
|
||||
ArrayName = ArrayLine.substr(0,q1-1);
|
||||
}
|
||||
|
||||
// Ignore the remainder of the line which may contain explanatory comments
|
||||
data[ArrayName].Load(in, 0);
|
||||
if (q1+2 < ArrayLine.size())
|
||||
{
|
||||
// Read the remainder of the line which contains the array data
|
||||
std::istringstream ArrayDataStream(ArrayLine.substr(q1+2,
|
||||
ArrayLine.size()));
|
||||
data[ArrayName].Load(ArrayDataStream, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Read the array data starting on the next line
|
||||
data[ArrayName].Load(in, 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+4
-4
@@ -726,16 +726,16 @@ std::string Device::GetUUID(const int device_id)
|
||||
MFEM_GPU_CHECK(cudaGetDeviceProperties(&prop, device_id));
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
res << std::setfill('0') << std::setw(2) << std::hex
|
||||
<< static_cast<unsigned>(prop.uuid.bytes[i]);
|
||||
const unsigned b = static_cast<unsigned char>(prop.uuid.bytes[i]);
|
||||
res << std::setfill('0') << std::setw(2) << std::hex << b;
|
||||
}
|
||||
#elif defined(MFEM_USE_HIP)
|
||||
hipUUID uuid;
|
||||
MFEM_GPU_CHECK(hipDeviceGetUuid(&uuid, device_id));
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
res << std::setfill('0') << std::setw(2) << std::hex
|
||||
<< static_cast<unsigned>(uuid.bytes[i]);
|
||||
const unsigned b = static_cast<unsigned char>(uuid.bytes[i]);
|
||||
res << std::setfill('0') << std::setw(2) << std::hex << b;
|
||||
}
|
||||
#endif
|
||||
return res.str();
|
||||
|
||||
@@ -160,9 +160,6 @@ const char *GetConfigStr()
|
||||
#ifdef MFEM_USE_RAJA
|
||||
"MFEM_USE_RAJA\n"
|
||||
#endif
|
||||
#ifdef MFEM_USE_SIDRE
|
||||
"MFEM_USE_SIDRE\n"
|
||||
#endif
|
||||
#ifdef MFEM_USE_SIMD
|
||||
"MFEM_USE_SIMD\n"
|
||||
#endif
|
||||
|
||||
@@ -317,6 +317,9 @@ void HypreParVector::WrapHypreParVector(hypre_ParVector *y, bool owner)
|
||||
|
||||
Vector * HypreParVector::GlobalVector() const
|
||||
{
|
||||
MFEM_VERIFY(size > 0,
|
||||
"GlobalVector method can only be called on vectors wherein each "
|
||||
"process owns one or more entries");
|
||||
hypre_Vector *hv = hypre_ParVectorToVectorAll(*this);
|
||||
Vector *v = new Vector(hv->data, internal::to_int(hv->size));
|
||||
v->MakeDataOwner();
|
||||
|
||||
+17
-6
@@ -4156,20 +4156,31 @@ void PetscNonlinearSolver::SetUpdate(void (*update)(Operator *,int,
|
||||
void PetscNonlinearSolver::Mult(const Vector &b, Vector &x) const
|
||||
{
|
||||
SNES snes = (SNES)obj;
|
||||
MPI_Comm comm = PetscObjectComm(obj);
|
||||
|
||||
bool b_nonempty = b.Size();
|
||||
if (!B) { B = new PetscParVector(PetscObjectComm(obj), *this, true); }
|
||||
if (!X) { X = new PetscParVector(PetscObjectComm(obj), *this, false, false); }
|
||||
// Reduction needed: some processes may have null local size while others don't,
|
||||
// and VecPlaceArray (used by PlaceMemory) is a logically collective operation.
|
||||
PetscBool b_nonempty = b.Size() ? PETSC_TRUE : PETSC_FALSE;
|
||||
#if PETSC_VERSION_LT(3,24,0)
|
||||
mpiierr = MPI_Allreduce(MPI_IN_PLACE,&b_nonempty,1,MPIU_BOOL,MPI_LOR,comm);
|
||||
#else
|
||||
mpiierr = MPI_Allreduce(MPI_IN_PLACE,&b_nonempty,1,MPI_C_BOOL,MPI_LOR,comm);
|
||||
#endif
|
||||
CCHKERRQ(comm,mpiierr);
|
||||
|
||||
// Always create B with allocate=false so that PlaceMemory can be called on
|
||||
// it regardless of whether b was empty on a previous call.
|
||||
if (!B) { B = new PetscParVector(comm, *this, true, false); }
|
||||
if (!X) { X = new PetscParVector(comm, *this, false, false); }
|
||||
X->PlaceMemory(x.GetMemory(),iterative_mode);
|
||||
if (b_nonempty) { B->PlaceMemory(b.GetMemory()); }
|
||||
else { *B = 0.0; }
|
||||
|
||||
Customize();
|
||||
|
||||
if (!iterative_mode) { *X = 0.; }
|
||||
|
||||
// Solve the system.
|
||||
ierr = SNESSolve(snes, B->x, X->x); PCHKERRQ(snes, ierr);
|
||||
// Solve the system. Pass nullptr for b when empty (PETSc treats it as zero RHS).
|
||||
ierr = SNESSolve(snes, b_nonempty ? B->x : nullptr, X->x); PCHKERRQ(snes, ierr);
|
||||
X->ResetMemory();
|
||||
if (b_nonempty) { B->ResetMemory(); }
|
||||
}
|
||||
|
||||
@@ -299,7 +299,7 @@ ifeq ($(MFEM_USE_LEGACY_OPENMP),YES)
|
||||
endif
|
||||
|
||||
# List of MFEM dependencies, that require the *_LIB variable to be non-empty
|
||||
MFEM_REQ_LIB_DEPS = SUPERLU MUMPS METIS FMS CONDUIT SIDRE LAPACK SUNDIALS\
|
||||
MFEM_REQ_LIB_DEPS = SUPERLU MUMPS METIS FMS CONDUIT LAPACK SUNDIALS\
|
||||
SUITESPARSE STRUMPACK GINKGO GNUTLS HDF5 NETCDF SLEPC PETSC MPFR PUMI HIOP\
|
||||
GSLIB OCCA CEED RAJA UMPIRE MKL_CPARDISO MKL_PARDISO AMGX MAGMA CALIPER PARELAG\
|
||||
TRIBOL BENCHMARK MOONOLITH ALGOIM
|
||||
@@ -365,7 +365,7 @@ MFEM_DEFINES = MFEM_VERSION MFEM_VERSION_STRING MFEM_GIT_STRING MFEM_USE_MPI\
|
||||
MFEM_USE_LEGACY_OPENMP MFEM_USE_MEMALLOC MFEM_TIMER_TYPE MFEM_USE_SUNDIALS\
|
||||
MFEM_USE_SUITESPARSE MFEM_USE_GINKGO MFEM_USE_SUPERLU MFEM_USE_SUPERLU5\
|
||||
MFEM_USE_STRUMPACK MFEM_USE_GNUTLS MFEM_USE_HDF5 MFEM_USE_NETCDF MFEM_USE_PETSC\
|
||||
MFEM_USE_SLEPC MFEM_USE_MPFR MFEM_USE_SIDRE MFEM_USE_FMS MFEM_USE_CONDUIT\
|
||||
MFEM_USE_SLEPC MFEM_USE_MPFR MFEM_USE_FMS MFEM_USE_CONDUIT\
|
||||
MFEM_USE_PUMI MFEM_USE_HIOP MFEM_USE_GSLIB MFEM_USE_CUDA MFEM_USE_HIP\
|
||||
MFEM_USE_OCCA MFEM_USE_MOONOLITH MFEM_USE_CEED MFEM_USE_RAJA MFEM_USE_UMPIRE\
|
||||
MFEM_USE_SIMD MFEM_USE_ADIOS2 MFEM_USE_MKL_CPARDISO MFEM_USE_MKL_PARDISO MFEM_USE_AMGX\
|
||||
@@ -746,7 +746,6 @@ status info:
|
||||
$(info MFEM_USE_PETSC = $(MFEM_USE_PETSC))
|
||||
$(info MFEM_USE_SLEPC = $(MFEM_USE_SLEPC))
|
||||
$(info MFEM_USE_MPFR = $(MFEM_USE_MPFR))
|
||||
$(info MFEM_USE_SIDRE = $(MFEM_USE_SIDRE))
|
||||
$(info MFEM_USE_FMS = $(MFEM_USE_FMS))
|
||||
$(info MFEM_USE_CONDUIT = $(MFEM_USE_CONDUIT))
|
||||
$(info MFEM_USE_PUMI = $(MFEM_USE_PUMI))
|
||||
|
||||
@@ -3206,10 +3206,22 @@ public:
|
||||
|
||||
|
||||
/// Extrude a 1D mesh
|
||||
/**
|
||||
* @param mesh 1D mesh
|
||||
* @param ny number of transverse elements of the extruded mesh
|
||||
* @param sy physical size in the direction of extrusion
|
||||
* @param closed if false, only the original boundaries are extruded,
|
||||
* otherwise boundaries are generated all around the domain
|
||||
*/
|
||||
Mesh *Extrude1D(Mesh *mesh, const int ny, const real_t sy,
|
||||
const bool closed = false);
|
||||
|
||||
/// Extrude a 2D mesh
|
||||
/**
|
||||
* @param mesh 2D mesh
|
||||
* @param nz number of transverse elements of the extruded mesh
|
||||
* @param sz physical size in the direction of extrusion
|
||||
*/
|
||||
Mesh *Extrude2D(Mesh *mesh, const int nz, const real_t sz);
|
||||
|
||||
/** @brief Constructs the smallest possible [0,1]^dim serial mesh that can be
|
||||
|
||||
@@ -1516,12 +1516,15 @@ void Mesh::ReadInlineMesh(std::istream &input, bool generate_edges)
|
||||
void Mesh::ReadGmshMesh(std::istream &input, int &curved, int &read_gf)
|
||||
{
|
||||
string buff;
|
||||
real_t version;
|
||||
string version;
|
||||
int binary, dsize;
|
||||
input >> version >> binary >> dsize;
|
||||
if (version < 2.2)
|
||||
if (version != "2.2")
|
||||
{
|
||||
MFEM_ABORT("Gmsh file version < 2.2");
|
||||
MFEM_ABORT("Gmsh file version must be 2.2, found version "
|
||||
<< version << ".\n"
|
||||
"To convert your mesh to the required format, use:\n"
|
||||
" gmsh -format msh22 -save -o output.msh input.msh");
|
||||
}
|
||||
if (dsize != sizeof(double))
|
||||
{
|
||||
|
||||
@@ -5639,6 +5639,12 @@ Mesh ParMesh::GetSerialMesh(int save_rank) const
|
||||
}
|
||||
}
|
||||
|
||||
if (MyRank == save_rank)
|
||||
{
|
||||
attribute_sets.Copy(serialmesh.attribute_sets);
|
||||
bdr_attribute_sets.Copy(serialmesh.bdr_attribute_sets);
|
||||
}
|
||||
|
||||
MPI_Barrier(MyComm);
|
||||
return serialmesh;
|
||||
}
|
||||
|
||||
@@ -82,6 +82,43 @@ Although Tribol can be built automatically via **uberenv** and **Spack**,
|
||||
for this miniapp it is simpler to build **Axom** and **MFEM** manually and
|
||||
point Tribol to them. The steps are as follows:
|
||||
|
||||
### Using pre-built Tribol/Axom installs
|
||||
|
||||
If you already have compatible installs of Tribol and Axom, point MFEM to the install prefixes.
|
||||
|
||||
- Hypre install prefix: `<path/to/hypre>`
|
||||
- METIS install prefix: `<path/to/metis>`
|
||||
- Axom install prefix: `<path/to/axom>`
|
||||
- Tribol install prefix: `<path/to/tribol>`
|
||||
|
||||
**MFEM make build (configure):**
|
||||
```bash
|
||||
make config MFEM_USE_MPI=YES MFEM_USE_METIS=YES MFEM_USE_TRIBOL=YES \
|
||||
HYPRE_DIR=<path/to/hypre> METIS_DIR=<path/to/metis> \
|
||||
AXOM_DIR=<path/to/axom> TRIBOL_DIR=<path/to/tribol> ADIAK_DIR=<path/to/adiak> CAMP_DIR=<path/to/camp> RAJA_DIR=<path/to/raja> \
|
||||
UMPIRE_DIR=<path/to/umpire> FMT_DIR=<path/to/fmt> CALIPER_DIR=<path/to/caliper>
|
||||
```
|
||||
|
||||
**MFEM CMake build (configure):**
|
||||
```bash
|
||||
cmake -S . -B <mfem-build-dir> -DMFEM_USE_MPI=YES -DMFEM_USE_METIS=YES -DMFEM_USE_TRIBOL=YES \
|
||||
HYPRE_DIR=<path/to/hypre> METIS_DIR=<path/to/metis> \
|
||||
AXOM_DIR=<path/to/axom> TRIBOL_DIR=<path/to/tribol> ADIAK_DIR=<path/to/adiak> CAMP_DIR=<path/to/camp> RAJA_DIR=<path/to/raja> \
|
||||
UMPIRE_DIR=<path/to/umpire> FMT_DIR=<path/to/fmt> CALIPER_DIR=<path/to/caliper>
|
||||
```
|
||||
|
||||
Note: RAJA/UMPIRE/CALIPER are optional for MFEM itself, but many Tribol builds
|
||||
enable them. If your Tribol install does not depend on them, you can omit the
|
||||
corresponding `*_DIR` entries above.
|
||||
|
||||
Note: `FMT_DIR` only needs to be added for the make-based build (and only when
|
||||
the Umpire install uses `fmt`). If `FMT_DIR` is not set and a sibling `fmt-*`
|
||||
directory exists next to your `UMPIRE_DIR`, MFEM's make configuration will try
|
||||
to pick it up automatically.
|
||||
|
||||
Note: when using pre-built Tribol/Axom, you typically need to use a compatible
|
||||
compiler/MPI wrapper (same C++ standard library ABI).
|
||||
|
||||
### Manual Build Steps
|
||||
|
||||
1. Pull axom and tribol (starting from the mfem folder):
|
||||
@@ -99,7 +136,7 @@ point Tribol to them. The steps are as follows:
|
||||
TRIBOL_DIR = @MFEM_DIR@/../tribol-repo/tribol
|
||||
TRIBOL_OPT = -I$(TRIBOL_DIR)/include -I$(AXOM_DIR)/include
|
||||
TRIBOL_LIB = -L$(TRIBOL_DIR)/lib -ltribol -lredecomp -L$(AXOM_DIR)/lib \
|
||||
-laxom_mint -laxom_slam -laxom_slic -laxom_core
|
||||
-laxom_quest -laxom_mint -laxom_slam -laxom_slic -laxom_lumberjack -laxom_core
|
||||
```
|
||||
3. [**Axom:**](https://github.com/LLNL/axom.git) Starting from the MFEM root
|
||||
directory (we assume this directory is named mfem):
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
//
|
||||
// Currently supported data collection type options:
|
||||
// visit: VisItDataCollection (default)
|
||||
// sidre or sidre_hdf5: SidreDataCollection
|
||||
// json: ConduitDataCollection w/ protocol json
|
||||
// conduit_json: ConduitDataCollection w/ protocol conduit_json
|
||||
// conduit_bin: ConduitDataCollection w/ protocol conduit_bin
|
||||
@@ -52,14 +51,6 @@ DataCollection *create_data_collection(const std::string &dc_name,
|
||||
dc = new VisItDataCollection(MPI_COMM_WORLD, dc_name);
|
||||
#else
|
||||
dc = new VisItDataCollection(dc_name);
|
||||
#endif
|
||||
}
|
||||
else if ( dc_type == "sidre" || dc_type == "sidre_hdf5")
|
||||
{
|
||||
#ifdef MFEM_USE_SIDRE
|
||||
dc = new SidreDataCollection(dc_name);
|
||||
#else
|
||||
MFEM_ABORT("Must build with MFEM_USE_SIDRE=YES for sidre support.");
|
||||
#endif
|
||||
}
|
||||
else if ( dc_type == "json" ||
|
||||
@@ -140,7 +131,6 @@ int main(int argc, char *argv[])
|
||||
args.AddOption(&src_coll_type, "-st", "--source-type",
|
||||
"Set the source data collection type. Options:\n"
|
||||
"\t visit: VisItDataCollection (default)\n"
|
||||
"\t sidre or sidre_hdf5: SidreDataCollection\n"
|
||||
"\t json: ConduitDataCollection w/ protocol json\n"
|
||||
"\t conduit_json: ConduitDataCollection w/ protocol conduit_json\n"
|
||||
"\t conduit_bin: ConduitDataCollection w/ protocol conduit_bin\n"
|
||||
@@ -152,7 +142,6 @@ int main(int argc, char *argv[])
|
||||
args.AddOption(&out_coll_type, "-ot", "--output-type",
|
||||
"Set the output data collection type. Options:\n"
|
||||
"\t visit: VisItDataCollection (default)\n"
|
||||
"\t sidre or sidre_hdf5: SidreDataCollection\n"
|
||||
"\t json: ConduitDataCollection w/ protocol json\n"
|
||||
"\t conduit_json: ConduitDataCollection w/ protocol conduit_json\n"
|
||||
"\t conduit_bin: ConduitDataCollection w/ protocol conduit_bin\n"
|
||||
|
||||
@@ -71,6 +71,7 @@ set(UNIT_TESTS_SRCS
|
||||
linalg/test_ode2.cpp
|
||||
linalg/test_operator.cpp
|
||||
linalg/test_particlevector.cpp
|
||||
linalg/test_petsc_nonlinear.cpp
|
||||
linalg/test_sparsesmoothers.cpp
|
||||
linalg/test_vector.cpp
|
||||
mesh/mesh_test_utils.cpp
|
||||
|
||||
@@ -105,39 +105,39 @@ TEST_CASE("Integration rule order initialization", "[IntegrationRules]")
|
||||
SECTION("Segment rule constructed by accessing square rule")
|
||||
{
|
||||
auto &quad5_ir = intrules.Get(Geometry::SQUARE, 5);
|
||||
REQUIRE(quad5_ir.GetOrder() == 5);
|
||||
REQUIRE(quad5_ir.GetOrder() >= 5);
|
||||
// The segment integration rule of order 5 is lazy constructed when we get
|
||||
// the square integration rule of order 5. Make sure its order was
|
||||
// properly set:
|
||||
auto &line5_ir = intrules.Get(Geometry::SEGMENT, 5);
|
||||
REQUIRE(line5_ir.GetOrder() == 5);
|
||||
REQUIRE(line5_ir.GetOrder() >= 5);
|
||||
}
|
||||
|
||||
SECTION("Segment rule constructed by accessing cube rule")
|
||||
{
|
||||
auto &hex7_ir = intrules.Get(Geometry::CUBE, 7);
|
||||
REQUIRE(hex7_ir.GetOrder() == 7);
|
||||
REQUIRE(hex7_ir.GetOrder() >= 7);
|
||||
// The segment integration rule of order 7 is lazy constructed when we get
|
||||
// the cube integration rule of order 7. Make sure its order was properly
|
||||
// set:
|
||||
auto &line7_ir = intrules.Get(Geometry::SEGMENT, 7);
|
||||
REQUIRE(line7_ir.GetOrder() == 7);
|
||||
REQUIRE(line7_ir.GetOrder() >= 7);
|
||||
}
|
||||
|
||||
SECTION("Segment and triangle rules constructed by accessing prism rule")
|
||||
{
|
||||
auto &prism3_ir = intrules.Get(Geometry::PRISM, 3);
|
||||
REQUIRE(prism3_ir.GetOrder() == 3);
|
||||
REQUIRE(prism3_ir.GetOrder() >= 3);
|
||||
// The segment integration rule of order 3 is lazy constructed when we get
|
||||
// the prism integration rule of order 3. Make sure its order was properly
|
||||
// set:
|
||||
auto &line3_ir = intrules.Get(Geometry::SEGMENT, 3);
|
||||
REQUIRE(line3_ir.GetOrder() == 3);
|
||||
REQUIRE(line3_ir.GetOrder() >= 3);
|
||||
// The triangle integration rule of order 3 is lazy constructed when we
|
||||
// get the prism integration rule of order 3. Make sure its order was
|
||||
// properly set:
|
||||
auto &tri3_ir = intrules.Get(Geometry::TRIANGLE, 3);
|
||||
REQUIRE(tri3_ir.GetOrder() == 3);
|
||||
REQUIRE(tri3_ir.GetOrder() >= 3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,3 +271,43 @@ TEST_CASE("Simplex integration rules", "[SimplexRules]")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Monomial exactness is tested by [SimplexRules] above, which now uses
|
||||
// positive-weight rules by default. The tests below verify properties
|
||||
// specific to the positive-weight rules: weight positivity, stability,
|
||||
// and interior point placement.
|
||||
|
||||
TEST_CASE("Simplex rule positivity", "[IntegrationRules]")
|
||||
{
|
||||
IntegrationRules rules;
|
||||
|
||||
SECTION("triangle rules have all positive weights for orders 0-25")
|
||||
{
|
||||
for (int order = 0; order <= 25; order++)
|
||||
{
|
||||
const IntegrationRule &ir = rules.Get(Geometry::TRIANGLE, order);
|
||||
for (int i = 0; i < ir.GetNPoints(); i++)
|
||||
{
|
||||
INFO("order=" << order << ", point=" << i);
|
||||
REQUIRE(ir.IntPoint(i).weight > 0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("tet rules have all positive weights for orders 0-20")
|
||||
{
|
||||
for (int order = 0; order <= 20; order++)
|
||||
{
|
||||
const IntegrationRule &ir =
|
||||
rules.Get(Geometry::TETRAHEDRON, order);
|
||||
for (int i = 0; i < ir.GetNPoints(); i++)
|
||||
{
|
||||
INFO("order=" << order << ", point=" << i);
|
||||
REQUIRE(ir.IntPoint(i).weight > 0.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -25,15 +25,201 @@ void Func_3D_lin(const Vector &x, Vector &v)
|
||||
v[2] = -2.572 * x[0] + 1.321 * x[1] + 3.234 * x[2];
|
||||
}
|
||||
|
||||
TEST_CASE("3D ProjectBdrCoefficientNormal Vector",
|
||||
"[GridFunction]"
|
||||
"[VectorGridFunctionCoefficient]")
|
||||
{
|
||||
const int n = 1;
|
||||
const int dim = 3;
|
||||
const int order = 1;
|
||||
|
||||
const double tol = 1e-6;
|
||||
|
||||
for (int type = (int)Element::TETRAHEDRON;
|
||||
type <= (int)Element::HEXAHEDRON; type++)
|
||||
{
|
||||
Mesh mesh = Mesh::MakeCartesian3D(
|
||||
n, n, n, (Element::Type)type, 2.0, 3.0, 5.0);
|
||||
|
||||
VectorFunctionCoefficient funcCoef(dim, Func_3D_lin);
|
||||
|
||||
SECTION("3D GetVectorValue tests for element type " +
|
||||
std::to_string(type))
|
||||
{
|
||||
RT_FECollection rt_fec(order+1, dim);
|
||||
|
||||
FiniteElementSpace rt_fespace(&mesh, &rt_fec);
|
||||
|
||||
GridFunction rt_x( &rt_fespace);
|
||||
|
||||
VectorGridFunctionCoefficient rt_xCoef( &rt_x);
|
||||
|
||||
Array<int> bdr_marker(6);
|
||||
|
||||
Vector normal(dim);
|
||||
Vector f_val(dim);
|
||||
Vector rt_val(dim);
|
||||
|
||||
for (int b = 1; b<=6; b++)
|
||||
{
|
||||
bdr_marker = 0;
|
||||
bdr_marker[b-1] = 1;
|
||||
|
||||
rt_x = 0.0;
|
||||
rt_x.ProjectBdrCoefficientNormal(funcCoef, bdr_marker);
|
||||
|
||||
for (int be = 0; be < mesh.GetNBE(); be++)
|
||||
{
|
||||
Element *e = mesh.GetBdrElement(be);
|
||||
if (e->GetAttribute() != b) { continue; }
|
||||
|
||||
ElementTransformation *T = mesh.GetBdrElementTransformation(be);
|
||||
const FiniteElement *fe = rt_fespace.GetBE(be);
|
||||
const IntegrationRule &ir = IntRules.Get(fe->GetGeomType(),
|
||||
2*order + 2);
|
||||
|
||||
double rt_err = 0.0;
|
||||
|
||||
for (int j=0; j<ir.GetNPoints(); j++)
|
||||
{
|
||||
const IntegrationPoint &ip = ir.IntPoint(j);
|
||||
T->SetIntPoint(&ip);
|
||||
|
||||
CalcOrtho(T->Jacobian(), normal);
|
||||
|
||||
funcCoef.Eval(f_val, *T, ip);
|
||||
rt_xCoef.Eval(rt_val, *T, ip);
|
||||
|
||||
rt_val -= f_val;
|
||||
|
||||
double rt_dist = rt_val * normal;
|
||||
|
||||
rt_err += rt_dist;
|
||||
|
||||
if (verbose_tests && rt_dist > tol)
|
||||
{
|
||||
mfem::out << be << ":" << j << " rt ("
|
||||
<< f_val[0] << "," << f_val[1] << "," << f_val[2]
|
||||
<< ") vs. ("
|
||||
<< rt_val[0] << "," << rt_val[1] << ","
|
||||
<< rt_val[2] << ") " << rt_dist << std::endl;
|
||||
}
|
||||
}
|
||||
rt_err /= ir.GetNPoints();
|
||||
|
||||
REQUIRE( rt_err == MFEM_Approx(0.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("3D ProjectBdrCoefficientNormal Scalar",
|
||||
"[GridFunction]"
|
||||
"[VectorGridFunctionCoefficient]")
|
||||
{
|
||||
const int n = 1;
|
||||
const int dim = 3;
|
||||
const int order = 1;
|
||||
|
||||
const double tol = 1e-6;
|
||||
|
||||
const char bdrs_axis[] = {2, 1, 0, 1, 0, 2};
|
||||
const char bdrs_sign[] = {-1, -1, +1, +1, -1, +1};
|
||||
|
||||
for (int type = (int)Element::TETRAHEDRON;
|
||||
type <= (int)Element::HEXAHEDRON; type++)
|
||||
{
|
||||
Mesh mesh = Mesh::MakeCartesian3D(
|
||||
n, n, n, (Element::Type)type, 2.0, 3.0, 5.0);
|
||||
|
||||
VectorFunctionCoefficient funcCoef(dim, Func_3D_lin);
|
||||
|
||||
SECTION("3D GetVectorValue tests for element type " +
|
||||
std::to_string(type))
|
||||
{
|
||||
RT_FECollection rt_fec(order+1, dim);
|
||||
|
||||
FiniteElementSpace rt_fespace(&mesh, &rt_fec);
|
||||
|
||||
GridFunction rt_x( &rt_fespace);
|
||||
|
||||
VectorGridFunctionCoefficient rt_xCoef( &rt_x);
|
||||
|
||||
Array<int> bdr_marker(6);
|
||||
|
||||
Vector normal(dim);
|
||||
Vector f_val(dim);
|
||||
Vector rt_val(dim);
|
||||
|
||||
for (int b = 1; b<=6; b++)
|
||||
{
|
||||
bdr_marker = 0;
|
||||
bdr_marker[b-1] = 1;
|
||||
|
||||
rt_x = 0.0;
|
||||
|
||||
normal = 0.;
|
||||
normal(bdrs_axis[b-1]) = (bdrs_sign[b-1] > 0)?(+1.):(-1.);
|
||||
VectorConstantCoefficient normCoef(normal);
|
||||
InnerProductCoefficient prodCoef(funcCoef, normCoef);
|
||||
rt_x.ProjectBdrCoefficientNormal(prodCoef, bdr_marker);
|
||||
|
||||
for (int be = 0; be < mesh.GetNBE(); be++)
|
||||
{
|
||||
Element *e = mesh.GetBdrElement(be);
|
||||
if (e->GetAttribute() != b) { continue; }
|
||||
|
||||
ElementTransformation *T = mesh.GetBdrElementTransformation(be);
|
||||
const FiniteElement *fe = rt_fespace.GetBE(be);
|
||||
const IntegrationRule &ir = IntRules.Get(fe->GetGeomType(),
|
||||
2*order + 2);
|
||||
|
||||
double rt_err = 0.0;
|
||||
|
||||
for (int j=0; j<ir.GetNPoints(); j++)
|
||||
{
|
||||
const IntegrationPoint &ip = ir.IntPoint(j);
|
||||
T->SetIntPoint(&ip);
|
||||
|
||||
CalcOrtho(T->Jacobian(), normal);
|
||||
|
||||
funcCoef.Eval(f_val, *T, ip);
|
||||
rt_xCoef.Eval(rt_val, *T, ip);
|
||||
|
||||
rt_val -= f_val;
|
||||
|
||||
double rt_dist = rt_val * normal;
|
||||
|
||||
rt_err += rt_dist;
|
||||
|
||||
if (verbose_tests && rt_dist > tol)
|
||||
{
|
||||
mfem::out << be << ":" << j << " rt ("
|
||||
<< f_val[0] << "," << f_val[1] << "," << f_val[2]
|
||||
<< ") vs. ("
|
||||
<< rt_val[0] << "," << rt_val[1] << ","
|
||||
<< rt_val[2] << ") " << rt_dist << std::endl;
|
||||
}
|
||||
}
|
||||
rt_err /= ir.GetNPoints();
|
||||
|
||||
REQUIRE( rt_err == MFEM_Approx(0.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("3D ProjectBdrCoefficientTangent",
|
||||
"[GridFunction]"
|
||||
"[VectorGridFunctionCoefficient]")
|
||||
{
|
||||
int n = 1;
|
||||
int dim = 3;
|
||||
int order = 1;
|
||||
const int n = 1;
|
||||
const int dim = 3;
|
||||
const int order = 1;
|
||||
|
||||
double tol = 1e-6;
|
||||
const double tol = 1e-6;
|
||||
|
||||
for (int type = (int)Element::TETRAHEDRON;
|
||||
type <= (int)Element::HEXAHEDRON; type++)
|
||||
|
||||
@@ -271,6 +271,8 @@ TEST_CASE("Variable Order FiniteElementSpace",
|
||||
|
||||
const auto space_type = GENERATE(SpaceType::RT, SpaceType::ND);
|
||||
const int dim = GENERATE(2, 3);
|
||||
CAPTURE(space_type);
|
||||
CAPTURE(dim);
|
||||
|
||||
Mesh mesh = MakeCartesianMesh(dim == 2 ? 4 : 2, dim);
|
||||
mesh.EnsureNCMesh();
|
||||
@@ -698,7 +700,14 @@ static void TestSolveVec(FiniteElementSpace &fespace)
|
||||
|
||||
GridFunction x(&fespace);
|
||||
x = 0.0;
|
||||
x.ProjectBdrCoefficient(exsol, ess_attr);
|
||||
if (x.FESpace()->GetTypicalBE()->GetRangeDim() == 0)
|
||||
{
|
||||
x.ProjectBdrCoefficientNormal(exsol, ess_attr);
|
||||
}
|
||||
else
|
||||
{
|
||||
x.ProjectBdrCoefficientTangent(exsol, ess_attr);
|
||||
}
|
||||
|
||||
// Assemble the linear form
|
||||
LinearForm lf(&fespace);
|
||||
@@ -1082,7 +1091,14 @@ static void TestSolveParVec(ParFiniteElementSpace &fespace)
|
||||
|
||||
ParGridFunction x(&fespace);
|
||||
x = 0.0;
|
||||
x.ProjectBdrCoefficient(exsol, ess_attr);
|
||||
if (x.FESpace()->GetTypicalBE()->GetRangeDim() == 0)
|
||||
{
|
||||
x.ProjectBdrCoefficientNormal(exsol, ess_attr);
|
||||
}
|
||||
else
|
||||
{
|
||||
x.ProjectBdrCoefficientTangent(exsol, ess_attr);
|
||||
}
|
||||
|
||||
// Assemble the linear form
|
||||
ParLinearForm lf(&fespace);
|
||||
|
||||
@@ -200,3 +200,39 @@ TEST_CASE("ArraysByName Sort/Unique Methods", "[ArraysByName]")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("ArraysByName Print/Load Methods", "[ArraysByName]")
|
||||
{
|
||||
ArraysByName<int> abn;
|
||||
|
||||
FillArraysByName(abn);
|
||||
|
||||
// Print object to string using default format
|
||||
std::ostringstream oss1;
|
||||
abn.Print(oss1);
|
||||
|
||||
// Load new object from printed output
|
||||
ArraysByName<int> abn_load1;
|
||||
std::istringstream iss1(oss1.str());
|
||||
abn_load1.Load(iss1);
|
||||
REQUIRE(abn == abn_load1);
|
||||
|
||||
// Print object to string using one line per array
|
||||
std::ostringstream oss2;
|
||||
oss2 << abn.Size() << '\n';
|
||||
for (auto a : abn)
|
||||
{
|
||||
oss2 << '"' << a.first << "\" " << a.second.Size();
|
||||
for (auto d : a.second)
|
||||
{
|
||||
oss2 << ' ' << d;
|
||||
}
|
||||
oss2 << '\n';
|
||||
}
|
||||
|
||||
// Load new object from printed output
|
||||
ArraysByName<int> abn_load2;
|
||||
std::istringstream iss2(oss2.str());
|
||||
abn_load2.Load(iss2);
|
||||
REQUIRE(abn == abn_load2);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
// Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
|
||||
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
|
||||
// LICENSE and NOTICE for details. LLNL-CODE-806117.
|
||||
//
|
||||
// This file is part of the MFEM library. For more information and source code
|
||||
// availability visit https://mfem.org.
|
||||
//
|
||||
// MFEM is free software; you can redistribute it and/or modify it under the
|
||||
// terms of the BSD-3 license. We welcome feedback and contributions, see file
|
||||
// CONTRIBUTING.md for details.
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include "unit_tests.hpp"
|
||||
|
||||
using namespace mfem;
|
||||
|
||||
#if defined(MFEM_USE_MPI) && defined(MFEM_USE_PETSC)
|
||||
|
||||
namespace
|
||||
{
|
||||
struct PetscSession
|
||||
{
|
||||
PetscSession() { MFEMInitializePetsc(); }
|
||||
~PetscSession() { MFEMFinalizePetsc(); }
|
||||
};
|
||||
|
||||
class IdentityGradientOperator : public IdentityOperator
|
||||
{
|
||||
public:
|
||||
IdentityGradientOperator() : IdentityOperator(1), _jac(1)
|
||||
{
|
||||
_jac.Add(0, 0, 1.0);
|
||||
_jac.Finalize();
|
||||
}
|
||||
|
||||
Operator &GetGradient(const Vector &) const override
|
||||
{
|
||||
return const_cast<SparseMatrix &>(_jac);
|
||||
}
|
||||
|
||||
private:
|
||||
SparseMatrix _jac;
|
||||
};
|
||||
}
|
||||
|
||||
TEST_CASE("PetscNonlinearSolver accepts non-empty rhs", "[Parallel][PETSc]")
|
||||
{
|
||||
static PetscSession petsc_session;
|
||||
|
||||
IdentityGradientOperator oper;
|
||||
PetscNonlinearSolver solver(MPI_COMM_WORLD, "nl_");
|
||||
solver.SetRelTol(1.0e-12);
|
||||
solver.SetAbsTol(1.0e-12);
|
||||
solver.SetMaxIter(5);
|
||||
solver.SetPrintLevel(0);
|
||||
solver.SetJacobianType(Operator::PETSC_MATAIJ);
|
||||
solver.SetOperator(oper);
|
||||
|
||||
Vector x(1);
|
||||
|
||||
Vector empty_rhs;
|
||||
x = 0.0;
|
||||
solver.Mult(empty_rhs, x);
|
||||
REQUIRE(x(0) == MFEM_Approx(0.0));
|
||||
|
||||
Vector nonempty_rhs(1);
|
||||
nonempty_rhs(0) = 2.5;
|
||||
x = 0.0;
|
||||
solver.Mult(nonempty_rhs, x);
|
||||
REQUIRE(x.Size() == 1);
|
||||
REQUIRE(x(0) == MFEM_Approx(nonempty_rhs(0)));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -486,8 +486,14 @@ void multidomain_test_3d(FECType fec_type)
|
||||
{
|
||||
cylinder_gf.ProjectCoefficient(vcoeff);
|
||||
outer_gf.ProjectCoefficient(vcoeff);
|
||||
outer_gf.ProjectBdrCoefficient(vzerocoeff,
|
||||
outer_cyl_surf_marker);
|
||||
if (fec_type == FECType::RT)
|
||||
{
|
||||
outer_gf.ProjectBdrCoefficientNormal(vzerocoeff, outer_cyl_surf_marker);
|
||||
}
|
||||
else
|
||||
{
|
||||
outer_gf.ProjectBdrCoefficientTangent(vzerocoeff, outer_cyl_surf_marker);
|
||||
}
|
||||
outer_gf_ex.ProjectCoefficient(vcoeff);
|
||||
}
|
||||
ParSubMesh::Transfer(cylinder_gf, outer_gf);
|
||||
@@ -507,8 +513,14 @@ void multidomain_test_3d(FECType fec_type)
|
||||
{
|
||||
outer_gf.ProjectCoefficient(vcoeff);
|
||||
cylinder_gf.ProjectCoefficient(vcoeff);
|
||||
cylinder_gf.ProjectBdrCoefficient(vzerocoeff,
|
||||
cylinder_cyl_surf_marker);
|
||||
if (fec_type == FECType::RT)
|
||||
{
|
||||
cylinder_gf.ProjectBdrCoefficientNormal(vzerocoeff, cylinder_cyl_surf_marker);
|
||||
}
|
||||
else
|
||||
{
|
||||
cylinder_gf.ProjectBdrCoefficientTangent(vzerocoeff, cylinder_cyl_surf_marker);
|
||||
}
|
||||
cylinder_gf_ex.ProjectCoefficient(vcoeff);
|
||||
}
|
||||
ParSubMesh::Transfer(outer_gf, cylinder_gf);
|
||||
|
||||
Reference in New Issue
Block a user