Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
96a17e9b48 | ||
|
|
53e372e7b4 | ||
|
|
0d4834ba46 | ||
|
|
d9960236c4 |
@@ -1,6 +1,7 @@
|
||||
name: "Docker"
|
||||
|
||||
on:
|
||||
|
||||
# Always have a base image ready to go - this is a nightly build
|
||||
schedule:
|
||||
- cron: 0 3 * * *
|
||||
@@ -25,6 +26,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
||||
# Dockerfiles to build, a matrix supports future expanded builds
|
||||
container: [["config/docker/Dockerfile.base", "ghcr.io/mfem/mfem-ubuntu-base"],
|
||||
["config/docker/Dockerfile", "ghcr.io/mfem/mfem-ubuntu"]]
|
||||
@@ -32,20 +34,15 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Build
|
||||
steps:
|
||||
- name: Run Actions Cleaner
|
||||
uses: easimon/maximize-build-space@v8
|
||||
with:
|
||||
overprovision-lvm: 'true'
|
||||
remove-dotnet: 'true'
|
||||
remove-android: 'true'
|
||||
remove-haskell: 'true'
|
||||
remove-codeql: 'true'
|
||||
remove-docker-images: 'true'
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# It's easier to reference named variables than indexes of the matrix
|
||||
- name: Make Space For Build
|
||||
run: |
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
sudo rm -rf /opt/ghc
|
||||
|
||||
# It's easier to reference named variables than indexes of the matrix
|
||||
- name: Set Environment
|
||||
env:
|
||||
dockerfile: ${{ matrix.container[0] }}
|
||||
@@ -65,16 +65,13 @@ jobs:
|
||||
# - Add a new combination.
|
||||
# 'build-system: cmake' and 'hypre-target: int64'
|
||||
#
|
||||
# Note: we will gather coverage info for any non-debug run except the
|
||||
# note: we will gather coverage info for any non-debug run except the
|
||||
# CMake build.
|
||||
include:
|
||||
- target: dbg
|
||||
codecov: NO
|
||||
- target: opt
|
||||
codecov: YES
|
||||
- os: ubuntu-latest
|
||||
target: dbg
|
||||
config-opts: 'CPPFLAGS+=-Og'
|
||||
- os: windows-latest
|
||||
codecov: NO
|
||||
- os: windows-latest
|
||||
@@ -101,189 +98,181 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
# This external action allows to interrupt a workflow already running on
|
||||
# the same branch to save resources.
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.11.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
# This external action allows to interrupt a workflow already running on
|
||||
# the same branch to save resource
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.11.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
# Fix 'No space left on device' errors for Ubuntu builds.
|
||||
- name: Run Actions Cleaner
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
uses: easimon/maximize-build-space@v8
|
||||
with:
|
||||
overprovision-lvm: 'true'
|
||||
remove-android: 'true'
|
||||
# Checkout MFEM in "mfem" subdirectory. Final path:
|
||||
# /home/runner/work/mfem/mfem/mfem
|
||||
# Note: Done now to access "install-hypre" and "install-metis" actions.
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: ${{ env.MFEM_TOP_DIR }}
|
||||
# Fetch the complete history for codecov to access commits ID
|
||||
fetch-depth: 0
|
||||
|
||||
# Checkout MFEM in "mfem" subdirectory. Final path:
|
||||
# /home/runner/work/mfem/mfem/mfem
|
||||
# Note: Done now to access "install-hypre" and "install-metis" actions.
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: ${{ env.MFEM_TOP_DIR }}
|
||||
# Fetch the complete history for codecov to access commits ID
|
||||
fetch-depth: 0
|
||||
# Only get MPI if defined for the job.
|
||||
# TODO: It would be nice to have only one step, e.g. with a dedicated
|
||||
# action, but I (@adrienbernede) don't see how at the moment.
|
||||
- name: get MPI (Linux)
|
||||
if: matrix.mpi == 'par' && matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo apt-get install mpich libmpich-dev
|
||||
|
||||
# Only get MPI if defined for the job.
|
||||
# TODO: It would be nice to have only one step, e.g. with a dedicated
|
||||
# action, but I (@adrienbernede) don't see how at the moment.
|
||||
- name: get MPI (Linux)
|
||||
if: matrix.mpi == 'par' && matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo apt-get install mpich libmpich-dev
|
||||
- name: get lcov (Linux)
|
||||
if: matrix.codecov == 'YES' && matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo apt-get install lcov
|
||||
|
||||
- name: get lcov (Linux)
|
||||
if: matrix.codecov == 'YES' && matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo apt-get install lcov
|
||||
# Keep the following section in case we need it again in the future,
|
||||
# see: https://github.com/mfem/mfem/pull/3385#discussion_r1058013032
|
||||
# - name: Set up Homebrew
|
||||
# if: ( matrix.mpi == 'par' || matrix.codecov == 'YES' ) && matrix.os == 'macos-latest'
|
||||
# uses: Homebrew/actions/setup-homebrew@master
|
||||
|
||||
# Keep the following section in case we need it again in the future,
|
||||
# see: https://github.com/mfem/mfem/pull/3385#discussion_r1058013032
|
||||
# - name: Set up Homebrew
|
||||
# if: ( matrix.mpi == 'par' || matrix.codecov == 'YES' ) && matrix.os == 'macos-latest'
|
||||
# uses: Homebrew/actions/setup-homebrew@master
|
||||
- name: get MPI (MacOS)
|
||||
if: matrix.mpi == 'par' && matrix.os == 'macos-latest'
|
||||
run: |
|
||||
export HOMEBREW_NO_INSTALL_CLEANUP=1
|
||||
brew install openmpi
|
||||
|
||||
- name: get MPI (MacOS)
|
||||
if: matrix.mpi == 'par' && matrix.os == 'macos-latest'
|
||||
run: |
|
||||
export HOMEBREW_NO_INSTALL_CLEANUP=1
|
||||
brew install openmpi
|
||||
- name: get lcov (MacOS)
|
||||
if: matrix.codecov == 'YES' && matrix.os == 'macos-latest'
|
||||
run: |
|
||||
export HOMEBREW_NO_INSTALL_CLEANUP=1
|
||||
brew install lcov
|
||||
|
||||
- name: get lcov (MacOS)
|
||||
if: matrix.codecov == 'YES' && matrix.os == 'macos-latest'
|
||||
run: |
|
||||
export HOMEBREW_NO_INSTALL_CLEANUP=1
|
||||
brew install lcov
|
||||
- name: get MPI (Windows)
|
||||
if: matrix.mpi == 'par' && matrix.os == 'windows-latest'
|
||||
uses: mpi4py/setup-mpi@v1.1.4
|
||||
|
||||
- name: get MPI (Windows)
|
||||
if: matrix.mpi == 'par' && matrix.os == 'windows-latest'
|
||||
uses: mpi4py/setup-mpi@v1.1.4
|
||||
# Get Hypre through cache, or build it.
|
||||
# Install will only run on cache miss.
|
||||
- name: cache hypre
|
||||
id: hypre-cache
|
||||
if: matrix.mpi == 'par'
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ env.HYPRE_TOP_DIR }}
|
||||
key: ${{ runner.os }}-build-${{ env.HYPRE_TOP_DIR }}-${{ matrix.hypre-target }}-v2.2
|
||||
|
||||
# Get Hypre through cache, or build it.
|
||||
# Install will only run on cache miss.
|
||||
- name: cache hypre
|
||||
id: hypre-cache
|
||||
if: matrix.mpi == 'par'
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ env.HYPRE_TOP_DIR }}
|
||||
key: ${{ runner.os }}-build-${{ env.HYPRE_TOP_DIR }}-${{ matrix.hypre-target }}-v2.2
|
||||
- name: get hypre
|
||||
if: matrix.mpi == 'par' && steps.hypre-cache.outputs.cache-hit != 'true' && matrix.os != 'windows-latest'
|
||||
uses: mfem/github-actions/build-hypre@v2.4
|
||||
with:
|
||||
archive: ${{ env.HYPRE_ARCHIVE }}
|
||||
dir: ${{ env.HYPRE_TOP_DIR }}
|
||||
target: ${{ matrix.hypre-target }}
|
||||
build-system: make
|
||||
|
||||
- name: get hypre
|
||||
if: matrix.mpi == 'par' && steps.hypre-cache.outputs.cache-hit != 'true' && matrix.os != 'windows-latest'
|
||||
uses: mfem/github-actions/build-hypre@v2.4
|
||||
with:
|
||||
archive: ${{ env.HYPRE_ARCHIVE }}
|
||||
dir: ${{ env.HYPRE_TOP_DIR }}
|
||||
target: ${{ matrix.hypre-target }}
|
||||
build-system: make
|
||||
- name: get hypre (Windows)
|
||||
if: matrix.mpi == 'par' && steps.hypre-cache.outputs.cache-hit != 'true' && matrix.os == 'windows-latest'
|
||||
uses: mfem/github-actions/build-hypre@v2.4
|
||||
with:
|
||||
archive: ${{ env.HYPRE_ARCHIVE }}
|
||||
dir: ${{ env.HYPRE_TOP_DIR }}
|
||||
target: ${{ matrix.hypre-target }}
|
||||
build-system: cmake
|
||||
|
||||
- name: get hypre (Windows)
|
||||
if: matrix.mpi == 'par' && steps.hypre-cache.outputs.cache-hit != 'true' && matrix.os == 'windows-latest'
|
||||
uses: mfem/github-actions/build-hypre@v2.4
|
||||
with:
|
||||
archive: ${{ env.HYPRE_ARCHIVE }}
|
||||
dir: ${{ env.HYPRE_TOP_DIR }}
|
||||
target: ${{ matrix.hypre-target }}
|
||||
build-system: cmake
|
||||
# Get Metis through cache, or build it.
|
||||
# Install will only run on cache miss.
|
||||
- name: cache metis
|
||||
id: metis-cache
|
||||
if: matrix.mpi == 'par' && matrix.os != 'windows-latest'
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ env.METIS_TOP_DIR }}
|
||||
key: ${{ runner.os }}-build-${{ env.METIS_TOP_DIR }}-v2.2
|
||||
|
||||
# Get Metis through cache, or build it.
|
||||
# Install will only run on cache miss.
|
||||
- name: cache metis
|
||||
id: metis-cache
|
||||
if: matrix.mpi == 'par' && matrix.os != 'windows-latest'
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ env.METIS_TOP_DIR }}
|
||||
key: ${{ runner.os }}-build-${{ env.METIS_TOP_DIR }}-v2.2
|
||||
- name: install metis
|
||||
if: matrix.mpi == 'par' && matrix.os != 'windows-latest' && steps.metis-cache.outputs.cache-hit != 'true'
|
||||
uses: mfem/github-actions/build-metis@v2.4
|
||||
with:
|
||||
archive: ${{ env.METIS_ARCHIVE }}
|
||||
dir: ${{ env.METIS_TOP_DIR }}
|
||||
|
||||
- name: install metis
|
||||
if: matrix.mpi == 'par' && matrix.os != 'windows-latest' && steps.metis-cache.outputs.cache-hit != 'true'
|
||||
uses: mfem/github-actions/build-metis@v2.4
|
||||
with:
|
||||
archive: ${{ env.METIS_ARCHIVE }}
|
||||
dir: ${{ env.METIS_TOP_DIR }}
|
||||
- name: cache vcpkg (Windows)
|
||||
id: vcpkg-cache
|
||||
if: matrix.os == 'windows-latest'
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: vcpkg_cache
|
||||
key: ${{ runner.os }}-${{ matrix.mpi }}-vcpkg-v1
|
||||
|
||||
- name: cache vcpkg (Windows)
|
||||
id: vcpkg-cache
|
||||
if: matrix.os == 'windows-latest'
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: vcpkg_cache
|
||||
key: ${{ runner.os }}-${{ matrix.mpi }}-vcpkg-v1
|
||||
- name: prepare vcpkg binary cache location (Windows)
|
||||
if: matrix.os == 'windows-latest' && steps.vcpkg-cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
mkdir -p vcpkg_cache
|
||||
|
||||
- name: prepare vcpkg binary cache location (Windows)
|
||||
if: matrix.os == 'windows-latest' && steps.vcpkg-cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
mkdir -p vcpkg_cache
|
||||
- name: install metis (Windows)
|
||||
if: matrix.mpi == 'par' && matrix.os == 'windows-latest'
|
||||
env:
|
||||
VCPKG_DEFAULT_BINARY_CACHE: ${{ github.workspace }}/vcpkg_cache
|
||||
run: |
|
||||
vcpkg install metis-mfem --triplet=x64-windows-static --overlay-ports=${{ env.MFEM_TOP_DIR }}/config/vcpkg/ports
|
||||
|
||||
- name: install metis (Windows)
|
||||
if: matrix.mpi == 'par' && matrix.os == 'windows-latest'
|
||||
env:
|
||||
VCPKG_DEFAULT_BINARY_CACHE: ${{ github.workspace }}/vcpkg_cache
|
||||
run: |
|
||||
vcpkg install metis-mfem --triplet=x64-windows-static --overlay-ports=${{ env.MFEM_TOP_DIR }}/config/vcpkg/ports
|
||||
# MFEM build and test
|
||||
- name: build
|
||||
uses: mfem/github-actions/build-mfem@v2.4
|
||||
env:
|
||||
VCPKG_DEFAULT_BINARY_CACHE: ${{ github.workspace }}/vcpkg_cache
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
target: ${{ matrix.target }}
|
||||
codecov: ${{ matrix.codecov }}
|
||||
mpi: ${{ matrix.mpi }}
|
||||
build-system: ${{ matrix.build-system }}
|
||||
hypre-dir: ${{ env.HYPRE_TOP_DIR }}
|
||||
metis-dir: ${{ env.METIS_TOP_DIR }}
|
||||
mfem-dir: ${{ env.MFEM_TOP_DIR }}
|
||||
config-options: ${{ matrix.config-opts }}
|
||||
library-only: ${{ matrix.target == 'dbg' }}
|
||||
|
||||
# MFEM build and test
|
||||
- name: build
|
||||
uses: mfem/github-actions/build-mfem@v2.4
|
||||
env:
|
||||
VCPKG_DEFAULT_BINARY_CACHE: ${{ github.workspace }}/vcpkg_cache
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
target: ${{ matrix.target }}
|
||||
codecov: ${{ matrix.codecov }}
|
||||
mpi: ${{ matrix.mpi }}
|
||||
build-system: ${{ matrix.build-system }}
|
||||
hypre-dir: ${{ env.HYPRE_TOP_DIR }}
|
||||
metis-dir: ${{ env.METIS_TOP_DIR }}
|
||||
mfem-dir: ${{ env.MFEM_TOP_DIR }}
|
||||
config-options: ${{ matrix.config-opts }}
|
||||
library-only: ${{ matrix.target == 'dbg' && matrix.os != 'ubuntu-latest' }}
|
||||
# Run checks (and only checks) on debug targets
|
||||
- name: checks
|
||||
if: matrix.build-system == 'make' && matrix.target == 'dbg'
|
||||
run: |
|
||||
cd ${{ env.MFEM_TOP_DIR }} && make check
|
||||
|
||||
# Run checks (and only checks) on debug targets
|
||||
- name: checks
|
||||
if: matrix.build-system == 'make' && matrix.target == 'dbg'
|
||||
run: |
|
||||
cd ${{ env.MFEM_TOP_DIR }} && make check
|
||||
# Note: 'tests' include the unit tests
|
||||
- name: tests
|
||||
if: matrix.build-system == 'make' && matrix.target == 'opt'
|
||||
run: |
|
||||
cd ${{ env.MFEM_TOP_DIR }} && make test
|
||||
|
||||
# Note: 'tests' include the unit tests
|
||||
- name: tests
|
||||
if: matrix.build-system == 'make' && (matrix.target == 'opt' || matrix.os == 'ubuntu-latest')
|
||||
run: |
|
||||
cd ${{ env.MFEM_TOP_DIR }} && make test
|
||||
- name: cmake checks
|
||||
if: matrix.build-system == 'cmake' && matrix.target == 'dbg'
|
||||
run: |
|
||||
CTEST_CONFIG="Debug"
|
||||
cd ${{ env.MFEM_TOP_DIR }} && cmake --build build --target check --config ${CTEST_CONFIG}
|
||||
shell: bash
|
||||
|
||||
- name: cmake checks
|
||||
if: matrix.build-system == 'cmake' && matrix.target == 'dbg'
|
||||
run: |
|
||||
CTEST_CONFIG="Debug"
|
||||
cd ${{ env.MFEM_TOP_DIR }} && cmake --build build --target check --config ${CTEST_CONFIG}
|
||||
shell: bash
|
||||
- name: cmake unit tests (Ubuntu)
|
||||
if: matrix.build-system == 'cmake' && matrix.target == 'opt' && matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
CTEST_CONFIG="Release"
|
||||
[[ ${{ matrix.target }} == 'dbg' ]] && CTEST_CONFIG="Debug"
|
||||
cd ${{ env.MFEM_TOP_DIR }}/build/tests/unit && ctest --output-on-failure -C ${CTEST_CONFIG}
|
||||
shell: bash
|
||||
|
||||
- name: cmake unit tests (Ubuntu)
|
||||
if: matrix.build-system == 'cmake' && matrix.target == 'opt' && matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
CTEST_CONFIG="Release"
|
||||
[[ ${{ matrix.target }} == 'dbg' ]] && CTEST_CONFIG="Debug"
|
||||
cd ${{ env.MFEM_TOP_DIR }}/build/tests/unit && ctest --output-on-failure -C ${CTEST_CONFIG}
|
||||
shell: bash
|
||||
- name: cmake tests
|
||||
if: matrix.build-system == 'cmake' && matrix.target == 'opt' && matrix.os != 'ubuntu-latest'
|
||||
run: |
|
||||
CTEST_CONFIG="Release"
|
||||
cd ${{ env.MFEM_TOP_DIR }}/build && \
|
||||
ctest --output-on-failure -C ${CTEST_CONFIG} || \
|
||||
ctest --rerun-failed --output-on-failure -C ${CTEST_CONFIG}
|
||||
shell: bash
|
||||
|
||||
- name: cmake tests
|
||||
if: matrix.build-system == 'cmake' && matrix.target == 'opt' && matrix.os != 'ubuntu-latest'
|
||||
run: |
|
||||
CTEST_CONFIG="Release"
|
||||
cd ${{ env.MFEM_TOP_DIR }}/build && \
|
||||
ctest --output-on-failure -C ${CTEST_CONFIG} || \
|
||||
ctest --rerun-failed --output-on-failure -C ${CTEST_CONFIG}
|
||||
shell: bash
|
||||
|
||||
# Code coverage (process and upload reports)
|
||||
- name: codecov
|
||||
if: matrix.codecov == 'YES'
|
||||
uses: mfem/github-actions/upload-coverage@v2.4
|
||||
with:
|
||||
name: ${{ matrix.os }}-${{ matrix.build-system }}-${{ matrix.target }}-${{ matrix.mpi }}-${{ matrix.hypre-target }}
|
||||
project_dir: ${{ env.MFEM_TOP_DIR }}
|
||||
directories: "fem general linalg mesh"
|
||||
# Code coverage (process and upload reports)
|
||||
- name: codecov
|
||||
if: matrix.codecov == 'YES'
|
||||
uses: mfem/github-actions/upload-coverage@v2.4
|
||||
with:
|
||||
name: ${{ matrix.os }}-${{ matrix.build-system }}-${{ matrix.target }}-${{ matrix.mpi }}-${{ matrix.hypre-target }}
|
||||
project_dir: ${{ env.MFEM_TOP_DIR }}
|
||||
directories: "fem general linalg mesh"
|
||||
|
||||
@@ -13,10 +13,10 @@ name: "Static Analysis"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["master", "next"]
|
||||
branches: [ "master", "next"]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: ["master"]
|
||||
branches: [ "master" ]
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
@@ -35,35 +35,36 @@ jobs:
|
||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
# 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
|
||||
|
||||
# ℹ️ 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
|
||||
# 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
|
||||
|
||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||
# ℹ️ 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
|
||||
|
||||
# - run: |
|
||||
# echo "Run, Build Application using script"
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
# - run: |
|
||||
# echo "Run, Build Application using script"
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
||||
@@ -34,67 +34,67 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.11.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.11.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
- name: checkout MFEM
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: mfem
|
||||
- name: checkout MFEM
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: mfem
|
||||
|
||||
- name: Get MPI (Linux)
|
||||
run: |
|
||||
sudo apt-get install mpich libmpich-dev
|
||||
- name: Get MPI (Linux)
|
||||
run: |
|
||||
sudo apt-get install mpich libmpich-dev
|
||||
|
||||
- name: Cache Hypre Install
|
||||
id: hypre-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ env.HYPRE_TOP_DIR }}
|
||||
key: ${{ runner.os }}-build-${{ env.HYPRE_TOP_DIR }}-v2.2
|
||||
- name: Cache Hypre Install
|
||||
id: hypre-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ env.HYPRE_TOP_DIR }}
|
||||
key: ${{ runner.os }}-build-${{ env.HYPRE_TOP_DIR }}-v2.2
|
||||
|
||||
- name: Get Hypre
|
||||
if: steps.hypre-cache.outputs.cache-hit != 'true'
|
||||
uses: mfem/github-actions/build-hypre@v2.4
|
||||
with:
|
||||
archive: ${{ env.HYPRE_ARCHIVE }}
|
||||
dir: ${{ env.HYPRE_TOP_DIR }}
|
||||
target: int32
|
||||
- name: Get Hypre
|
||||
if: steps.hypre-cache.outputs.cache-hit != 'true'
|
||||
uses: mfem/github-actions/build-hypre@v2.4
|
||||
with:
|
||||
archive: ${{ env.HYPRE_ARCHIVE }}
|
||||
dir: ${{ env.HYPRE_TOP_DIR }}
|
||||
target: int32
|
||||
|
||||
- name: Cache Metis Install
|
||||
id: metis-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ env.METIS_TOP_DIR }}
|
||||
key: ${{ runner.os }}-build-${{ env.METIS_TOP_DIR }}-v2.2
|
||||
- name: Cache Metis Install
|
||||
id: metis-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ env.METIS_TOP_DIR }}
|
||||
key: ${{ runner.os }}-build-${{ env.METIS_TOP_DIR }}-v2.2
|
||||
|
||||
- name: Install Metis
|
||||
if: steps.metis-cache.outputs.cache-hit != 'true'
|
||||
uses: mfem/github-actions/build-metis@v2.4
|
||||
with:
|
||||
archive: ${{ env.METIS_ARCHIVE }}
|
||||
dir: ${{ env.METIS_TOP_DIR }}
|
||||
- name: Install Metis
|
||||
if: steps.metis-cache.outputs.cache-hit != 'true'
|
||||
uses: mfem/github-actions/build-metis@v2.4
|
||||
with:
|
||||
archive: ${{ env.METIS_ARCHIVE }}
|
||||
dir: ${{ env.METIS_TOP_DIR }}
|
||||
|
||||
# MFEM build and test
|
||||
- name: build-mfem
|
||||
uses: mfem/github-actions/build-mfem@v2.4
|
||||
with:
|
||||
os: ${{ runner.os }}
|
||||
target: opt
|
||||
codecov: NO
|
||||
mpi: par
|
||||
build-system: make
|
||||
hypre-dir: ${{ env.HYPRE_TOP_DIR }}
|
||||
metis-dir: ${{ env.METIS_TOP_DIR }}
|
||||
mfem-dir: mfem
|
||||
# MFEM build and test
|
||||
- name: build-mfem
|
||||
uses: mfem/github-actions/build-mfem@v2.4
|
||||
with:
|
||||
os: ${{ runner.os }}
|
||||
target: opt
|
||||
codecov: NO
|
||||
mpi: par
|
||||
build-system: make
|
||||
hypre-dir: ${{ env.HYPRE_TOP_DIR }}
|
||||
metis-dir: ${{ env.METIS_TOP_DIR }}
|
||||
mfem-dir: mfem
|
||||
|
||||
- name: test (no clean)
|
||||
run: |
|
||||
cd mfem && make test-noclean
|
||||
- name: test (no clean)
|
||||
run: |
|
||||
cd mfem && make test-noclean
|
||||
|
||||
- name: gitignore
|
||||
run: |
|
||||
cd mfem/tests/scripts
|
||||
./runtest gitignore
|
||||
- name: gitignore
|
||||
run: |
|
||||
cd mfem/tests/scripts
|
||||
./runtest gitignore
|
||||
|
||||
@@ -27,44 +27,44 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.11.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.11.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
- name: MFEM Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: mfem
|
||||
- name: MFEM Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: mfem
|
||||
|
||||
- name: MFEM Build
|
||||
uses: mfem/github-actions/build-mfem@v2.4
|
||||
with:
|
||||
os: ${{ runner.os }}
|
||||
target: opt
|
||||
mpi: seq
|
||||
hypre-dir: unused-hypre-dir
|
||||
metis-dir: unused-metis-dir
|
||||
mfem-dir: mfem
|
||||
build-system: make
|
||||
library-only: false
|
||||
config-options:
|
||||
CXX="clang++-14"
|
||||
CXXFLAGS="-g -O1 -std=c++11
|
||||
-fsanitize=address
|
||||
-fno-omit-frame-pointer
|
||||
-fsanitize-address-use-after-scope"
|
||||
- name: MFEM Build
|
||||
uses: mfem/github-actions/build-mfem@v2.4
|
||||
with:
|
||||
os: ${{ runner.os }}
|
||||
target: opt
|
||||
mpi: seq
|
||||
hypre-dir: unused-hypre-dir
|
||||
metis-dir: unused-metis-dir
|
||||
mfem-dir: mfem
|
||||
build-system: make
|
||||
library-only: false
|
||||
config-options:
|
||||
CXX="clang++-14"
|
||||
CXXFLAGS="-g -O1 -std=c++11
|
||||
-fsanitize=address
|
||||
-fno-omit-frame-pointer
|
||||
-fsanitize-address-use-after-scope"
|
||||
|
||||
- name: MFEM Info
|
||||
working-directory: mfem
|
||||
run: make info
|
||||
- name: MFEM Info
|
||||
working-directory: mfem
|
||||
run: make info
|
||||
|
||||
- name: MFEM Sanitize
|
||||
working-directory: mfem
|
||||
run:
|
||||
ASAN_OPTIONS="detect_leaks=1,
|
||||
strict_init_order=1,
|
||||
strict_string_checks=1,
|
||||
check_initialization_order=1,
|
||||
detect_stack_use_after_return=1"
|
||||
make test
|
||||
- name: MFEM Sanitize
|
||||
working-directory: mfem
|
||||
run:
|
||||
ASAN_OPTIONS="detect_leaks=1,
|
||||
strict_init_order=1,
|
||||
strict_string_checks=1,
|
||||
check_initialization_order=1,
|
||||
detect_stack_use_after_return=1"
|
||||
make test
|
||||
|
||||
@@ -33,49 +33,49 @@ jobs:
|
||||
(github.event_name == 'push' ||
|
||||
github.event.pull_request.head.repo.full_name != github.repository)
|
||||
steps:
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.11.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.11.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v3
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: copyright check
|
||||
id: copyright
|
||||
run: |
|
||||
./config/githooks/pre-push --copyright
|
||||
- name: copyright check
|
||||
id: copyright
|
||||
run: |
|
||||
./config/githooks/pre-push --copyright
|
||||
|
||||
continue-on-error: true
|
||||
continue-on-error: true
|
||||
|
||||
- name: license check
|
||||
id: license
|
||||
run: |
|
||||
./config/githooks/pre-push --license
|
||||
continue-on-error: true
|
||||
- name: license check
|
||||
id: license
|
||||
run: |
|
||||
./config/githooks/pre-push --license
|
||||
continue-on-error: true
|
||||
|
||||
- name: release check
|
||||
id: release
|
||||
run: |
|
||||
./config/githooks/pre-push --release
|
||||
continue-on-error: true
|
||||
- name: release check
|
||||
id: release
|
||||
run: |
|
||||
./config/githooks/pre-push --release
|
||||
continue-on-error: true
|
||||
|
||||
- name: wrap-up
|
||||
if: |
|
||||
steps.copyright.outcome != 'success' ||
|
||||
steps.license.outcome != 'success' ||
|
||||
steps.release.outcome != 'success'
|
||||
run: |
|
||||
if [[ "${{ steps.copyright.outcome }}" != "success" ]]; then
|
||||
echo "copyright check failed, unroll log for details"
|
||||
fi
|
||||
if [[ "${{ steps.license.outcome }}" != "success" ]]; then
|
||||
echo "license check failed, unroll log for details"
|
||||
fi
|
||||
if [[ "${{ steps.release.outcome }}" != "success" ]]; then
|
||||
echo "release check failed, unroll log for details"
|
||||
fi
|
||||
exit 1
|
||||
- name: wrap-up
|
||||
if: |
|
||||
steps.copyright.outcome != 'success' ||
|
||||
steps.license.outcome != 'success' ||
|
||||
steps.release.outcome != 'success'
|
||||
run: |
|
||||
if [[ "${{ steps.copyright.outcome }}" != "success" ]]; then
|
||||
echo "copyright check failed, unroll log for details"
|
||||
fi
|
||||
if [[ "${{ steps.license.outcome }}" != "success" ]]; then
|
||||
echo "license check failed, unroll log for details"
|
||||
fi
|
||||
if [[ "${{ steps.release.outcome }}" != "success" ]]; then
|
||||
echo "release check failed, unroll log for details"
|
||||
fi
|
||||
exit 1
|
||||
|
||||
code-style:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -83,16 +83,16 @@ jobs:
|
||||
(github.event_name == 'push' ||
|
||||
github.event.pull_request.head.repo.full_name != github.repository)
|
||||
steps:
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v3
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: get astyle
|
||||
run: |
|
||||
sudo apt-get install astyle
|
||||
- name: get astyle
|
||||
run: |
|
||||
sudo apt-get install astyle
|
||||
|
||||
- name: style check
|
||||
run: |
|
||||
./config/githooks/pre-push --style
|
||||
- name: style check
|
||||
run: |
|
||||
./config/githooks/pre-push --style
|
||||
|
||||
documentation:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -100,22 +100,22 @@ jobs:
|
||||
(github.event_name == 'push' ||
|
||||
github.event.pull_request.head.repo.full_name != github.repository)
|
||||
steps:
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v3
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: get doxygen and graphviz
|
||||
run: |
|
||||
sudo apt-get install doxygen graphviz
|
||||
- name: get doxygen and graphviz
|
||||
run: |
|
||||
sudo apt-get install doxygen graphviz
|
||||
|
||||
- name: update doxygen config file
|
||||
run: |
|
||||
cd doc
|
||||
doxygen -u CodeDocumentation.conf.in
|
||||
- name: update doxygen config file
|
||||
run: |
|
||||
cd doc
|
||||
doxygen -u CodeDocumentation.conf.in
|
||||
|
||||
- name: build documentation
|
||||
run: |
|
||||
cd tests/scripts
|
||||
./runtest documentation
|
||||
- name: build documentation
|
||||
run: |
|
||||
cd tests/scripts
|
||||
./runtest documentation
|
||||
|
||||
branch-history:
|
||||
if: |
|
||||
@@ -125,16 +125,16 @@ jobs:
|
||||
github.event.pull_request.head.repo.full_name != github.repository)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: branch-history
|
||||
run: |
|
||||
# We override origin to make sure we point to the main repo.
|
||||
# This is to have consistent test results on PRs from forks.
|
||||
git remote remove origin
|
||||
git remote add origin https://github.com/mfem/mfem.git
|
||||
git checkout -b gh-actions-branch-history
|
||||
./config/githooks/pre-push --history
|
||||
- name: branch-history
|
||||
run: |
|
||||
# We override origin to make sure we point to the main repo.
|
||||
# This is to have consistent test results on PRs from forks.
|
||||
git remote remove origin
|
||||
git remote add origin https://github.com/mfem/mfem.git
|
||||
git checkout -b gh-actions-branch-history
|
||||
./config/githooks/pre-push --history
|
||||
|
||||
-11
@@ -213,7 +213,6 @@ miniapps/meshing/twist
|
||||
miniapps/meshing/mesh-explorer
|
||||
miniapps/meshing/shaper
|
||||
miniapps/meshing/extruder
|
||||
miniapps/meshing/fit-node-position
|
||||
miniapps/meshing/trimmer
|
||||
miniapps/meshing/reflector
|
||||
miniapps/meshing/mesh-optimizer
|
||||
@@ -266,16 +265,11 @@ miniapps/navier/*_output
|
||||
miniapps/nurbs/nurbs_ex1
|
||||
miniapps/nurbs/nurbs_ex1p
|
||||
miniapps/nurbs/nurbs_ex11p
|
||||
miniapps/nurbs/nurbs_printfunc
|
||||
miniapps/nurbs/nurbs_patch_ex1
|
||||
miniapps/nurbs/nurbs_curveint
|
||||
miniapps/nurbs/refined.mesh
|
||||
miniapps/nurbs/mesh.*
|
||||
miniapps/nurbs/sol.*
|
||||
miniapps/nurbs/mode_*
|
||||
miniapps/nurbs/Example1*
|
||||
miniapps/nurbs/sin-fit.mesh
|
||||
miniapps/nurbs/CurveInt
|
||||
|
||||
miniapps/performance/ex1
|
||||
miniapps/performance/ex1p
|
||||
@@ -298,14 +292,9 @@ miniapps/tools/display-basis
|
||||
miniapps/tools/load-dc
|
||||
miniapps/tools/convert-dc
|
||||
miniapps/tools/lor-transfer
|
||||
miniapps/tools/plor-transfer
|
||||
miniapps/tools/get-values
|
||||
miniapps/tools/check-tmop-metric
|
||||
miniapps/tools/tmop-metric-magnitude
|
||||
miniapps/tools/nodal-transfer
|
||||
miniapps/tools/ParaView
|
||||
miniapps/tools/gridfunc_*
|
||||
miniapps/tools/mesh_*
|
||||
|
||||
miniapps/toys/automata
|
||||
miniapps/toys/life
|
||||
|
||||
@@ -8,148 +8,88 @@
|
||||
https://mfem.org
|
||||
|
||||
|
||||
Version 4.6.1 (development)
|
||||
Version 4.5.3 (development)
|
||||
===========================
|
||||
|
||||
Discretization improvements
|
||||
---------------------------
|
||||
- Introduced support for higher order non conformal Nedelec elements on
|
||||
simplices in ParMesh.
|
||||
|
||||
Miscellaneous
|
||||
-------------
|
||||
- The ReadCubit Genesis mesh importer has been rewritten to improve readability.
|
||||
|
||||
|
||||
Version 4.6, released on September 27, 2023
|
||||
===========================================
|
||||
|
||||
- MFEM is now available in Homebrew and can be installed on a Mac with just
|
||||
"brew install mfem". See https://formulae.brew.sh/formula/mfem.
|
||||
|
||||
Meshing improvements
|
||||
--------------------
|
||||
- Added asymptotically-balanced TMOP compound metrics 90, 94, 328, 338. A new
|
||||
tool, tmop-metric-magnitude, can be used to track how metrics change under
|
||||
geometric perturbations. See miniapps/tools.
|
||||
|
||||
- Several NURBS meshing improvements:
|
||||
* Support for free connectivity of NURBS patches allowing for more complex
|
||||
patch configurations such as C-meshes.
|
||||
* New methods to set and get attributes on NURBS patches and patch boundaries.
|
||||
* The edge to knot map for NURBS meshes can be determined automatically. It is
|
||||
no longer needed to specify this in the NURBS mesh.
|
||||
* Added curve interpolation method for NURBS.
|
||||
* Added new small miniapp for printing of shape functions of a KnotVector
|
||||
* See miniapps/nurbs for example meshes and miniapps.
|
||||
|
||||
Discretization improvements
|
||||
---------------------------
|
||||
- SubMesh and ParSubMesh have been extended to support the transfer of
|
||||
Nedelec and Raviart-Thomas finite element spaces.
|
||||
|
||||
- Added support for partial assembly on NURBS patches, and NURBS-patch sparse
|
||||
matrix assembly. Patch matrix assembly includes the option to use reduced
|
||||
approximate integration rules, computed by the newly implemented non-negative
|
||||
least-squares (NNLS) solver.
|
||||
|
||||
- Support for parallel transfer of H1 fields using the low-order refined (LOR)
|
||||
transfer operators in L2ProjectionGridTransfer
|
||||
|
||||
- Added KDTree class for 2D/3D set of points, which is then utilized in the new
|
||||
KDTreeNodalProjection class to project a function defined on an arbitrary set
|
||||
of points onto an MFEM grid function. This functionality is demonstrated in
|
||||
the nodal-transfer miniapp. The current implementation is serial only. Further
|
||||
extensions can include search in arbitrary dimensional spaces.
|
||||
|
||||
- Added support for p-refined meshes in GSLIB-FindPoints.
|
||||
|
||||
- Device kernels can now access device-specific DOF and quadrature limits using
|
||||
the DofQuadLimits structure, allowing increased limits when executing on CPU.
|
||||
The limits for the runtime selected device can be accessed in host code using
|
||||
DeviceDofQuadLimits::Get(). The global constants MAX_D1D and MAX_Q1D are no
|
||||
longer available.
|
||||
|
||||
- Face restriction operators for Nedelec and Raviart-Thomas finite element
|
||||
spaces are now supported through the ConformingFaceRestriction class.
|
||||
|
||||
- VectorFEBoundaryFluxLFIntegrator is now supported on device/GPU.
|
||||
|
||||
Linear and nonlinear solvers
|
||||
----------------------------
|
||||
- Updated the MUMPS interface to support multiple right-hand sides, block
|
||||
low-rank compression, builds using 64-bit integers, and other improvements.
|
||||
|
||||
- Added an interface to the MKL Pardiso sparse direct solver developed by Intel.
|
||||
The interface provides a serial (OpenMP shared memory) version of Pardiso for
|
||||
use with SparseMatrix. This complements the existing parallel (MPI distributed
|
||||
memory) version already available through the CPardiso MFEM integration.
|
||||
|
||||
- Added HIP support to the PETSc and SUNDIALS interfaces.
|
||||
|
||||
New and updated examples and miniapps
|
||||
-------------------------------------
|
||||
- Added a new H(div) solver miniapp demonstrating the use of a matrix-free
|
||||
saddle-point solver methodology, suitable for high-order discretizations and
|
||||
for GPU acceleration. Examples illustrating the solution of Darcy and grad-div
|
||||
problems are included. See miniapps/hdiv-linear-solver.
|
||||
- Added a new example code, Example 36/36p, to demonstrate the solution of
|
||||
the obstacle problem with a new finite element method.
|
||||
|
||||
- Added a new miniapp, Mesh Quality, for evaluating mesh quality using size,
|
||||
skewness, and aspect-ratio computed from the Jacobian of the transformation.
|
||||
|
||||
- Added a new miniapp for interface and boundary fitting to implicit domains
|
||||
defined using level-set functions. See miniapps/meshing/pmesh-fitting.cpp
|
||||
|
||||
- Added new Discontinuous Petrov-Galerkin (DPG) miniapp which includes serial
|
||||
and parallel examples for diffusion, convection-diffusion, acoustics and
|
||||
Maxwell equations. The miniapp includes new classes such as (Par)DPGWeakForm,
|
||||
(Par)ComplexDPGWeakForm and (Complex)BlockStaticCondensation. Three new
|
||||
integrators are added in support of DPG systems: TraceIntegrator,
|
||||
NormalTraceIntegrator and TangentTraceIntegrator. See miniapps/dpg.
|
||||
NormalTraceIntegrator and TangentTraceIntegrator.
|
||||
|
||||
- Added a new miniapp that implements the SPDE method for generating Gaussian
|
||||
random fields of Matern covariance. The resulting random field can be used,
|
||||
e.g., to model material uncertainties. See miniapps/spde.
|
||||
- Added new SubMesh examples demonstrating source terms and boundary conditions
|
||||
transferred from SubMesh objects.
|
||||
|
||||
- Added a new parallel LOR transfer miniapp, plor-transfer, which mirrors the
|
||||
functionality of the serial LOR transfer miniapp. See miniapps/tools.
|
||||
|
||||
- New serial miniapp, nodal-transfer, demonstrating the use of KDTree to map a
|
||||
parallel grid function to a different parallel partitioning of the same mesh.
|
||||
|
||||
- Added 3 additional TMOP miniapps in miniapps/meshing:
|
||||
* Mesh-Quality evaluates quality using size, skewness, and aspect-ratio
|
||||
computed from the Jacobian of the transformation.
|
||||
* Mesh-Fitting can be used for interface and boundary fitting to implicit
|
||||
domains defined using level-set functions.
|
||||
* Fit-Node-Position fits selected mesh nodes to specified positions, while
|
||||
maintaining overall mesh quality.
|
||||
|
||||
- Added 4 new example codes:
|
||||
* Example 34/34p solves a simple magnetostatic problem where source terms and
|
||||
boundary conditions are transferred with SubMesh objects.
|
||||
* Example 35p implements H1, H(curl) and H(div) variants of a damped harmonic
|
||||
oscillator with field transfer using SubMesh objects.
|
||||
* Example 36/36p demonstrates the solution of the obstacle problem with a new
|
||||
finite element method (proximal Galerkin).
|
||||
* Example 37/37p demonstrates topology optimization with MFEM.
|
||||
- Added a new H(div) solvers miniapp in miniapps/hdiv-linear-solver,
|
||||
demonstrating the use of a matrix-free saddle-point solver methodology,
|
||||
suitable for high-order discretizations and for GPU acceleration. Examples
|
||||
illustrating the solution of Darcy and grad-div problems are included.
|
||||
|
||||
- Added a random refinement option to the mesh-explorer miniapp to assist users
|
||||
in experimenting with nonconforming meshes.
|
||||
|
||||
- Moved the distance solver methods from miniapps/shifted to miniapps/common.
|
||||
|
||||
Meshing improvements
|
||||
--------------------
|
||||
- Added new methods in the Mesh class to set and get attributes on NURBS patches
|
||||
and patch boundaries.
|
||||
|
||||
- Added HIP support to the SUNDIALS interface.
|
||||
|
||||
- TMOP improvement: added asymptotically-balanced compound metrics 90, 94, 328,
|
||||
338. Added the tmop-metric-magnitude tool for tracking how metrics change
|
||||
under geometric perturbations.
|
||||
|
||||
Discretization improvements
|
||||
---------------------------
|
||||
- Face restriction operators for Nedelec and Raviart-Thomas finite element
|
||||
spaces are now supported through the ConformingFaceRestriction class.
|
||||
|
||||
- SubMesh and ParSubMesh have been extended to support the transfer of
|
||||
Nedelec and Raviart-Thomas finite element spaces.
|
||||
|
||||
- VectorFEBoundaryFluxLFIntegrator is now supported on device/GPU.
|
||||
|
||||
- Added support for p-refined meshes in FindPointsGSLIB.
|
||||
|
||||
Linear and nonlinear solvers
|
||||
----------------------------
|
||||
- Updated interface to MUMPS direct solver to support multiple right-hand
|
||||
sides, block low-rank compression, builds using 64-bit integers, and other
|
||||
improvements.
|
||||
|
||||
- Added an interface to the MKL Pardiso sparse direct solver developed by Intel.
|
||||
This interface provides a serial (OpenMP shared memory) version of Pardiso for
|
||||
use with SparseMatrix. This complements the existing parallel (MPI distributed
|
||||
memory) version already available through the CPardiso MFEM integration.
|
||||
|
||||
Integrations, testing and documentation
|
||||
---------------------------------------
|
||||
- Added an address sanitizer GitHub action for a serial build/test on Ubuntu,
|
||||
based on Clang/LLVM (https://clang.llvm.org/docs/AddressSanitizer.html).
|
||||
|
||||
Miscellaneous
|
||||
-------------
|
||||
- Improved lambda body debugging with the addition of mfem::forall functions.
|
||||
These functions can take the place of the MFEM_FORALL macros, which have been
|
||||
preserved for backwards compatibility.
|
||||
|
||||
- Added an address sanitizer GitHub action for a serial build/test on Ubuntu,
|
||||
based on Clang/LLVM (https://clang.llvm.org/docs/AddressSanitizer.html).
|
||||
|
||||
- Reorganized files for bilinear form, linear form, and nonlinear form integrators
|
||||
in the fem/integ/ subdirectory.
|
||||
|
||||
- FiniteElementSpace::GetFE has been updated to abort instead of returning NULL for
|
||||
an empty partition.
|
||||
|
||||
- Various other simplifications, extensions, and bugfixes in the code.
|
||||
|
||||
|
||||
Version 4.5.2, released on March 23, 2023
|
||||
=========================================
|
||||
|
||||
+2
-2
@@ -57,7 +57,7 @@ project(mfem NONE)
|
||||
# Current version of MFEM, see also `makefile`.
|
||||
# mfem_VERSION = (string)
|
||||
# MFEM_VERSION = (int) [automatically derived from mfem_VERSION]
|
||||
set(${PROJECT_NAME}_VERSION 4.6.1)
|
||||
set(${PROJECT_NAME}_VERSION 4.5.3)
|
||||
|
||||
# Prohibit in-source build
|
||||
if (${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR})
|
||||
@@ -138,7 +138,7 @@ if (MFEM_USE_CUDA)
|
||||
set(CUDA_FLAGS "-ccbin=${CMAKE_CXX_COMPILER} ${CUDA_FLAGS}")
|
||||
set(CMAKE_CUDA_HOST_LINK_LAUNCHER ${CMAKE_CXX_COMPILER})
|
||||
endif()
|
||||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} ${CUDA_FLAGS}")
|
||||
set(CMAKE_CUDA_FLAGS ${CMAKE_CUDA_FLAGS} ${CUDA_FLAGS})
|
||||
set(CUSPARSE_FOUND TRUE)
|
||||
set(CUSPARSE_LIBRARIES "cusparse")
|
||||
set(CUBLAS_FOUND TRUE)
|
||||
|
||||
@@ -135,7 +135,6 @@ The MFEM source code has the following structure:
|
||||
│ ├── adjoint
|
||||
│ ├── autodiff
|
||||
│ ├── common
|
||||
│ ├── dpg
|
||||
│ ├── electromagnetics
|
||||
│ ├── gslib
|
||||
│ ├── hdiv-linear-solver
|
||||
@@ -149,7 +148,6 @@ The MFEM source code has the following structure:
|
||||
│ ├── performance
|
||||
│ ├── shifted
|
||||
│ ├── solvers
|
||||
│ ├── spde
|
||||
│ ├── tools
|
||||
│ └── toys
|
||||
└── tests
|
||||
|
||||
@@ -699,15 +699,12 @@ The specific libraries and their options are:
|
||||
PETSc has been cloned on the same level as mfem and hypre:
|
||||
./configure --download-fblaslapack=yes --download-scalapack=yes \
|
||||
--download-mumps=yes --download-suitesparse=yes \
|
||||
--with-hypre-dir=../hypre/src/hypre \
|
||||
--with-hypre-dir=../hypre-2.10.0b/src/hypre \
|
||||
--with-shared-libraries=0
|
||||
When building PETSc with HIP, one may need to add a flag like -std=c2x to
|
||||
CFLAGS to allow proper parsing of the hipsparse header under C.
|
||||
URL: https://www.mcs.anl.gov/petsc
|
||||
Options: PETSC_OPT, PETSC_LIB.
|
||||
Versions: PETSc >= 3.8.0 (PETSc build without CUDA/HIP)
|
||||
Versions: PETSc >= 3.8.0 (PETSc build without CUDA)
|
||||
PETSc >= 3.15.0 (PETSc built with CUDA)
|
||||
PETSc >= 3.19.0 (PETSc built with HIP, older versions may work too)
|
||||
|
||||
- SLEPc (optional), used when MFEM_USE_SLEPC = YES. SLEPc depends on PETSc and
|
||||
uses some of the PETSc options when compiled.
|
||||
|
||||
+5
-20
@@ -331,30 +331,16 @@ STRUMPACK_OPT = -I$(STRUMPACK_DIR)/include $(SCOTCH_OPT)
|
||||
STRUMPACK_LIB = -L$(STRUMPACK_DIR)/lib -lstrumpack $(MPI_FORTRAN_LIB)\
|
||||
$(SCOTCH_LIB) $(SCALAPACK_LIB)
|
||||
|
||||
# Ginkgo library configuration
|
||||
# Ginkgo library configuration (currently not needed)
|
||||
GINKGO_DIR = @MFEM_DIR@/../ginkgo/install
|
||||
GINKGO_SEARCH_DIR = $(subst @MFEM_DIR@,$(MFEM_DIR),$(GINKGO_DIR))
|
||||
GINKGO_BUILD_TYPE=Release
|
||||
ifeq ($(MFEM_USE_GINKGO),YES)
|
||||
BASE_FLAGS = -std=c++14
|
||||
endif
|
||||
GINKGO_OPT = -isystem $(GINKGO_DIR)/include
|
||||
GINKGO_LIB_DIR = $(sort $(dir $(wildcard\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*.a\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*.so\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*.dylib\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*.dll)))
|
||||
GINKGO_LINK_LIB_DIR = $(GINKGO_DIR)$(subst $(GINKGO_SEARCH_DIR),,$(GINKGO_LIB_DIR))
|
||||
ALL_GINKGO_LIBS_DEBUG = $(notdir $(basename $(wildcard\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*d.a\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*d.so\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*d.dylib\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*d.dll)))
|
||||
ALL_GINKGO_LIBS = $(notdir $(basename $(wildcard\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*.a\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*.so\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*.dylib\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*.dll)))
|
||||
GINKGO_LIB_DIR = $(sort $(dir $(wildcard $(GINKGO_DIR)/lib*/libginkgo*.a $(GINKGO_DIR)/lib*/libginkgo*.so $(GINKGO_DIR)/lib*/libginkgo*.dylib $(GINKGO_DIR)/lib*/libginkgo*.dll)))
|
||||
ALL_GINKGO_LIBS_DEBUG = $(notdir $(basename $(wildcard $(GINKGO_DIR)/lib*/libginkgo*d.a $(GINKGO_DIR)/lib*/libginkgo*d.so $(GINKGO_DIR)/lib*/libginkgo*d.dylib $(GINKGO_DIR)/lib*/libginkgo*d.dll)))
|
||||
ALL_GINKGO_LIBS = $(notdir $(basename $(wildcard $(GINKGO_DIR)/lib*/libginkgo*.a $(GINKGO_DIR)/lib*/libginkgo*.so $(GINKGO_DIR)/lib*/libginkgo*.dylib $(GINKGO_DIR)/lib*/libginkgo*.dll)))
|
||||
ALL_GINKGO_LIBS_RELEASE = $(filter-out $(ALL_GINKGO_LIBS_DEBUG),$(ALL_GINKGO_LIBS))
|
||||
GINKGO_LINK = $(subst libginkgo,-lginkgo,$(ALL_GINKGO_LIBS_RELEASE))
|
||||
ifeq ($(GINKGO_BUILD_TYPE),Debug)
|
||||
@@ -363,8 +349,7 @@ ifeq ($(GINKGO_BUILD_TYPE),Debug)
|
||||
endif
|
||||
else
|
||||
endif
|
||||
GINKGO_LIB = $(XLINKER)-rpath,$(GINKGO_LINK_LIB_DIR) -L$(GINKGO_LINK_LIB_DIR)\
|
||||
$(GINKGO_LINK)
|
||||
GINKGO_LIB = $(XLINKER)-rpath,$(GINKGO_LIB_DIR) -L$(GINKGO_LIB_DIR) $(GINKGO_LINK)
|
||||
|
||||
# AmgX library configuration
|
||||
AMGX_DIR = @MFEM_DIR@/../amgx
|
||||
|
||||
@@ -19,7 +19,9 @@ RUN apt-get update && \
|
||||
apt-get install -y libcurl4-openssl-dev libssl-dev
|
||||
|
||||
ENV PATH=$PATH:/opt/mfem-view/bin
|
||||
ENV LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/mfem-view/lib:/opt/mfem-view/lib64
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
# The user will see the view on shell into the container
|
||||
WORKDIR /opt/mfem-view
|
||||
ENTRYPOINT ["/bin/bash"]
|
||||
|
||||
@@ -34,14 +34,14 @@ RUN cd /opt/mfem-env && \
|
||||
. /opt/spack/share/spack/setup-env.sh && \
|
||||
spack env activate . && \
|
||||
spack develop --path /code mfem@master+examples+miniapps && \
|
||||
spack add mfem@master+examples+miniapps && \
|
||||
spack install
|
||||
spack add mfem@master+examples+miniapps # && \
|
||||
# spack install
|
||||
|
||||
# ensure mfem always on various paths
|
||||
RUN cd /opt/mfem-env && \
|
||||
spack env activate --sh -d . >> /etc/profile.d/z10_spack_environment.sh
|
||||
#RUN cd /opt/mfem-env && \
|
||||
# spack env activate --sh -d . >> /etc/profile.d/z10_spack_environment.sh
|
||||
|
||||
# Present the software install when we shell in
|
||||
# The view is at /opt/mfem-env/.spack-env/view
|
||||
WORKDIR /opt/software
|
||||
ENTRYPOINT ["/bin/bash", "--rcfile", "/etc/profile", "-l", "-c"]
|
||||
#WORKDIR /opt/software
|
||||
#ENTRYPOINT ["/bin/bash", "--rcfile", "/etc/profile", "-l", "-c"]
|
||||
|
||||
+46
-108
@@ -7,31 +7,21 @@ You can use this image for a demo of using mfem! 🎉️
|
||||
Updated containers are built and deployed on merges to the main branch and releases.
|
||||
If you want to request a build on demand, you can [manually run the workflow](https://docs.github.com/en/actions/managing-workflow-runs/manually-running-a-workflow) thanks to the workflow dispatch event.
|
||||
|
||||
## Usage
|
||||
### Usage
|
||||
|
||||
We provide two containers, which you can either build or use directly from
|
||||
[GitHub packages](https://github.com/orgs/mfem/packages?repo_name=mfem).
|
||||
|
||||
- `ghcr.io/mfem/mfem-ubuntu-base`: a "build from scratch" for mfem
|
||||
- `ghcr.io/mfem/mfem-ubuntu`: a quick build that uses the base container
|
||||
|
||||
In the above, "ghcr.io" means "GitHub Container Registry" and
|
||||
Here is how to build the container. Note that we build so it belongs to the same
|
||||
namespace as the repository here. "ghcr.io" means "GitHub Container Registry" and
|
||||
is the [GitHub packages](https://github.com/features/packages) registry that supports
|
||||
Docker images and other OCI artifacts.
|
||||
|
||||
### Ubuntu
|
||||
|
||||
> Use or build this container for a multi-stage, slimmer base to develop on top of mfem
|
||||
|
||||
Note that this container is provided on GitHub packages [here](https://github.com/mfem/mfem/pkgs/container/mfem-ubuntu)
|
||||
so you don't need to build it. However, if you want to, you can do the following:
|
||||
Docker images and other OCI artifacts. From the root of the repository:
|
||||
|
||||
```bash
|
||||
$ docker build -f config/docker/Dockerfile -t ghcr.io/mfem/mfem-ubuntu .
|
||||
$ docker build -f config/docker/Dockerfile.base -t ghcr.io/mfem/mfem-ubuntu-base .
|
||||
```
|
||||
|
||||
Note that this will pull the base image. If you want to rebuild it, see [ubuntu base](#ubuntu-base)
|
||||
below. Once you have built (or prefer to pull) you can shell into the container as follows:
|
||||
### Shell Ubuntu
|
||||
|
||||
To shell into the container:
|
||||
|
||||
```bash
|
||||
$ docker run -it ghcr.io/mfem/mfem-ubuntu
|
||||
@@ -47,13 +37,39 @@ bin etc include lib libexec sbin share var
|
||||
- Examples are in share/mfem/examples
|
||||
- Examples are in share/mfem/miniapps
|
||||
|
||||
Using this container, if you want to develop a tool that _uses_ mfem, you can find the libraries / includes in:
|
||||
You can read more about interaction with these examples and miniapps below.
|
||||
|
||||
### Shell Ubuntu Base
|
||||
|
||||
To shell into the container:
|
||||
|
||||
```bash
|
||||
$ ls include/ | grep mfem
|
||||
mfem
|
||||
mfem-performance.hpp
|
||||
mfem.hpp
|
||||
$ docker run -it ghcr.io/mfem/mfem-ubuntu-base bash
|
||||
```
|
||||
|
||||
Off the bat, you can see mfem libraries are in your path so you can jump into development:
|
||||
|
||||
```bash
|
||||
env | grep mfem
|
||||
```
|
||||
```bash
|
||||
PKG_CONFIG_PATH=/opt/mfem-env/.spack-env/view/lib/pkgconfig:/opt/mfem-env/.spack-env/view/share/pkgconfig:/opt/mfem-env/.spack-env/view/lib64/pkgconfig
|
||||
PWD=/opt/mfem-env
|
||||
MANPATH=/opt/mfem-env/.spack-env/view/share/man:/opt/mfem-env/.spack-env/view/man:
|
||||
CMAKE_PREFIX_PATH=/opt/mfem-env/.spack-env/view
|
||||
SPACK_ENV=/opt/mfem-env
|
||||
ACLOCAL_PATH=/opt/mfem-env/.spack-env/view/share/aclocal
|
||||
LD_LIBRARY_PATH=/opt/mfem-env/.spack-env/view/lib:/opt/mfem-env/.spack-env/view/lib64
|
||||
PATH=/opt/mfem-env/.spack-env/view/bin:/opt/view/bin:/opt/spack/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||
```
|
||||
|
||||
#### Examples and MiniApps
|
||||
|
||||
If you want to develop a tool that _uses_ mfem, you can find the built libraries in:
|
||||
|
||||
```
|
||||
$ ls /opt/mfem-env/.spack-env/view/
|
||||
bin etc include lib libexec sbin share var
|
||||
```
|
||||
|
||||
And yes, this is the working directory when you shell into the container!
|
||||
@@ -63,16 +79,6 @@ You can find the examples here:
|
||||
```bash
|
||||
cd share/mfem/examples
|
||||
```
|
||||
|
||||
Try quickly setting the `LD_LIBRARY_PATH` so we can see the shared libraries
|
||||
we need:
|
||||
|
||||
```bash
|
||||
export LD_LIBRARY_PATH=/opt/mfem-view/lib:$LD_LIBRARY_PATH
|
||||
```
|
||||
|
||||
And then run:
|
||||
|
||||
```bash
|
||||
$ ./ex0
|
||||
Options used:
|
||||
@@ -91,6 +97,7 @@ Number of unknowns: 101
|
||||
Average reduction factor = 0.140201
|
||||
```
|
||||
|
||||
Try running a few, and look at the associated .cpp file for the source code!
|
||||
You can also explore the "mini apps," also in share/mfem, but under miniapps.
|
||||
|
||||
```bash
|
||||
@@ -123,87 +130,18 @@ Rule:
|
||||
Applying rule...done.
|
||||
```
|
||||
|
||||
Have fun! As a reminder, this container is ideal for developing your own
|
||||
applications that might use mfem, or having a nice environment to test out
|
||||
examples.
|
||||
Have fun!
|
||||
|
||||
|
||||
### Ubuntu Base
|
||||
|
||||
> Use this build for a development environment with spack and mfem
|
||||
|
||||
This container is also [provided on GitHub packages](https://github.com/mfem/mfem/pkgs/container/mfem-ubuntu-base),
|
||||
however you can build it locally too:
|
||||
#### Your own App
|
||||
If you want to develop with your own code base
|
||||
(and mfem as is in the container) you can bind to somewhere else in the container (e.g., src)
|
||||
|
||||
```bash
|
||||
$ docker build -f config/docker/Dockerfile.base -t ghcr.io/mfem/mfem-ubuntu-base .
|
||||
```
|
||||
|
||||
To shell into the container:
|
||||
|
||||
```bash
|
||||
$ docker run -it ghcr.io/mfem/mfem-ubuntu-base bash
|
||||
```
|
||||
|
||||
Change directory to the mfem environment, setup spack, and activate the environment:
|
||||
|
||||
```bash
|
||||
source /opt/spack/share/spack/setup-env.sh
|
||||
cd /opt/mfem-env/
|
||||
spack env activate .
|
||||
```
|
||||
|
||||
Note that this environment is installing to the view at `/opt/view`. Since the environment
|
||||
knows to install mfem from `/code` this means that you could make changes in the container (or bind
|
||||
`/code` to your container) and then update spack:
|
||||
|
||||
```bash
|
||||
# Note that concretization takes a hot minute!
|
||||
$ spack install
|
||||
```
|
||||
|
||||
And if you want to load mfem:
|
||||
|
||||
```bash
|
||||
$ spack load mfem
|
||||
$ env | grep mfem
|
||||
```
|
||||
|
||||
In this development container, you can find the examples and miniapps alongside
|
||||
mfem under `/code`:
|
||||
|
||||
```bash
|
||||
cd /code/examples
|
||||
```
|
||||
```bash
|
||||
$ ./ex0
|
||||
```
|
||||
```console
|
||||
Options used:
|
||||
--mesh ../data/star.mesh
|
||||
--order 1
|
||||
Number of unknowns: 101
|
||||
Iteration : 0 (B r, r) = 0.184259
|
||||
Iteration : 1 (B r, r) = 0.102754
|
||||
Iteration : 2 (B r, r) = 0.00558141
|
||||
Iteration : 3 (B r, r) = 1.5247e-05
|
||||
Iteration : 4 (B r, r) = 1.13807e-07
|
||||
Iteration : 5 (B r, r) = 6.27231e-09
|
||||
Iteration : 6 (B r, r) = 3.76268e-11
|
||||
Iteration : 7 (B r, r) = 6.07423e-13
|
||||
Iteration : 8 (B r, r) = 4.10615e-15
|
||||
Average reduction factor = 0.140201
|
||||
```
|
||||
|
||||
This container is likely ideal for someone that wants to develop mfem itself.
|
||||
For other use cases, we recommend using the slimmer image. As an example,
|
||||
if you want to develop with your own code base (and mfem as is in the container)
|
||||
you can bind to somewhere else in the container (e.g., src)
|
||||
|
||||
```bash
|
||||
$ docker run -it ghcr.io/mfem/mfem-ubuntu-base -v $PWD:/code bash
|
||||
$ docker run -it ghcr.io/mfem/mfem-ubuntu-base -v $PWD:/src bash
|
||||
```
|
||||
|
||||
In the above, we can pretend your project is in the present working directory (PWD) and we are
|
||||
binding to source. You can then use the mfem in the container for development, and if you
|
||||
want to distribute your library or app in a container, you can use the mfem container as the base.
|
||||
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
MFEM mesh v1.0
|
||||
|
||||
#
|
||||
# MFEM Geometry Types (see mesh/geom.hpp):
|
||||
#
|
||||
# POINT = 0
|
||||
# SEGMENT = 1
|
||||
# TRIANGLE = 2
|
||||
# SQUARE = 3
|
||||
# TETRAHEDRON = 4
|
||||
# CUBE = 5
|
||||
# PRISM = 6
|
||||
#
|
||||
|
||||
dimension
|
||||
1
|
||||
|
||||
elements
|
||||
4
|
||||
1 1 0 1
|
||||
1 1 1 2
|
||||
1 1 2 3
|
||||
1 1 3 4
|
||||
|
||||
boundary
|
||||
2
|
||||
1 0 0
|
||||
2 0 4
|
||||
|
||||
vertices
|
||||
5
|
||||
2
|
||||
0 0
|
||||
0.25 0.25
|
||||
0.50 0.50
|
||||
0.75 0.75
|
||||
1 1
|
||||
@@ -1,37 +0,0 @@
|
||||
MFEM mesh v1.0
|
||||
|
||||
#
|
||||
# MFEM Geometry Types (see mesh/geom.hpp):
|
||||
#
|
||||
# POINT = 0
|
||||
# SEGMENT = 1
|
||||
# TRIANGLE = 2
|
||||
# SQUARE = 3
|
||||
# TETRAHEDRON = 4
|
||||
# CUBE = 5
|
||||
# PRISM = 6
|
||||
#
|
||||
|
||||
dimension
|
||||
1
|
||||
|
||||
elements
|
||||
4
|
||||
1 1 0 1
|
||||
1 1 1 2
|
||||
1 1 2 3
|
||||
1 1 3 4
|
||||
|
||||
boundary
|
||||
2
|
||||
1 0 0
|
||||
2 0 4
|
||||
|
||||
vertices
|
||||
5
|
||||
3
|
||||
0 0 0
|
||||
0.25 0.25 0.25
|
||||
0.50 0.50 0.50
|
||||
0.75 0.75 0.75
|
||||
1 1 1
|
||||
@@ -38,7 +38,7 @@ PROJECT_NAME = "MFEM"
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = v4.6.1
|
||||
PROJECT_NUMBER = v4.5.3
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
|
||||
@@ -105,13 +105,8 @@ namespace mfem {
|
||||
* - <a class="el" href="ex32p_8cpp_source.html">Example 32p</a>: parallel anisotropic Maxwell eigensolver
|
||||
* - <a class="el" href="ex33_8cpp_source.html">Example 33</a>: nodal H1 FEM for the fractional Laplacian problem
|
||||
* - <a class="el" href="ex33p_8cpp_source.html">Example 33p</a>: parallel nodal H1 FEM for the fractional Laplacian problem
|
||||
* - <a class="el" href="ex34_8cpp_source.html">Example 34</a>: multi-domain magnetostatics
|
||||
* - <a class="el" href="ex34p_8cpp_source.html">Example 34p</a>: parallel multi-domain magnetostatics
|
||||
* - <a class="el" href="ex35p_8cpp_source.html">Example 35p</a>: parallel multi-domain damped harmonic oscillators
|
||||
* - <a class="el" href="ex36_8cpp_source.html">Example 36</a>: Proximal Galerkin FEM for the obstacle problem
|
||||
* - <a class="el" href="ex36p_8cpp_source.html">Example 36p</a>: parallel Proximal Galerkin FEM for the obstacle problem
|
||||
* - <a class="el" href="ex37_8cpp_source.html">Example 37</a>: Topology optimization
|
||||
* - <a class="el" href="ex37p_8cpp_source.html">Example 37p</a>: parallel topology optimization
|
||||
*
|
||||
* <H4>AmgX Examples</H4>
|
||||
* - Variants of Examples
|
||||
|
||||
@@ -42,7 +42,6 @@ list(APPEND ALL_EXE_SRCS
|
||||
ex33.cpp
|
||||
ex34.cpp
|
||||
ex36.cpp
|
||||
ex37.cpp
|
||||
)
|
||||
|
||||
if (MFEM_USE_MPI)
|
||||
@@ -83,7 +82,6 @@ if (MFEM_USE_MPI)
|
||||
ex34p.cpp
|
||||
ex35p.cpp
|
||||
ex36p.cpp
|
||||
ex37p.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -109,8 +107,6 @@ if (MFEM_ENABLE_TESTING)
|
||||
list(APPEND THIS_TEST_OPTIONS "-e" "1")
|
||||
elseif(${TEST_NAME} MATCHES "ex27p*")
|
||||
list(APPEND THIS_TEST_OPTIONS "-dg")
|
||||
elseif(${TEST_NAME} MATCHES "ex37p*")
|
||||
list(APPEND THIS_TEST_OPTIONS "-mi" "3")
|
||||
endif()
|
||||
|
||||
if (NOT (${TEST_NAME} MATCHES ".*p$"))
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ using namespace mfem;
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// 1. Parse command line options.
|
||||
string mesh_file = "../data/star.mesh";
|
||||
const char *mesh_file = "../data/star.mesh";
|
||||
int order = 1;
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ int main(int argc, char *argv[])
|
||||
Hypre::Init();
|
||||
|
||||
// 2. Parse command line options.
|
||||
string mesh_file = "../data/star.mesh";
|
||||
const char *mesh_file = "../data/star.mesh";
|
||||
int order = 1;
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
// Sample runs: mpirun -np 4 ex13p -m ../data/star.mesh
|
||||
// mpirun -np 4 ex13p -m ../data/square-disc.mesh -o 2 -n 4
|
||||
// mpirun -np 4 ex13p -m ../data/beam-tet.mesh
|
||||
// mpirun -np 4 ex13p -m ../data/beam-tet.mesh -nc -o 2 -rs 1
|
||||
// mpirun -np 4 ex13p -m ../data/beam-hex.mesh
|
||||
// mpirun -np 4 ex13p -m ../data/escher.mesh
|
||||
// mpirun -np 4 ex13p -m ../data/fichera.mesh
|
||||
@@ -55,7 +54,6 @@ int main(int argc, char *argv[])
|
||||
int par_ref_levels = 1;
|
||||
int order = 1;
|
||||
int nev = 5;
|
||||
bool nc = false;
|
||||
bool visualization = 1;
|
||||
const char *device_config = "cpu";
|
||||
|
||||
@@ -71,9 +69,6 @@ int main(int argc, char *argv[])
|
||||
" isoparametric space.");
|
||||
args.AddOption(&nev, "-n", "--num-eigs",
|
||||
"Number of desired eigenmodes.");
|
||||
args.AddOption(&nc, "-nc", "--non-conforming", "-c",
|
||||
"--conforming",
|
||||
"Mark the mesh as nonconforming before partitioning.");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
@@ -103,10 +98,6 @@ int main(int argc, char *argv[])
|
||||
// and volume meshes with the same code.
|
||||
Mesh *mesh = new Mesh(mesh_file, 1, 1);
|
||||
int dim = mesh->Dimension();
|
||||
if (nc)
|
||||
{
|
||||
mesh->EnsureNCMesh(true);
|
||||
}
|
||||
|
||||
// 5. Refine the serial mesh on all processors to increase the resolution. In
|
||||
// this example we do 'ref_levels' of uniform refinement (2 by default, or
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
// mpirun -np 4 ex15p -m ../data/square-disc-nurbs.mesh
|
||||
// mpirun -np 4 ex15p -m ../data/disc-nurbs.mesh
|
||||
// mpirun -np 4 ex15p -m ../data/fichera.mesh -tf 0.5
|
||||
// mpirun -np 4 ex15p -m ../data/fichera-mixed.mesh -tf 0.5
|
||||
// mpirun -np 4 ex15p -m ../data/ball-nurbs.mesh -tf 0.5
|
||||
// mpirun -np 4 ex15p -m ../data/mobius-strip.mesh
|
||||
// mpirun -np 4 ex15p -m ../data/amr-quad.mesh
|
||||
|
||||
@@ -63,7 +63,6 @@ int main(int argc, char *argv[])
|
||||
int order = 1;
|
||||
bool static_cond = false;
|
||||
bool pa = false;
|
||||
bool nc = false;
|
||||
const char *device_config = "cpu";
|
||||
bool visualization = 1;
|
||||
|
||||
@@ -78,9 +77,6 @@ int main(int argc, char *argv[])
|
||||
"--no-static-condensation", "Enable static condensation.");
|
||||
args.AddOption(&pa, "-pa", "--partial-assembly", "-no-pa",
|
||||
"--no-partial-assembly", "Enable Partial Assembly.");
|
||||
args.AddOption(&nc, "-nc", "--non-conforming", "-c",
|
||||
"--conforming",
|
||||
"Mark the mesh as nonconforming before partitioning.");
|
||||
args.AddOption(&device_config, "-d", "--device",
|
||||
"Device configuration string, see Device::Configure().");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
@@ -106,11 +102,6 @@ int main(int argc, char *argv[])
|
||||
Mesh *mesh = new Mesh(mesh_file, 1, 1);
|
||||
dim = mesh->Dimension();
|
||||
int sdim = mesh->SpaceDimension();
|
||||
if (nc)
|
||||
{
|
||||
// Can set to false to use conformal refinement for simplices.
|
||||
mesh->EnsureNCMesh(true);
|
||||
}
|
||||
|
||||
// 4. Refine the mesh to increase the resolution. In this example we do
|
||||
// 'ref_levels' of uniform refinement. We choose 'ref_levels' to be the
|
||||
|
||||
+25
-24
@@ -267,9 +267,9 @@ int main(int argc, char *argv[])
|
||||
<< "window_geometry 400 0 400 350" << flush;
|
||||
}
|
||||
|
||||
// 7. Define a parallel finite element space on the full mesh. Here we use
|
||||
// the H(curl) finite elements for the vector potential and H(div) for the
|
||||
// current density.
|
||||
// 7. Define a parallel finite element space on the full mesh. Here we
|
||||
// use the H(curl) finite elements for the vector potential and H(div)
|
||||
// for the current density.
|
||||
ND_FECollection fec_nd(order, dim);
|
||||
RT_FECollection fec_rt(order - 1, dim);
|
||||
FiniteElementSpace fespace_nd(&mesh, &fec_nd);
|
||||
@@ -292,10 +292,10 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// 8. Determine the list of true (i.e. parallel conforming) essential
|
||||
// boundary dofs. In this example, the boundary conditions are defined by
|
||||
// marking all the boundary attributes except for those on a symmetry
|
||||
// plane as essential (Dirichlet) and converting them to a list of true
|
||||
// dofs.
|
||||
// boundary dofs. In this example, the boundary conditions are defined
|
||||
// by marking all the boundary attributes except for those on a symmetry
|
||||
// plane as essential (Dirichlet) and converting them to a list of
|
||||
// true dofs.
|
||||
Array<int> ess_tdof_list;
|
||||
Array<int> ess_bdr;
|
||||
if (mesh.bdr_attributes.Size())
|
||||
@@ -324,13 +324,14 @@ int main(int argc, char *argv[])
|
||||
GridFunction x(&fespace_nd);
|
||||
x = 0.0;
|
||||
|
||||
// 11. Set up the parallel bilinear form corresponding to the EM diffusion
|
||||
// operator curl muinv curl + delta I, by adding the curl-curl and the
|
||||
// mass domain integrators. For standard magnetostatics equations choose
|
||||
// delta << 1. Larger values of delta should make the linear system
|
||||
// easier to solve at the expense of resembling a diffusive quasistatic
|
||||
// magnetic field. A reasonable balance must be found whenever the mesh
|
||||
// or problem setup is altered.
|
||||
// 11. Set up the parallel bilinear form corresponding to the EM
|
||||
// diffusion operator curl muinv curl + delta I, by adding the
|
||||
// curl-curl and the mass domain integrators. For standard
|
||||
// magnetostatics equations choose delta << 1. Larger values of
|
||||
// delta should make the linear system easier to solve at the
|
||||
// expense of resembling a diffusive quasistatic magnetic field.
|
||||
// A reasonable balance must be found whenever the mesh or problem
|
||||
// setup is altered.
|
||||
ConstantCoefficient muinv(1.0);
|
||||
ConstantCoefficient delta(delta_const);
|
||||
BilinearForm a(&fespace_nd);
|
||||
@@ -422,8 +423,8 @@ int main(int argc, char *argv[])
|
||||
GridFunction dx(&fespace_rt);
|
||||
curl.Mult(x, dx);
|
||||
|
||||
// 18. Save the curl of the solution in parallel. This output can be viewed
|
||||
// later using GLVis: "glvis -np <np> -m mesh -g dsol".
|
||||
// 18. Save the curl of the solution in parallel. This output can
|
||||
// be viewed later using GLVis: "glvis -np <np> -m mesh -g dsol".
|
||||
{
|
||||
ostringstream dsol_name;
|
||||
dsol_name << "dsol.gf";
|
||||
@@ -455,18 +456,18 @@ void ComputeCurrentDensityOnSubMesh(int order,
|
||||
const Array<int> &jn_zero_attr,
|
||||
GridFunction &j_cond)
|
||||
{
|
||||
// Extract the finite element space and mesh on which j_cond is defined
|
||||
// Exract the finite element space and mesh on which j_cond is defined
|
||||
FiniteElementSpace &fes_cond_rt = *j_cond.FESpace();
|
||||
Mesh &mesh_cond = *fes_cond_rt.GetMesh();
|
||||
int dim = mesh_cond.Dimension();
|
||||
|
||||
// Define a parallel finite element space on the SubMesh. Here we use the H1
|
||||
// finite elements for the electrostatic potential.
|
||||
// Define a parallel finite element space on the SubMesh. Here we use the
|
||||
// H1 finite elements for the electrostatic potential.
|
||||
H1_FECollection fec_h1(order, dim);
|
||||
FiniteElementSpace fes_cond_h1(&mesh_cond, &fec_h1);
|
||||
|
||||
// Define the conductivity coefficient and the boundaries associated with the
|
||||
// fixed potentials phi0 and phi1 which will drive the current.
|
||||
// Define the conductivity coefficient and the boundaries associated with
|
||||
// the fixed potentials phi0 and phi1 which will drive the current.
|
||||
ConstantCoefficient sigmaCoef(1.0);
|
||||
Array<int> ess_bdr_phi(mesh_cond.bdr_attributes.Max());
|
||||
Array<int> ess_bdr_j(mesh_cond.bdr_attributes.Max());
|
||||
@@ -577,9 +578,9 @@ void ComputeCurrentDensityOnSubMesh(int order,
|
||||
<< "window_geometry 0 0 400 350" << flush;
|
||||
}
|
||||
|
||||
// Solve for the current density J = -sigma Grad phi with boundary conditions
|
||||
// J.n = 0 on the walls of the conductor but not on the ports where phi=0 and
|
||||
// phi=1.
|
||||
// Solve for the current density J = -sigma Grad phi with boundary
|
||||
// conditions J.n = 0 on the walls of the conductor but not on the
|
||||
// ports where phi=0 and phi=1.
|
||||
|
||||
// J will be computed in H(div) so we need an RT mass matrix
|
||||
BilinearForm m_rt(&fes_cond_rt);
|
||||
|
||||
+17
-16
@@ -302,9 +302,9 @@ int main(int argc, char *argv[])
|
||||
<< "window_geometry 400 0 400 350" << flush;
|
||||
}
|
||||
|
||||
// 8. Define a parallel finite element space on the full mesh. Here we use
|
||||
// the H(curl) finite elements for the vector potential and H(div) for the
|
||||
// current density.
|
||||
// 8. Define a parallel finite element space on the full mesh. Here we
|
||||
// use the H(curl) finite elements for the vector potential and H(div)
|
||||
// for the current density.
|
||||
ND_FECollection fec_nd(order, dim);
|
||||
RT_FECollection fec_rt(order - 1, dim);
|
||||
ParFiniteElementSpace fespace_nd(&pmesh, &fec_nd);
|
||||
@@ -360,13 +360,14 @@ int main(int argc, char *argv[])
|
||||
ParGridFunction x(&fespace_nd);
|
||||
x = 0.0;
|
||||
|
||||
// 12. Set up the parallel bilinear form corresponding to the EM diffusion
|
||||
// operator curl muinv curl + delta I, by adding the curl-curl and the
|
||||
// mass domain integrators. For standard magnetostatics equations choose
|
||||
// delta << 1. Larger values of delta should make the linear system
|
||||
// easier to solve at the expense of resembling a diffusive quasistatic
|
||||
// magnetic field. A reasonable balance must be found whenever the mesh
|
||||
// or problem setup is altered.
|
||||
// 12. Set up the parallel bilinear form corresponding to the EM
|
||||
// diffusion operator curl muinv curl + delta I, by adding the
|
||||
// curl-curl and the mass domain integrators. For standard
|
||||
// magnetostatics equations choose delta << 1. Larger values of
|
||||
// delta should make the linear system easier to solve at the
|
||||
// expense of resembling a diffusive quasistatic magnetic field.
|
||||
// A reasonable balance must be found whenever the mesh or problem
|
||||
// setup is altered.
|
||||
ConstantCoefficient muinv(1.0);
|
||||
ConstantCoefficient delta(delta_const);
|
||||
ParBilinearForm a(&fespace_nd);
|
||||
@@ -503,7 +504,7 @@ void ComputeCurrentDensityOnSubMesh(int order,
|
||||
const Array<int> &jn_zero_attr,
|
||||
ParGridFunction &j_cond)
|
||||
{
|
||||
// Extract the finite element space and mesh on which j_cond is defined
|
||||
// Exract the finite element space and mesh on which j_cond is defined
|
||||
ParFiniteElementSpace &fes_cond_rt = *j_cond.ParFESpace();
|
||||
ParMesh &pmesh_cond = *fes_cond_rt.GetParMesh();
|
||||
int myid = fes_cond_rt.GetMyRank();
|
||||
@@ -514,8 +515,8 @@ void ComputeCurrentDensityOnSubMesh(int order,
|
||||
H1_FECollection fec_h1(order, dim);
|
||||
ParFiniteElementSpace fes_cond_h1(&pmesh_cond, &fec_h1);
|
||||
|
||||
// Define the conductivity coefficient and the boundaries associated with the
|
||||
// fixed potentials phi0 and phi1 which will drive the current.
|
||||
// Define the conductivity coefficient and the boundaries associated with
|
||||
// the fixed potentials phi0 and phi1 which will drive the current.
|
||||
ConstantCoefficient sigmaCoef(1.0);
|
||||
Array<int> ess_bdr_phi(pmesh_cond.bdr_attributes.Max());
|
||||
Array<int> ess_bdr_j(pmesh_cond.bdr_attributes.Max());
|
||||
@@ -598,9 +599,9 @@ void ComputeCurrentDensityOnSubMesh(int order,
|
||||
<< "window_geometry 0 0 400 350" << flush;
|
||||
}
|
||||
|
||||
// Solve for the current density J = -sigma Grad phi with boundary conditions
|
||||
// J.n = 0 on the walls of the conductor but not on the ports where phi=0 and
|
||||
// phi=1.
|
||||
// Solve for the current density J = -sigma Grad phi with boundary
|
||||
// conditions J.n = 0 on the walls of the conductor but not on the
|
||||
// ports where phi=0 and phi=1.
|
||||
|
||||
// J will be computed in H(div) so we need an RT mass matrix
|
||||
ParBilinearForm m_rt(&fes_cond_rt);
|
||||
|
||||
+25
-22
@@ -35,10 +35,10 @@
|
||||
// conductivity, sigma = c. The user can specify these constants
|
||||
// using either set of names.
|
||||
//
|
||||
// This example demonstrates how to transfer fields computed on a
|
||||
// boundary generated SubMesh to the full mesh and apply them as
|
||||
// boundary conditions. The default mesh and corresponding
|
||||
// boundary attributes were chosen to verify proper behavior on
|
||||
// This example demonstrates how to transfer fields computed on
|
||||
// a boundary generated SubMesh to the full mesh and apply them
|
||||
// as boundary conditions. The default mesh and corresponding
|
||||
// boundary attriburtes were chosen to verify proper behavior on
|
||||
// both triangular and quadrilateral faces of tetrahedral,
|
||||
// wedge-shaped, and hexahedral elements.
|
||||
//
|
||||
@@ -420,6 +420,7 @@ int main(int argc, char *argv[])
|
||||
//
|
||||
// 2) A vector H(Div) field
|
||||
// -Grad(a Div) - omega^2 b + i omega c
|
||||
//
|
||||
ParBilinearForm pcOp(&fespace);
|
||||
if (pa) { pcOp.SetAssemblyLevel(AssemblyLevel::PARTIAL); }
|
||||
switch (prob)
|
||||
@@ -444,8 +445,8 @@ int main(int argc, char *argv[])
|
||||
pcOp.Assemble();
|
||||
|
||||
// 14b. Define and apply a parallel FGMRES solver for AU=B with a block
|
||||
// diagonal preconditioner based on the appropriate multigrid
|
||||
// preconditioner from hypre.
|
||||
// diagonal preconditioner based on the appropriate multigrid
|
||||
// preconditioner from hypre.
|
||||
Array<int> blockTrueOffsets;
|
||||
blockTrueOffsets.SetSize(3);
|
||||
blockTrueOffsets[0] = 0;
|
||||
@@ -608,9 +609,10 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/**
|
||||
Solves the eigenvalue problem -Div(Grad x) = lambda x with homogeneous
|
||||
Dirichlet boundary conditions on the boundary of the domain. Returns mode
|
||||
number "mode" (counting from zero) in the ParGridFunction "x".
|
||||
Solves the eigenvalue problem -Div(Grad x) = lambda x with
|
||||
homogeneous Dirichlet boundary conditions on the boundary of the
|
||||
domain. Returns mode number "mode" (counting from zero) in the
|
||||
ParGridFunction "x".
|
||||
*/
|
||||
void ScalarWaveGuide(int mode, ParGridFunction &x)
|
||||
{
|
||||
@@ -665,10 +667,10 @@ void ScalarWaveGuide(int mode, ParGridFunction &x)
|
||||
}
|
||||
|
||||
/**
|
||||
Solves the eigenvalue problem -Curl(Curl x) = lambda x with homogeneous
|
||||
Dirichlet boundary conditions, on the tangential component of x, on the
|
||||
boundary of the domain. Returns mode number "mode" (counting from zero) in
|
||||
the ParGridFunction "x".
|
||||
Solves the eigenvalue problem -Curl(Curl x) = lambda x with
|
||||
homogeneous Dirichlet boundary conditions, on the tangential
|
||||
component of x, on the boundary of the domain. Returns mode number
|
||||
"mode" (counting from zero) in the ParGridFunction "x".
|
||||
*/
|
||||
void VectorWaveGuide(int mode, ParGridFunction &x)
|
||||
{
|
||||
@@ -721,12 +723,13 @@ void VectorWaveGuide(int mode, ParGridFunction &x)
|
||||
}
|
||||
|
||||
/**
|
||||
Solves the eigenvalue problem -Div(Grad x) = lambda x with homogeneous
|
||||
Neumann boundary conditions on the boundary of the domain. Returns mode
|
||||
number "mode" (counting from zero) in the ParGridFunction "x_l2". Note that
|
||||
mode 0 is a constant field so higher mode numbers are often more
|
||||
interesting. The eigenmode is solved using continuous H1 basis of the
|
||||
appropriate order and then projected onto the L2 basis and returned.
|
||||
Solves the eigenvalue problem -Div(Grad x) = lambda x with
|
||||
homogeneous Neumann boundary conditions on the boundary of the
|
||||
domain. Returns mode number "mode" (counting from zero) in the
|
||||
ParGridFunction "x_l2". Note that mode 0 is a constant field so
|
||||
higher mode numbers are often more interesting. The eigenmode is
|
||||
solved using continuous H1 basis of the appropriate order and then
|
||||
projected onto the L2 basis and returned.
|
||||
*/
|
||||
void PseudoScalarWaveGuide(int mode, ParGridFunction &x_l2)
|
||||
{
|
||||
@@ -788,9 +791,9 @@ void PseudoScalarWaveGuide(int mode, ParGridFunction &x_l2)
|
||||
delete M;
|
||||
}
|
||||
|
||||
// Compute eigenmode "mode" of either a Dirichlet or Neumann Laplacian or of a
|
||||
// Dirichlet curl curl operator based on the problem type and dimension of the
|
||||
// domain.
|
||||
// Compute eigenmode "mode" of either a Dirichlet or Neumann Laplacian
|
||||
// or of a Dirichlet curl curl operator based on the problem type and
|
||||
// dimension of the domain.
|
||||
void SetPortBC(int prob, int dim, int mode, ParGridFunction &port_bc)
|
||||
{
|
||||
switch (prob)
|
||||
|
||||
+7
-3
@@ -1,10 +1,12 @@
|
||||
// MFEM Example 36
|
||||
//
|
||||
//
|
||||
// Compile with: make ex36
|
||||
//
|
||||
// Sample runs: ex36 -o 2
|
||||
// ex36 -o 2 -r 4
|
||||
//
|
||||
//
|
||||
// Description: This example code demonstrates the use of MFEM to solve the
|
||||
// bound-constrained energy minimization problem
|
||||
//
|
||||
@@ -26,10 +28,12 @@
|
||||
// order solutions to variation inequality problems and
|
||||
// showcases how to set up and solve nonlinear mixed methods.
|
||||
//
|
||||
//
|
||||
// [1] Keith, B. and Surowiec, T. (2023) Proximal Galerkin: A structure-
|
||||
// preserving finite element method for pointwise bound constraints.
|
||||
// arXiv:2307.12444 [math.NA]
|
||||
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
@@ -59,7 +63,7 @@ public:
|
||||
class ExponentialGridFunctionCoefficient : public Coefficient
|
||||
{
|
||||
protected:
|
||||
GridFunction *u;
|
||||
GridFunction *u; // grid function
|
||||
Coefficient *obstacle;
|
||||
double min_val;
|
||||
double max_val;
|
||||
@@ -84,7 +88,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
args.AddOption(&order, "-o", "--order",
|
||||
"Finite element order (polynomial degree).");
|
||||
"Finite element order (polynomial degree)");
|
||||
args.AddOption(&ref_levels, "-r", "--refs",
|
||||
"Number of h-refinements.");
|
||||
args.AddOption(&max_it, "-mi", "--max-it",
|
||||
@@ -194,7 +198,7 @@ int main(int argc, char *argv[])
|
||||
u_gf.ProjectCoefficient(IC_coef);
|
||||
u_old_gf = u_gf;
|
||||
|
||||
// 9. Initialize the slack variable ψₕ = ln(uₕ)
|
||||
// 9. Initialize the slack variable ψₕ = exp(uₕ)
|
||||
LogarithmGridFunctionCoefficient ln_u(u_gf, obstacle);
|
||||
psi_gf.ProjectCoefficient(ln_u);
|
||||
psi_old_gf = psi_gf;
|
||||
|
||||
+8
-3
@@ -1,10 +1,12 @@
|
||||
// MFEM Example 36 - Parallel Version
|
||||
// MFEM Example 36 - Parallel Version
|
||||
//
|
||||
//
|
||||
// Compile with: make ex36p
|
||||
//
|
||||
// Sample runs: mpirun -np 4 ex36p -o 2
|
||||
// mpirun -np 4 ex36p -o 2 -r 4
|
||||
//
|
||||
//
|
||||
// Description: This example code demonstrates the use of MFEM to solve the
|
||||
// bound-constrained energy minimization problem
|
||||
//
|
||||
@@ -26,10 +28,12 @@
|
||||
// order solutions to variation inequality problems and
|
||||
// showcases how to set up and solve nonlinear mixed methods.
|
||||
//
|
||||
//
|
||||
// [1] Keith, B. and Surowiec, T. (2023) Proximal Galerkin: A structure-
|
||||
// preserving finite element method for pointwise bound constraints.
|
||||
// arXiv:2307.12444 [math.NA]
|
||||
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
@@ -59,7 +63,7 @@ public:
|
||||
class ExponentialGridFunctionCoefficient : public Coefficient
|
||||
{
|
||||
protected:
|
||||
GridFunction *u;
|
||||
GridFunction *u; // grid function
|
||||
Coefficient *obstacle;
|
||||
double min_val;
|
||||
double max_val;
|
||||
@@ -216,6 +220,7 @@ int main(int argc, char *argv[])
|
||||
u_old_gf = 0.0;
|
||||
psi_old_gf = 0.0;
|
||||
|
||||
|
||||
// 8. Define the function coefficients for the solution and use them to
|
||||
// initialize the initial guess
|
||||
FunctionCoefficient exact_coef(exact_solution_obstacle);
|
||||
@@ -226,7 +231,7 @@ int main(int argc, char *argv[])
|
||||
u_gf.ProjectCoefficient(IC_coef);
|
||||
u_old_gf = u_gf;
|
||||
|
||||
// 9. Initialize the slack variable ψₕ = ln(uₕ)
|
||||
// 9. Initialize the slack variable ψₕ = exp(uₕ)
|
||||
LogarithmGridFunctionCoefficient ln_u(u_gf, obstacle);
|
||||
psi_gf.ProjectCoefficient(ln_u);
|
||||
psi_old_gf = psi_gf;
|
||||
|
||||
@@ -1,466 +0,0 @@
|
||||
// MFEM Example 37
|
||||
//
|
||||
// Compile with: make ex37
|
||||
//
|
||||
// Sample runs:
|
||||
// ex37 -alpha 10
|
||||
// ex37 -alpha 10 -pv
|
||||
// ex37 -lambda 0.1 -mu 0.1
|
||||
// ex37 -o 2 -alpha 5.0 -mi 50 -vf 0.4 -ntol 1e-5
|
||||
// ex37 -r 6 -o 1 -alpha 25.0 -epsilon 0.02 -mi 50 -ntol 1e-5
|
||||
//
|
||||
// Description: This example code demonstrates the use of MFEM to solve a
|
||||
// density-filtered [3] topology optimization problem. The
|
||||
// objective is to minimize the compliance
|
||||
//
|
||||
// minimize ∫_Ω f⋅u dx over u ∈ [H¹(Ω)]² and ρ ∈ L¹(Ω)
|
||||
//
|
||||
// subject to
|
||||
//
|
||||
// -Div(r(ρ̃)Cε(u)) = f in Ω + BCs
|
||||
// -ϵ²Δρ̃ + ρ̃ = ρ in Ω + Neumann BCs
|
||||
// 0 ≤ ρ ≤ 1 in Ω
|
||||
// ∫_Ω ρ dx = θ vol(Ω)
|
||||
//
|
||||
// Here, r(ρ̃) = ρ₀ + ρ̃³ (1-ρ₀) is the solid isotropic material
|
||||
// penalization (SIMP) law, C is the elasticity tensor for an
|
||||
// isotropic linearly elastic material, ϵ > 0 is the design
|
||||
// length scale, and 0 < θ < 1 is the volume fraction.
|
||||
//
|
||||
// The problem is discretized and gradients are computing using
|
||||
// finite elements [1]. The design is optimized using an entropic
|
||||
// mirror descent algorithm introduced by Keith and Surowiec [2]
|
||||
// that is tailored to the bound constraint 0 ≤ ρ ≤ 1.
|
||||
//
|
||||
// This example highlights the ability of MFEM to deliver high-
|
||||
// order solutions to inverse design problems and showcases how
|
||||
// to set up and solve PDE-constrained optimization problems
|
||||
// using the so-called reduced space approach.
|
||||
//
|
||||
// [1] Andreassen, E., Clausen, A., Schevenels, M., Lazarov, B. S., & Sigmund, O.
|
||||
// (2011). Efficient topology optimization in MATLAB using 88 lines of
|
||||
// code. Structural and Multidisciplinary Optimization, 43(1), 1-16.
|
||||
// [2] Keith, B. and Surowiec, T. (2023) Proximal Galerkin: A structure-
|
||||
// preserving finite element method for pointwise bound constraints.
|
||||
// arXiv:2307.12444 [math.NA]
|
||||
// [3] Lazarov, B. S., & Sigmund, O. (2011). Filters in topology optimization
|
||||
// based on Helmholtz‐type differential equations. International Journal
|
||||
// for Numerical Methods in Engineering, 86(6), 765-781.
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "ex37.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace mfem;
|
||||
|
||||
/**
|
||||
* @brief Bregman projection of ρ = sigmoid(ψ) onto the subspace
|
||||
* ∫_Ω ρ dx = θ vol(Ω) as follows:
|
||||
*
|
||||
* 1. Compute the root of the R → R function
|
||||
* f(c) = ∫_Ω sigmoid(ψ + c) dx - θ vol(Ω)
|
||||
* 2. Set ψ ← ψ + c.
|
||||
*
|
||||
* @param psi a GridFunction to be updated
|
||||
* @param target_volume θ vol(Ω)
|
||||
* @param tol Newton iteration tolerance
|
||||
* @param max_its Newton maximum iteration number
|
||||
* @return double Final volume, ∫_Ω sigmoid(ψ)
|
||||
*/
|
||||
double proj(GridFunction &psi, double target_volume, double tol=1e-12,
|
||||
int max_its=10)
|
||||
{
|
||||
MappedGridFunctionCoefficient sigmoid_psi(&psi, sigmoid);
|
||||
MappedGridFunctionCoefficient der_sigmoid_psi(&psi, der_sigmoid);
|
||||
|
||||
LinearForm int_sigmoid_psi(psi.FESpace());
|
||||
int_sigmoid_psi.AddDomainIntegrator(new DomainLFIntegrator(sigmoid_psi));
|
||||
LinearForm int_der_sigmoid_psi(psi.FESpace());
|
||||
int_der_sigmoid_psi.AddDomainIntegrator(new DomainLFIntegrator(
|
||||
der_sigmoid_psi));
|
||||
bool done = false;
|
||||
for (int k=0; k<max_its; k++) // Newton iteration
|
||||
{
|
||||
int_sigmoid_psi.Assemble(); // Recompute f(c) with updated ψ
|
||||
const double f = int_sigmoid_psi.Sum() - target_volume;
|
||||
|
||||
int_der_sigmoid_psi.Assemble(); // Recompute df(c) with updated ψ
|
||||
const double df = int_der_sigmoid_psi.Sum();
|
||||
|
||||
const double dc = -f/df;
|
||||
psi += dc;
|
||||
if (abs(dc) < tol) { done = true; break; }
|
||||
}
|
||||
if (!done)
|
||||
{
|
||||
mfem_warning("Projection reached maximum iteration without converging. "
|
||||
"Result may not be accurate.");
|
||||
}
|
||||
int_sigmoid_psi.Assemble();
|
||||
return int_sigmoid_psi.Sum();
|
||||
}
|
||||
|
||||
/**
|
||||
* ---------------------------------------------------------------
|
||||
* ALGORITHM PREAMBLE
|
||||
* ---------------------------------------------------------------
|
||||
*
|
||||
* The Lagrangian for this problem is
|
||||
*
|
||||
* L(u,ρ,ρ̃,w,w̃) = (f,u) - (r(ρ̃) C ε(u),ε(w)) + (f,w)
|
||||
* - (ϵ² ∇ρ̃,∇w̃) - (ρ̃,w̃) + (ρ,w̃)
|
||||
*
|
||||
* where
|
||||
*
|
||||
* r(ρ̃) = ρ₀ + ρ̃³ (1 - ρ₀) (SIMP rule)
|
||||
*
|
||||
* ε(u) = (∇u + ∇uᵀ)/2 (symmetric gradient)
|
||||
*
|
||||
* C e = λtr(e)I + 2μe (isotropic material)
|
||||
*
|
||||
* NOTE: The Lame parameters can be computed from Young's modulus E
|
||||
* and Poisson's ratio ν as follows:
|
||||
*
|
||||
* λ = E ν/((1+ν)(1-2ν)), μ = E/(2(1+ν))
|
||||
*
|
||||
* ---------------------------------------------------------------
|
||||
*
|
||||
* Discretization choices:
|
||||
*
|
||||
* u ∈ V ⊂ (H¹)ᵈ (order p)
|
||||
* ψ ∈ L² (order p - 1), ρ = sigmoid(ψ)
|
||||
* ρ̃ ∈ H¹ (order p)
|
||||
* w ∈ V (order p)
|
||||
* w̃ ∈ H¹ (order p)
|
||||
*
|
||||
* ---------------------------------------------------------------
|
||||
* ALGORITHM
|
||||
* ---------------------------------------------------------------
|
||||
*
|
||||
* Update ρ with projected mirror descent via the following algorithm.
|
||||
*
|
||||
* 1. Initialize ψ = inv_sigmoid(vol_fraction) so that ∫ sigmoid(ψ) = θ vol(Ω)
|
||||
*
|
||||
* While not converged:
|
||||
*
|
||||
* 2. Solve filter equation ∂_w̃ L = 0; i.e.,
|
||||
*
|
||||
* (ϵ² ∇ ρ̃, ∇ v ) + (ρ̃,v) = (ρ,v) ∀ v ∈ H¹.
|
||||
*
|
||||
* 3. Solve primal problem ∂_w L = 0; i.e.,
|
||||
*
|
||||
* (λ r(ρ̃) ∇⋅u, ∇⋅v) + (2 μ r(ρ̃) ε(u), ε(v)) = (f,v) ∀ v ∈ V.
|
||||
*
|
||||
* NB. The dual problem ∂_u L = 0 is the negative of the primal problem due to symmetry.
|
||||
*
|
||||
* 4. Solve for filtered gradient ∂_ρ̃ L = 0; i.e.,
|
||||
*
|
||||
* (ϵ² ∇ w̃ , ∇ v ) + (w̃ ,v) = (-r'(ρ̃) ( λ |∇⋅u|² + 2 μ |ε(u)|²),v) ∀ v ∈ H¹.
|
||||
*
|
||||
* 5. Project the gradient onto the discrete latent space; i.e., solve
|
||||
*
|
||||
* (G,v) = (w̃,v) ∀ v ∈ L².
|
||||
*
|
||||
* 6. Bregman proximal gradient update; i.e.,
|
||||
*
|
||||
* ψ ← ψ - αG + c,
|
||||
*
|
||||
* where α > 0 is a step size parameter and c ∈ R is a constant ensuring
|
||||
*
|
||||
* ∫_Ω sigmoid(ψ - αG + c) dx = θ vol(Ω).
|
||||
*
|
||||
* end
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// 1. Parse command-line options.
|
||||
int ref_levels = 5;
|
||||
int order = 2;
|
||||
double alpha = 1.0;
|
||||
double epsilon = 0.01;
|
||||
double vol_fraction = 0.5;
|
||||
int max_it = 1e3;
|
||||
double itol = 1e-1;
|
||||
double ntol = 1e-4;
|
||||
double rho_min = 1e-6;
|
||||
double lambda = 1.0;
|
||||
double mu = 1.0;
|
||||
bool glvis_visualization = true;
|
||||
bool paraview_output = false;
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
args.AddOption(&ref_levels, "-r", "--refine",
|
||||
"Number of times to refine the mesh uniformly.");
|
||||
args.AddOption(&order, "-o", "--order",
|
||||
"Order (degree) of the finite elements.");
|
||||
args.AddOption(&alpha, "-alpha", "--alpha-step-length",
|
||||
"Step length for gradient descent.");
|
||||
args.AddOption(&epsilon, "-epsilon", "--epsilon-thickness",
|
||||
"Length scale for ρ.");
|
||||
args.AddOption(&max_it, "-mi", "--max-it",
|
||||
"Maximum number of gradient descent iterations.");
|
||||
args.AddOption(&ntol, "-ntol", "--rel-tol",
|
||||
"Normalized exit tolerance.");
|
||||
args.AddOption(&itol, "-itol", "--abs-tol",
|
||||
"Increment exit tolerance.");
|
||||
args.AddOption(&vol_fraction, "-vf", "--volume-fraction",
|
||||
"Volume fraction for the material density.");
|
||||
args.AddOption(&lambda, "-lambda", "--lambda",
|
||||
"Lamé constant λ.");
|
||||
args.AddOption(&mu, "-mu", "--mu",
|
||||
"Lamé constant μ.");
|
||||
args.AddOption(&rho_min, "-rmin", "--psi-min",
|
||||
"Minimum of density coefficient.");
|
||||
args.AddOption(&glvis_visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
args.AddOption(¶view_output, "-pv", "--paraview", "-no-pv",
|
||||
"--no-paraview",
|
||||
"Enable or disable ParaView output.");
|
||||
args.Parse();
|
||||
if (!args.Good())
|
||||
{
|
||||
args.PrintUsage(mfem::out);
|
||||
return 1;
|
||||
}
|
||||
args.PrintOptions(mfem::out);
|
||||
|
||||
Mesh mesh = Mesh::MakeCartesian2D(3, 1, mfem::Element::Type::QUADRILATERAL,
|
||||
true, 3.0, 1.0);
|
||||
int dim = mesh.Dimension();
|
||||
|
||||
// 2. Set BCs.
|
||||
for (int i = 0; i<mesh.GetNBE(); i++)
|
||||
{
|
||||
Element * be = mesh.GetBdrElement(i);
|
||||
Array<int> vertices;
|
||||
be->GetVertices(vertices);
|
||||
|
||||
double * coords1 = mesh.GetVertex(vertices[0]);
|
||||
double * coords2 = mesh.GetVertex(vertices[1]);
|
||||
|
||||
Vector center(2);
|
||||
center(0) = 0.5*(coords1[0] + coords2[0]);
|
||||
center(1) = 0.5*(coords1[1] + coords2[1]);
|
||||
|
||||
if (abs(center(0) - 0.0) < 1e-10)
|
||||
{
|
||||
// the left edge
|
||||
be->SetAttribute(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// all other boundaries
|
||||
be->SetAttribute(2);
|
||||
}
|
||||
}
|
||||
mesh.SetAttributes();
|
||||
|
||||
// 3. Refine the mesh.
|
||||
for (int lev = 0; lev < ref_levels; lev++)
|
||||
{
|
||||
mesh.UniformRefinement();
|
||||
}
|
||||
|
||||
// 4. Define the necessary finite element spaces on the mesh.
|
||||
H1_FECollection state_fec(order, dim); // space for u
|
||||
H1_FECollection filter_fec(order, dim); // space for ρ̃
|
||||
L2_FECollection control_fec(order-1, dim,
|
||||
BasisType::GaussLobatto); // space for ψ
|
||||
FiniteElementSpace state_fes(&mesh, &state_fec,dim);
|
||||
FiniteElementSpace filter_fes(&mesh, &filter_fec);
|
||||
FiniteElementSpace control_fes(&mesh, &control_fec);
|
||||
|
||||
int state_size = state_fes.GetTrueVSize();
|
||||
int control_size = control_fes.GetTrueVSize();
|
||||
int filter_size = filter_fes.GetTrueVSize();
|
||||
mfem::out << "Number of state unknowns: " << state_size << std::endl;
|
||||
mfem::out << "Number of filter unknowns: " << filter_size << std::endl;
|
||||
mfem::out << "Number of control unknowns: " << control_size << std::endl;
|
||||
|
||||
// 5. Set the initial guess for ρ.
|
||||
GridFunction u(&state_fes);
|
||||
GridFunction psi(&control_fes);
|
||||
GridFunction psi_old(&control_fes);
|
||||
GridFunction rho_filter(&filter_fes);
|
||||
u = 0.0;
|
||||
rho_filter = vol_fraction;
|
||||
psi = inv_sigmoid(vol_fraction);
|
||||
psi_old = inv_sigmoid(vol_fraction);
|
||||
|
||||
// ρ = sigmoid(ψ)
|
||||
MappedGridFunctionCoefficient rho(&psi, sigmoid);
|
||||
// Interpolation of ρ = sigmoid(ψ) in control fes (for ParaView output)
|
||||
GridFunction rho_gf(&control_fes);
|
||||
// ρ - ρ_old = sigmoid(ψ) - sigmoid(ψ_old)
|
||||
DiffMappedGridFunctionCoefficient succ_diff_rho(&psi, &psi_old, sigmoid);
|
||||
|
||||
// 6. Set-up the physics solver.
|
||||
int maxat = mesh.bdr_attributes.Max();
|
||||
Array<int> ess_bdr(maxat);
|
||||
ess_bdr = 0;
|
||||
ess_bdr[0] = 1;
|
||||
ConstantCoefficient one(1.0);
|
||||
ConstantCoefficient lambda_cf(lambda);
|
||||
ConstantCoefficient mu_cf(mu);
|
||||
LinearElasticitySolver * ElasticitySolver = new LinearElasticitySolver();
|
||||
ElasticitySolver->SetMesh(&mesh);
|
||||
ElasticitySolver->SetOrder(state_fec.GetOrder());
|
||||
ElasticitySolver->SetupFEM();
|
||||
Vector center(2); center(0) = 2.9; center(1) = 0.5;
|
||||
Vector force(2); force(0) = 0.0; force(1) = -1.0;
|
||||
double r = 0.05;
|
||||
VolumeForceCoefficient vforce_cf(r,center,force);
|
||||
ElasticitySolver->SetRHSCoefficient(&vforce_cf);
|
||||
ElasticitySolver->SetEssentialBoundary(ess_bdr);
|
||||
|
||||
// 7. Set-up the filter solver.
|
||||
ConstantCoefficient eps2_cf(epsilon*epsilon);
|
||||
DiffusionSolver * FilterSolver = new DiffusionSolver();
|
||||
FilterSolver->SetMesh(&mesh);
|
||||
FilterSolver->SetOrder(filter_fec.GetOrder());
|
||||
FilterSolver->SetDiffusionCoefficient(&eps2_cf);
|
||||
FilterSolver->SetMassCoefficient(&one);
|
||||
Array<int> ess_bdr_filter;
|
||||
if (mesh.bdr_attributes.Size())
|
||||
{
|
||||
ess_bdr_filter.SetSize(mesh.bdr_attributes.Max());
|
||||
ess_bdr_filter = 0;
|
||||
}
|
||||
FilterSolver->SetEssentialBoundary(ess_bdr_filter);
|
||||
FilterSolver->SetupFEM();
|
||||
|
||||
BilinearForm mass(&control_fes);
|
||||
mass.AddDomainIntegrator(new InverseIntegrator(new MassIntegrator(one)));
|
||||
mass.Assemble();
|
||||
SparseMatrix M;
|
||||
Array<int> empty;
|
||||
mass.FormSystemMatrix(empty,M);
|
||||
|
||||
// 8. Define the Lagrange multiplier and gradient functions.
|
||||
GridFunction grad(&control_fes);
|
||||
GridFunction w_filter(&filter_fes);
|
||||
|
||||
// 9. Define some tools for later.
|
||||
ConstantCoefficient zero(0.0);
|
||||
GridFunction onegf(&control_fes);
|
||||
onegf = 1.0;
|
||||
GridFunction zerogf(&control_fes);
|
||||
zerogf = 0.0;
|
||||
LinearForm vol_form(&control_fes);
|
||||
vol_form.AddDomainIntegrator(new DomainLFIntegrator(one));
|
||||
vol_form.Assemble();
|
||||
double domain_volume = vol_form(onegf);
|
||||
const double target_volume = domain_volume * vol_fraction;
|
||||
|
||||
// 10. Connect to GLVis. Prepare for VisIt output.
|
||||
char vishost[] = "localhost";
|
||||
int visport = 19916;
|
||||
socketstream sout_r;
|
||||
if (glvis_visualization)
|
||||
{
|
||||
sout_r.open(vishost, visport);
|
||||
sout_r.precision(8);
|
||||
}
|
||||
|
||||
mfem::ParaViewDataCollection paraview_dc("ex37", &mesh);
|
||||
if (paraview_output)
|
||||
{
|
||||
rho_gf.ProjectCoefficient(rho);
|
||||
paraview_dc.SetPrefixPath("ParaView");
|
||||
paraview_dc.SetLevelsOfDetail(order);
|
||||
paraview_dc.SetDataFormat(VTKFormat::BINARY);
|
||||
paraview_dc.SetHighOrderOutput(true);
|
||||
paraview_dc.SetCycle(0);
|
||||
paraview_dc.SetTime(0.0);
|
||||
paraview_dc.RegisterField("displacement",&u);
|
||||
paraview_dc.RegisterField("density",&rho_gf);
|
||||
paraview_dc.RegisterField("filtered_density",&rho_filter);
|
||||
paraview_dc.Save();
|
||||
}
|
||||
|
||||
// 11. Iterate:
|
||||
for (int k = 1; k <= max_it; k++)
|
||||
{
|
||||
if (k > 1) { alpha *= ((double) k) / ((double) k-1); }
|
||||
|
||||
mfem::out << "\nStep = " << k << std::endl;
|
||||
|
||||
// Step 1 - Filter solve
|
||||
// Solve (ϵ^2 ∇ ρ̃, ∇ v ) + (ρ̃,v) = (ρ,v)
|
||||
FilterSolver->SetRHSCoefficient(&rho);
|
||||
FilterSolver->Solve();
|
||||
rho_filter = *FilterSolver->GetFEMSolution();
|
||||
|
||||
// Step 2 - State solve
|
||||
// Solve (λ r(ρ̃) ∇⋅u, ∇⋅v) + (2 μ r(ρ̃) ε(u), ε(v)) = (f,v)
|
||||
SIMPInterpolationCoefficient SIMP_cf(&rho_filter,rho_min, 1.0);
|
||||
ProductCoefficient lambda_SIMP_cf(lambda_cf,SIMP_cf);
|
||||
ProductCoefficient mu_SIMP_cf(mu_cf,SIMP_cf);
|
||||
ElasticitySolver->SetLameCoefficients(&lambda_SIMP_cf,&mu_SIMP_cf);
|
||||
ElasticitySolver->Solve();
|
||||
u = *ElasticitySolver->GetFEMSolution();
|
||||
|
||||
// Step 3 - Adjoint filter solve
|
||||
// Solve (ϵ² ∇ w̃, ∇ v) + (w̃ ,v) = (-r'(ρ̃) ( λ |∇⋅u|² + 2 μ |ε(u)|²),v)
|
||||
StrainEnergyDensityCoefficient rhs_cf(&lambda_cf,&mu_cf,&u, &rho_filter,
|
||||
rho_min);
|
||||
FilterSolver->SetRHSCoefficient(&rhs_cf);
|
||||
FilterSolver->Solve();
|
||||
w_filter = *FilterSolver->GetFEMSolution();
|
||||
|
||||
// Step 4 - Compute gradient
|
||||
// Solve G = M⁻¹w̃
|
||||
GridFunctionCoefficient w_cf(&w_filter);
|
||||
LinearForm w_rhs(&control_fes);
|
||||
w_rhs.AddDomainIntegrator(new DomainLFIntegrator(w_cf));
|
||||
w_rhs.Assemble();
|
||||
M.Mult(w_rhs,grad);
|
||||
|
||||
// Step 5 - Update design variable ψ ← proj(ψ - αG)
|
||||
psi.Add(-alpha, grad);
|
||||
const double material_volume = proj(psi, target_volume);
|
||||
|
||||
// Compute ||ρ - ρ_old|| in control fes.
|
||||
double norm_increment = zerogf.ComputeL1Error(succ_diff_rho);
|
||||
double norm_reduced_gradient = norm_increment/alpha;
|
||||
psi_old = psi;
|
||||
|
||||
double compliance = (*(ElasticitySolver->GetLinearForm()))(u);
|
||||
mfem::out << "norm of the reduced gradient = " << norm_reduced_gradient <<
|
||||
std::endl;
|
||||
mfem::out << "norm of the increment = " << norm_increment << endl;
|
||||
mfem::out << "compliance = " << compliance << std::endl;
|
||||
mfem::out << "volume fraction = " << material_volume / domain_volume <<
|
||||
std::endl;
|
||||
|
||||
if (glvis_visualization)
|
||||
{
|
||||
GridFunction r_gf(&filter_fes);
|
||||
r_gf.ProjectCoefficient(SIMP_cf);
|
||||
sout_r << "solution\n" << mesh << r_gf
|
||||
<< "window_title 'Design density r(ρ̃)'" << flush;
|
||||
}
|
||||
|
||||
if (paraview_output)
|
||||
{
|
||||
rho_gf.ProjectCoefficient(rho);
|
||||
paraview_dc.SetCycle(k);
|
||||
paraview_dc.SetTime((double)k);
|
||||
paraview_dc.Save();
|
||||
}
|
||||
|
||||
if (norm_reduced_gradient < ntol && norm_increment < itol)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete ElasticitySolver;
|
||||
delete FilterSolver;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,748 +0,0 @@
|
||||
// MFEM Example 37 - Serial/Parallel Shared Code
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
/// @brief Inverse sigmoid function
|
||||
double inv_sigmoid(double x)
|
||||
{
|
||||
double tol = 1e-12;
|
||||
x = std::min(std::max(tol,x),1.0-tol);
|
||||
return std::log(x/(1.0-x));
|
||||
}
|
||||
|
||||
/// @brief Sigmoid function
|
||||
double sigmoid(double x)
|
||||
{
|
||||
if (x >= 0)
|
||||
{
|
||||
return 1.0/(1.0+std::exp(-x));
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::exp(x)/(1.0+std::exp(x));
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Derivative of sigmoid function
|
||||
double der_sigmoid(double x)
|
||||
{
|
||||
double tmp = sigmoid(-x);
|
||||
return tmp - std::pow(tmp,2);
|
||||
}
|
||||
|
||||
/// @brief Returns f(u(x)) where u is a scalar GridFunction and f:R → R
|
||||
class MappedGridFunctionCoefficient : public GridFunctionCoefficient
|
||||
{
|
||||
protected:
|
||||
std::function<double(const double)> fun; // f:R → R
|
||||
public:
|
||||
MappedGridFunctionCoefficient()
|
||||
:GridFunctionCoefficient(),
|
||||
fun([](double x) {return x;}) {}
|
||||
MappedGridFunctionCoefficient(const GridFunction *gf,
|
||||
std::function<double(const double)> fun_,
|
||||
int comp=1)
|
||||
:GridFunctionCoefficient(gf, comp),
|
||||
fun(fun_) {}
|
||||
|
||||
|
||||
virtual double Eval(ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
return fun(GridFunctionCoefficient::Eval(T, ip));
|
||||
}
|
||||
void SetFunction(std::function<double(const double)> fun_) { fun = fun_; }
|
||||
};
|
||||
|
||||
|
||||
/// @brief Returns f(u(x)) - f(v(x)) where u, v are scalar GridFunctions and f:R → R
|
||||
class DiffMappedGridFunctionCoefficient : public GridFunctionCoefficient
|
||||
{
|
||||
protected:
|
||||
const GridFunction *OtherGridF;
|
||||
GridFunctionCoefficient OtherGridF_cf;
|
||||
std::function<double(const double)> fun; // f:R → R
|
||||
public:
|
||||
DiffMappedGridFunctionCoefficient()
|
||||
:GridFunctionCoefficient(),
|
||||
OtherGridF(nullptr),
|
||||
OtherGridF_cf(),
|
||||
fun([](double x) {return x;}) {}
|
||||
DiffMappedGridFunctionCoefficient(const GridFunction *gf,
|
||||
const GridFunction *other_gf,
|
||||
std::function<double(const double)> fun_,
|
||||
int comp=1)
|
||||
:GridFunctionCoefficient(gf, comp),
|
||||
OtherGridF(other_gf),
|
||||
OtherGridF_cf(OtherGridF),
|
||||
fun(fun_) {}
|
||||
|
||||
virtual double Eval(ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
const double value1 = fun(GridFunctionCoefficient::Eval(T, ip));
|
||||
const double value2 = fun(OtherGridF_cf.Eval(T, ip));
|
||||
return value1 - value2;
|
||||
}
|
||||
void SetFunction(std::function<double(const double)> fun_) { fun = fun_; }
|
||||
};
|
||||
|
||||
/// @brief Solid isotropic material penalization (SIMP) coefficient
|
||||
class SIMPInterpolationCoefficient : public Coefficient
|
||||
{
|
||||
protected:
|
||||
GridFunction *rho_filter;
|
||||
double min_val;
|
||||
double max_val;
|
||||
double exponent;
|
||||
|
||||
public:
|
||||
SIMPInterpolationCoefficient(GridFunction *rho_filter_, double min_val_= 1e-6,
|
||||
double max_val_ = 1.0, double exponent_ = 3)
|
||||
: rho_filter(rho_filter_), min_val(min_val_), max_val(max_val_),
|
||||
exponent(exponent_) { }
|
||||
|
||||
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip)
|
||||
{
|
||||
double val = rho_filter->GetValue(T, ip);
|
||||
double coeff = min_val + pow(val,exponent)*(max_val-min_val);
|
||||
return coeff;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// @brief Strain energy density coefficient
|
||||
class StrainEnergyDensityCoefficient : public Coefficient
|
||||
{
|
||||
protected:
|
||||
Coefficient * lambda=nullptr;
|
||||
Coefficient * mu=nullptr;
|
||||
GridFunction *u = nullptr; // displacement
|
||||
GridFunction *rho_filter = nullptr; // filter density
|
||||
DenseMatrix grad; // auxiliary matrix, used in Eval
|
||||
double exponent;
|
||||
double rho_min;
|
||||
|
||||
public:
|
||||
StrainEnergyDensityCoefficient(Coefficient *lambda_, Coefficient *mu_,
|
||||
GridFunction * u_, GridFunction * rho_filter_, double rho_min_=1e-6,
|
||||
double exponent_ = 3.0)
|
||||
: lambda(lambda_), mu(mu_), u(u_), rho_filter(rho_filter_),
|
||||
exponent(exponent_), rho_min(rho_min_)
|
||||
{
|
||||
MFEM_ASSERT(rho_min_ >= 0.0, "rho_min must be >= 0");
|
||||
MFEM_ASSERT(rho_min_ < 1.0, "rho_min must be > 1");
|
||||
MFEM_ASSERT(u, "displacement field is not set");
|
||||
MFEM_ASSERT(rho_filter, "density field is not set");
|
||||
}
|
||||
|
||||
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip)
|
||||
{
|
||||
double L = lambda->Eval(T, ip);
|
||||
double M = mu->Eval(T, ip);
|
||||
u->GetVectorGradient(T, grad);
|
||||
double div_u = grad.Trace();
|
||||
double density = L*div_u*div_u;
|
||||
int dim = T.GetSpaceDim();
|
||||
for (int i=0; i<dim; i++)
|
||||
{
|
||||
for (int j=0; j<dim; j++)
|
||||
{
|
||||
density += M*grad(i,j)*(grad(i,j)+grad(j,i));
|
||||
}
|
||||
}
|
||||
double val = rho_filter->GetValue(T,ip);
|
||||
|
||||
return -exponent * pow(val, exponent-1.0) * (1-rho_min) * density;
|
||||
}
|
||||
};
|
||||
|
||||
/// @brief Volumetric force for linear elasticity
|
||||
class VolumeForceCoefficient : public VectorCoefficient
|
||||
{
|
||||
private:
|
||||
double r;
|
||||
Vector center;
|
||||
Vector force;
|
||||
public:
|
||||
VolumeForceCoefficient(double r_,Vector & center_, Vector & force_) :
|
||||
VectorCoefficient(center_.Size()), r(r_), center(center_), force(force_) { }
|
||||
|
||||
using VectorCoefficient::Eval;
|
||||
|
||||
virtual void Eval(Vector &V, ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
Vector xx; xx.SetSize(T.GetDimension());
|
||||
T.Transform(ip,xx);
|
||||
for (int i=0; i<xx.Size(); i++)
|
||||
{
|
||||
xx[i]=xx[i]-center[i];
|
||||
}
|
||||
|
||||
double cr=xx.Norml2();
|
||||
V.SetSize(T.GetDimension());
|
||||
if (cr <= r)
|
||||
{
|
||||
V = force;
|
||||
}
|
||||
else
|
||||
{
|
||||
V = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
void Set(double r_,Vector & center_, Vector & force_)
|
||||
{
|
||||
r=r_;
|
||||
center = center_;
|
||||
force = force_;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Class for solving Poisson's equation:
|
||||
*
|
||||
* - ∇ ⋅(κ ∇ u) = f in Ω
|
||||
*
|
||||
*/
|
||||
class DiffusionSolver
|
||||
{
|
||||
private:
|
||||
Mesh * mesh = nullptr;
|
||||
int order = 1;
|
||||
// diffusion coefficient
|
||||
Coefficient * diffcf = nullptr;
|
||||
// mass coefficient
|
||||
Coefficient * masscf = nullptr;
|
||||
Coefficient * rhscf = nullptr;
|
||||
Coefficient * essbdr_cf = nullptr;
|
||||
Coefficient * neumann_cf = nullptr;
|
||||
VectorCoefficient * gradient_cf = nullptr;
|
||||
|
||||
// FEM solver
|
||||
int dim;
|
||||
FiniteElementCollection * fec = nullptr;
|
||||
FiniteElementSpace * fes = nullptr;
|
||||
Array<int> ess_bdr;
|
||||
Array<int> neumann_bdr;
|
||||
GridFunction * u = nullptr;
|
||||
LinearForm * b = nullptr;
|
||||
bool parallel;
|
||||
#ifdef MFEM_USE_MPI
|
||||
ParMesh * pmesh = nullptr;
|
||||
ParFiniteElementSpace * pfes = nullptr;
|
||||
#endif
|
||||
|
||||
public:
|
||||
DiffusionSolver() { }
|
||||
DiffusionSolver(Mesh * mesh_, int order_, Coefficient * diffcf_,
|
||||
Coefficient * cf_);
|
||||
|
||||
void SetMesh(Mesh * mesh_)
|
||||
{
|
||||
mesh = mesh_;
|
||||
parallel = false;
|
||||
#ifdef MFEM_USE_MPI
|
||||
pmesh = dynamic_cast<ParMesh *>(mesh);
|
||||
if (pmesh) { parallel = true; }
|
||||
#endif
|
||||
}
|
||||
void SetOrder(int order_) { order = order_ ; }
|
||||
void SetDiffusionCoefficient(Coefficient * diffcf_) { diffcf = diffcf_; }
|
||||
void SetMassCoefficient(Coefficient * masscf_) { masscf = masscf_; }
|
||||
void SetRHSCoefficient(Coefficient * rhscf_) { rhscf = rhscf_; }
|
||||
void SetEssentialBoundary(const Array<int> & ess_bdr_) { ess_bdr = ess_bdr_;};
|
||||
void SetNeumannBoundary(const Array<int> & neumann_bdr_) { neumann_bdr = neumann_bdr_;};
|
||||
void SetNeumannData(Coefficient * neumann_cf_) {neumann_cf = neumann_cf_;}
|
||||
void SetEssBdrData(Coefficient * essbdr_cf_) {essbdr_cf = essbdr_cf_;}
|
||||
void SetGradientData(VectorCoefficient * gradient_cf_) {gradient_cf = gradient_cf_;}
|
||||
|
||||
void ResetFEM();
|
||||
void SetupFEM();
|
||||
|
||||
void Solve();
|
||||
GridFunction * GetFEMSolution();
|
||||
LinearForm * GetLinearForm() {return b;}
|
||||
#ifdef MFEM_USE_MPI
|
||||
ParGridFunction * GetParFEMSolution();
|
||||
ParLinearForm * GetParLinearForm()
|
||||
{
|
||||
if (parallel)
|
||||
{
|
||||
return dynamic_cast<ParLinearForm *>(b);
|
||||
}
|
||||
else
|
||||
{
|
||||
MFEM_ABORT("Wrong code path. Call GetLinearForm");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
~DiffusionSolver();
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Class for solving linear elasticity:
|
||||
*
|
||||
* -∇ ⋅ σ(u) = f in Ω + BCs
|
||||
*
|
||||
* where
|
||||
*
|
||||
* σ(u) = λ ∇⋅u I + μ (∇ u + ∇uᵀ)
|
||||
*
|
||||
*/
|
||||
class LinearElasticitySolver
|
||||
{
|
||||
private:
|
||||
Mesh * mesh = nullptr;
|
||||
int order = 1;
|
||||
Coefficient * lambda_cf = nullptr;
|
||||
Coefficient * mu_cf = nullptr;
|
||||
VectorCoefficient * essbdr_cf = nullptr;
|
||||
VectorCoefficient * rhs_cf = nullptr;
|
||||
|
||||
// FEM solver
|
||||
int dim;
|
||||
FiniteElementCollection * fec = nullptr;
|
||||
FiniteElementSpace * fes = nullptr;
|
||||
Array<int> ess_bdr;
|
||||
Array<int> neumann_bdr;
|
||||
GridFunction * u = nullptr;
|
||||
LinearForm * b = nullptr;
|
||||
bool parallel;
|
||||
#ifdef MFEM_USE_MPI
|
||||
ParMesh * pmesh = nullptr;
|
||||
ParFiniteElementSpace * pfes = nullptr;
|
||||
#endif
|
||||
|
||||
public:
|
||||
LinearElasticitySolver() { }
|
||||
LinearElasticitySolver(Mesh * mesh_, int order_,
|
||||
Coefficient * lambda_cf_, Coefficient * mu_cf_);
|
||||
|
||||
void SetMesh(Mesh * mesh_)
|
||||
{
|
||||
mesh = mesh_;
|
||||
parallel = false;
|
||||
#ifdef MFEM_USE_MPI
|
||||
pmesh = dynamic_cast<ParMesh *>(mesh);
|
||||
if (pmesh) { parallel = true; }
|
||||
#endif
|
||||
}
|
||||
void SetOrder(int order_) { order = order_ ; }
|
||||
void SetLameCoefficients(Coefficient * lambda_cf_, Coefficient * mu_cf_) { lambda_cf = lambda_cf_; mu_cf = mu_cf_; }
|
||||
void SetRHSCoefficient(VectorCoefficient * rhs_cf_) { rhs_cf = rhs_cf_; }
|
||||
void SetEssentialBoundary(const Array<int> & ess_bdr_) { ess_bdr = ess_bdr_;};
|
||||
void SetNeumannBoundary(const Array<int> & neumann_bdr_) { neumann_bdr = neumann_bdr_;};
|
||||
void SetEssBdrData(VectorCoefficient * essbdr_cf_) {essbdr_cf = essbdr_cf_;}
|
||||
|
||||
void ResetFEM();
|
||||
void SetupFEM();
|
||||
|
||||
void Solve();
|
||||
GridFunction * GetFEMSolution();
|
||||
LinearForm * GetLinearForm() {return b;}
|
||||
#ifdef MFEM_USE_MPI
|
||||
ParGridFunction * GetParFEMSolution();
|
||||
ParLinearForm * GetParLinearForm()
|
||||
{
|
||||
if (parallel)
|
||||
{
|
||||
return dynamic_cast<ParLinearForm *>(b);
|
||||
}
|
||||
else
|
||||
{
|
||||
MFEM_ABORT("Wrong code path. Call GetLinearForm");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
~LinearElasticitySolver();
|
||||
|
||||
};
|
||||
|
||||
|
||||
// Poisson solver
|
||||
|
||||
DiffusionSolver::DiffusionSolver(Mesh * mesh_, int order_,
|
||||
Coefficient * diffcf_, Coefficient * rhscf_)
|
||||
: mesh(mesh_), order(order_), diffcf(diffcf_), rhscf(rhscf_)
|
||||
{
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
pmesh = dynamic_cast<ParMesh *>(mesh);
|
||||
if (pmesh) { parallel = true; }
|
||||
#endif
|
||||
|
||||
SetupFEM();
|
||||
}
|
||||
|
||||
void DiffusionSolver::SetupFEM()
|
||||
{
|
||||
dim = mesh->Dimension();
|
||||
fec = new H1_FECollection(order, dim);
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
if (parallel)
|
||||
{
|
||||
pfes = new ParFiniteElementSpace(pmesh, fec);
|
||||
u = new ParGridFunction(pfes);
|
||||
b = new ParLinearForm(pfes);
|
||||
}
|
||||
else
|
||||
{
|
||||
fes = new FiniteElementSpace(mesh, fec);
|
||||
u = new GridFunction(fes);
|
||||
b = new LinearForm(fes);
|
||||
}
|
||||
#else
|
||||
fes = new FiniteElementSpace(mesh, fec);
|
||||
u = new GridFunction(fes);
|
||||
b = new LinearForm(fes);
|
||||
#endif
|
||||
*u=0.0;
|
||||
|
||||
if (!ess_bdr.Size())
|
||||
{
|
||||
if (mesh->bdr_attributes.Size())
|
||||
{
|
||||
ess_bdr.SetSize(mesh->bdr_attributes.Max());
|
||||
ess_bdr = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DiffusionSolver::Solve()
|
||||
{
|
||||
OperatorPtr A;
|
||||
Vector B, X;
|
||||
Array<int> ess_tdof_list;
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
if (parallel)
|
||||
{
|
||||
pfes->GetEssentialTrueDofs(ess_bdr,ess_tdof_list);
|
||||
}
|
||||
else
|
||||
{
|
||||
fes->GetEssentialTrueDofs(ess_bdr,ess_tdof_list);
|
||||
}
|
||||
#else
|
||||
fes->GetEssentialTrueDofs(ess_bdr,ess_tdof_list);
|
||||
#endif
|
||||
*u=0.0;
|
||||
if (b)
|
||||
{
|
||||
delete b;
|
||||
#ifdef MFEM_USE_MPI
|
||||
if (parallel)
|
||||
{
|
||||
b = new ParLinearForm(pfes);
|
||||
}
|
||||
else
|
||||
{
|
||||
b = new LinearForm(fes);
|
||||
}
|
||||
#else
|
||||
b = new LinearForm(fes);
|
||||
#endif
|
||||
}
|
||||
if (rhscf)
|
||||
{
|
||||
b->AddDomainIntegrator(new DomainLFIntegrator(*rhscf));
|
||||
}
|
||||
if (neumann_cf)
|
||||
{
|
||||
MFEM_VERIFY(neumann_bdr.Size(), "neumann_bdr attributes not provided");
|
||||
b->AddBoundaryIntegrator(new BoundaryLFIntegrator(*neumann_cf),neumann_bdr);
|
||||
}
|
||||
else if (gradient_cf)
|
||||
{
|
||||
MFEM_VERIFY(neumann_bdr.Size(), "neumann_bdr attributes not provided");
|
||||
b->AddBoundaryIntegrator(new BoundaryNormalLFIntegrator(*gradient_cf),
|
||||
neumann_bdr);
|
||||
}
|
||||
|
||||
b->Assemble();
|
||||
|
||||
BilinearForm * a = nullptr;
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
if (parallel)
|
||||
{
|
||||
a = new ParBilinearForm(pfes);
|
||||
}
|
||||
else
|
||||
{
|
||||
a = new BilinearForm(fes);
|
||||
}
|
||||
#else
|
||||
a = new BilinearForm(fes);
|
||||
#endif
|
||||
a->AddDomainIntegrator(new DiffusionIntegrator(*diffcf));
|
||||
if (masscf)
|
||||
{
|
||||
a->AddDomainIntegrator(new MassIntegrator(*masscf));
|
||||
}
|
||||
a->Assemble();
|
||||
if (essbdr_cf)
|
||||
{
|
||||
u->ProjectBdrCoefficient(*essbdr_cf,ess_bdr);
|
||||
}
|
||||
a->FormLinearSystem(ess_tdof_list, *u, *b, A, X, B);
|
||||
|
||||
CGSolver * cg = nullptr;
|
||||
Solver * M = nullptr;
|
||||
#ifdef MFEM_USE_MPI
|
||||
if (parallel)
|
||||
{
|
||||
M = new HypreBoomerAMG;
|
||||
dynamic_cast<HypreBoomerAMG*>(M)->SetPrintLevel(0);
|
||||
cg = new CGSolver(pmesh->GetComm());
|
||||
}
|
||||
else
|
||||
{
|
||||
M = new GSSmoother((SparseMatrix&)(*A));
|
||||
cg = new CGSolver;
|
||||
}
|
||||
#else
|
||||
M = new GSSmoother((SparseMatrix&)(*A));
|
||||
cg = new CGSolver;
|
||||
#endif
|
||||
cg->SetRelTol(1e-12);
|
||||
cg->SetMaxIter(10000);
|
||||
cg->SetPrintLevel(0);
|
||||
cg->SetPreconditioner(*M);
|
||||
cg->SetOperator(*A);
|
||||
cg->Mult(B, X);
|
||||
delete M;
|
||||
delete cg;
|
||||
a->RecoverFEMSolution(X, *b, *u);
|
||||
delete a;
|
||||
}
|
||||
|
||||
GridFunction * DiffusionSolver::GetFEMSolution()
|
||||
{
|
||||
return u;
|
||||
}
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
ParGridFunction * DiffusionSolver::GetParFEMSolution()
|
||||
{
|
||||
if (parallel)
|
||||
{
|
||||
return dynamic_cast<ParGridFunction*>(u);
|
||||
}
|
||||
else
|
||||
{
|
||||
MFEM_ABORT("Wrong code path. Call GetFEMSolution");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
DiffusionSolver::~DiffusionSolver()
|
||||
{
|
||||
delete u; u = nullptr;
|
||||
delete fes; fes = nullptr;
|
||||
#ifdef MFEM_USE_MPI
|
||||
delete pfes; pfes=nullptr;
|
||||
#endif
|
||||
delete fec; fec = nullptr;
|
||||
delete b;
|
||||
}
|
||||
|
||||
|
||||
// Elasticity solver
|
||||
|
||||
LinearElasticitySolver::LinearElasticitySolver(Mesh * mesh_, int order_,
|
||||
Coefficient * lambda_cf_, Coefficient * mu_cf_)
|
||||
: mesh(mesh_), order(order_), lambda_cf(lambda_cf_), mu_cf(mu_cf_)
|
||||
{
|
||||
#ifdef MFEM_USE_MPI
|
||||
pmesh = dynamic_cast<ParMesh *>(mesh);
|
||||
if (pmesh) { parallel = true; }
|
||||
#endif
|
||||
SetupFEM();
|
||||
}
|
||||
|
||||
void LinearElasticitySolver::SetupFEM()
|
||||
{
|
||||
dim = mesh->Dimension();
|
||||
fec = new H1_FECollection(order, dim,BasisType::Positive);
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
if (parallel)
|
||||
{
|
||||
pfes = new ParFiniteElementSpace(pmesh, fec, dim);
|
||||
u = new ParGridFunction(pfes);
|
||||
b = new ParLinearForm(pfes);
|
||||
}
|
||||
else
|
||||
{
|
||||
fes = new FiniteElementSpace(mesh, fec,dim);
|
||||
u = new GridFunction(fes);
|
||||
b = new LinearForm(fes);
|
||||
}
|
||||
#else
|
||||
fes = new FiniteElementSpace(mesh, fec, dim);
|
||||
u = new GridFunction(fes);
|
||||
b = new LinearForm(fes);
|
||||
#endif
|
||||
*u=0.0;
|
||||
|
||||
if (!ess_bdr.Size())
|
||||
{
|
||||
if (mesh->bdr_attributes.Size())
|
||||
{
|
||||
ess_bdr.SetSize(mesh->bdr_attributes.Max());
|
||||
ess_bdr = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LinearElasticitySolver::Solve()
|
||||
{
|
||||
GridFunction * x = nullptr;
|
||||
OperatorPtr A;
|
||||
Vector B, X;
|
||||
Array<int> ess_tdof_list;
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
if (parallel)
|
||||
{
|
||||
x = new ParGridFunction(pfes);
|
||||
pfes->GetEssentialTrueDofs(ess_bdr,ess_tdof_list);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = new GridFunction(fes);
|
||||
fes->GetEssentialTrueDofs(ess_bdr,ess_tdof_list);
|
||||
}
|
||||
#else
|
||||
x = new GridFunction(fes);
|
||||
fes->GetEssentialTrueDofs(ess_bdr,ess_tdof_list);
|
||||
#endif
|
||||
*u=0.0;
|
||||
if (b)
|
||||
{
|
||||
delete b;
|
||||
#ifdef MFEM_USE_MPI
|
||||
if (parallel)
|
||||
{
|
||||
b = new ParLinearForm(pfes);
|
||||
}
|
||||
else
|
||||
{
|
||||
b = new LinearForm(fes);
|
||||
}
|
||||
#else
|
||||
b = new LinearForm(fes);
|
||||
#endif
|
||||
}
|
||||
if (rhs_cf)
|
||||
{
|
||||
b->AddDomainIntegrator(new VectorDomainLFIntegrator(*rhs_cf));
|
||||
}
|
||||
|
||||
b->Assemble();
|
||||
|
||||
*x = 0.0;
|
||||
|
||||
BilinearForm * a = nullptr;
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
if (parallel)
|
||||
{
|
||||
a = new ParBilinearForm(pfes);
|
||||
}
|
||||
else
|
||||
{
|
||||
a = new BilinearForm(fes);
|
||||
}
|
||||
#else
|
||||
a = new BilinearForm(fes);
|
||||
#endif
|
||||
a->AddDomainIntegrator(new ElasticityIntegrator(*lambda_cf, *mu_cf));
|
||||
a->Assemble();
|
||||
if (essbdr_cf)
|
||||
{
|
||||
u->ProjectBdrCoefficient(*essbdr_cf,ess_bdr);
|
||||
}
|
||||
a->FormLinearSystem(ess_tdof_list, *x, *b, A, X, B);
|
||||
|
||||
CGSolver * cg = nullptr;
|
||||
Solver * M = nullptr;
|
||||
#ifdef MFEM_USE_MPI
|
||||
if (parallel)
|
||||
{
|
||||
M = new HypreBoomerAMG;
|
||||
dynamic_cast<HypreBoomerAMG*>(M)->SetPrintLevel(0);
|
||||
cg = new CGSolver(pmesh->GetComm());
|
||||
}
|
||||
else
|
||||
{
|
||||
M = new GSSmoother((SparseMatrix&)(*A));
|
||||
cg = new CGSolver;
|
||||
}
|
||||
#else
|
||||
M = new GSSmoother((SparseMatrix&)(*A));
|
||||
cg = new CGSolver;
|
||||
#endif
|
||||
cg->SetRelTol(1e-10);
|
||||
cg->SetMaxIter(10000);
|
||||
cg->SetPrintLevel(0);
|
||||
cg->SetPreconditioner(*M);
|
||||
cg->SetOperator(*A);
|
||||
cg->Mult(B, X);
|
||||
delete M;
|
||||
delete cg;
|
||||
a->RecoverFEMSolution(X, *b, *x);
|
||||
*u+=*x;
|
||||
delete a;
|
||||
delete x;
|
||||
}
|
||||
|
||||
GridFunction * LinearElasticitySolver::GetFEMSolution()
|
||||
{
|
||||
return u;
|
||||
}
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
ParGridFunction * LinearElasticitySolver::GetParFEMSolution()
|
||||
{
|
||||
if (parallel)
|
||||
{
|
||||
return dynamic_cast<ParGridFunction*>(u);
|
||||
}
|
||||
else
|
||||
{
|
||||
MFEM_ABORT("Wrong code path. Call GetFEMSolution");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
LinearElasticitySolver::~LinearElasticitySolver()
|
||||
{
|
||||
delete u; u = nullptr;
|
||||
delete fes; fes = nullptr;
|
||||
#ifdef MFEM_USE_MPI
|
||||
delete pfes; pfes=nullptr;
|
||||
#endif
|
||||
delete fec; fec = nullptr;
|
||||
delete b;
|
||||
}
|
||||
|
||||
} // namespace mfem
|
||||
|
||||
@@ -1,497 +0,0 @@
|
||||
// MFEM Example 37 - Parallel Version
|
||||
//
|
||||
// Compile with: make ex37p
|
||||
//
|
||||
// Sample runs:
|
||||
// mpirun -np 4 ex37p -alpha 10 -pv
|
||||
// mpirun -np 4 ex37p -lambda 0.1 -mu 0.1
|
||||
// mpirun -np 4 ex37p -o 2 -alpha 5.0 -mi 50 -vf 0.4 -ntol 1e-5
|
||||
// mpirun -np 4 ex37p -r 6 -o 2 -alpha 10.0 -epsilon 0.02 -mi 50 -ntol 1e-5
|
||||
//
|
||||
// Description: This example code demonstrates the use of MFEM to solve a
|
||||
// density-filtered [3] topology optimization problem. The
|
||||
// objective is to minimize the compliance
|
||||
//
|
||||
// minimize ∫_Ω f⋅u dx over u ∈ [H¹(Ω)]² and ρ ∈ L¹(Ω)
|
||||
//
|
||||
// subject to
|
||||
//
|
||||
// -Div(r(ρ̃)Cε(u)) = f in Ω + BCs
|
||||
// -ϵ²Δρ̃ + ρ̃ = ρ in Ω + Neumann BCs
|
||||
// 0 ≤ ρ ≤ 1 in Ω
|
||||
// ∫_Ω ρ dx = θ vol(Ω)
|
||||
//
|
||||
// Here, r(ρ̃) = ρ₀ + ρ̃³ (1-ρ₀) is the solid isotropic material
|
||||
// penalization (SIMP) law, C is the elasticity tensor for an
|
||||
// isotropic linearly elastic material, ϵ > 0 is the design
|
||||
// length scale, and 0 < θ < 1 is the volume fraction.
|
||||
//
|
||||
// The problem is discretized and gradients are computing using
|
||||
// finite elements [1]. The design is optimized using an entropic
|
||||
// mirror descent algorithm introduced by Keith and Surowiec [2]
|
||||
// that is tailored to the bound constraint 0 ≤ ρ ≤ 1.
|
||||
//
|
||||
// This example highlights the ability of MFEM to deliver high-
|
||||
// order solutions to inverse design problems and showcases how
|
||||
// to set up and solve PDE-constrained optimization problems
|
||||
// using the so-called reduced space approach.
|
||||
//
|
||||
// [1] Andreassen, E., Clausen, A., Schevenels, M., Lazarov, B. S., & Sigmund, O.
|
||||
// (2011). Efficient topology optimization in MATLAB using 88 lines of
|
||||
// code. Structural and Multidisciplinary Optimization, 43(1), 1-16.
|
||||
// [2] Keith, B. and Surowiec, T. (2023) Proximal Galerkin: A structure-
|
||||
// preserving finite element method for pointwise bound constraints.
|
||||
// arXiv:2307.12444 [math.NA]
|
||||
// [3] Lazarov, B. S., & Sigmund, O. (2011). Filters in topology optimization
|
||||
// based on Helmholtz‐type differential equations. International Journal
|
||||
// for Numerical Methods in Engineering, 86(6), 765-781.
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "ex37.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace mfem;
|
||||
|
||||
/**
|
||||
* @brief Bregman projection of ρ = sigmoid(ψ) onto the subspace
|
||||
* ∫_Ω ρ dx = θ vol(Ω) as follows:
|
||||
*
|
||||
* 1. Compute the root of the R → R function
|
||||
* f(c) = ∫_Ω sigmoid(ψ + c) dx - θ vol(Ω)
|
||||
* 2. Set ψ ← ψ + c.
|
||||
*
|
||||
* @param psi a GridFunction to be updated
|
||||
* @param target_volume θ vol(Ω)
|
||||
* @param tol Newton iteration tolerance
|
||||
* @param max_its Newton maximum iteration number
|
||||
* @return double Final volume, ∫_Ω sigmoid(ψ)
|
||||
*/
|
||||
double proj(ParGridFunction &psi, double target_volume, double tol=1e-12,
|
||||
int max_its=10)
|
||||
{
|
||||
MappedGridFunctionCoefficient sigmoid_psi(&psi, sigmoid);
|
||||
MappedGridFunctionCoefficient der_sigmoid_psi(&psi, der_sigmoid);
|
||||
|
||||
ParLinearForm int_sigmoid_psi(psi.ParFESpace());
|
||||
int_sigmoid_psi.AddDomainIntegrator(new DomainLFIntegrator(sigmoid_psi));
|
||||
ParLinearForm int_der_sigmoid_psi(psi.ParFESpace());
|
||||
int_der_sigmoid_psi.AddDomainIntegrator(new DomainLFIntegrator(
|
||||
der_sigmoid_psi));
|
||||
bool done = false;
|
||||
for (int k=0; k<max_its; k++) // Newton iteration
|
||||
{
|
||||
int_sigmoid_psi.Assemble(); // Recompute f(c) with updated ψ
|
||||
double f = int_sigmoid_psi.Sum();
|
||||
MPI_Allreduce(MPI_IN_PLACE, &f, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
|
||||
f -= target_volume;
|
||||
|
||||
int_der_sigmoid_psi.Assemble(); // Recompute df(c) with updated ψ
|
||||
double df = int_der_sigmoid_psi.Sum();
|
||||
MPI_Allreduce(MPI_IN_PLACE, &df, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
|
||||
|
||||
const double dc = -f/df;
|
||||
psi += dc;
|
||||
if (abs(dc) < tol) { done = true; break; }
|
||||
}
|
||||
if (!done)
|
||||
{
|
||||
mfem_warning("Projection reached maximum iteration without converging. "
|
||||
"Result may not be accurate.");
|
||||
}
|
||||
int_sigmoid_psi.Assemble();
|
||||
double material_volume = int_sigmoid_psi.Sum();
|
||||
MPI_Allreduce(MPI_IN_PLACE, &material_volume, 1, MPI_DOUBLE, MPI_SUM,
|
||||
MPI_COMM_WORLD);
|
||||
return material_volume;
|
||||
}
|
||||
|
||||
/**
|
||||
* ---------------------------------------------------------------
|
||||
* ALGORITHM PREAMBLE
|
||||
* ---------------------------------------------------------------
|
||||
*
|
||||
* The Lagrangian for this problem is
|
||||
*
|
||||
* L(u,ρ,ρ̃,w,w̃) = (f,u) - (r(ρ̃) C ε(u),ε(w)) + (f,w)
|
||||
* - (ϵ² ∇ρ̃,∇w̃) - (ρ̃,w̃) + (ρ,w̃)
|
||||
*
|
||||
* where
|
||||
*
|
||||
* r(ρ̃) = ρ₀ + ρ̃³ (1 - ρ₀) (SIMP rule)
|
||||
*
|
||||
* ε(u) = (∇u + ∇uᵀ)/2 (symmetric gradient)
|
||||
*
|
||||
* C e = λtr(e)I + 2μe (isotropic material)
|
||||
*
|
||||
* NOTE: The Lame parameters can be computed from Young's modulus E
|
||||
* and Poisson's ratio ν as follows:
|
||||
*
|
||||
* λ = E ν/((1+ν)(1-2ν)), μ = E/(2(1+ν))
|
||||
*
|
||||
* ---------------------------------------------------------------
|
||||
*
|
||||
* Discretization choices:
|
||||
*
|
||||
* u ∈ V ⊂ (H¹)ᵈ (order p)
|
||||
* ψ ∈ L² (order p - 1), ρ = sigmoid(ψ)
|
||||
* ρ̃ ∈ H¹ (order p)
|
||||
* w ∈ V (order p)
|
||||
* w̃ ∈ H¹ (order p)
|
||||
*
|
||||
* ---------------------------------------------------------------
|
||||
* ALGORITHM
|
||||
* ---------------------------------------------------------------
|
||||
*
|
||||
* Update ρ with projected mirror descent via the following algorithm.
|
||||
*
|
||||
* 1. Initialize ψ = inv_sigmoid(vol_fraction) so that ∫ sigmoid(ψ) = θ vol(Ω)
|
||||
*
|
||||
* While not converged:
|
||||
*
|
||||
* 2. Solve filter equation ∂_w̃ L = 0; i.e.,
|
||||
*
|
||||
* (ϵ² ∇ ρ̃, ∇ v ) + (ρ̃,v) = (ρ,v) ∀ v ∈ H¹.
|
||||
*
|
||||
* 3. Solve primal problem ∂_w L = 0; i.e.,
|
||||
*
|
||||
* (λ r(ρ̃) ∇⋅u, ∇⋅v) + (2 μ r(ρ̃) ε(u), ε(v)) = (f,v) ∀ v ∈ V.
|
||||
*
|
||||
* NB. The dual problem ∂_u L = 0 is the negative of the primal problem due to symmetry.
|
||||
*
|
||||
* 4. Solve for filtered gradient ∂_ρ̃ L = 0; i.e.,
|
||||
*
|
||||
* (ϵ² ∇ w̃ , ∇ v ) + (w̃ ,v) = (-r'(ρ̃) ( λ |∇⋅u|² + 2 μ |ε(u)|²),v) ∀ v ∈ H¹.
|
||||
*
|
||||
* 5. Project the gradient onto the discrete latent space; i.e., solve
|
||||
*
|
||||
* (G,v) = (w̃,v) ∀ v ∈ L².
|
||||
*
|
||||
* 6. Bregman proximal gradient update; i.e.,
|
||||
*
|
||||
* ψ ← ψ - αG + c,
|
||||
*
|
||||
* where α > 0 is a step size parameter and c ∈ R is a constant ensuring
|
||||
*
|
||||
* ∫_Ω sigmoid(ψ - αG + c) dx = θ vol(Ω).
|
||||
*
|
||||
* end
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// 0. Initialize MPI and HYPRE.
|
||||
Mpi::Init();
|
||||
int num_procs = Mpi::WorldSize();
|
||||
int myid = Mpi::WorldRank();
|
||||
Hypre::Init();
|
||||
|
||||
// 1. Parse command-line options.
|
||||
int ref_levels = 5;
|
||||
int order = 2;
|
||||
double alpha = 1.0;
|
||||
double epsilon = 0.01;
|
||||
double vol_fraction = 0.5;
|
||||
int max_it = 1e3;
|
||||
double itol = 1e-1;
|
||||
double ntol = 1e-4;
|
||||
double rho_min = 1e-6;
|
||||
double lambda = 1.0;
|
||||
double mu = 1.0;
|
||||
bool glvis_visualization = true;
|
||||
bool paraview_output = false;
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
args.AddOption(&ref_levels, "-r", "--refine",
|
||||
"Number of times to refine the mesh uniformly.");
|
||||
args.AddOption(&order, "-o", "--order",
|
||||
"Order (degree) of the finite elements.");
|
||||
args.AddOption(&alpha, "-alpha", "--alpha-step-length",
|
||||
"Step length for gradient descent.");
|
||||
args.AddOption(&epsilon, "-epsilon", "--epsilon-thickness",
|
||||
"Length scale for ρ.");
|
||||
args.AddOption(&max_it, "-mi", "--max-it",
|
||||
"Maximum number of gradient descent iterations.");
|
||||
args.AddOption(&ntol, "-ntol", "--rel-tol",
|
||||
"Normalized exit tolerance.");
|
||||
args.AddOption(&itol, "-itol", "--abs-tol",
|
||||
"Increment exit tolerance.");
|
||||
args.AddOption(&vol_fraction, "-vf", "--volume-fraction",
|
||||
"Volume fraction for the material density.");
|
||||
args.AddOption(&lambda, "-lambda", "--lambda",
|
||||
"Lamé constant λ.");
|
||||
args.AddOption(&mu, "-mu", "--mu",
|
||||
"Lamé constant μ.");
|
||||
args.AddOption(&rho_min, "-rmin", "--psi-min",
|
||||
"Minimum of density coefficient.");
|
||||
args.AddOption(&glvis_visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
args.AddOption(¶view_output, "-pv", "--paraview", "-no-pv",
|
||||
"--no-paraview",
|
||||
"Enable or disable ParaView output.");
|
||||
args.Parse();
|
||||
if (!args.Good())
|
||||
{
|
||||
if (myid == 0)
|
||||
{
|
||||
args.PrintUsage(cout);
|
||||
}
|
||||
MPI_Finalize();
|
||||
return 1;
|
||||
}
|
||||
if (myid == 0)
|
||||
{
|
||||
mfem::out << num_procs << " number of process created.\n";
|
||||
args.PrintOptions(cout);
|
||||
}
|
||||
|
||||
Mesh mesh = Mesh::MakeCartesian2D(3, 1, mfem::Element::Type::QUADRILATERAL,
|
||||
true, 3.0, 1.0);
|
||||
int dim = mesh.Dimension();
|
||||
|
||||
// 2. Set BCs.
|
||||
for (int i = 0; i<mesh.GetNBE(); i++)
|
||||
{
|
||||
Element * be = mesh.GetBdrElement(i);
|
||||
Array<int> vertices;
|
||||
be->GetVertices(vertices);
|
||||
|
||||
double * coords1 = mesh.GetVertex(vertices[0]);
|
||||
double * coords2 = mesh.GetVertex(vertices[1]);
|
||||
|
||||
Vector center(2);
|
||||
center(0) = 0.5*(coords1[0] + coords2[0]);
|
||||
center(1) = 0.5*(coords1[1] + coords2[1]);
|
||||
|
||||
if (abs(center(0) - 0.0) < 1e-10)
|
||||
{
|
||||
// the left edge
|
||||
be->SetAttribute(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// all other boundaries
|
||||
be->SetAttribute(2);
|
||||
}
|
||||
}
|
||||
mesh.SetAttributes();
|
||||
|
||||
// 3. Refine the mesh.
|
||||
for (int lev = 0; lev < ref_levels; lev++)
|
||||
{
|
||||
mesh.UniformRefinement();
|
||||
}
|
||||
|
||||
ParMesh pmesh(MPI_COMM_WORLD, mesh);
|
||||
mesh.Clear();
|
||||
|
||||
// 4. Define the necessary finite element spaces on the mesh.
|
||||
H1_FECollection state_fec(order, dim); // space for u
|
||||
H1_FECollection filter_fec(order, dim); // space for ρ̃
|
||||
L2_FECollection control_fec(order-1, dim,
|
||||
BasisType::GaussLobatto); // space for ψ
|
||||
ParFiniteElementSpace state_fes(&pmesh, &state_fec,dim);
|
||||
ParFiniteElementSpace filter_fes(&pmesh, &filter_fec);
|
||||
ParFiniteElementSpace control_fes(&pmesh, &control_fec);
|
||||
|
||||
HYPRE_BigInt state_size = state_fes.GlobalTrueVSize();
|
||||
HYPRE_BigInt control_size = control_fes.GlobalTrueVSize();
|
||||
HYPRE_BigInt filter_size = filter_fes.GlobalTrueVSize();
|
||||
if (myid==0)
|
||||
{
|
||||
cout << "Number of state unknowns: " << state_size << endl;
|
||||
cout << "Number of filter unknowns: " << filter_size << endl;
|
||||
cout << "Number of control unknowns: " << control_size << endl;
|
||||
}
|
||||
|
||||
// 5. Set the initial guess for ρ.
|
||||
ParGridFunction u(&state_fes);
|
||||
ParGridFunction psi(&control_fes);
|
||||
ParGridFunction psi_old(&control_fes);
|
||||
ParGridFunction rho_filter(&filter_fes);
|
||||
u = 0.0;
|
||||
rho_filter = vol_fraction;
|
||||
psi = inv_sigmoid(vol_fraction);
|
||||
psi_old = inv_sigmoid(vol_fraction);
|
||||
|
||||
// ρ = sigmoid(ψ)
|
||||
MappedGridFunctionCoefficient rho(&psi, sigmoid);
|
||||
// Interpolation of ρ = sigmoid(ψ) in control fes (for ParaView output)
|
||||
ParGridFunction rho_gf(&control_fes);
|
||||
// ρ - ρ_old = sigmoid(ψ) - sigmoid(ψ_old)
|
||||
DiffMappedGridFunctionCoefficient succ_diff_rho(&psi, &psi_old, sigmoid);
|
||||
|
||||
// 6. Set-up the physics solver.
|
||||
int maxat = pmesh.bdr_attributes.Max();
|
||||
Array<int> ess_bdr(maxat);
|
||||
ess_bdr = 0;
|
||||
ess_bdr[0] = 1;
|
||||
ConstantCoefficient one(1.0);
|
||||
ConstantCoefficient lambda_cf(lambda);
|
||||
ConstantCoefficient mu_cf(mu);
|
||||
LinearElasticitySolver * ElasticitySolver = new LinearElasticitySolver();
|
||||
ElasticitySolver->SetMesh(&pmesh);
|
||||
ElasticitySolver->SetOrder(state_fec.GetOrder());
|
||||
ElasticitySolver->SetupFEM();
|
||||
Vector center(2); center(0) = 2.9; center(1) = 0.5;
|
||||
Vector force(2); force(0) = 0.0; force(1) = -1.0;
|
||||
double r = 0.05;
|
||||
VolumeForceCoefficient vforce_cf(r,center,force);
|
||||
ElasticitySolver->SetRHSCoefficient(&vforce_cf);
|
||||
ElasticitySolver->SetEssentialBoundary(ess_bdr);
|
||||
|
||||
// 7. Set-up the filter solver.
|
||||
ConstantCoefficient eps2_cf(epsilon*epsilon);
|
||||
DiffusionSolver * FilterSolver = new DiffusionSolver();
|
||||
FilterSolver->SetMesh(&pmesh);
|
||||
FilterSolver->SetOrder(filter_fec.GetOrder());
|
||||
FilterSolver->SetDiffusionCoefficient(&eps2_cf);
|
||||
FilterSolver->SetMassCoefficient(&one);
|
||||
Array<int> ess_bdr_filter;
|
||||
if (pmesh.bdr_attributes.Size())
|
||||
{
|
||||
ess_bdr_filter.SetSize(pmesh.bdr_attributes.Max());
|
||||
ess_bdr_filter = 0;
|
||||
}
|
||||
FilterSolver->SetEssentialBoundary(ess_bdr_filter);
|
||||
FilterSolver->SetupFEM();
|
||||
|
||||
ParBilinearForm mass(&control_fes);
|
||||
mass.AddDomainIntegrator(new InverseIntegrator(new MassIntegrator(one)));
|
||||
mass.Assemble();
|
||||
HypreParMatrix M;
|
||||
Array<int> empty;
|
||||
mass.FormSystemMatrix(empty,M);
|
||||
|
||||
// 8. Define the Lagrange multiplier and gradient functions.
|
||||
ParGridFunction grad(&control_fes);
|
||||
ParGridFunction w_filter(&filter_fes);
|
||||
|
||||
// 9. Define some tools for later.
|
||||
ConstantCoefficient zero(0.0);
|
||||
ParGridFunction onegf(&control_fes);
|
||||
onegf = 1.0;
|
||||
ParGridFunction zerogf(&control_fes);
|
||||
zerogf = 0.0;
|
||||
ParLinearForm vol_form(&control_fes);
|
||||
vol_form.AddDomainIntegrator(new DomainLFIntegrator(one));
|
||||
vol_form.Assemble();
|
||||
double domain_volume = vol_form(onegf);
|
||||
const double target_volume = domain_volume * vol_fraction;
|
||||
|
||||
// 10. Connect to GLVis. Prepare for VisIt output.
|
||||
char vishost[] = "localhost";
|
||||
int visport = 19916;
|
||||
socketstream sout_r;
|
||||
if (glvis_visualization)
|
||||
{
|
||||
sout_r.open(vishost, visport);
|
||||
sout_r.precision(8);
|
||||
}
|
||||
|
||||
mfem::ParaViewDataCollection paraview_dc("ex37p", &pmesh);
|
||||
if (paraview_output)
|
||||
{
|
||||
rho_gf.ProjectCoefficient(rho);
|
||||
paraview_dc.SetPrefixPath("ParaView");
|
||||
paraview_dc.SetLevelsOfDetail(order);
|
||||
paraview_dc.SetDataFormat(VTKFormat::BINARY);
|
||||
paraview_dc.SetHighOrderOutput(true);
|
||||
paraview_dc.SetCycle(0);
|
||||
paraview_dc.SetTime(0.0);
|
||||
paraview_dc.RegisterField("displacement",&u);
|
||||
paraview_dc.RegisterField("density",&rho_gf);
|
||||
paraview_dc.RegisterField("filtered_density",&rho_filter);
|
||||
paraview_dc.Save();
|
||||
}
|
||||
|
||||
// 11. Iterate:
|
||||
for (int k = 1; k <= max_it; k++)
|
||||
{
|
||||
if (k > 1) { alpha *= ((double) k) / ((double) k-1); }
|
||||
|
||||
if (myid == 0)
|
||||
{
|
||||
cout << "\nStep = " << k << endl;
|
||||
}
|
||||
|
||||
// Step 1 - Filter solve
|
||||
// Solve (ϵ^2 ∇ ρ̃, ∇ v ) + (ρ̃,v) = (ρ,v)
|
||||
FilterSolver->SetRHSCoefficient(&rho);
|
||||
FilterSolver->Solve();
|
||||
rho_filter = *FilterSolver->GetFEMSolution();
|
||||
|
||||
// Step 2 - State solve
|
||||
// Solve (λ r(ρ̃) ∇⋅u, ∇⋅v) + (2 μ r(ρ̃) ε(u), ε(v)) = (f,v)
|
||||
SIMPInterpolationCoefficient SIMP_cf(&rho_filter,rho_min, 1.0);
|
||||
ProductCoefficient lambda_SIMP_cf(lambda_cf,SIMP_cf);
|
||||
ProductCoefficient mu_SIMP_cf(mu_cf,SIMP_cf);
|
||||
ElasticitySolver->SetLameCoefficients(&lambda_SIMP_cf,&mu_SIMP_cf);
|
||||
ElasticitySolver->Solve();
|
||||
u = *ElasticitySolver->GetFEMSolution();
|
||||
|
||||
// Step 3 - Adjoint filter solve
|
||||
// Solve (ϵ² ∇ w̃, ∇ v) + (w̃ ,v) = (-r'(ρ̃) ( λ |∇⋅u|² + 2 μ |ε(u)|²),v)
|
||||
StrainEnergyDensityCoefficient rhs_cf(&lambda_cf,&mu_cf,&u, &rho_filter,
|
||||
rho_min);
|
||||
FilterSolver->SetRHSCoefficient(&rhs_cf);
|
||||
FilterSolver->Solve();
|
||||
w_filter = *FilterSolver->GetFEMSolution();
|
||||
|
||||
// Step 4 - Compute gradient
|
||||
// Solve G = M⁻¹w̃
|
||||
GridFunctionCoefficient w_cf(&w_filter);
|
||||
ParLinearForm w_rhs(&control_fes);
|
||||
w_rhs.AddDomainIntegrator(new DomainLFIntegrator(w_cf));
|
||||
w_rhs.Assemble();
|
||||
M.Mult(w_rhs,grad);
|
||||
|
||||
// Step 5 - Update design variable ψ ← proj(ψ - αG)
|
||||
psi.Add(-alpha, grad);
|
||||
const double material_volume = proj(psi, target_volume);
|
||||
|
||||
// Compute ||ρ - ρ_old|| in control fes.
|
||||
double norm_increment = zerogf.ComputeL1Error(succ_diff_rho);
|
||||
double norm_reduced_gradient = norm_increment/alpha;
|
||||
psi_old = psi;
|
||||
|
||||
double compliance = (*(ElasticitySolver->GetLinearForm()))(u);
|
||||
MPI_Allreduce(MPI_IN_PLACE,&compliance,1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD);
|
||||
if (myid == 0)
|
||||
{
|
||||
mfem::out << "norm of the reduced gradient = " << norm_reduced_gradient << endl;
|
||||
mfem::out << "norm of the increment = " << norm_increment << endl;
|
||||
mfem::out << "compliance = " << compliance << endl;
|
||||
mfem::out << "volume fraction = " << material_volume / domain_volume << endl;
|
||||
}
|
||||
|
||||
if (glvis_visualization)
|
||||
{
|
||||
ParGridFunction r_gf(&filter_fes);
|
||||
r_gf.ProjectCoefficient(SIMP_cf);
|
||||
sout_r << "parallel " << num_procs << " " << myid << "\n";
|
||||
sout_r << "solution\n" << pmesh << r_gf
|
||||
<< "window_title 'Design density r(ρ̃)'" << flush;
|
||||
}
|
||||
|
||||
if (paraview_output)
|
||||
{
|
||||
rho_gf.ProjectCoefficient(rho);
|
||||
paraview_dc.SetCycle(k);
|
||||
paraview_dc.SetTime((double)k);
|
||||
paraview_dc.Save();
|
||||
}
|
||||
|
||||
if (norm_reduced_gradient < ntol && norm_increment < itol)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete ElasticitySolver;
|
||||
delete FilterSolver;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -5,7 +5,6 @@
|
||||
// Sample runs: mpirun -np 4 ex3p -m ../data/star.mesh
|
||||
// mpirun -np 4 ex3p -m ../data/square-disc.mesh -o 2
|
||||
// mpirun -np 4 ex3p -m ../data/beam-tet.mesh
|
||||
// mpirun -np 4 ex3p -m ../data/beam-tet.mesh -nc -o 2
|
||||
// mpirun -np 4 ex3p -m ../data/beam-hex.mesh
|
||||
// mpirun -np 4 ex3p -m ../data/beam-hex.mesh -o 2 -pa
|
||||
// mpirun -np 4 ex3p -m ../data/escher.mesh
|
||||
@@ -71,7 +70,6 @@ int main(int argc, char *argv[])
|
||||
int order = 1;
|
||||
bool static_cond = false;
|
||||
bool pa = false;
|
||||
bool nc = false;
|
||||
const char *device_config = "cpu";
|
||||
bool visualization = true;
|
||||
#ifdef MFEM_USE_AMGX
|
||||
@@ -89,9 +87,6 @@ int main(int argc, char *argv[])
|
||||
"--no-static-condensation", "Enable static condensation.");
|
||||
args.AddOption(&pa, "-pa", "--partial-assembly", "-no-pa",
|
||||
"--no-partial-assembly", "Enable Partial Assembly.");
|
||||
args.AddOption(&nc, "-nc", "--non-conforming", "-c",
|
||||
"--conforming",
|
||||
"Mark the mesh as nonconforming before partitioning.");
|
||||
args.AddOption(&device_config, "-d", "--device",
|
||||
"Device configuration string, see Device::Configure().");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
@@ -129,11 +124,6 @@ int main(int argc, char *argv[])
|
||||
Mesh *mesh = new Mesh(mesh_file, 1, 1);
|
||||
dim = mesh->Dimension();
|
||||
int sdim = mesh->SpaceDimension();
|
||||
if (nc)
|
||||
{
|
||||
// Can set to false to use conformal refinement for simplices.
|
||||
mesh->EnsureNCMesh(true);
|
||||
}
|
||||
|
||||
// 5. Refine the serial mesh on all processors to increase the resolution. In
|
||||
// this example we do 'ref_levels' of uniform refinement. We choose
|
||||
|
||||
+1
-2
@@ -450,8 +450,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
// Implementation of class FE_Evolution
|
||||
FE_Evolution::FE_Evolution(BilinearForm &M_, BilinearForm &K_, const Vector &b_)
|
||||
: TimeDependentOperator(M_.FESpace()->GetTrueVSize()),
|
||||
M(M_), K(K_), b(b_), z(height)
|
||||
: TimeDependentOperator(M_.Height()), M(M_), K(K_), b(b_), z(M_.Height())
|
||||
{
|
||||
Array<int> ess_tdof_list;
|
||||
if (M.GetAssemblyLevel() == AssemblyLevel::LEGACY)
|
||||
|
||||
+2
-2
@@ -659,9 +659,9 @@ int main(int argc, char *argv[])
|
||||
// Implementation of class FE_Evolution
|
||||
FE_Evolution::FE_Evolution(ParBilinearForm &M_, ParBilinearForm &K_,
|
||||
const Vector &b_, PrecType prec_type)
|
||||
: TimeDependentOperator(M_.ParFESpace()->GetTrueVSize()), b(b_),
|
||||
: TimeDependentOperator(M_.Height()), b(b_),
|
||||
M_solver(M_.ParFESpace()->GetComm()),
|
||||
z(height)
|
||||
z(M_.Height())
|
||||
{
|
||||
if (M_.GetAssemblyLevel()==AssemblyLevel::LEGACY)
|
||||
{
|
||||
|
||||
+2
-9
@@ -23,11 +23,10 @@ MFEM_LIB_FILE = mfem_is_not_built
|
||||
|
||||
SEQ_EXAMPLES = ex0 ex1 ex2 ex3 ex4 ex5 ex6 ex7 ex8 ex9 ex10 ex14 ex15 ex16 \
|
||||
ex17 ex18 ex19 ex20 ex21 ex22 ex23 ex24 ex25 ex26 ex27 ex28 ex29 ex30 \
|
||||
ex31 ex33 ex34 ex36 ex37
|
||||
ex31 ex33 ex34 ex36
|
||||
PAR_EXAMPLES = ex0p ex1p ex2p ex3p ex4p ex5p ex6p ex7p ex8p ex9p ex10p ex11p \
|
||||
ex12p ex13p ex14p ex15p ex16p ex17p ex18p ex19p ex20p ex21p ex22p ex24p \
|
||||
ex25p ex26p ex27p ex28p ex29p ex30p ex31p ex32p ex33p ex34p ex35p ex36p \
|
||||
ex37p
|
||||
ex25p ex26p ex27p ex28p ex29p ex30p ex31p ex32p ex33p ex34p ex35p ex36p
|
||||
SEQ_DEVICE_EXAMPLES = ex1 ex3 ex4 ex5 ex6 ex9 ex22 ex24 ex25 ex26 ex34
|
||||
PAR_DEVICE_EXAMPLES = ex1p ex2p ex3p ex4p ex5p ex6p ex7p ex9p ex13p ex22p \
|
||||
ex24p ex25p ex26p ex34p ex35p
|
||||
@@ -93,12 +92,10 @@ $(SUBDIRS_TPRINT):
|
||||
# Additional dependencies
|
||||
ex18: $(SRC)ex18.hpp
|
||||
ex33: $(SRC)ex33.hpp
|
||||
ex37: $(SRC)ex37.hpp
|
||||
|
||||
ifeq ($(MFEM_USE_MPI),YES)
|
||||
ex18p: $(SRC)ex18.hpp
|
||||
ex33p: $(SRC)ex33.hpp
|
||||
ex37p: $(SRC)ex37.hpp
|
||||
endif
|
||||
|
||||
MFEM_TESTS = EXAMPLES
|
||||
@@ -142,10 +139,6 @@ ex27-test-seq: ex27
|
||||
@$(call mfem-test,$<,, Serial example,-dg)
|
||||
ex27p-test-par: ex27p
|
||||
@$(call mfem-test,$<, $(RUN_MPI), Parallel example,-dg)
|
||||
ex37-test-seq: ex37
|
||||
@$(call mfem-test,$<,, Serial example,-mi 3)
|
||||
ex37p-test-par: ex37p
|
||||
@$(call mfem-test,$<, $(RUN_MPI), Parallel example,-mi 3)
|
||||
# Testing: optional tests
|
||||
ifeq ($(MFEM_USE_STRUMPACK),YES)
|
||||
ex11p-test-strumpack: ex11p
|
||||
|
||||
@@ -24,13 +24,13 @@ if (MFEM_USE_MPI)
|
||||
ex10p.cpp
|
||||
)
|
||||
list(APPEND PETSC_RC_FILES
|
||||
rc_ex1p rc_ex1p_device rc_ex1p_deviceamg
|
||||
rc_ex2p rc_ex2p_bddc rc_ex2p_asm
|
||||
rc_ex1p
|
||||
rc_ex2p
|
||||
rc_ex3p rc_ex3p_bddc
|
||||
rc_ex4p rc_ex4p_bddc
|
||||
rc_ex5p_bddc rc_ex5p_fieldsplit
|
||||
rc_ex9p_expl rc_ex9p_expl_device rc_ex9p_impl
|
||||
rc_ex10p rc_ex10p_mf rc_ex10p_mfop rc_ex10p_jfnk
|
||||
rc_ex9p_expl rc_ex9p_impl
|
||||
rc_ex10p
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -39,7 +39,7 @@ if (MFEM_USE_SLEPC)
|
||||
ex11p.cpp
|
||||
)
|
||||
list(APPEND PETSC_RC_FILES
|
||||
rc_ex11p_lobpcg rc_ex11p_lobpcg_device rc_ex11p_gd
|
||||
rc_ex11p_lobpcg rc_ex11p_gd
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -74,13 +74,7 @@ add_mfem_examples(PETSC_EXAMPLES_SRCS ${PFX} copy_petsc_rc_files test_petsc)
|
||||
# Command line options for the tests.
|
||||
set(EX1_ARGS_W -m ../../data/amr-quad.mesh --usepetsc)
|
||||
set(EX1_ARGS_P -m ../../data/amr-quad.mesh --usepetsc --petscopts rc_ex1p)
|
||||
set(EX1_ARGS_CUDA -m ../../data/star.mesh --usepetsc --partial-assembly --device cuda --petscopts rc_ex1p_device)
|
||||
set(EX1_ARGS_CUDAAMG -m ../../data/star.mesh --usepetsc --device cuda --petscopts rc_ex1p_deviceamg)
|
||||
set(EX1_ARGS_HIP -m ../../data/star.mesh --usepetsc --partial-assembly --device hip --petscopts rc_ex1p_device)
|
||||
set(EX1_ARGS_HIPAMG -m ../../data/star.mesh --usepetsc --device hip --petscopts rc_ex1p_deviceamg)
|
||||
set(EX2_ARGS -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex2p)
|
||||
set(EX2_ARGS_BDDC -m ../../data/beam-tri.mesh --usepetsc --nonoverlapping --petscopts rc_ex2p_bddc)
|
||||
set(EX2_ARGS_ASM -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex2p_asm)
|
||||
set(EX3_ARGS -m ../../data/klein-bottle.mesh -o 2 -f 0.1 --usepetsc --petscopts rc_ex3p_bddc --nonoverlapping)
|
||||
set(EX4_ARGS -m ../../data/klein-bottle.mesh -o 2 --usepetsc --petscopts rc_ex4p_bddc --nonoverlapping)
|
||||
set(EX4_HYB_ARGS -m ../../data/klein-bottle.mesh -o 2 --usepetsc --petscopts rc_ex4p_bddc --nonoverlapping --hybridization)
|
||||
@@ -91,46 +85,22 @@ set(EX6_ARGS -m ../../data/amr-quad.mesh --usepetsc)
|
||||
set(EX6_NONOVL_ARGS -m ../../data/amr-quad.mesh --usepetsc --nonoverlapping)
|
||||
set(EX9_E_ARGS -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_expl -dt 0.1)
|
||||
set(EX9_ES_ARGS -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_expl --no-step)
|
||||
set(EX9_ES_ARGS_CUDA -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_expl_device --no-step --partial-assembly --device cuda)
|
||||
set(EX9_ES_ARGS_HIP -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_expl_device --no-step --partial-assembly --device hip)
|
||||
set(EX9_IS_ARGS -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_impl --implicit -tf 0.5)
|
||||
set(EX10_ARGS -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex10p -tf 30 -s 3 -rs 2 -dt 3)
|
||||
set(EX10_MF_ARGS -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex10p_mf -tf 6 -s 3 -rs 0 -dt 3)
|
||||
set(EX10_MFOP_ARGS -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex10p_mfop -tf 6 -s 3 -rs 0 -dt 3)
|
||||
set(EX10_JFNK_ARGS -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex10p_jfnk --jfnk -tf 6 -s 3 -rs 0 -dt 3)
|
||||
if (MFEM_USE_SLEPC)
|
||||
set(EX11_ARGS_SINV -m ../../data/star.mesh --useslepc)
|
||||
set(EX11_ARGS_LOBPCG -m ../../data/star.mesh --useslepc --slepcopts rc_ex11p_lobpcg)
|
||||
set(EX11_ARGS_LOBPCG_CUDA -m ../../data/star.mesh --useslepc --slepcopts rc_ex11p_lobpcg_device --device cuda)
|
||||
set(EX11_ARGS_LOBPCG_HIP -m ../../data/star.mesh --useslepc --slepcopts rc_ex11p_lobpcg_device --device hip)
|
||||
set(EX11_ARGS_GD -m ../../data/star.mesh --useslepc --slepcopts rc_ex11p_gd)
|
||||
endif()
|
||||
|
||||
# Add the tests: one test per command-line-variable.
|
||||
if (MFEM_ENABLE_TESTING)
|
||||
set(TEST_OPTIONS_VARS
|
||||
EX1_ARGS_W EX1_ARGS_P EX2_ARGS EX2_ARGS_BDDC EX2_ARGS_ASM EX3_ARGS
|
||||
EX4_ARGS EX4_HYB_ARGS EX5_BDDC_LB_ARGS EX5_BDDC_GB_ARGS EX5_FSPL_ARGS
|
||||
EX6_ARGS EX6_NONOVL_ARGS EX9_E_ARGS EX9_ES_ARGS EX9_IS_ARGS EX10_ARGS
|
||||
EX10_MF_ARGS EX10_MFOP_ARGS EX10_JFNK_ARGS)
|
||||
EX1_ARGS_W EX1_ARGS_P EX2_ARGS EX3_ARGS EX4_ARGS EX4_HYB_ARGS
|
||||
EX5_BDDC_LB_ARGS EX5_BDDC_GB_ARGS EX5_FSPL_ARGS EX6_ARGS EX6_NONOVL_ARGS
|
||||
EX9_E_ARGS EX9_ES_ARGS EX9_IS_ARGS EX10_ARGS)
|
||||
if (MFEM_USE_SLEPC)
|
||||
list(APPEND TEST_OPTIONS_VARS
|
||||
EX11_ARGS_SINV EX11_ARGS_LOBPCG EX11_ARGS_GD)
|
||||
endif()
|
||||
# CUDA/HIP tests
|
||||
if (MFEM_USE_CUDA)
|
||||
list(APPEND TEST_OPTIONS_VARS
|
||||
EX1_ARGS_CUDA EX1_ARGS_CUDAAMG EX9_ES_ARGS_CUDA)
|
||||
if (MFEM_USE_SLEPC)
|
||||
list(APPEND TEST_OPTIONS_VARS EX11_ARGS_LOBPCG_CUDA)
|
||||
endif()
|
||||
elseif (MFEM_USE_HIP)
|
||||
list(APPEND TEST_OPTIONS_VARS
|
||||
EX1_ARGS_HIP EX1_ARGS_HIPAMG EX9_ES_ARGS_HIP)
|
||||
if (MFEM_USE_SLEPC)
|
||||
# SLEPc does not support BVSVEC with HIP
|
||||
# list(APPEND TEST_OPTIONS_VARS EX11_ARGS_LOBPCG_HIP)
|
||||
endif()
|
||||
list(APPEND TEST_OPTIONS_VARS EX11_ARGS_SINV EX11_ARGS_LOBPCG EX11_ARGS_GD)
|
||||
endif()
|
||||
|
||||
foreach(TEST_OPTIONS_VAR ${TEST_OPTIONS_VARS})
|
||||
@@ -145,7 +115,7 @@ if (MFEM_ENABLE_TESTING)
|
||||
|
||||
# All PETSC tests are parallel.
|
||||
if (MFEM_USE_MPI)
|
||||
add_test(NAME ${TEST_NAME_FULL}_np=${MFEM_MPI_NP}
|
||||
add_test(NAME ${TEST_NAME_FULL}_np=4
|
||||
COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MFEM_MPI_NP}
|
||||
${MPIEXEC_PREFLAGS}
|
||||
$<TARGET_FILE:${TEST_NAME}> ${TEST_OPTIONS}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
// mpirun -np 4 ex1p -m ../../data/amr-quad.mesh --petscopts rc_ex1p
|
||||
//
|
||||
// Device sample runs:
|
||||
// mpirun -np 4 ex1p -pa -d cuda --petscopts rc_ex1p_device
|
||||
// mpirun -np 4 ex1p -pa -d cuda --petscopts rc_ex1p_cuda
|
||||
//
|
||||
// Description: This example code demonstrates the use of MFEM to define a
|
||||
// simple finite element discretization of the Laplace problem
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
// finite elements (velocity u) and piecewise discontinuous
|
||||
// polynomials (pressure p).
|
||||
//
|
||||
// The example demonstrates the use of the BlockOperator class, as
|
||||
// The example demonstrates the use of the BlockMatrix class, as
|
||||
// well as the collective saving of several grid functions in a
|
||||
// VisIt (visit.llnl.gov) visualization format.
|
||||
//
|
||||
|
||||
@@ -520,10 +520,10 @@ int main(int argc, char *argv[])
|
||||
// Implementation of class FE_Evolution
|
||||
FE_Evolution::FE_Evolution(ParBilinearForm &M_, ParBilinearForm &K_,
|
||||
const Vector &b_,bool M_in_lhs)
|
||||
: TimeDependentOperator(M_.ParFESpace()->GetTrueVSize(), 0.0,
|
||||
: TimeDependentOperator(M_.Height(), 0.0,
|
||||
M_in_lhs ? TimeDependentOperator::IMPLICIT
|
||||
: TimeDependentOperator::EXPLICIT),
|
||||
b(b_), comm(M_.ParFESpace()->GetComm()), M_solver(comm), z(height),
|
||||
b(b_), comm(M_.ParFESpace()->GetComm()), M_solver(comm), z(M_.Height()),
|
||||
iJacobian(NULL), rJacobian(NULL)
|
||||
{
|
||||
MAlev = M_.GetAssemblyLevel();
|
||||
|
||||
+9
-29
@@ -66,9 +66,7 @@ include $(MFEM_TEST_MK)
|
||||
|
||||
# Testing: Parallel runs
|
||||
RUN_MPI = $(MFEM_MPIEXEC) $(MFEM_MPIEXEC_NP) $(MFEM_MPI_NP)
|
||||
TESTNAME = Parallel PETSc example
|
||||
TESTNAME_CUDA = Parallel CUDA PETSc example
|
||||
TESTNAME_HIP = Parallel HIP PETSc example
|
||||
TESTNAME = Parallel PETSc example
|
||||
%-test-par: %
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME))
|
||||
|
||||
@@ -76,10 +74,8 @@ TESTNAME_HIP = Parallel HIP PETSc example
|
||||
# Testing PETSc execution options.
|
||||
EX1_ARGS_W := -m ../../data/amr-quad.mesh --usepetsc
|
||||
EX1_ARGS_P := -m ../../data/amr-quad.mesh --usepetsc --petscopts rc_ex1p
|
||||
EX1_ARGS_CUDA := -m ../../data/star.mesh --usepetsc --partial-assembly --device cuda --petscopts rc_ex1p_device
|
||||
EX1_ARGS_CUDAAMG := -m ../../data/star.mesh --usepetsc --device cuda --petscopts rc_ex1p_deviceamg
|
||||
EX1_ARGS_HIP := -m ../../data/star.mesh --usepetsc --partial-assembly --device hip --petscopts rc_ex1p_device
|
||||
EX1_ARGS_HIPAMG := -m ../../data/star.mesh --usepetsc --device hip --petscopts rc_ex1p_deviceamg
|
||||
EX1_ARGS_CUDA := -m ../../data/star.mesh --usepetsc --partial-assembly --device cuda --petscopts rc_ex1p_cuda
|
||||
EX1_ARGS_CUDAAMG := -m ../../data/star.mesh --usepetsc --device cuda --petscopts rc_ex1p_cudaamg
|
||||
EX2_ARGS := -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex2p
|
||||
EX2_ARGS_BDDC := -m ../../data/beam-tri.mesh --usepetsc --nonoverlapping --petscopts rc_ex2p_bddc
|
||||
EX2_ARGS_ASM := -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex2p_asm
|
||||
@@ -93,8 +89,7 @@ EX6_ARGS := -m ../../data/amr-quad.mesh --usepetsc
|
||||
EX6_NONOVL_ARGS := -m ../../data/amr-quad.mesh --usepetsc --nonoverlapping
|
||||
EX9_E_ARGS := -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_expl -dt 0.1
|
||||
EX9_ES_ARGS := -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_expl --no-step
|
||||
EX9_ES_ARGS_CUDA := -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_expl_device --no-step --partial-assembly --device cuda
|
||||
EX9_ES_ARGS_HIP := -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_expl_device --no-step --partial-assembly --device hip
|
||||
EX9_ES_ARGS_CUDA := -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_expl_cuda --no-step --partial-assembly --device cuda
|
||||
EX9_IS_ARGS := -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_impl --implicit -tf 0.5
|
||||
EX10_ARGS := -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex10p -tf 30 -s 3 -rs 2 -dt 3
|
||||
EX10_MF_ARGS := -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex10p_mf -tf 6 -s 3 -rs 0 -dt 3
|
||||
@@ -102,20 +97,15 @@ EX10_MFOP_ARGS := -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_
|
||||
EX10_JFNK_ARGS := -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex10p_jfnk --jfnk -tf 6 -s 3 -rs 0 -dt 3
|
||||
EX11_ARGS_SINV := -m ../../data/star.mesh --useslepc
|
||||
EX11_ARGS_LOBPCG := -m ../../data/star.mesh --useslepc --slepcopts rc_ex11p_lobpcg
|
||||
EX11_ARGS_LOBPCG_CUDA := -m ../../data/star.mesh --useslepc --slepcopts rc_ex11p_lobpcg_device --device cuda
|
||||
EX11_ARGS_LOBPCG_HIP := -m ../../data/star.mesh --useslepc --slepcopts rc_ex11p_lobpcg_device --device hip
|
||||
EX11_ARGS_LOBPCG_CUDA := -m ../../data/star.mesh --useslepc --slepcopts rc_ex11p_lobpcg_cuda --device cuda
|
||||
EX11_ARGS_GD := -m ../../data/star.mesh --useslepc --slepcopts rc_ex11p_gd
|
||||
|
||||
ex1p-test-par: ex1p
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX1_ARGS_W))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX1_ARGS_P))
|
||||
ifeq ($(MFEM_USE_CUDA),YES)
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME_CUDA),$(EX1_ARGS_CUDA))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME_CUDA),$(EX1_ARGS_CUDAAMG))
|
||||
endif
|
||||
ifeq ($(MFEM_USE_HIP),YES)
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME_HIP),$(EX1_ARGS_HIP))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME_HIP),$(EX1_ARGS_HIPAMG))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX1_ARGS_CUDA))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX1_ARGS_CUDAAMG))
|
||||
endif
|
||||
ex2p-test-par: ex2p
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX2_ARGS))
|
||||
@@ -138,10 +128,7 @@ ex9p-test-par: ex9p
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX9_ES_ARGS))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX9_IS_ARGS))
|
||||
ifeq ($(MFEM_USE_CUDA),YES)
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME_CUDA),$(EX9_ES_ARGS_CUDA))
|
||||
endif
|
||||
ifeq ($(MFEM_USE_HIP),YES)
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME_HIP),$(EX9_ES_ARGS_HIP))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX9_ES_ARGS_CUDA))
|
||||
endif
|
||||
ex10p-test-par: ex10p
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX10_ARGS))
|
||||
@@ -153,12 +140,8 @@ ex11p-test-par: ex11p
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX11_ARGS_SINV))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX11_ARGS_LOBPCG))
|
||||
ifeq ($(MFEM_USE_CUDA),YES)
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME_CUDA),$(EX11_ARGS_LOBPCG_CUDA))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX11_ARGS_LOBPCG_CUDA))
|
||||
endif
|
||||
# SLEPc does not support BVSVEC with HIP
|
||||
#ifeq ($(MFEM_USE_HIP),YES)
|
||||
# @$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME_HIP),$(EX11_ARGS_LOBPCG_HIP))
|
||||
#endif
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX11_ARGS_GD))
|
||||
endif
|
||||
|
||||
@@ -173,9 +156,6 @@ clean: clean-build clean-exec
|
||||
clean-build:
|
||||
rm -f *.o *~ $(SEQ_EXAMPLES) $(PAR_EXAMPLES)
|
||||
rm -rf *.dSYM *.TVD.*breakpoints
|
||||
ifneq ($(SRC),)
|
||||
rm -f $(RC_FILES)
|
||||
endif
|
||||
|
||||
clean-exec:
|
||||
@rm -rf mesh.* sol.* sol_p.* sol_u.* Example5*
|
||||
|
||||
@@ -476,8 +476,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
// Implementation of class FE_Evolution
|
||||
FE_Evolution::FE_Evolution(BilinearForm &M_, BilinearForm &K_, const Vector &b_)
|
||||
: TimeDependentOperator(M_.FESpace()->GetTrueVSize()),
|
||||
M(M_), K(K_), b(b_), z(height)
|
||||
: TimeDependentOperator(M_.Height()), M(M_), K(K_), b(b_), z(M_.Height())
|
||||
{
|
||||
Array<int> ess_tdof_list;
|
||||
if (M.GetAssemblyLevel() == AssemblyLevel::LEGACY)
|
||||
|
||||
@@ -679,10 +679,10 @@ int main(int argc, char *argv[])
|
||||
// Implementation of class FE_Evolution
|
||||
FE_Evolution::FE_Evolution(ParBilinearForm &M_, ParBilinearForm &K_,
|
||||
const Vector &b_, PrecType prec_type)
|
||||
: TimeDependentOperator(M_.ParFESpace()->GetTrueVSize()),
|
||||
: TimeDependentOperator(M_.Height()),
|
||||
b(b_),
|
||||
M_solver(M_.ParFESpace()->GetComm()),
|
||||
z(height)
|
||||
z(M_.Height())
|
||||
{
|
||||
if (M_.GetAssemblyLevel()==AssemblyLevel::LEGACY)
|
||||
{
|
||||
|
||||
@@ -23,7 +23,6 @@ set(SRCS
|
||||
integ/bilininteg_diffusion_mf.cpp
|
||||
integ/bilininteg_diffusion_pa.cpp
|
||||
integ/bilininteg_diffusion_ea.cpp
|
||||
integ/bilininteg_diffusion_patch.cpp
|
||||
integ/bilininteg_divdiv_pa.cpp
|
||||
integ/bilininteg_gradient_pa.cpp
|
||||
integ/bilininteg_interp_pa.cpp
|
||||
@@ -88,7 +87,6 @@ set(SRCS
|
||||
ceed/solvers/algebraic.cpp
|
||||
ceed/solvers/full-assembly.cpp
|
||||
ceed/solvers/solvers-atpmg.cpp
|
||||
kdtree.cpp
|
||||
linearform.cpp
|
||||
linearform_ext.cpp
|
||||
lininteg.cpp
|
||||
@@ -200,7 +198,6 @@ set(HDRS
|
||||
ceed/solvers/algebraic.hpp
|
||||
ceed/solvers/full-assembly.hpp
|
||||
ceed/solvers/solvers-atpmg.hpp
|
||||
kdtree.hpp
|
||||
linearform.hpp
|
||||
linearform_ext.hpp
|
||||
lininteg.hpp
|
||||
|
||||
+2
-48
@@ -13,7 +13,6 @@
|
||||
|
||||
#include "fem.hpp"
|
||||
#include "../general/device.hpp"
|
||||
#include "../mesh/nurbs.hpp"
|
||||
#include <cmath>
|
||||
|
||||
namespace mfem
|
||||
@@ -422,17 +421,11 @@ void BilinearForm::Assemble(int skip_zeros)
|
||||
"invalid element marker for domain integrator #"
|
||||
<< k << ", counting from zero");
|
||||
}
|
||||
|
||||
if (domain_integs[k]->Patchwise())
|
||||
{
|
||||
MFEM_VERIFY(fes->GetNURBSext(), "Patchwise integration requires a "
|
||||
<< "NURBS FE space");
|
||||
}
|
||||
}
|
||||
|
||||
// Element-wise integration
|
||||
for (int i = 0; i < fes -> GetNE(); i++)
|
||||
{
|
||||
int elem_attr = fes->GetMesh()->GetAttribute(i);
|
||||
doftrans = fes->GetElementVDofs(i, vdofs);
|
||||
if (element_matrices)
|
||||
{
|
||||
@@ -440,13 +433,11 @@ void BilinearForm::Assemble(int skip_zeros)
|
||||
}
|
||||
else
|
||||
{
|
||||
const int elem_attr = fes->GetMesh()->GetAttribute(i);
|
||||
elmat.SetSize(0);
|
||||
for (int k = 0; k < domain_integs.Size(); k++)
|
||||
{
|
||||
if ((domain_integs_marker[k] == NULL ||
|
||||
if ( domain_integs_marker[k] == NULL ||
|
||||
(*(domain_integs_marker[k]))[elem_attr-1] == 1)
|
||||
&& !domain_integs[k]->Patchwise())
|
||||
{
|
||||
const FiniteElement &fe = *fes->GetFE(i);
|
||||
eltrans = fes->GetElementTransformation(i);
|
||||
@@ -488,43 +479,6 @@ void BilinearForm::Assemble(int skip_zeros)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Patch-wise integration
|
||||
if (fes->GetNURBSext())
|
||||
{
|
||||
for (int p=0; p<mesh->NURBSext->GetNP(); ++p)
|
||||
{
|
||||
bool vdofsSet = false;
|
||||
for (int k = 0; k < domain_integs.Size(); k++)
|
||||
{
|
||||
if (domain_integs[k]->Patchwise())
|
||||
{
|
||||
if (!vdofsSet)
|
||||
{
|
||||
fes->GetPatchVDofs(p, vdofs);
|
||||
vdofsSet = true;
|
||||
}
|
||||
|
||||
SparseMatrix* spmat = nullptr;
|
||||
domain_integs[k]->AssemblePatchMatrix(p, *fes, spmat);
|
||||
Array<int> cols;
|
||||
Vector srow;
|
||||
|
||||
for (int r=0; r<spmat->Height(); ++r)
|
||||
{
|
||||
spmat->GetRow(r, cols, srow);
|
||||
for (int i=0; i<cols.Size(); ++i)
|
||||
{
|
||||
cols[i] = vdofs[cols[i]];
|
||||
}
|
||||
mat->AddRow(vdofs[r], cols, srow);
|
||||
}
|
||||
|
||||
delete spmat;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (boundary_integs.Size())
|
||||
|
||||
@@ -254,12 +254,6 @@ public:
|
||||
/// Access all the integrators added with AddDomainIntegrator().
|
||||
Array<BilinearFormIntegrator*> *GetDBFI() { return &domain_integs; }
|
||||
|
||||
/// @brief Access all boundary markers added with AddDomainIntegrator().
|
||||
///
|
||||
/// If no marker was specified when the integrator was added, the
|
||||
/// corresponding pointer (to Array<int>) will be NULL. */
|
||||
Array<Array<int>*> *GetDBFI_Marker() { return &domain_integs_marker; }
|
||||
|
||||
/// Access all the integrators added with AddBoundaryIntegrator().
|
||||
Array<BilinearFormIntegrator*> *GetBBFI() { return &boundary_integs; }
|
||||
/** @brief Access all boundary markers added with AddBoundaryIntegrator().
|
||||
@@ -458,7 +452,7 @@ public:
|
||||
practice it is convenient to have it in transposed form for
|
||||
construction of RAP operators in matrix-free methods. */
|
||||
virtual const Operator *GetOutputRestrictionTranspose() const
|
||||
{ return fes->GetRestrictionTransposeOperator(); }
|
||||
{ return GetOutputProlongation(); }
|
||||
/// Get the output finite element space restriction matrix
|
||||
virtual const Operator *GetOutputRestriction() const
|
||||
{ return GetRestriction(); }
|
||||
|
||||
+13
-166
@@ -264,14 +264,6 @@ void PABilinearFormExtension::SetupRestrictionOperators(const L2FaceValues m)
|
||||
localX.SetSize(elem_restrict->Height(), Device::GetDeviceMemoryType());
|
||||
localY.SetSize(elem_restrict->Height(), Device::GetDeviceMemoryType());
|
||||
localY.UseDevice(true); // ensure 'localY = 0.0' is done on device
|
||||
|
||||
// Gather the attributes on the host from all the elements
|
||||
const Mesh &mesh = *trial_fes->GetMesh();
|
||||
elem_attributes.SetSize(mesh.GetNE());
|
||||
for (int i = 0; i < mesh.GetNE(); ++i)
|
||||
{
|
||||
elem_attributes[i] = mesh.GetAttribute(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Construct face restriction operators only if the bilinear form has
|
||||
@@ -297,46 +289,6 @@ void PABilinearFormExtension::SetupRestrictionOperators(const L2FaceValues m)
|
||||
bdr_face_X.SetSize(bdr_face_restrict_lex->Height(), Device::GetMemoryType());
|
||||
bdr_face_Y.SetSize(bdr_face_restrict_lex->Height(), Device::GetMemoryType());
|
||||
bdr_face_Y.UseDevice(true); // ensure 'faceBoundY = 0.0' is done on device
|
||||
|
||||
const Mesh &mesh = *trial_fes->GetMesh();
|
||||
// See LinearFormExtension::Update for explanation of f_to_be logic.
|
||||
std::unordered_map<int,int> f_to_be;
|
||||
for (int i = 0; i < mesh.GetNBE(); ++i)
|
||||
{
|
||||
const int f = mesh.GetBdrElementEdgeIndex(i);
|
||||
f_to_be[f] = i;
|
||||
}
|
||||
const int nf_bdr = trial_fes->GetNFbyType(FaceType::Boundary);
|
||||
bdr_attributes.SetSize(nf_bdr);
|
||||
int f_ind = 0;
|
||||
int missing_bdr_elems = 0;
|
||||
for (int f = 0; f < mesh.GetNumFaces(); ++f)
|
||||
{
|
||||
if (!mesh.GetFaceInformation(f).IsOfFaceType(FaceType::Boundary))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int attribute = 1; // default value
|
||||
if (f_to_be.find(f) != f_to_be.end())
|
||||
{
|
||||
const int be = f_to_be[f];
|
||||
attribute = mesh.GetBdrAttribute(be);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If a boundary face does not correspond to the a boundary element,
|
||||
// we assign it the default attribute of 1. We also generate a
|
||||
// warning at runtime with the number of such missing elements.
|
||||
++missing_bdr_elems;
|
||||
}
|
||||
bdr_attributes[f_ind] = attribute;
|
||||
++f_ind;
|
||||
}
|
||||
if (missing_bdr_elems)
|
||||
{
|
||||
MFEM_WARNING("Missing " << missing_bdr_elems << " boundary elements "
|
||||
"for boundary faces.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,16 +299,7 @@ void PABilinearFormExtension::Assemble()
|
||||
Array<BilinearFormIntegrator*> &integrators = *a->GetDBFI();
|
||||
for (BilinearFormIntegrator *integ : integrators)
|
||||
{
|
||||
if (integ->Patchwise())
|
||||
{
|
||||
MFEM_VERIFY(a->FESpace()->GetNURBSext(),
|
||||
"Patchwise integration requires a NURBS FE space");
|
||||
integ->AssembleNURBSPA(*a->FESpace());
|
||||
}
|
||||
else
|
||||
{
|
||||
integ->AssemblePA(*a->FESpace());
|
||||
}
|
||||
integ->AssemblePA(*a->FESpace());
|
||||
}
|
||||
|
||||
Array<BilinearFormIntegrator*> &bdr_integrators = *a->GetBBFI();
|
||||
@@ -467,52 +410,24 @@ void PABilinearFormExtension::Mult(const Vector &x, Vector &y) const
|
||||
Array<BilinearFormIntegrator*> &integrators = *a->GetDBFI();
|
||||
|
||||
const int iSz = integrators.Size();
|
||||
|
||||
bool allPatchwise = true;
|
||||
bool somePatchwise = false;
|
||||
|
||||
for (int i = 0; i < iSz; ++i)
|
||||
{
|
||||
if (integrators[i]->Patchwise())
|
||||
{
|
||||
somePatchwise = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
allPatchwise = false;
|
||||
}
|
||||
}
|
||||
|
||||
MFEM_VERIFY(!(somePatchwise && !allPatchwise),
|
||||
"All or none of the integrators should be patchwise");
|
||||
|
||||
if (DeviceCanUseCeed() || !elem_restrict || allPatchwise)
|
||||
if (DeviceCanUseCeed() || !elem_restrict)
|
||||
{
|
||||
y.UseDevice(true); // typically this is a large vector, so store on device
|
||||
y = 0.0;
|
||||
for (int i = 0; i < iSz; ++i)
|
||||
{
|
||||
if (integrators[i]->Patchwise())
|
||||
{
|
||||
integrators[i]->AddMultNURBSPA(x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
integrators[i]->AddMultPA(x, y);
|
||||
}
|
||||
integrators[i]->AddMultPA(x, y);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (iSz)
|
||||
{
|
||||
Array<Array<int>*> &elem_markers = *a->GetDBFI_Marker();
|
||||
elem_restrict->Mult(x, localX);
|
||||
localY = 0.0;
|
||||
for (int i = 0; i < iSz; ++i)
|
||||
{
|
||||
AddMultWithMarkers(*integrators[i], localX, elem_markers[i], elem_attributes,
|
||||
false, localY);
|
||||
integrators[i]->AddMultPA(localX, localY);
|
||||
}
|
||||
elem_restrict->MultTranspose(localY, y);
|
||||
}
|
||||
@@ -545,21 +460,17 @@ void PABilinearFormExtension::Mult(const Vector &x, Vector &y) const
|
||||
const bool has_bdr_integs = (n_bdr_face_integs > 0 || n_bdr_integs > 0);
|
||||
if (bdr_face_restrict_lex && has_bdr_integs)
|
||||
{
|
||||
Array<Array<int>*> &bdr_markers = *a->GetBBFI_Marker();
|
||||
Array<Array<int>*> &bdr_face_markers = *a->GetBFBFI_Marker();
|
||||
bdr_face_restrict_lex->Mult(x, bdr_face_X);
|
||||
if (bdr_face_X.Size()>0)
|
||||
{
|
||||
bdr_face_Y = 0.0;
|
||||
for (int i = 0; i < n_bdr_integs; ++i)
|
||||
{
|
||||
AddMultWithMarkers(*bdr_integs[i], bdr_face_X, bdr_markers[i], bdr_attributes,
|
||||
false, bdr_face_Y);
|
||||
bdr_integs[i]->AddMultPA(bdr_face_X, bdr_face_Y);
|
||||
}
|
||||
for (int i = 0; i < n_bdr_face_integs; ++i)
|
||||
{
|
||||
AddMultWithMarkers(*bdr_face_integs[i], bdr_face_X, bdr_face_markers[i],
|
||||
bdr_attributes, false, bdr_face_Y);
|
||||
bdr_face_integs[i]->AddMultPA(bdr_face_X, bdr_face_Y);
|
||||
}
|
||||
bdr_face_restrict_lex->AddMultTransposeInPlace(bdr_face_Y, y);
|
||||
}
|
||||
@@ -572,13 +483,11 @@ void PABilinearFormExtension::MultTranspose(const Vector &x, Vector &y) const
|
||||
const int iSz = integrators.Size();
|
||||
if (elem_restrict)
|
||||
{
|
||||
Array<Array<int>*> &elem_markers = *a->GetDBFI_Marker();
|
||||
elem_restrict->Mult(x, localX);
|
||||
localY = 0.0;
|
||||
for (int i = 0; i < iSz; ++i)
|
||||
{
|
||||
AddMultWithMarkers(*integrators[i], localX, elem_markers[i], elem_attributes,
|
||||
true, localY);
|
||||
integrators[i]->AddMultTransposePA(localX, localY);
|
||||
}
|
||||
elem_restrict->MultTranspose(localY, y);
|
||||
}
|
||||
@@ -608,85 +517,23 @@ void PABilinearFormExtension::MultTranspose(const Vector &x, Vector &y) const
|
||||
}
|
||||
}
|
||||
|
||||
Array<BilinearFormIntegrator*> &bdr_integs = *a->GetBBFI();
|
||||
Array<BilinearFormIntegrator*> &bdr_face_integs = *a->GetBFBFI();
|
||||
const int n_bdr_integs = bdr_integs.Size();
|
||||
const int n_bdr_face_integs = bdr_face_integs.Size();
|
||||
const bool has_bdr_integs = (n_bdr_face_integs > 0 || n_bdr_integs > 0);
|
||||
if (bdr_face_restrict_lex && has_bdr_integs)
|
||||
Array<BilinearFormIntegrator*> &bdrFaceIntegrators = *a->GetBFBFI();
|
||||
const int bFISz = bdrFaceIntegrators.Size();
|
||||
if (bdr_face_restrict_lex && bFISz>0)
|
||||
{
|
||||
Array<Array<int>*> &bdr_markers = *a->GetBBFI_Marker();
|
||||
Array<Array<int>*> &bdr_face_markers = *a->GetBFBFI_Marker();
|
||||
|
||||
bdr_face_restrict_lex->Mult(x, bdr_face_X);
|
||||
if (bdr_face_X.Size() > 0)
|
||||
if (bdr_face_X.Size()>0)
|
||||
{
|
||||
bdr_face_Y = 0.0;
|
||||
for (int i = 0; i < n_bdr_integs; ++i)
|
||||
for (int i = 0; i < bFISz; ++i)
|
||||
{
|
||||
AddMultWithMarkers(*bdr_integs[i], bdr_face_X, bdr_markers[i], bdr_attributes,
|
||||
true, bdr_face_Y);
|
||||
}
|
||||
for (int i = 0; i < n_bdr_face_integs; ++i)
|
||||
{
|
||||
AddMultWithMarkers(*bdr_face_integs[i], bdr_face_X, bdr_face_markers[i],
|
||||
bdr_attributes, true, bdr_face_Y);
|
||||
bdrFaceIntegrators[i]->AddMultTransposePA(bdr_face_X, bdr_face_Y);
|
||||
}
|
||||
bdr_face_restrict_lex->AddMultTransposeInPlace(bdr_face_Y, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compute kernels for PABilinearFormExtension::AddMultWithMarkers.
|
||||
// Cannot be in member function with non-public visibility.
|
||||
static void AddWithMarkers_(
|
||||
const int ne,
|
||||
const int nd,
|
||||
const Vector &x,
|
||||
const Array<int> &markers,
|
||||
const Array<int> &attributes,
|
||||
Vector &y)
|
||||
{
|
||||
const auto d_x = Reshape(x.Read(), nd, ne);
|
||||
const auto d_m = Reshape(markers.Read(), markers.Size());
|
||||
const auto d_attr = Reshape(attributes.Read(), ne);
|
||||
auto d_y = Reshape(y.ReadWrite(), nd, ne);
|
||||
mfem::forall(ne, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
const int attr = d_attr[e];
|
||||
if (d_m[attr - 1] == 0) { return; }
|
||||
for (int i = 0; i < nd; ++i)
|
||||
{
|
||||
d_y(i, e) += d_x(i, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void PABilinearFormExtension::AddMultWithMarkers(
|
||||
const BilinearFormIntegrator &integ,
|
||||
const Vector &x,
|
||||
const Array<int> *markers,
|
||||
const Array<int> &attributes,
|
||||
const bool transpose,
|
||||
Vector &y) const
|
||||
{
|
||||
if (markers)
|
||||
{
|
||||
tmp_evec.SetSize(y.Size());
|
||||
tmp_evec = 0.0;
|
||||
if (transpose) { integ.AddMultTransposePA(x, tmp_evec); }
|
||||
else { integ.AddMultPA(x, tmp_evec); }
|
||||
const int ne = attributes.Size();
|
||||
const int nd = x.Size() / ne;
|
||||
AddWithMarkers_(ne, nd, tmp_evec, *markers, attributes, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (transpose) { integ.AddMultTransposePA(x, y); }
|
||||
else { integ.AddMultPA(x, y); }
|
||||
}
|
||||
}
|
||||
|
||||
// Data and methods for element-assembled bilinear forms
|
||||
EABilinearFormExtension::EABilinearFormExtension(BilinearForm *form)
|
||||
: PABilinearFormExtension(form),
|
||||
|
||||
@@ -68,9 +68,6 @@ class PABilinearFormExtension : public BilinearFormExtension
|
||||
{
|
||||
protected:
|
||||
const FiniteElementSpace *trial_fes, *test_fes; // Not owned
|
||||
/// Attributes of all mesh elements.
|
||||
Array<int> elem_attributes, bdr_attributes;
|
||||
mutable Vector tmp_evec; // Work array
|
||||
mutable Vector localX, localY;
|
||||
mutable Vector int_face_X, int_face_Y;
|
||||
mutable Vector bdr_face_X, bdr_face_Y;
|
||||
@@ -94,25 +91,6 @@ public:
|
||||
|
||||
protected:
|
||||
void SetupRestrictionOperators(const L2FaceValues m);
|
||||
|
||||
/// @brief Accumulate the action (or transpose) of the integrator on @a x
|
||||
/// into @a y, taking into account the (possibly null) @a markers array.
|
||||
///
|
||||
/// If @a markers is non-null, then only those elements or boundary elements
|
||||
/// whose attribute is marked in the markers array will be added to @a y.
|
||||
///
|
||||
/// @param integ The integrator (domain, boundary, or boundary face).
|
||||
/// @param x Input E-vector.
|
||||
/// @param markers Marked attributes (possibly null, meaning all attributes).
|
||||
/// @param attributes Array of element or boundary element attributes.
|
||||
/// @param transpose Compute the action or transpose of the integrator .
|
||||
/// @param y Output E-vector
|
||||
void AddMultWithMarkers(const BilinearFormIntegrator &integ,
|
||||
const Vector &x,
|
||||
const Array<int> *markers,
|
||||
const Array<int> &attributes,
|
||||
const bool transpose,
|
||||
Vector &y) const;
|
||||
};
|
||||
|
||||
/// Data and methods for element-assembled bilinear forms
|
||||
|
||||
+10
-47
@@ -26,12 +26,6 @@ void BilinearFormIntegrator::AssemblePA(const FiniteElementSpace&)
|
||||
" is not implemented for this class.");
|
||||
}
|
||||
|
||||
void BilinearFormIntegrator::AssembleNURBSPA(const FiniteElementSpace&)
|
||||
{
|
||||
mfem_error ("BilinearFormIntegrator::AssembleNURBSPA(fes)\n"
|
||||
" is not implemented for this class.");
|
||||
}
|
||||
|
||||
void BilinearFormIntegrator::AssemblePA(const FiniteElementSpace&,
|
||||
const FiniteElementSpace&)
|
||||
{
|
||||
@@ -98,13 +92,7 @@ void BilinearFormIntegrator::AssembleDiagonalPA_ADAt(const Vector &, Vector &)
|
||||
|
||||
void BilinearFormIntegrator::AddMultPA(const Vector &, Vector &) const
|
||||
{
|
||||
MFEM_ABORT("BilinearFormIntegrator:AddMultPA:(...)\n"
|
||||
" is not implemented for this class.");
|
||||
}
|
||||
|
||||
void BilinearFormIntegrator::AddMultNURBSPA(const Vector &, Vector &) const
|
||||
{
|
||||
MFEM_ABORT("BilinearFormIntegrator::AddMultNURBSPA(...)\n"
|
||||
MFEM_ABORT("BilinearFormIntegrator::MultAssembled(...)\n"
|
||||
" is not implemented for this class.");
|
||||
}
|
||||
|
||||
@@ -138,30 +126,23 @@ void BilinearFormIntegrator::AssembleDiagonalMF(Vector &)
|
||||
" is not implemented for this class.");
|
||||
}
|
||||
|
||||
void BilinearFormIntegrator::AssembleElementMatrix(
|
||||
void BilinearFormIntegrator::AssembleElementMatrix (
|
||||
const FiniteElement &el, ElementTransformation &Trans,
|
||||
DenseMatrix &elmat)
|
||||
DenseMatrix &elmat )
|
||||
{
|
||||
MFEM_ABORT("BilinearFormIntegrator::AssembleElementMatrix(...)\n"
|
||||
" is not implemented for this class.");
|
||||
}
|
||||
|
||||
void BilinearFormIntegrator::AssembleElementMatrix2(
|
||||
void BilinearFormIntegrator::AssembleElementMatrix2 (
|
||||
const FiniteElement &el1, const FiniteElement &el2,
|
||||
ElementTransformation &Trans, DenseMatrix &elmat)
|
||||
ElementTransformation &Trans, DenseMatrix &elmat )
|
||||
{
|
||||
MFEM_ABORT("BilinearFormIntegrator::AssembleElementMatrix2(...)\n"
|
||||
" is not implemented for this class.");
|
||||
}
|
||||
|
||||
void BilinearFormIntegrator::AssemblePatchMatrix(
|
||||
const int patch, const FiniteElementSpace &fes, SparseMatrix*& smat)
|
||||
{
|
||||
mfem_error ("BilinearFormIntegrator::AssemblePatchMatrix(...)\n"
|
||||
" is not implemented for this class.");
|
||||
}
|
||||
|
||||
void BilinearFormIntegrator::AssembleFaceMatrix(
|
||||
void BilinearFormIntegrator::AssembleFaceMatrix (
|
||||
const FiniteElement &el1, const FiniteElement &el2,
|
||||
FaceElementTransformations &Trans, DenseMatrix &elmat)
|
||||
{
|
||||
@@ -867,19 +848,6 @@ void DiffusionIntegrator::AssembleElementMatrix
|
||||
|
||||
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(el, el);
|
||||
|
||||
const NURBSFiniteElement *NURBSFE =
|
||||
dynamic_cast<const NURBSFiniteElement *>(&el);
|
||||
|
||||
bool deleteRule = false;
|
||||
if (NURBSFE && patchRules)
|
||||
{
|
||||
const int patch = NURBSFE->GetPatch();
|
||||
const int* ijk = NURBSFE->GetIJK();
|
||||
Array<const KnotVector*>& kv = NURBSFE->KnotVectors();
|
||||
ir = &patchRules->GetElementRule(NURBSFE->GetElement(), patch, ijk, kv,
|
||||
deleteRule);
|
||||
}
|
||||
|
||||
elmat = 0.0;
|
||||
for (int i = 0; i < ir->GetNPoints(); i++)
|
||||
{
|
||||
@@ -914,11 +882,6 @@ void DiffusionIntegrator::AssembleElementMatrix
|
||||
AddMult_a_AAt(w, dshapedxt, elmat);
|
||||
}
|
||||
}
|
||||
|
||||
if (deleteRule)
|
||||
{
|
||||
delete ir;
|
||||
}
|
||||
}
|
||||
|
||||
void DiffusionIntegrator::AssembleElementMatrix2(
|
||||
@@ -2456,7 +2419,7 @@ void VectorFEMassIntegrator::AssembleElementMatrix(
|
||||
{
|
||||
int dof = el.GetDof();
|
||||
int spaceDim = Trans.GetSpaceDim();
|
||||
int vdim = std::max(spaceDim, el.GetRangeDim());
|
||||
int vdim = std::max(spaceDim, el.GetVDim());
|
||||
|
||||
double w;
|
||||
|
||||
@@ -2524,7 +2487,7 @@ void VectorFEMassIntegrator::AssembleElementMatrix2(
|
||||
{
|
||||
// assume test_fe is scalar FE and trial_fe is vector FE
|
||||
int spaceDim = Trans.GetSpaceDim();
|
||||
int vdim = std::max(spaceDim, trial_fe.GetRangeDim());
|
||||
int vdim = std::max(spaceDim, trial_fe.GetVDim());
|
||||
int trial_dof = trial_fe.GetDof();
|
||||
int test_dof = test_fe.GetDof();
|
||||
double w;
|
||||
@@ -2622,8 +2585,8 @@ void VectorFEMassIntegrator::AssembleElementMatrix2(
|
||||
{
|
||||
// assume both test_fe and trial_fe are vector FE
|
||||
int spaceDim = Trans.GetSpaceDim();
|
||||
int trial_vdim = std::max(spaceDim, trial_fe.GetRangeDim());
|
||||
int test_vdim = std::max(spaceDim, test_fe.GetRangeDim());
|
||||
int trial_vdim = std::max(spaceDim, trial_fe.GetVDim());
|
||||
int test_vdim = std::max(spaceDim, test_fe.GetVDim());
|
||||
int trial_dof = trial_fe.GetDof();
|
||||
int test_dof = test_fe.GetDof();
|
||||
double w;
|
||||
|
||||
+23
-92
@@ -20,6 +20,17 @@
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
// Local maximum size of dofs and quads in 1D
|
||||
constexpr int HCURL_MAX_D1D = 5;
|
||||
#ifdef MFEM_USE_HIP
|
||||
constexpr int HCURL_MAX_Q1D = 5;
|
||||
#else
|
||||
constexpr int HCURL_MAX_Q1D = 6;
|
||||
#endif
|
||||
|
||||
constexpr int HDIV_MAX_D1D = 5;
|
||||
constexpr int HDIV_MAX_Q1D = 6;
|
||||
|
||||
/// Abstract base class BilinearFormIntegrator
|
||||
class BilinearFormIntegrator : public NonlinearFormIntegrator
|
||||
{
|
||||
@@ -50,11 +61,6 @@ public:
|
||||
virtual void AssemblePA(const FiniteElementSpace &trial_fes,
|
||||
const FiniteElementSpace &test_fes);
|
||||
|
||||
/// Method defining partial assembly on NURBS patches.
|
||||
/** The result of the partial assembly is stored internally so that it can be
|
||||
used later in the method AddMultNURBSPA(). */
|
||||
virtual void AssembleNURBSPA(const FiniteElementSpace &fes);
|
||||
|
||||
virtual void AssemblePABoundary(const FiniteElementSpace &fes);
|
||||
|
||||
virtual void AssemblePAInteriorFaces(const FiniteElementSpace &fes);
|
||||
@@ -76,9 +82,6 @@ public:
|
||||
called. */
|
||||
virtual void AddMultPA(const Vector &x, Vector &y) const;
|
||||
|
||||
/// Method for partially assembled action on NURBS patches.
|
||||
virtual void AddMultNURBSPA(const Vector&x, Vector&y) const;
|
||||
|
||||
/// Method for partially assembled transposed action.
|
||||
/** Perform the transpose action of integrator on the input @a x and add the
|
||||
result to the output @a y. Both @a x and @a y are E-vectors, i.e. they
|
||||
@@ -145,13 +148,6 @@ public:
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &elmat);
|
||||
|
||||
/** Given a particular NURBS patch, computes the patch matrix as a
|
||||
SparseMatrix @a smat.
|
||||
*/
|
||||
virtual void AssemblePatchMatrix(const int patch,
|
||||
const FiniteElementSpace &fes,
|
||||
SparseMatrix*& smat);
|
||||
|
||||
virtual void AssembleFaceMatrix(const FiniteElement &el1,
|
||||
const FiniteElement &el2,
|
||||
FaceElementTransformations &Trans,
|
||||
@@ -580,7 +576,7 @@ protected:
|
||||
|
||||
|
||||
inline virtual int GetTestVDim(const FiniteElement & test_fe)
|
||||
{ return std::max(space_dim, test_fe.GetRangeDim()); }
|
||||
{ return std::max(space_dim, test_fe.GetVDim()); }
|
||||
|
||||
inline virtual void CalcTestShape(const FiniteElement & test_fe,
|
||||
ElementTransformation &Trans,
|
||||
@@ -588,7 +584,7 @@ protected:
|
||||
{ test_fe.CalcVShape(Trans, shape); }
|
||||
|
||||
inline virtual int GetTrialVDim(const FiniteElement & trial_fe)
|
||||
{ return std::max(space_dim, trial_fe.GetRangeDim()); }
|
||||
{ return std::max(space_dim, trial_fe.GetVDim()); }
|
||||
|
||||
inline virtual void CalcTrialShape(const FiniteElement & trial_fe,
|
||||
ElementTransformation &Trans,
|
||||
@@ -678,7 +674,7 @@ protected:
|
||||
|
||||
|
||||
inline virtual int GetVDim(const FiniteElement & vector_fe)
|
||||
{ return std::max(space_dim, vector_fe.GetRangeDim()); }
|
||||
{ return std::max(space_dim, vector_fe.GetVDim()); }
|
||||
|
||||
inline virtual void CalcVShape(const FiniteElement & vector_fe,
|
||||
ElementTransformation &Trans,
|
||||
@@ -1105,7 +1101,7 @@ public:
|
||||
const FiniteElement & trial_fe,
|
||||
const FiniteElement & test_fe) const
|
||||
{
|
||||
return (trial_fe.GetRangeDim() == 3 &&
|
||||
return (trial_fe.GetVDim() == 3 &&
|
||||
trial_fe.GetRangeType() == mfem::FiniteElement::VECTOR &&
|
||||
test_fe.GetRangeType() == mfem::FiniteElement::SCALAR &&
|
||||
test_fe.GetDerivType() == mfem::FiniteElement::GRAD );
|
||||
@@ -1288,8 +1284,8 @@ public:
|
||||
const FiniteElement & trial_fe,
|
||||
const FiniteElement & test_fe) const
|
||||
{
|
||||
return (trial_fe.GetCurlDim() == 3 && trial_fe.GetRangeDim() == 3 &&
|
||||
test_fe.GetCurlDim() == 3 && test_fe.GetRangeDim() == 3 &&
|
||||
return (trial_fe.GetCurlDim() == 3 && trial_fe.GetVDim() == 3 &&
|
||||
test_fe.GetCurlDim() == 3 && test_fe.GetVDim() == 3 &&
|
||||
trial_fe.GetRangeType() == mfem::FiniteElement::VECTOR &&
|
||||
trial_fe.GetDerivType() == mfem::FiniteElement::CURL &&
|
||||
test_fe.GetRangeType() == mfem::FiniteElement::VECTOR &&
|
||||
@@ -1419,7 +1415,7 @@ public:
|
||||
const FiniteElement & trial_fe,
|
||||
const FiniteElement & test_fe) const
|
||||
{
|
||||
return (trial_fe.GetRangeDim() == 3 && test_fe.GetCurlDim() == 3 &&
|
||||
return (trial_fe.GetVDim() == 3 && test_fe.GetCurlDim() == 3 &&
|
||||
trial_fe.GetRangeType() == mfem::FiniteElement::VECTOR &&
|
||||
test_fe.GetRangeType() == mfem::FiniteElement::VECTOR &&
|
||||
test_fe.GetDerivType() == mfem::FiniteElement::CURL );
|
||||
@@ -1489,7 +1485,7 @@ public:
|
||||
const FiniteElement & trial_fe,
|
||||
const FiniteElement & test_fe) const
|
||||
{
|
||||
return (test_fe.GetRangeDim() == 3 &&
|
||||
return (test_fe.GetVDim() == 3 &&
|
||||
trial_fe.GetRangeType() == mfem::FiniteElement::SCALAR &&
|
||||
trial_fe.GetDerivType() == mfem::FiniteElement::GRAD &&
|
||||
test_fe.GetRangeType() == mfem::FiniteElement::VECTOR );
|
||||
@@ -1529,7 +1525,7 @@ public:
|
||||
const FiniteElement & trial_fe,
|
||||
const FiniteElement & test_fe) const
|
||||
{
|
||||
return (trial_fe.GetCurlDim() == 3 && test_fe.GetRangeDim() == 3 &&
|
||||
return (trial_fe.GetCurlDim() == 3 && test_fe.GetVDim() == 3 &&
|
||||
trial_fe.GetRangeType() == mfem::FiniteElement::VECTOR &&
|
||||
trial_fe.GetDerivType() == mfem::FiniteElement::CURL &&
|
||||
test_fe.GetRangeType() == mfem::FiniteElement::VECTOR );
|
||||
@@ -1900,7 +1896,7 @@ protected:
|
||||
const FiniteElement & trial_fe,
|
||||
const FiniteElement & test_fe) const
|
||||
{
|
||||
return (trial_fe.GetCurlDim() == 3 && test_fe.GetRangeDim() == 3 &&
|
||||
return (trial_fe.GetCurlDim() == 3 && test_fe.GetVDim() == 3 &&
|
||||
trial_fe.GetDerivType() == mfem::FiniteElement::CURL &&
|
||||
test_fe.GetRangeType() == mfem::FiniteElement::VECTOR );
|
||||
}
|
||||
@@ -1959,7 +1955,7 @@ protected:
|
||||
const FiniteElement & trial_fe,
|
||||
const FiniteElement & test_fe) const
|
||||
{
|
||||
return (trial_fe.GetRangeDim() == 3 && test_fe.GetCurlDim() == 3 &&
|
||||
return (trial_fe.GetVDim() == 3 && test_fe.GetCurlDim() == 3 &&
|
||||
trial_fe.GetRangeType() == mfem::FiniteElement::VECTOR &&
|
||||
test_fe.GetDerivType() == mfem::FiniteElement::CURL );
|
||||
}
|
||||
@@ -2115,59 +2111,6 @@ private:
|
||||
Vector pa_data;
|
||||
bool symmetric = true; ///< False if using a nonsymmetric matrix coefficient
|
||||
|
||||
// Data for NURBS patch PA
|
||||
|
||||
// Type for a variable-row-length 2D array, used for data related to 1D
|
||||
// quadrature rules in each dimension.
|
||||
typedef std::vector<std::vector<int>> IntArrayVar2D;
|
||||
|
||||
int numPatches = 0;
|
||||
static constexpr int numTypes = 2; // Number of rule types
|
||||
|
||||
// In the case integrationMode == Mode::PATCHWISE_REDUCED, an approximate
|
||||
// integration rule with sparse nonzero weights is computed by NNLSSolver,
|
||||
// for each 1D basis function on each patch, in each spatial dimension. For a
|
||||
// fixed 1D basis function b_i with DOF index i, in the tensor product basis
|
||||
// of patch p, the prescribed exact 1D rule is of the form
|
||||
// \sum_k a_{i,j,k} w_k for some integration points indexed by k, with
|
||||
// weights w_k and coefficients a_{i,j,k} depending on Q(x), an element
|
||||
// transformation, b_i, and b_j, for all 1D basis functions b_j whose support
|
||||
// overlaps that of b_i. Define the constraint matrix G = [g_{j,k}] with
|
||||
// g_{j,k} = a_{i,j,k} and the vector of exact weights w = [w_k]. A reduced
|
||||
// rule should have different weights w_r, many of them zero, and should
|
||||
// approximately satisfy Gw_r = Gw. A sparse approximate solution to this
|
||||
// underdetermined system is computed by NNLSSolver, and its data is stored
|
||||
// in the following members.
|
||||
|
||||
// For each patch p, spatial dimension d (total dim), and rule type t (total
|
||||
// numTypes), an std::vector<Vector> of reduced quadrature weights for all
|
||||
// basis functions is stored in reducedWeights[t + numTypes * (d + dim * p)],
|
||||
// reshaped as rw(t,d,p). Note that nd may vary with respect to the patch and
|
||||
// spatial dimension. Array reducedIDs is treated similarly.
|
||||
std::vector<std::vector<Vector>> reducedWeights;
|
||||
std::vector<IntArrayVar2D> reducedIDs;
|
||||
std::vector<Array<int>> pQ1D, pD1D;
|
||||
std::vector<std::vector<Array2D<double>>> pB, pG;
|
||||
std::vector<IntArrayVar2D> pminD, pmaxD, pminQ, pmaxQ, pminDD, pmaxDD;
|
||||
|
||||
std::vector<Array<const IntegrationRule*>> pir1d;
|
||||
|
||||
void SetupPatchPA(const int patch, Mesh *mesh, bool unitWeights=false);
|
||||
|
||||
void SetupPatchBasisData(Mesh *mesh, unsigned int patch);
|
||||
|
||||
/** Called by AssemblePatchMatrix for sparse matrix assembly on a NURBS patch
|
||||
with full 1D quadrature rules. */
|
||||
void AssemblePatchMatrix_fullQuadrature(const int patch,
|
||||
const FiniteElementSpace &fes,
|
||||
SparseMatrix*& smat);
|
||||
|
||||
/** Called by AssemblePatchMatrix for sparse matrix assembly on a NURBS patch
|
||||
with reduced 1D quadrature rules. */
|
||||
void AssemblePatchMatrix_reducedQuadrature(const int patch,
|
||||
const FiniteElementSpace &fes,
|
||||
SparseMatrix*& smat);
|
||||
|
||||
public:
|
||||
/// Construct a diffusion integrator with coefficient Q = 1
|
||||
DiffusionIntegrator(const IntegrationRule *ir = nullptr)
|
||||
@@ -2203,14 +2146,6 @@ public:
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &elmat);
|
||||
|
||||
virtual void AssemblePatchMatrix(const int patch,
|
||||
const FiniteElementSpace &fes,
|
||||
SparseMatrix*& smat);
|
||||
|
||||
virtual void AssembleNURBSPA(const FiniteElementSpace &fes);
|
||||
|
||||
void AssemblePatchPA(const int patch, const FiniteElementSpace &fes);
|
||||
|
||||
/// Perform the local action of the BilinearFormIntegrator
|
||||
virtual void AssembleElementVector(const FiniteElement &el,
|
||||
ElementTransformation &Tr,
|
||||
@@ -2245,10 +2180,6 @@ public:
|
||||
|
||||
virtual void AddMultTransposePA(const Vector&, Vector&) const;
|
||||
|
||||
virtual void AddMultNURBSPA(const Vector&, Vector&) const;
|
||||
|
||||
void AddMultPatchPA(const int patch, const Vector &x, Vector &y) const;
|
||||
|
||||
static const IntegrationRule &GetRule(const FiniteElement &trial_fe,
|
||||
const FiniteElement &test_fe);
|
||||
|
||||
@@ -3440,7 +3371,7 @@ private:
|
||||
void cross_product(const Vector & x, const DenseMatrix & Y, DenseMatrix & Z)
|
||||
{
|
||||
int dim = x.Size();
|
||||
MFEM_VERIFY(Y.Width() == dim, "Size mismatch");
|
||||
MFEM_VERIFY(Y.Width() == dim, "Size missmatch");
|
||||
int dimc = dim == 3 ? dim : 1;
|
||||
int h = Y.Height();
|
||||
Z.SetSize(h,dimc);
|
||||
|
||||
+6
-18
@@ -220,12 +220,12 @@ double TransformedCoefficient::Eval(ElementTransformation &T,
|
||||
{
|
||||
if (Q2)
|
||||
{
|
||||
return Transform2(Q1->Eval(T, ip, GetTime()),
|
||||
Q2->Eval(T, ip, GetTime()));
|
||||
return (*Transform2)(Q1->Eval(T, ip, GetTime()),
|
||||
Q2->Eval(T, ip, GetTime()));
|
||||
}
|
||||
else
|
||||
{
|
||||
return Transform1(Q1->Eval(T, ip, GetTime()));
|
||||
return (*Transform1)(Q1->Eval(T, ip, GetTime()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1591,21 +1591,14 @@ void VectorQuadratureFunctionCoefficient::Eval(Vector &V,
|
||||
{
|
||||
QuadF.HostRead();
|
||||
|
||||
const int el_idx = QuadF.GetSpace()->GetEntityIndex(T);
|
||||
// Handle the case of "interior boundary elements" and FaceQuadratureSpace
|
||||
// with FaceType::Boundary.
|
||||
if (el_idx < 0) { V = 0.0; return; }
|
||||
|
||||
const int ip_idx = QuadF.GetSpace()->GetPermutedIndex(el_idx, ip.index);
|
||||
|
||||
if (index == 0 && vdim == QuadF.GetVDim())
|
||||
{
|
||||
QuadF.GetValues(el_idx, ip_idx, V);
|
||||
QuadF.GetValues(T.ElementNo, ip.index, V);
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector temp;
|
||||
QuadF.GetValues(el_idx, ip_idx, temp);
|
||||
QuadF.GetValues(T.ElementNo, ip.index, temp);
|
||||
V.SetSize(vdim);
|
||||
for (int i = 0; i < vdim; i++)
|
||||
{
|
||||
@@ -1632,12 +1625,7 @@ double QuadratureFunctionCoefficient::Eval(ElementTransformation &T,
|
||||
{
|
||||
QuadF.HostRead();
|
||||
Vector temp(1);
|
||||
const int el_idx = QuadF.GetSpace()->GetEntityIndex(T);
|
||||
// Handle the case of "interior boundary elements" and FaceQuadratureSpace
|
||||
// with FaceType::Boundary.
|
||||
if (el_idx < 0) { return 0.0; }
|
||||
const int ip_idx = QuadF.GetSpace()->GetPermutedIndex(el_idx, ip.index);
|
||||
QuadF.GetValues(el_idx, ip_idx, temp);
|
||||
QuadF.GetValues(T.ElementNo, ip.index, temp);
|
||||
return temp[0];
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -422,15 +422,15 @@ class TransformedCoefficient : public Coefficient
|
||||
private:
|
||||
Coefficient * Q1;
|
||||
Coefficient * Q2;
|
||||
std::function<double(double)> Transform1;
|
||||
std::function<double(double, double)> Transform2;
|
||||
double (*Transform1)(double);
|
||||
double (*Transform2)(double,double);
|
||||
|
||||
public:
|
||||
TransformedCoefficient (Coefficient * q, std::function<double(double)> F)
|
||||
: Q1(q), Transform1(std::move(F)) { Q2 = 0; Transform2 = 0; }
|
||||
TransformedCoefficient (Coefficient * q,double (*F)(double))
|
||||
: Q1(q), Transform1(F) { Q2 = 0; Transform2 = 0; }
|
||||
TransformedCoefficient (Coefficient * q1,Coefficient * q2,
|
||||
std::function<double(double, double)> F)
|
||||
: Q1(q1), Q2(q2), Transform2(std::move(F)) { Transform1 = 0; }
|
||||
double (*F)(double,double))
|
||||
: Q1(q1), Q2(q2), Transform2(F) { Transform1 = 0; }
|
||||
|
||||
/// Set the time for internally stored coefficients
|
||||
void SetTime(double t);
|
||||
|
||||
@@ -922,7 +922,7 @@ void ParaViewDataCollection::Save()
|
||||
{
|
||||
const std::string &field_name = qfield.first;
|
||||
std::ofstream os(vtu_prefix + GenerateVTUFileName(field_name, myid));
|
||||
qfield.second->SaveVTU(os, pv_data_format, GetCompressionLevel(), field_name);
|
||||
qfield.second->SaveVTU(os, pv_data_format, GetCompressionLevel());
|
||||
}
|
||||
|
||||
// MPI rank 0 also creates a "PVTU" file that points to all of the separately
|
||||
|
||||
+6
-4
@@ -166,19 +166,21 @@ void DGMassInverse::DGMassCGIteration(const Vector &b_, Vector &u_) const
|
||||
b = b_.Read();
|
||||
}
|
||||
|
||||
static constexpr int NB = Q1D ? Q1D : 1; // block size
|
||||
constexpr int NB = Q1D ? Q1D : 1; // block size
|
||||
|
||||
mfem::forall_2D(NE, NB, NB, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr int NB = Q1D ? Q1D : 1; // redefine here for some compilers
|
||||
|
||||
// Perform change of basis if needed
|
||||
if (CHANGE_BASIS)
|
||||
{
|
||||
// Transform RHS
|
||||
DGMassBasis<DIM,D1D>(e, NE, q2d_Bt, b_orig, b2, d1d);
|
||||
DGMassBasis<DIM,D1D,MAX_D1D>(e, NE, q2d_Bt, b_orig, b2, d1d);
|
||||
if (IT_MODE)
|
||||
{
|
||||
// Transform initial guess
|
||||
DGMassBasis<DIM,D1D>(e, NE, d2q_B, u, u, d1d);
|
||||
DGMassBasis<DIM,D1D,MAX_D1D>(e, NE, d2q_B, u, u, d1d);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,7 +257,7 @@ void DGMassInverse::DGMassCGIteration(const Vector &b_, Vector &u_) const
|
||||
|
||||
if (CHANGE_BASIS)
|
||||
{
|
||||
DGMassBasis<DIM,D1D>(e, NE, q2d_B, u, u, d1d);
|
||||
DGMassBasis<DIM,D1D,MAX_D1D>(e, NE, q2d_B, u, u, d1d);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ double DGMassDot(const int e,
|
||||
return s_dot[0];
|
||||
}
|
||||
|
||||
template<int T_D1D = 0>
|
||||
template<int T_D1D = 0, int MAX_D1D = 0>
|
||||
MFEM_HOST_DEVICE inline
|
||||
void DGMassBasis2D(const int e,
|
||||
const int NE,
|
||||
@@ -181,7 +181,7 @@ void DGMassBasis2D(const int e,
|
||||
double *y_,
|
||||
const int d1d = 0)
|
||||
{
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
|
||||
const auto b = Reshape(b_, D1D, D1D);
|
||||
@@ -213,7 +213,7 @@ void DGMassBasis2D(const int e,
|
||||
MFEM_SYNC_THREAD;
|
||||
}
|
||||
|
||||
template<int T_D1D = 0>
|
||||
template<int T_D1D = 0, int MAX_D1D = 0>
|
||||
MFEM_HOST_DEVICE inline
|
||||
void DGMassBasis3D(const int e,
|
||||
const int NE,
|
||||
@@ -228,7 +228,7 @@ void DGMassBasis3D(const int e,
|
||||
const auto x = Reshape(x_, D1D, D1D, D1D, NE);
|
||||
auto y = Reshape(y_, D1D, D1D, D1D, NE);
|
||||
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
|
||||
MFEM_SHARED double sB[MD1*MD1];
|
||||
MFEM_SHARED double sm0[MD1*MD1*MD1];
|
||||
@@ -260,7 +260,7 @@ void DGMassBasis3D(const int e,
|
||||
MFEM_SYNC_THREAD;
|
||||
}
|
||||
|
||||
template<int DIM, int T_D1D = 0>
|
||||
template<int DIM, int T_D1D = 0, int MAX_D1D = 0>
|
||||
MFEM_HOST_DEVICE inline
|
||||
void DGMassBasis(const int e,
|
||||
const int NE,
|
||||
@@ -271,11 +271,11 @@ void DGMassBasis(const int e,
|
||||
{
|
||||
if (DIM == 2)
|
||||
{
|
||||
DGMassBasis2D<T_D1D>(e, NE, b_, x_, y_, d1d);
|
||||
DGMassBasis2D<T_D1D, MAX_D1D>(e, NE, b_, x_, y_, d1d);
|
||||
}
|
||||
else if (DIM == 3)
|
||||
{
|
||||
DGMassBasis3D<T_D1D>(e, NE, b_, x_, y_, d1d);
|
||||
DGMassBasis3D<T_D1D, MAX_D1D>(e, NE, b_, x_, y_, d1d);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+1
-1
@@ -125,7 +125,7 @@ public:
|
||||
DofTransformation objects are provided by the FiniteElementSpace which has
|
||||
access to the mesh and can therefore provide the face orientations. This is
|
||||
convenient when working with GridFunction, LinearForm, or BilinearForm
|
||||
objects or their parallel counterparts.
|
||||
obejcts or their parallel counterparts.
|
||||
|
||||
StatelessDofTransformation objects are provided by FiniteElement or
|
||||
FiniteElementCollection objects which do not have access to face
|
||||
|
||||
@@ -492,7 +492,6 @@ int IsoparametricTransformation::OrderGrad(const FiniteElement *fe) const
|
||||
void IsoparametricTransformation::Transform (const IntegrationPoint &ip,
|
||||
Vector &trans)
|
||||
{
|
||||
MFEM_ASSERT(FElem != nullptr, "Must provide a valid FiniteElement object!");
|
||||
shape.SetSize(FElem->GetDof());
|
||||
trans.SetSize(PointMat.Height());
|
||||
|
||||
|
||||
+1
-1
@@ -807,7 +807,7 @@ void NodalFiniteElement::Project(
|
||||
else
|
||||
{
|
||||
DenseMatrix vshape(fe.GetDof(), std::max(Trans.GetSpaceDim(),
|
||||
fe.GetRangeDim()));
|
||||
fe.GetVDim()));
|
||||
|
||||
I.SetSize(vshape.Width()*dof, fe.GetDof());
|
||||
for (int k = 0; k < dof; k++)
|
||||
|
||||
+6
-7
@@ -307,20 +307,19 @@ public:
|
||||
FiniteElement(int D, Geometry::Type G, int Do, int O,
|
||||
int F = FunctionSpace::Pk);
|
||||
|
||||
/// Returns the reference space dimension for the finite element.
|
||||
/// Returns the reference space dimension for the finite element
|
||||
int GetDim() const { return dim; }
|
||||
|
||||
/** @brief Returns the vector dimension for vector-valued finite elements,
|
||||
which is also the dimension of the interpolation operatrion. */
|
||||
int GetRangeDim() const { return vdim; }
|
||||
/// Returns the vector dimension for vector-valued finite elements
|
||||
int GetVDim() const { return vdim; }
|
||||
|
||||
/// Returns the dimension of the curl for vector-valued finite elements.
|
||||
/// Returns the dimension of the curl for vector-valued finite elements
|
||||
int GetCurlDim() const { return cdim; }
|
||||
|
||||
/// Returns the Geometry::Type of the reference element.
|
||||
/// Returns the Geometry::Type of the reference element
|
||||
Geometry::Type GetGeomType() const { return geom_type; }
|
||||
|
||||
/// Returns the number of degrees of freedom in the finite element.
|
||||
/// Returns the number of degrees of freedom in the finite element
|
||||
int GetDof() const { return dof; }
|
||||
|
||||
/** @brief Returns the order of the finite element. In the case of
|
||||
|
||||
+2
-2
@@ -1852,7 +1852,7 @@ void ND_R1D_SegmentElement::Project(const FiniteElement &fe,
|
||||
else
|
||||
{
|
||||
double vk[Geometry::MaxDim];
|
||||
DenseMatrix vshape(fe.GetDof(), fe.GetRangeDim());
|
||||
DenseMatrix vshape(fe.GetDof(), fe.GetVDim());
|
||||
|
||||
double * tk_ptr = const_cast<double*>(tk);
|
||||
|
||||
@@ -2293,7 +2293,7 @@ void ND_R2D_FiniteElement::Project(const FiniteElement &fe,
|
||||
else
|
||||
{
|
||||
double vk[Geometry::MaxDim];
|
||||
DenseMatrix vshape(fe.GetDof(), fe.GetRangeDim());
|
||||
DenseMatrix vshape(fe.GetDof(), fe.GetVDim());
|
||||
|
||||
double * tk_ptr = const_cast<double*>(tk);
|
||||
|
||||
|
||||
@@ -56,10 +56,6 @@ public:
|
||||
Vector &Weights () const { return weights; }
|
||||
/// Update the NURBSFiniteElement according to the currently set knot vectors
|
||||
virtual void SetOrder () const { }
|
||||
|
||||
/// Returns the indices (i,j) in 2D or (i,j,k) in 3D of this element in the
|
||||
/// tensor product ordering of the patch.
|
||||
const int* GetIJK() const { return ijk; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
+4
-4
@@ -1486,7 +1486,7 @@ void RT_R1D_SegmentElement::Project(const FiniteElement &fe,
|
||||
else
|
||||
{
|
||||
double vk[Geometry::MaxDim];
|
||||
DenseMatrix vshape(fe.GetDof(), fe.GetRangeDim());
|
||||
DenseMatrix vshape(fe.GetDof(), fe.GetVDim());
|
||||
|
||||
double * nk_ptr = const_cast<double*>(nk);
|
||||
|
||||
@@ -1523,7 +1523,7 @@ void RT_R1D_SegmentElement::ProjectCurl(const FiniteElement &fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &curl) const
|
||||
{
|
||||
DenseMatrix curl_shape(fe.GetDof(), fe.GetRangeDim());
|
||||
DenseMatrix curl_shape(fe.GetDof(), fe.GetVDim());
|
||||
Vector curl_k(fe.GetDof());
|
||||
|
||||
double * nk_ptr = const_cast<double*>(nk);
|
||||
@@ -1849,7 +1849,7 @@ void RT_R2D_FiniteElement::Project(const FiniteElement &fe,
|
||||
else
|
||||
{
|
||||
double vk[Geometry::MaxDim];
|
||||
DenseMatrix vshape(fe.GetDof(), fe.GetRangeDim());
|
||||
DenseMatrix vshape(fe.GetDof(), fe.GetVDim());
|
||||
|
||||
double * nk_ptr = const_cast<double*>(nk);
|
||||
|
||||
@@ -1888,7 +1888,7 @@ void RT_R2D_FiniteElement::ProjectCurl(const FiniteElement &fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &curl) const
|
||||
{
|
||||
DenseMatrix curl_shape(fe.GetDof(), fe.GetRangeDim());
|
||||
DenseMatrix curl_shape(fe.GetDof(), fe.GetVDim());
|
||||
Vector curl_k(fe.GetDof());
|
||||
|
||||
double * nk_ptr = const_cast<double*>(nk);
|
||||
|
||||
+17
-27
@@ -87,16 +87,6 @@ int FiniteElementCollection::GetDerivMapType(int dim) const
|
||||
return FiniteElement::UNKNOWN_MAP_TYPE;
|
||||
}
|
||||
|
||||
int FiniteElementCollection::GetRangeDim(int dim) const
|
||||
{
|
||||
const FiniteElement *fe = FiniteElementForDim(dim);
|
||||
if (fe)
|
||||
{
|
||||
return fe->GetRangeDim();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FiniteElementCollection::HasFaceDofs(Geometry::Type geom, int p) const
|
||||
{
|
||||
switch (geom)
|
||||
@@ -1723,7 +1713,7 @@ H1_FECollection::H1_FECollection(const int p, const int dim, const int btype)
|
||||
H1_Elements[Geometry::SEGMENT] = new H1_SegmentElement(p, btype);
|
||||
}
|
||||
|
||||
SegDofOrd[0] = (pm1 > 0) ? new int[2*pm1] : nullptr;
|
||||
SegDofOrd[0] = new int[2*pm1];
|
||||
SegDofOrd[1] = SegDofOrd[0] + pm1;
|
||||
for (int i = 0; i < pm1; i++)
|
||||
{
|
||||
@@ -1761,7 +1751,7 @@ H1_FECollection::H1_FECollection(const int p, const int dim, const int btype)
|
||||
|
||||
const int &TriDof = H1_dof[Geometry::TRIANGLE];
|
||||
const int &QuadDof = H1_dof[Geometry::SQUARE];
|
||||
TriDofOrd[0] = (TriDof > 0) ? new int[6*TriDof] : nullptr;
|
||||
TriDofOrd[0] = new int[6*TriDof];
|
||||
for (int i = 1; i < 6; i++)
|
||||
{
|
||||
TriDofOrd[i] = TriDofOrd[i-1] + TriDof;
|
||||
@@ -1782,7 +1772,7 @@ H1_FECollection::H1_FECollection(const int p, const int dim, const int btype)
|
||||
}
|
||||
}
|
||||
|
||||
QuadDofOrd[0] = (QuadDof > 0) ? new int[8*QuadDof] : nullptr;
|
||||
QuadDofOrd[0] = new int[8*QuadDof];
|
||||
for (int i = 1; i < 8; i++)
|
||||
{
|
||||
QuadDofOrd[i] = QuadDofOrd[i-1] + QuadDof;
|
||||
@@ -1865,7 +1855,7 @@ H1_FECollection::H1_FECollection(const int p, const int dim, const int btype)
|
||||
H1_Elements[Geometry::PYRAMID] = new LinearPyramidFiniteElement;
|
||||
|
||||
const int &TetDof = H1_dof[Geometry::TETRAHEDRON];
|
||||
TetDofOrd[0] = (TetDof > 0) ? new int[24*TetDof] : nullptr;
|
||||
TetDofOrd[0] = new int[24*TetDof];
|
||||
for (int i = 1; i < 24; i++)
|
||||
{
|
||||
TetDofOrd[i] = TetDofOrd[i-1] + TetDof;
|
||||
@@ -2137,7 +2127,7 @@ L2_FECollection::L2_FECollection(const int p, const int dim, const int btype,
|
||||
// No need to set the map_type for Tr_Elements.
|
||||
|
||||
const int pp1 = p + 1;
|
||||
SegDofOrd[0] = (pp1 > 0) ? new int[2*pp1] : nullptr;
|
||||
SegDofOrd[0] = new int[2*pp1];
|
||||
SegDofOrd[1] = SegDofOrd[0] + pp1;
|
||||
for (int i = 0; i <= p; i++)
|
||||
{
|
||||
@@ -2170,7 +2160,7 @@ L2_FECollection::L2_FECollection(const int p, const int dim, const int btype,
|
||||
}
|
||||
|
||||
const int TriDof = L2_Elements[Geometry::TRIANGLE]->GetDof();
|
||||
TriDofOrd[0] = (TriDof > 0) ? new int[6*TriDof] : nullptr;
|
||||
TriDofOrd[0] = new int[6*TriDof];
|
||||
for (int i = 1; i < 6; i++)
|
||||
{
|
||||
TriDofOrd[i] = TriDofOrd[i-1] + TriDof;
|
||||
@@ -2191,7 +2181,7 @@ L2_FECollection::L2_FECollection(const int p, const int dim, const int btype,
|
||||
}
|
||||
}
|
||||
const int QuadDof = L2_Elements[Geometry::SQUARE]->GetDof();
|
||||
OtherDofOrd = (QuadDof > 0) ? new int[QuadDof] : nullptr;
|
||||
OtherDofOrd = new int[QuadDof];
|
||||
for (int j = 0; j < QuadDof; j++)
|
||||
{
|
||||
OtherDofOrd[j] = j; // for Or == 0
|
||||
@@ -2235,7 +2225,7 @@ L2_FECollection::L2_FECollection(const int p, const int dim, const int btype,
|
||||
const int PriDof = L2_Elements[Geometry::PRISM]->GetDof();
|
||||
const int MaxDof = std::max(TetDof, std::max(PriDof, HexDof));
|
||||
|
||||
TetDofOrd[0] = (TetDof > 0) ? new int[24*TetDof] : nullptr;
|
||||
TetDofOrd[0] = new int[24*TetDof];
|
||||
for (int i = 1; i < 24; i++)
|
||||
{
|
||||
TetDofOrd[i] = TetDofOrd[i-1] + TetDof;
|
||||
@@ -2324,7 +2314,7 @@ L2_FECollection::L2_FECollection(const int p, const int dim, const int btype,
|
||||
}
|
||||
}
|
||||
}
|
||||
OtherDofOrd = (MaxDof > 0) ? new int[MaxDof] : nullptr;
|
||||
OtherDofOrd = new int[MaxDof];
|
||||
for (int j = 0; j < MaxDof; j++)
|
||||
{
|
||||
OtherDofOrd[j] = j; // for Or == 0
|
||||
@@ -2512,7 +2502,7 @@ void RT_FECollection::InitFaces(const int p, const int dim_,
|
||||
RT_Elements[Geometry::SEGMENT] = l2_seg;
|
||||
RT_dof[Geometry::SEGMENT] = pp1;
|
||||
|
||||
SegDofOrd[0] = (pp1 > 0) ? new int[2*pp1] : nullptr;
|
||||
SegDofOrd[0] = new int[2*pp1];
|
||||
SegDofOrd[1] = SegDofOrd[0] + pp1;
|
||||
for (int i = 0; i <= p; i++)
|
||||
{
|
||||
@@ -2533,7 +2523,7 @@ void RT_FECollection::InitFaces(const int p, const int dim_,
|
||||
RT_dof[Geometry::SQUARE] = pp1*pp1;
|
||||
|
||||
int TriDof = RT_dof[Geometry::TRIANGLE];
|
||||
TriDofOrd[0] = (TriDof > 0) ? new int[6*TriDof] : nullptr;
|
||||
TriDofOrd[0] = new int[6*TriDof];
|
||||
for (int i = 1; i < 6; i++)
|
||||
{
|
||||
TriDofOrd[i] = TriDofOrd[i-1] + TriDof;
|
||||
@@ -2563,7 +2553,7 @@ void RT_FECollection::InitFaces(const int p, const int dim_,
|
||||
}
|
||||
|
||||
int QuadDof = RT_dof[Geometry::SQUARE];
|
||||
QuadDofOrd[0] = (QuadDof > 0) ? new int[8*QuadDof] : nullptr;
|
||||
QuadDofOrd[0] = new int[8*QuadDof];
|
||||
for (int i = 1; i < 8; i++)
|
||||
{
|
||||
QuadDofOrd[i] = QuadDofOrd[i-1] + QuadDof;
|
||||
@@ -2759,7 +2749,7 @@ ND_FECollection::ND_FECollection(const int p, const int dim,
|
||||
ND_Elements[Geometry::SEGMENT] = new ND_SegmentElement(p, ob_type);
|
||||
ND_dof[Geometry::SEGMENT] = p;
|
||||
|
||||
SegDofOrd[0] = (p > 0) ? new int[2*p] : nullptr;
|
||||
SegDofOrd[0] = new int[2*p];
|
||||
SegDofOrd[1] = SegDofOrd[0] + p;
|
||||
for (int i = 0; i < p; i++)
|
||||
{
|
||||
@@ -2779,7 +2769,7 @@ ND_FECollection::ND_FECollection(const int p, const int dim,
|
||||
ND_dof[Geometry::TRIANGLE] = p*pm1;
|
||||
|
||||
int QuadDof = ND_dof[Geometry::SQUARE];
|
||||
QuadDofOrd[0] = (QuadDof > 0) ? new int[8*QuadDof] : nullptr;
|
||||
QuadDofOrd[0] = new int[8*QuadDof];
|
||||
for (int i = 1; i < 8; i++)
|
||||
{
|
||||
QuadDofOrd[i] = QuadDofOrd[i-1] + QuadDof;
|
||||
@@ -2823,7 +2813,7 @@ ND_FECollection::ND_FECollection(const int p, const int dim,
|
||||
}
|
||||
|
||||
int TriDof = ND_dof[Geometry::TRIANGLE];
|
||||
TriDofOrd[0] = (TriDof > 0) ? new int[6*TriDof] : nullptr;
|
||||
TriDofOrd[0] = new int[6*TriDof];
|
||||
for (int i = 1; i < 6; i++)
|
||||
{
|
||||
TriDofOrd[i] = TriDofOrd[i-1] + TriDof;
|
||||
@@ -3173,7 +3163,7 @@ ND_R2D_FECollection::ND_R2D_FECollection(const int p, const int dim,
|
||||
ob_type);
|
||||
ND_dof[Geometry::SEGMENT] = 2 * p - 1;
|
||||
|
||||
SegDofOrd[0] = (4*p > 2) ? new int[4 * p - 2] : nullptr;
|
||||
SegDofOrd[0] = new int[4 * p - 2];
|
||||
SegDofOrd[1] = SegDofOrd[0] + 2 * p - 1;
|
||||
for (int i = 0; i < p; i++)
|
||||
{
|
||||
@@ -3357,7 +3347,7 @@ void RT_R2D_FECollection::InitFaces(const int p, const int dim,
|
||||
RT_Elements[Geometry::SEGMENT] = l2_seg;
|
||||
RT_dof[Geometry::SEGMENT] = pp1;
|
||||
|
||||
SegDofOrd[0] = (pp1 > 0) ? new int[2*pp1] : nullptr;
|
||||
SegDofOrd[0] = new int[2*pp1];
|
||||
SegDofOrd[1] = SegDofOrd[0] + pp1;
|
||||
for (int i = 0; i <= p; i++)
|
||||
{
|
||||
|
||||
+292
-346
File diff suppressed because it is too large
Load Diff
@@ -26,7 +26,6 @@
|
||||
#include "bilininteg.hpp"
|
||||
#include "fespace.hpp"
|
||||
#include "gridfunc.hpp"
|
||||
#include "kdtree.hpp"
|
||||
#include "linearform.hpp"
|
||||
#include "nonlinearform.hpp"
|
||||
#include "bilinearform.hpp"
|
||||
|
||||
+28
-80
@@ -64,7 +64,7 @@ FiniteElementSpace::FiniteElementSpace()
|
||||
face_dof(NULL),
|
||||
NURBSext(NULL), own_ext(false),
|
||||
DoFTrans(0), VDoFTrans(vdim, ordering),
|
||||
cP_is_set(false),
|
||||
cP(NULL), cR(NULL), cR_hp(NULL), cP_is_set(false),
|
||||
Th(Operator::ANY_TYPE),
|
||||
sequence(0), mesh_sequence(0), orders_changed(false), relaxed_hp(false)
|
||||
{ }
|
||||
@@ -123,24 +123,24 @@ void FiniteElementSpace::CopyProlongationAndRestriction(
|
||||
|
||||
if (fes.GetConformingProlongation() != NULL)
|
||||
{
|
||||
if (perm) { cP.reset(Mult(*perm_mat, *fes.GetConformingProlongation())); }
|
||||
else { cP.reset(new SparseMatrix(*fes.GetConformingProlongation())); }
|
||||
if (perm) { cP = Mult(*perm_mat, *fes.GetConformingProlongation()); }
|
||||
else { cP = new SparseMatrix(*fes.GetConformingProlongation()); }
|
||||
cP_is_set = true;
|
||||
}
|
||||
else if (perm != NULL)
|
||||
{
|
||||
cP.reset(perm_mat);
|
||||
cP = perm_mat;
|
||||
cP_is_set = true;
|
||||
perm_mat = NULL;
|
||||
}
|
||||
if (fes.GetConformingRestriction() != NULL)
|
||||
{
|
||||
if (perm) { cR.reset(Mult(*fes.GetConformingRestriction(), *perm_mat_tr)); }
|
||||
else { cR.reset(new SparseMatrix(*fes.GetConformingRestriction())); }
|
||||
if (perm) { cR = Mult(*fes.GetConformingRestriction(), *perm_mat_tr); }
|
||||
else { cR = new SparseMatrix(*fes.GetConformingRestriction()); }
|
||||
}
|
||||
else if (perm != NULL)
|
||||
{
|
||||
cR.reset(perm_mat_tr);
|
||||
cR = perm_mat_tr;
|
||||
perm_mat_tr = NULL;
|
||||
}
|
||||
|
||||
@@ -309,12 +309,6 @@ FiniteElementSpace::GetBdrElementVDofs(int i, Array<int> &vdofs) const
|
||||
}
|
||||
}
|
||||
|
||||
void FiniteElementSpace::GetPatchVDofs(int i, Array<int> &vdofs) const
|
||||
{
|
||||
GetPatchDofs(i, vdofs);
|
||||
DofsToVDofs(vdofs);
|
||||
}
|
||||
|
||||
void FiniteElementSpace::GetFaceVDofs(int i, Array<int> &vdofs) const
|
||||
{
|
||||
GetFaceDofs(i, vdofs);
|
||||
@@ -960,10 +954,7 @@ void FiniteElementSpace::BuildConformingInterpolation() const
|
||||
|
||||
if (FEColl()->GetContType() == FiniteElementCollection::DISCONTINUOUS)
|
||||
{
|
||||
cP.reset();
|
||||
cR.reset();
|
||||
cR_hp.reset();
|
||||
R_transpose.reset();
|
||||
cP = cR = cR_hp = NULL; // will be treated as identities
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1117,15 +1108,12 @@ void FiniteElementSpace::BuildConformingInterpolation() const
|
||||
// if all dofs are true dofs leave cP and cR NULL
|
||||
if (n_true_dofs == ndofs)
|
||||
{
|
||||
cP.reset();
|
||||
cR.reset();
|
||||
cR_hp.reset();
|
||||
R_transpose.reset();
|
||||
cP = cR = cR_hp = NULL; // will be treated as identities
|
||||
return;
|
||||
}
|
||||
|
||||
// create the conforming prolongation matrix cP
|
||||
cP.reset(new SparseMatrix(ndofs, n_true_dofs));
|
||||
cP = new SparseMatrix(ndofs, n_true_dofs);
|
||||
|
||||
// create the conforming restriction matrix cR
|
||||
int *cR_J;
|
||||
@@ -1139,19 +1127,12 @@ void FiniteElementSpace::BuildConformingInterpolation() const
|
||||
cR_A[i] = 1.0;
|
||||
}
|
||||
cR_I[n_true_dofs] = n_true_dofs;
|
||||
cR.reset(new SparseMatrix(cR_I, cR_J, cR_A, n_true_dofs, ndofs));
|
||||
cR = new SparseMatrix(cR_I, cR_J, cR_A, n_true_dofs, ndofs);
|
||||
}
|
||||
|
||||
// In var. order spaces, create the restriction matrix cR_hp which is similar
|
||||
// to cR, but has interpolation in the extra master edge/face DOFs.
|
||||
if (IsVariableOrder())
|
||||
{
|
||||
cR_hp.reset(new SparseMatrix(n_true_dofs, ndofs));
|
||||
}
|
||||
else
|
||||
{
|
||||
cR_hp.reset();
|
||||
}
|
||||
cR_hp = IsVariableOrder() ? new SparseMatrix(n_true_dofs, ndofs) : NULL;
|
||||
|
||||
Array<bool> finalized(ndofs);
|
||||
finalized = false;
|
||||
@@ -1269,28 +1250,21 @@ const SparseMatrix* FiniteElementSpace::GetConformingProlongation() const
|
||||
{
|
||||
if (Conforming()) { return NULL; }
|
||||
if (!cP_is_set) { BuildConformingInterpolation(); }
|
||||
return cP.get();
|
||||
return cP;
|
||||
}
|
||||
|
||||
const SparseMatrix* FiniteElementSpace::GetConformingRestriction() const
|
||||
{
|
||||
if (Conforming()) { return NULL; }
|
||||
if (!cP_is_set) { BuildConformingInterpolation(); }
|
||||
if (cR && !R_transpose) { R_transpose.reset(new TransposeOperator(*cR)); }
|
||||
return cR.get();
|
||||
return cR;
|
||||
}
|
||||
|
||||
const SparseMatrix* FiniteElementSpace::GetHpConformingRestriction() const
|
||||
{
|
||||
if (Conforming()) { return NULL; }
|
||||
if (!cP_is_set) { BuildConformingInterpolation(); }
|
||||
return IsVariableOrder() ? cR_hp.get() : cR.get();
|
||||
}
|
||||
|
||||
const Operator *FiniteElementSpace::GetRestrictionTransposeOperator() const
|
||||
{
|
||||
GetRestrictionOperator(); // Ensure that R_transpose is built
|
||||
return R_transpose.get();
|
||||
return IsVariableOrder() ? cR_hp : cR;
|
||||
}
|
||||
|
||||
int FiniteElementSpace::GetNConformingDofs() const
|
||||
@@ -2221,10 +2195,7 @@ void FiniteElementSpace::Constructor(Mesh *mesh_, NURBSExtension *NURBSext_,
|
||||
own_ext = 1;
|
||||
}
|
||||
UpdateNURBS();
|
||||
cP.reset();
|
||||
cR.reset();
|
||||
cR_hp.reset();
|
||||
R_transpose.reset();
|
||||
cP = cR = cR_hp = NULL;
|
||||
cP_is_set = false;
|
||||
|
||||
ConstructDoFTrans();
|
||||
@@ -2386,7 +2357,6 @@ void FiniteElementSpace::Construct()
|
||||
cR = NULL;
|
||||
cR_hp = NULL;
|
||||
cP_is_set = false;
|
||||
R_transpose = NULL;
|
||||
// 'Th' is initialized/destroyed before this method is called.
|
||||
|
||||
int dim = mesh->Dimension();
|
||||
@@ -2428,7 +2398,6 @@ void FiniteElementSpace::Construct()
|
||||
{
|
||||
// the simple case: all edges are of the same order
|
||||
nedofs = mesh->GetNEdges() * fec->GetNumDof(Geometry::SEGMENT, order);
|
||||
var_edge_dofs.Clear(); // ensure any old var_edge_dof table is dumped.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2447,7 +2416,6 @@ void FiniteElementSpace::Construct()
|
||||
// the simple case: all faces are of the same geometry and order
|
||||
uni_fdof = fec->GetNumDof(mesh->GetFaceGeometry(0), order);
|
||||
nfdofs = mesh->GetNFaces() * uni_fdof;
|
||||
var_face_dofs.Clear(); // ensure any old var_face_dof table is dumped.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2658,6 +2626,7 @@ int FiniteElementSpace::MakeDofTable(int ent_dim,
|
||||
int dofs = fec->GetNumDof(geom, order);
|
||||
list.Append(Connection(i, total_dofs));
|
||||
total_dofs += dofs;
|
||||
|
||||
if (var_ent_order) { var_ent_order->Append(order); }
|
||||
}
|
||||
}
|
||||
@@ -2668,6 +2637,7 @@ int FiniteElementSpace::MakeDofTable(int ent_dim,
|
||||
|
||||
// build the table
|
||||
entity_dofs.MakeFromList(num_ent+1, list);
|
||||
|
||||
return total_dofs;
|
||||
}
|
||||
|
||||
@@ -2831,24 +2801,11 @@ FiniteElementSpace::GetElementDofs(int elem, Array<int> &dofs) const
|
||||
return DoFTrans[mesh->GetElementBaseGeometry(elem)];
|
||||
}
|
||||
|
||||
void FiniteElementSpace::GetPatchDofs(int patch, Array<int> &dofs) const
|
||||
{
|
||||
MFEM_ASSERT(NURBSext,
|
||||
"FiniteElementSpace::GetPatchDofs needs a NURBSExtension");
|
||||
NURBSext->GetPatchDofs(patch, dofs);
|
||||
}
|
||||
|
||||
const FiniteElement *FiniteElementSpace::GetFE(int i) const
|
||||
{
|
||||
if (i < 0 || i >= mesh->GetNE())
|
||||
{
|
||||
if (mesh->GetNE() == 0)
|
||||
{
|
||||
MFEM_ABORT("Empty MPI partitions are not permitted!");
|
||||
}
|
||||
MFEM_ABORT("Invalid element id:" << i << "; minimum allowed:" << 0 <<
|
||||
", maximum allowed:" << mesh->GetNE()-1);
|
||||
}
|
||||
if (i < 0 || !mesh->GetNE()) { return NULL; }
|
||||
MFEM_VERIFY(i < mesh->GetNE(),
|
||||
"Invalid element id " << i << ", maximum allowed " << mesh->GetNE()-1);
|
||||
|
||||
const FiniteElement *FE =
|
||||
fec->GetFE(mesh->GetElementGeometry(i), GetElementOrderImpl(i));
|
||||
@@ -2996,14 +2953,7 @@ int FiniteElementSpace::GetFaceDofs(int face, Array<int> &dofs,
|
||||
|
||||
order = !IsVariableOrder() ? fec->GetOrder() :
|
||||
var_face_orders[var_face_dofs.GetI()[face] + variant];
|
||||
MFEM_ASSERT(fec->GetNumDof(fgeom, order) == nf, [&]()
|
||||
{
|
||||
std::stringstream msg;
|
||||
msg << "fec->GetNumDof(" << (fgeom == Geometry::SQUARE ? "square" : "triangle")
|
||||
<< ", " << order << ") = " << fec->GetNumDof(fgeom, order) << " nf " << nf;
|
||||
msg << " face " << face << " variant " << variant << std::endl;
|
||||
return msg.str();
|
||||
}());
|
||||
MFEM_ASSERT(fec->GetNumDof(fgeom, order) == nf, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3255,10 +3205,9 @@ FiniteElementSpace::~FiniteElementSpace()
|
||||
|
||||
void FiniteElementSpace::Destroy()
|
||||
{
|
||||
R_transpose.reset();
|
||||
cR.reset();
|
||||
cR_hp.reset();
|
||||
cP.reset();
|
||||
delete cR;
|
||||
delete cR_hp;
|
||||
delete cP;
|
||||
Th.Clear();
|
||||
L2E_nat.Clear();
|
||||
L2E_lex.Clear();
|
||||
@@ -3271,7 +3220,6 @@ void FiniteElementSpace::Destroy()
|
||||
{
|
||||
delete x.second;
|
||||
}
|
||||
L2F.clear();
|
||||
for (int i = 0; i < E2IFQ_array.Size(); i++)
|
||||
{
|
||||
delete E2IFQ_array[i];
|
||||
@@ -3371,14 +3319,14 @@ void FiniteElementSpace::GetTrueTransferOperator(
|
||||
switch (RP_case)
|
||||
{
|
||||
case 1:
|
||||
T.Reset(new ProductOperator(cR.get(), T.Ptr(), false, owner));
|
||||
T.Reset(new ProductOperator(cR, T.Ptr(), false, owner));
|
||||
break;
|
||||
case 2:
|
||||
T.Reset(new ProductOperator(T.Ptr(), coarse_P, owner, false));
|
||||
break;
|
||||
case 3:
|
||||
T.Reset(new TripleProductOperator(
|
||||
cR.get(), T.Ptr(), coarse_P, false, owner, false));
|
||||
cR, T.Ptr(), coarse_P, false, owner, false));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -3496,7 +3444,7 @@ void FiniteElementSpace::Update(bool want_transform)
|
||||
if (cP && cR)
|
||||
{
|
||||
Th.SetOperatorOwner(false);
|
||||
Th.Reset(new TripleProductOperator(cP.get(), cR.get(), Th.Ptr(),
|
||||
Th.Reset(new TripleProductOperator(cP, cR, Th.Ptr(),
|
||||
false, false, true));
|
||||
}
|
||||
break;
|
||||
|
||||
+11
-30
@@ -214,7 +214,7 @@ class FaceQuadratureInterpolator;
|
||||
@par
|
||||
Clearly the notion of a @b vdof is relevant in each of the three contexts
|
||||
mentioned above so extra care must be taken whenever @b vdim != 1 to ensure
|
||||
that the @b edof, @b ldof, or @b tdof is being interpreted correctly.
|
||||
that the @b edof, @b ldof, or @b tdof is being interpretted correctly.
|
||||
*/
|
||||
class FiniteElementSpace
|
||||
{
|
||||
@@ -277,14 +277,12 @@ protected:
|
||||
/** Matrix representing the prolongation from the global conforming dofs to
|
||||
a set of intermediate partially conforming dofs, e.g. the dofs associated
|
||||
with a "cut" space on a non-conforming mesh. */
|
||||
mutable std::unique_ptr<SparseMatrix> cP;
|
||||
mutable SparseMatrix *cP; // owned
|
||||
/// Conforming restriction matrix such that cR.cP=I.
|
||||
mutable std::unique_ptr<SparseMatrix> cR;
|
||||
mutable SparseMatrix *cR; // owned
|
||||
/// A version of the conforming restriction matrix for variable-order spaces.
|
||||
mutable std::unique_ptr<SparseMatrix> cR_hp;
|
||||
mutable SparseMatrix *cR_hp; // owned
|
||||
mutable bool cP_is_set;
|
||||
/// Operator computing the action of the transpose of the restriction.
|
||||
mutable std::unique_ptr<Operator> R_transpose;
|
||||
|
||||
/// Transformation to apply to GridFunctions after space Update().
|
||||
OperatorHandle Th;
|
||||
@@ -594,17 +592,10 @@ public:
|
||||
{ return GetConformingProlongation(); }
|
||||
|
||||
/// Return an operator that performs the transpose of GetRestrictionOperator
|
||||
/** The returned operator is owned by the FiniteElementSpace.
|
||||
|
||||
For a serial conforming space, this returns NULL, indicating the identity
|
||||
operator.
|
||||
|
||||
For a parallel conforming space, this will return a matrix-free
|
||||
(Device)ConformingProlongationOperator.
|
||||
|
||||
For a non-conforming mesh this will return a TransposeOperator wrapping
|
||||
the restriction matrix. */
|
||||
const Operator *GetRestrictionTransposeOperator() const;
|
||||
/** The returned operator is owned by the FiniteElementSpace. In serial this
|
||||
is the same as GetProlongationMatrix() */
|
||||
virtual const Operator *GetRestrictionTransposeOperator() const
|
||||
{ return GetConformingProlongation(); }
|
||||
|
||||
/// An abstract operator that performs the same action as GetRestrictionMatrix
|
||||
/** In some cases this is an optimized matrix-free implementation. The
|
||||
@@ -820,11 +811,6 @@ public:
|
||||
virtual DofTransformation *GetBdrElementDofs(int bel,
|
||||
Array<int> &dofs) const;
|
||||
|
||||
/** @brief Returns indices of degrees of freedom for NURBS patch index
|
||||
@a patch. Cartesian ordering is used, for the tensor-product degrees of
|
||||
freedom. */
|
||||
void GetPatchDofs(int patch, Array<int> &dofs) const;
|
||||
|
||||
/// @brief Returns the indices of the degrees of freedom for the specified
|
||||
/// face, including the DOFs for the edges and the vertices of the face.
|
||||
///
|
||||
@@ -907,7 +893,7 @@ public:
|
||||
/// changed in the forward mappings by passing a value for @a ndofs which
|
||||
/// differs from that returned by GetNDofs().
|
||||
///
|
||||
/// @note These methods, with the exception of VDofToDof(), are designed to
|
||||
/// @note Thse methods, with the exception of VDofToDof(), are designed to
|
||||
/// produce the correctly encoded values when dof entries are negative,
|
||||
/// see @ref ldof for more on negative dof indices.
|
||||
///
|
||||
@@ -1009,7 +995,7 @@ public:
|
||||
|
||||
/// @brief Returns indices of degrees of freedom for the @a i'th element.
|
||||
/// The returned indices are offsets into an @ref ldof vector with @b vdim
|
||||
/// not necessarily equal to 1. The returned indices are always ordered
|
||||
/// not necessarily equal to 1. The returned indexes are always ordered
|
||||
/// byNODES, irrespective of whether the space is byNODES or byVDIM.
|
||||
/// See also GetElementDofs().
|
||||
///
|
||||
@@ -1038,9 +1024,6 @@ public:
|
||||
/// @note The returned object should NOT be deleted by the caller.
|
||||
DofTransformation *GetBdrElementVDofs(int i, Array<int> &vdofs) const;
|
||||
|
||||
/// Returns indices of degrees of freedom in @a vdofs for NURBS patch @a i.
|
||||
void GetPatchVDofs(int i, Array<int> &vdofs) const;
|
||||
|
||||
/// @brief Returns the indices of the degrees of freedom for the specified
|
||||
/// face, including the DOFs for the edges and the vertices of the face.
|
||||
///
|
||||
@@ -1124,9 +1107,7 @@ public:
|
||||
int GetLocalDofForDof(int i) const { return dof_ldof_array[i]; }
|
||||
|
||||
/** @brief Returns pointer to the FiniteElement in the FiniteElementCollection
|
||||
associated with i'th element in the mesh object.
|
||||
Note: The method has been updated to abort instead of returning NULL for
|
||||
an empty partition. */
|
||||
associated with i'th element in the mesh object. */
|
||||
virtual const FiniteElement *GetFE(int i) const;
|
||||
|
||||
/** @brief Returns pointer to the FiniteElement in the FiniteElementCollection
|
||||
|
||||
+127
-56
@@ -27,6 +27,7 @@
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
@@ -38,9 +39,8 @@ GridFunction::GridFunction(Mesh *m, std::istream &input)
|
||||
// Grid functions are stored on the device
|
||||
UseDevice(true);
|
||||
|
||||
owned_fes.reset(new FiniteElementSpace);
|
||||
fes = owned_fes.get();
|
||||
fec.reset(fes->Load(m, input));
|
||||
fes = new FiniteElementSpace;
|
||||
fec = fes->Load(m, input);
|
||||
|
||||
skip_comment_lines(input, '#');
|
||||
istream::int_type next_char = input.peek();
|
||||
@@ -82,11 +82,10 @@ GridFunction::GridFunction(Mesh *m, GridFunction *gf_array[], int num_pieces)
|
||||
int vdim, ordering;
|
||||
|
||||
fes = gf_array[0]->FESpace();
|
||||
fec.reset(FiniteElementCollection::New(fes->FEColl()->Name()));
|
||||
fec = FiniteElementCollection::New(fes->FEColl()->Name());
|
||||
vdim = fes->GetVDim();
|
||||
ordering = fes->GetOrdering();
|
||||
owned_fes.reset(new FiniteElementSpace(m, fec.get(), vdim, ordering));
|
||||
fes = owned_fes.get();
|
||||
fes = new FiniteElementSpace(m, fec, vdim, ordering);
|
||||
SetSize(fes->GetVSize());
|
||||
|
||||
if (m->NURBSext)
|
||||
@@ -155,9 +154,12 @@ GridFunction::GridFunction(Mesh *m, GridFunction *gf_array[], int num_pieces)
|
||||
|
||||
void GridFunction::Destroy()
|
||||
{
|
||||
owned_fes.reset();
|
||||
fec.reset();
|
||||
fes = nullptr;
|
||||
if (fec)
|
||||
{
|
||||
delete fes;
|
||||
delete fec;
|
||||
fec = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void GridFunction::Update()
|
||||
@@ -339,7 +341,7 @@ int GridFunction::VectorDim() const
|
||||
return fes->GetVDim();
|
||||
}
|
||||
return fes->GetVDim()*std::max(fes->GetMesh()->SpaceDimension(),
|
||||
fe->GetRangeDim());
|
||||
fe->GetVDim());
|
||||
}
|
||||
|
||||
int GridFunction::CurlDim() const
|
||||
@@ -719,6 +721,56 @@ void GridFunction::GetVectorValues(int i, const IntegrationRule &ir,
|
||||
GetVectorValues(*Tr, ir, vals);
|
||||
}
|
||||
|
||||
void be_to_bfe(Geometry::Type geom, int o, const IntegrationPoint &ip,
|
||||
IntegrationPoint &fip)
|
||||
{
|
||||
if (geom == Geometry::TRIANGLE)
|
||||
{
|
||||
if (o == 2)
|
||||
{
|
||||
fip.x = 1.0 - ip.x - ip.y;
|
||||
fip.y = ip.x;
|
||||
}
|
||||
else if (o == 4)
|
||||
{
|
||||
fip.x = ip.y;
|
||||
fip.y = 1.0 - ip.x - ip.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
fip.x = ip.x;
|
||||
fip.y = ip.y;
|
||||
}
|
||||
fip.z = ip.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (o == 2)
|
||||
{
|
||||
fip.x = ip.y;
|
||||
fip.y = 1.0 - ip.x;
|
||||
}
|
||||
else if (o == 4)
|
||||
{
|
||||
fip.x = 1.0 - ip.x;
|
||||
fip.y = 1.0 - ip.y;
|
||||
}
|
||||
else if (o == 6)
|
||||
{
|
||||
fip.x = 1.0 - ip.y;
|
||||
fip.y = ip.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
fip.x = ip.x;
|
||||
fip.y = ip.y;
|
||||
}
|
||||
fip.z = ip.z;
|
||||
}
|
||||
fip.weight = ip.weight;
|
||||
fip.index = ip.index;
|
||||
}
|
||||
|
||||
double GridFunction::GetValue(ElementTransformation &T,
|
||||
const IntegrationPoint &ip,
|
||||
int comp, Vector *tr) const
|
||||
@@ -783,15 +835,18 @@ double GridFunction::GetValue(ElementTransformation &T,
|
||||
// boundary so we'll evaluate it in the neighboring element.
|
||||
FaceElementTransformations * FET =
|
||||
fes->GetMesh()->GetBdrFaceTransformations(T.ElementNo);
|
||||
MFEM_ASSERT(FET != nullptr,
|
||||
"FaceElementTransformation must be valid for a boundary element");
|
||||
|
||||
// Boundary elements and boundary faces may have different
|
||||
// Boundary elements and Boundary Faces may have different
|
||||
// orientations so adjust the integration point if necessary.
|
||||
int f, o;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
IntegrationPoint fip =
|
||||
Mesh::TransformBdrElementToFace(FET->GetGeometryType(), o, ip);
|
||||
int o = 0;
|
||||
if (fes->GetMesh()->Dimension() == 3)
|
||||
{
|
||||
int f;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
}
|
||||
|
||||
IntegrationPoint fip;
|
||||
be_to_bfe(FET->GetGeometryType(), o, ip, fip);
|
||||
|
||||
// Compute and set the point in element 1 from fip
|
||||
FET->SetAllIntPoints(&fip);
|
||||
@@ -919,15 +974,18 @@ void GridFunction::GetVectorValue(ElementTransformation &T,
|
||||
// the boundary so we'll evaluate it in the neighboring element.
|
||||
FaceElementTransformations * FET =
|
||||
fes->GetMesh()->GetBdrFaceTransformations(T.ElementNo);
|
||||
MFEM_ASSERT(FET != nullptr,
|
||||
"FaceElementTransformation must be valid for a boundary element");
|
||||
|
||||
// Boundary elements and boundary faces may have different
|
||||
// Boundary elements and Boundary Faces may have different
|
||||
// orientations so adjust the integration point if necessary.
|
||||
int f, o;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
IntegrationPoint fip =
|
||||
Mesh::TransformBdrElementToFace(FET->GetGeometryType(), o, ip);
|
||||
int o = 0;
|
||||
if (fes->GetMesh()->Dimension() == 3)
|
||||
{
|
||||
int f;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
}
|
||||
|
||||
IntegrationPoint fip;
|
||||
be_to_bfe(FET->GetGeometryType(), o, ip, fip);
|
||||
|
||||
// Compute and set the point in element 1 from fip
|
||||
FET->SetAllIntPoints(&fip);
|
||||
@@ -940,8 +998,6 @@ void GridFunction::GetVectorValue(ElementTransformation &T,
|
||||
{
|
||||
FaceElementTransformations * FET =
|
||||
dynamic_cast<FaceElementTransformations *>(&T);
|
||||
MFEM_ASSERT(FET != nullptr,
|
||||
"FaceElementTransformation must be valid for a boundary element");
|
||||
|
||||
// Evaluate in neighboring element for both continuous and
|
||||
// discontinuous fields (the integration point in T1 should have
|
||||
@@ -986,7 +1042,7 @@ void GridFunction::GetVectorValue(ElementTransformation &T,
|
||||
else
|
||||
{
|
||||
int spaceDim = fes->GetMesh()->SpaceDimension();
|
||||
int vdim = std::max(spaceDim, fe->GetRangeDim());
|
||||
int vdim = std::max(spaceDim, fe->GetVDim());
|
||||
DenseMatrix vshape(dof, vdim);
|
||||
fe->CalcVShape(T, vshape);
|
||||
val.SetSize(vdim);
|
||||
@@ -1038,7 +1094,7 @@ void GridFunction::GetVectorValues(ElementTransformation &T,
|
||||
else
|
||||
{
|
||||
int spaceDim = fes->GetMesh()->SpaceDimension();
|
||||
int vdim = std::max(spaceDim, FElem->GetRangeDim());
|
||||
int vdim = std::max(spaceDim, FElem->GetVDim());
|
||||
DenseMatrix vshape(dof, vdim);
|
||||
|
||||
vals.SetSize(vdim, nip);
|
||||
@@ -1060,10 +1116,11 @@ int GridFunction::GetFaceVectorValues(
|
||||
int i, int side, const IntegrationRule &ir,
|
||||
DenseMatrix &vals, DenseMatrix &tr) const
|
||||
{
|
||||
int di;
|
||||
int n, di;
|
||||
FaceElementTransformations *Transf;
|
||||
|
||||
IntegrationRule eir(ir.GetNPoints()); // ---
|
||||
n = ir.GetNPoints();
|
||||
IntegrationRule eir(n); // ---
|
||||
Transf = fes->GetMesh()->GetFaceElementTransformations(i, 0);
|
||||
if (side == 2)
|
||||
{
|
||||
@@ -1085,14 +1142,12 @@ int GridFunction::GetFaceVectorValues(
|
||||
if (di == 0)
|
||||
{
|
||||
Transf = fes->GetMesh()->GetFaceElementTransformations(i, 5);
|
||||
MFEM_ASSERT(Transf != nullptr, "FaceElementTransformation cannot be null!");
|
||||
Transf->Loc1.Transform(ir, eir);
|
||||
GetVectorValues(*Transf->Elem1, eir, vals, &tr);
|
||||
}
|
||||
else
|
||||
{
|
||||
Transf = fes->GetMesh()->GetFaceElementTransformations(i, 10);
|
||||
MFEM_ASSERT(Transf != nullptr, "FaceElementTransformation cannot be null!");
|
||||
Transf->Loc2.Transform(ir, eir);
|
||||
GetVectorValues(*Transf->Elem2, eir, vals, &tr);
|
||||
}
|
||||
@@ -1450,13 +1505,17 @@ double GridFunction::GetDivergence(ElementTransformation &T) const
|
||||
FaceElementTransformations * FET =
|
||||
fes->GetMesh()->GetBdrFaceTransformations(T.ElementNo);
|
||||
|
||||
// Boundary elements and boundary faces may have different
|
||||
// Boundary elements and Boundary Faces may have different
|
||||
// orientations so adjust the integration point if necessary.
|
||||
int f, o;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
IntegrationPoint fip =
|
||||
Mesh::TransformBdrElementToFace(FET->GetGeometryType(), o,
|
||||
T.GetIntPoint());
|
||||
int o = 0;
|
||||
if (fes->GetMesh()->Dimension() == 3)
|
||||
{
|
||||
int f;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
}
|
||||
|
||||
IntegrationPoint fip;
|
||||
be_to_bfe(FET->GetGeometryType(), o, T.GetIntPoint(), fip);
|
||||
|
||||
// Compute and set the point in element 1 from fip
|
||||
FET->SetAllIntPoints(&fip);
|
||||
@@ -1543,13 +1602,17 @@ void GridFunction::GetCurl(ElementTransformation &T, Vector &curl) const
|
||||
FaceElementTransformations * FET =
|
||||
fes->GetMesh()->GetBdrFaceTransformations(T.ElementNo);
|
||||
|
||||
// Boundary elements and boundary faces may have different
|
||||
// Boundary elements and Boundary Faces may have different
|
||||
// orientations so adjust the integration point if necessary.
|
||||
int f, o;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
IntegrationPoint fip =
|
||||
Mesh::TransformBdrElementToFace(FET->GetGeometryType(), o,
|
||||
T.GetIntPoint());
|
||||
int o = 0;
|
||||
if (fes->GetMesh()->Dimension() == 3)
|
||||
{
|
||||
int f;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
}
|
||||
|
||||
IntegrationPoint fip;
|
||||
be_to_bfe(FET->GetGeometryType(), o, T.GetIntPoint(), fip);
|
||||
|
||||
// Compute and set the point in element 1 from fip
|
||||
FET->SetAllIntPoints(&fip);
|
||||
@@ -1608,13 +1671,17 @@ void GridFunction::GetGradient(ElementTransformation &T, Vector &grad) const
|
||||
FaceElementTransformations * FET =
|
||||
fes->GetMesh()->GetBdrFaceTransformations(T.ElementNo);
|
||||
|
||||
// Boundary elements and boundary faces may have different
|
||||
// Boundary elements and Boundary Faces may have different
|
||||
// orientations so adjust the integration point if necessary.
|
||||
int f, o;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
IntegrationPoint fip =
|
||||
Mesh::TransformBdrElementToFace(FET->GetGeometryType(), o,
|
||||
T.GetIntPoint());
|
||||
int o = 0;
|
||||
if (fes->GetMesh()->Dimension() == 3)
|
||||
{
|
||||
int f;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
}
|
||||
|
||||
IntegrationPoint fip;
|
||||
be_to_bfe(FET->GetGeometryType(), o, T.GetIntPoint(), fip);
|
||||
|
||||
// Compute and set the point in element 1 from fip
|
||||
FET->SetAllIntPoints(&fip);
|
||||
@@ -1690,13 +1757,17 @@ void GridFunction::GetVectorGradient(
|
||||
FaceElementTransformations * FET =
|
||||
fes->GetMesh()->GetBdrFaceTransformations(T.ElementNo);
|
||||
|
||||
// Boundary elements and boundary faces may have different
|
||||
// Boundary elements and Boundary Faces may have different
|
||||
// orientations so adjust the integration point if necessary.
|
||||
int f, o;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
IntegrationPoint fip =
|
||||
Mesh::TransformBdrElementToFace(FET->GetGeometryType(), o,
|
||||
T.GetIntPoint());
|
||||
int o = 0;
|
||||
if (fes->GetMesh()->Dimension() == 3)
|
||||
{
|
||||
int f;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
}
|
||||
|
||||
IntegrationPoint fip;
|
||||
be_to_bfe(FET->GetGeometryType(), o, T.GetIntPoint(), fip);
|
||||
|
||||
// Compute and set the point in element 1 from fip
|
||||
FET->SetAllIntPoints(&fip);
|
||||
|
||||
+24
-7
@@ -20,7 +20,6 @@
|
||||
#include "../general/adios2stream.hpp"
|
||||
#endif
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
@@ -31,13 +30,14 @@ namespace mfem
|
||||
class GridFunction : public Vector
|
||||
{
|
||||
protected:
|
||||
/// FE space on which the grid function lives.
|
||||
/// FE space on which the grid function lives. Owned if #fec is not NULL.
|
||||
FiniteElementSpace *fes;
|
||||
|
||||
/** @brief Used when the grid function is read from a file. It can also be
|
||||
set explicitly, see MakeOwner(). */
|
||||
std::shared_ptr<FiniteElementCollection> fec;
|
||||
std::shared_ptr<FiniteElementSpace> owned_fes;
|
||||
set explicitly, see MakeOwner().
|
||||
|
||||
If not NULL, this pointer is owned by the GridFunction. */
|
||||
FiniteElementCollection *fec;
|
||||
|
||||
long fes_sequence; // see FiniteElementSpace::sequence, Mesh::sequence
|
||||
|
||||
@@ -74,6 +74,11 @@ public:
|
||||
|
||||
GridFunction() { fes = NULL; fec = NULL; fes_sequence = 0; UseDevice(true); }
|
||||
|
||||
/// Copy constructor. The internal true-dof vector #t_vec is not copied.
|
||||
GridFunction(const GridFunction &orig)
|
||||
: Vector(orig), fes(orig.fes), fec(NULL), fes_sequence(orig.fes_sequence)
|
||||
{ UseDevice(true); }
|
||||
|
||||
/// Construct a GridFunction associated with the FiniteElementSpace @a *f.
|
||||
GridFunction(FiniteElementSpace *f) : Vector(f->GetVSize())
|
||||
{ fes = f; fec = NULL; fes_sequence = f->GetSequence(); UseDevice(true); }
|
||||
@@ -102,12 +107,21 @@ public:
|
||||
|
||||
GridFunction(Mesh *m, GridFunction *gf_array[], int num_pieces);
|
||||
|
||||
/// Copy assignment. Only the data of the base class Vector is copied.
|
||||
/** It is assumed that this object and @a rhs use FiniteElementSpace%s that
|
||||
have the same size.
|
||||
|
||||
@note Defining this method overwrites the implicitly defined copy
|
||||
assignment operator. */
|
||||
GridFunction &operator=(const GridFunction &rhs)
|
||||
{ return operator=((const Vector &)rhs); }
|
||||
|
||||
/// Make the GridFunction the owner of #fec and #fes.
|
||||
/** If the new FiniteElementCollection, @a fec_, is NULL, ownership of #fec
|
||||
and #fes is taken away. */
|
||||
void MakeOwner(FiniteElementCollection *fec_) { fec.reset(fec_); }
|
||||
void MakeOwner(FiniteElementCollection *fec_) { fec = fec_; }
|
||||
|
||||
FiniteElementCollection *OwnFEC() { return fec.get(); }
|
||||
FiniteElementCollection *OwnFEC() { return fec; }
|
||||
|
||||
int VectorDim() const;
|
||||
int CurlDim() const;
|
||||
@@ -740,6 +754,9 @@ public:
|
||||
/** @brief Write the GridFunction in STL format. Note that the mesh dimension
|
||||
must be 2 and that quad elements will be broken into two triangles.*/
|
||||
void SaveSTL(std::ostream &out, int TimesToRefine = 1);
|
||||
|
||||
/// Destroys grid function.
|
||||
virtual ~GridFunction() { Destroy(); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
+11
-38
@@ -10,7 +10,6 @@
|
||||
// CONTRIBUTING.md for details.
|
||||
|
||||
#include "gslib.hpp"
|
||||
#include "geom.hpp"
|
||||
|
||||
#ifdef MFEM_USE_GSLIB
|
||||
|
||||
@@ -239,8 +238,7 @@ void FindPointsGSLIB::FindPoints(const Vector &point_pos,
|
||||
}
|
||||
|
||||
// Map element number for simplices, and ref_pos from [-1,1] to [0,1] for
|
||||
// both simplices and quads. Also sets code to 1 for points found on element
|
||||
// faces/edges.
|
||||
// both simplices and quads.
|
||||
MapRefPosAndElemIndices();
|
||||
}
|
||||
|
||||
@@ -683,9 +681,6 @@ void FindPointsGSLIB::MapRefPosAndElemIndices()
|
||||
int nptorig = points_cnt,
|
||||
npt = points_cnt;
|
||||
|
||||
// tolerance for point to be marked as on element edge/face
|
||||
double btol = 1e-12;
|
||||
|
||||
GridFunction *gf_rst_map_temp = NULL;
|
||||
int nptsend = 0;
|
||||
|
||||
@@ -699,7 +694,7 @@ void FindPointsGSLIB::MapRefPosAndElemIndices()
|
||||
|
||||
// Pack data to send via crystal router
|
||||
struct gslib::array *outpt = new gslib::array;
|
||||
struct out_pt { double r[3]; uint index, el, proc, code; };
|
||||
struct out_pt { double r[3]; uint index, el, proc; };
|
||||
struct out_pt *pt;
|
||||
array_init(struct out_pt, outpt, nptsend);
|
||||
outpt->n=nptsend;
|
||||
@@ -717,12 +712,12 @@ void FindPointsGSLIB::MapRefPosAndElemIndices()
|
||||
pt->index = index;
|
||||
pt->proc = gsl_proc[index];
|
||||
pt->el = gsl_elem[index];
|
||||
pt->code = gsl_code[index];
|
||||
++pt;
|
||||
}
|
||||
|
||||
// Transfer data to target MPI ranks
|
||||
sarray_transfer(struct out_pt, outpt, proc, 1, cr);
|
||||
|
||||
// Map received points
|
||||
npt = outpt->n;
|
||||
pt = (struct out_pt *)outpt->ptr;
|
||||
@@ -736,13 +731,7 @@ void FindPointsGSLIB::MapRefPosAndElemIndices()
|
||||
const Geometry::Type gt = fe->GetGeomType();
|
||||
pt->el = mesh_elem;
|
||||
|
||||
if (gt == Geometry::SQUARE || gt == Geometry::CUBE)
|
||||
{
|
||||
// check if it is on element boundary
|
||||
pt->code = Geometry::CheckPoint(gt, ip, -btol) ? 0 : 1;
|
||||
++pt;
|
||||
continue;
|
||||
}
|
||||
if (gt == Geometry::SQUARE || gt == Geometry::CUBE) { ++pt; continue; }
|
||||
else if (gt == Geometry::TRIANGLE)
|
||||
{
|
||||
gf_rst_map_temp = gf_rst_map[0];
|
||||
@@ -769,10 +758,6 @@ void FindPointsGSLIB::MapRefPosAndElemIndices()
|
||||
{
|
||||
pt->r[d] = mfem_ref(d);
|
||||
}
|
||||
|
||||
// check if point is on element boundary
|
||||
ip.Set3(&pt->r[0]);
|
||||
pt->code = Geometry::CheckPoint(gt, ip, -btol) ? 0 : 1;
|
||||
++pt;
|
||||
}
|
||||
|
||||
@@ -789,7 +774,6 @@ void FindPointsGSLIB::MapRefPosAndElemIndices()
|
||||
{
|
||||
gsl_mfem_ref(d + pt->index*dim) = pt->r[d];
|
||||
}
|
||||
gsl_code[pt->index] = pt->code;
|
||||
++pt;
|
||||
}
|
||||
array_free(outpt);
|
||||
@@ -800,22 +784,12 @@ void FindPointsGSLIB::MapRefPosAndElemIndices()
|
||||
{
|
||||
if (gsl_code[index] != 2 && gsl_proc[index] == gsl_comm->id)
|
||||
{
|
||||
|
||||
IntegrationPoint ip;
|
||||
Vector mfem_ref(gsl_mfem_ref.GetData()+index*dim, dim);
|
||||
ip.Set2(mfem_ref.GetData());
|
||||
if (dim == 3) { ip.z = mfem_ref(2); }
|
||||
|
||||
const int elem = gsl_elem[index];
|
||||
const int mesh_elem = split_element_map[elem];
|
||||
const FiniteElement *fe = mesh->GetNodalFESpace()->GetFE(mesh_elem);
|
||||
const Geometry::Type gt = fe->GetGeomType();
|
||||
gsl_mfem_elem[index] = mesh_elem;
|
||||
if (gt == Geometry::SQUARE || gt == Geometry::CUBE)
|
||||
{
|
||||
gsl_code[index] = Geometry::CheckPoint(gt, ip, -btol) ? 0 : 1;
|
||||
continue;
|
||||
}
|
||||
if (gt == Geometry::SQUARE || gt == Geometry::CUBE) { continue; }
|
||||
else if (gt == Geometry::TRIANGLE)
|
||||
{
|
||||
gf_rst_map_temp = gf_rst_map[0];
|
||||
@@ -834,12 +808,11 @@ void FindPointsGSLIB::MapRefPosAndElemIndices()
|
||||
}
|
||||
|
||||
int local_elem = split_element_index[elem];
|
||||
gf_rst_map_temp->GetVectorValue(local_elem, ip, mfem_ref);
|
||||
|
||||
// Check if the point is on element boundary
|
||||
IntegrationPoint ip;
|
||||
Vector mfem_ref(gsl_mfem_ref.GetData()+index*dim, dim);
|
||||
ip.Set2(mfem_ref.GetData());
|
||||
if (dim == 3) { ip.z = mfem_ref(2); }
|
||||
gsl_code[index] = Geometry::CheckPoint(gt, ip, -btol) ? 0 : 1;
|
||||
gf_rst_map_temp->GetVectorValue(local_elem, ip, mfem_ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1263,7 +1236,7 @@ void OversetFindPointsGSLIB::FindPoints(const Vector &point_pos,
|
||||
gsl_ref.SetSize(points_cnt * dim);
|
||||
gsl_dist.SetSize(points_cnt);
|
||||
|
||||
auto xvFill = [&](const double *xv_base[], unsigned xv_stride[])
|
||||
auto xvFill = [&](const double *xv_base[], unsigned xv_stride[], int dim)
|
||||
{
|
||||
for (int d = 0; d < dim; d++)
|
||||
{
|
||||
@@ -1283,7 +1256,7 @@ void OversetFindPointsGSLIB::FindPoints(const Vector &point_pos,
|
||||
{
|
||||
const double *xv_base[2];
|
||||
unsigned xv_stride[2];
|
||||
xvFill(xv_base, xv_stride);
|
||||
xvFill(xv_base, xv_stride, dim);
|
||||
findptsms_2(gsl_code.GetData(), sizeof(unsigned int),
|
||||
gsl_proc.GetData(), sizeof(unsigned int),
|
||||
gsl_elem.GetData(), sizeof(unsigned int),
|
||||
@@ -1297,7 +1270,7 @@ void OversetFindPointsGSLIB::FindPoints(const Vector &point_pos,
|
||||
{
|
||||
const double *xv_base[3];
|
||||
unsigned xv_stride[3];
|
||||
xvFill(xv_base, xv_stride);
|
||||
xvFill(xv_base, xv_stride, dim);
|
||||
findptsms_3(gsl_code.GetData(), sizeof(unsigned int),
|
||||
gsl_proc.GetData(), sizeof(unsigned int),
|
||||
gsl_elem.GetData(), sizeof(unsigned int),
|
||||
|
||||
@@ -28,8 +28,8 @@ static void EAConvectionAssemble1D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, NE);
|
||||
@@ -38,7 +38,7 @@ static void EAConvectionAssemble1D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
double r_Gi[MQ1];
|
||||
double r_Bj[MQ1];
|
||||
for (int q = 0; q < Q1D; q++)
|
||||
@@ -80,8 +80,8 @@ static void EAConvectionAssemble2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, Q1D, 2, NE);
|
||||
@@ -90,8 +90,8 @@ static void EAConvectionAssemble2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
double r_B[MQ1][MD1];
|
||||
double r_G[MQ1][MD1];
|
||||
for (int d = 0; d < D1D; d++)
|
||||
@@ -157,8 +157,8 @@ static void EAConvectionAssemble3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, Q1D, Q1D, 3, NE);
|
||||
@@ -167,8 +167,8 @@ static void EAConvectionAssemble3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
double r_B[MQ1][MD1];
|
||||
double r_G[MQ1][MD1];
|
||||
for (int d = 0; d < D1D; d++)
|
||||
|
||||
@@ -203,8 +203,8 @@ void PAConvectionApply2D(const int ne,
|
||||
const int NE = ne;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
@@ -216,8 +216,8 @@ void PAConvectionApply2D(const int ne,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
|
||||
double u[max_D1D][max_D1D];
|
||||
for (int dy = 0; dy < D1D; ++dy)
|
||||
@@ -323,8 +323,8 @@ void SmemPAConvectionApply2D(const int ne,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
@@ -338,8 +338,8 @@ void SmemPAConvectionApply2D(const int ne,
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
// constexpr int MDQ = (max_Q1D > max_D1D) ? max_Q1D : max_D1D;
|
||||
MFEM_SHARED double u[NBZ][max_D1D][max_D1D];
|
||||
MFEM_FOREACH_THREAD(dy,y,D1D)
|
||||
@@ -450,8 +450,8 @@ void PAConvectionApply3D(const int ne,
|
||||
const int NE = ne;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
@@ -463,8 +463,8 @@ void PAConvectionApply3D(const int ne,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
|
||||
double u[max_D1D][max_D1D][max_D1D];
|
||||
for (int dz = 0; dz < D1D; ++dz)
|
||||
@@ -631,8 +631,8 @@ void SmemPAConvectionApply3D(const int ne,
|
||||
const int NE = ne;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
@@ -644,8 +644,8 @@ void SmemPAConvectionApply3D(const int ne,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_DQ = (max_Q1D > max_D1D) ? max_Q1D : max_D1D;
|
||||
MFEM_SHARED double sm0[max_DQ*max_DQ*max_DQ];
|
||||
MFEM_SHARED double sm1[max_DQ*max_DQ*max_DQ];
|
||||
@@ -835,8 +835,8 @@ void PAConvectionApplyT2D(const int ne,
|
||||
const int NE = ne;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
auto Gt = Reshape(gt.Read(), D1D, Q1D);
|
||||
@@ -848,8 +848,8 @@ void PAConvectionApplyT2D(const int ne,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
|
||||
double u[max_D1D][max_D1D];
|
||||
for (int dy = 0; dy < D1D; ++dy)
|
||||
@@ -951,8 +951,8 @@ void SmemPAConvectionApplyT2D(const int ne,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
auto Gt = Reshape(gt.Read(), D1D, Q1D);
|
||||
@@ -966,8 +966,8 @@ void SmemPAConvectionApplyT2D(const int ne,
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
MFEM_SHARED double u[NBZ][max_D1D][max_D1D];
|
||||
MFEM_FOREACH_THREAD(dy,y,D1D)
|
||||
{
|
||||
@@ -1073,8 +1073,8 @@ void PAConvectionApplyT3D(const int ne,
|
||||
const int NE = ne;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
auto Gt = Reshape(gt.Read(), D1D, Q1D);
|
||||
@@ -1086,8 +1086,8 @@ void PAConvectionApplyT3D(const int ne,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
|
||||
double u[max_D1D][max_D1D][max_D1D];
|
||||
for (int dz = 0; dz < D1D; ++dz)
|
||||
@@ -1249,8 +1249,8 @@ void SmemPAConvectionApplyT3D(const int ne,
|
||||
const int NE = ne;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
auto Gt = Reshape(gt.Read(), D1D, Q1D);
|
||||
@@ -1262,8 +1262,8 @@ void SmemPAConvectionApplyT3D(const int ne,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_DQ = (max_Q1D > max_D1D) ? max_Q1D : max_D1D;
|
||||
MFEM_SHARED double sm0[3*max_DQ*max_DQ*max_DQ];
|
||||
MFEM_SHARED double sm1[3*max_DQ*max_DQ*max_DQ];
|
||||
|
||||
@@ -83,8 +83,8 @@ static void EADGTraceAssemble2DInt(const int NF,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(basis.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, 2, 2, NF);
|
||||
auto A_int = Reshape(eadata_int.ReadWrite(), D1D, D1D, 2, NF);
|
||||
@@ -138,8 +138,8 @@ static void EADGTraceAssemble2DBdr(const int NF,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(basis.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, 2, 2, NF);
|
||||
auto A_bdr = Reshape(eadata_bdr.ReadWrite(), D1D, D1D, NF);
|
||||
@@ -181,8 +181,8 @@ static void EADGTraceAssemble3DInt(const int NF,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(basis.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, Q1D, 2, 2, NF);
|
||||
auto A_int = Reshape(eadata_int.ReadWrite(), D1D, D1D, D1D, D1D, 2, NF);
|
||||
@@ -191,8 +191,8 @@ static void EADGTraceAssemble3DInt(const int NF,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
double r_B[MQ1][MD1];
|
||||
for (int d = 0; d < D1D; d++)
|
||||
{
|
||||
@@ -278,8 +278,8 @@ static void EADGTraceAssemble3DBdr(const int NF,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(basis.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, Q1D, 2, 2, NF);
|
||||
auto A_bdr = Reshape(eadata_bdr.ReadWrite(), D1D, D1D, D1D, D1D, NF);
|
||||
@@ -287,8 +287,8 @@ static void EADGTraceAssemble3DBdr(const int NF,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
double r_B[MQ1][MD1];
|
||||
for (int d = 0; d < D1D; d++)
|
||||
{
|
||||
|
||||
@@ -258,8 +258,8 @@ void PADGTraceApply2D(const int NF,
|
||||
const int VDIM = 1;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, 2, 2, NF);
|
||||
@@ -272,8 +272,8 @@ void PADGTraceApply2D(const int NF,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
double u0[max_D1D][VDIM];
|
||||
double u1[max_D1D][VDIM];
|
||||
for (int d = 0; d < D1D; d++)
|
||||
@@ -349,8 +349,8 @@ void PADGTraceApply3D(const int NF,
|
||||
const int VDIM = 1;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, Q1D, 2, 2, NF);
|
||||
@@ -363,8 +363,8 @@ void PADGTraceApply3D(const int NF,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
double u0[max_D1D][max_D1D][VDIM];
|
||||
double u1[max_D1D][max_D1D][VDIM];
|
||||
for (int d1 = 0; d1 < D1D; d1++)
|
||||
@@ -494,8 +494,8 @@ void SmemPADGTraceApply3D(const int NF,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, Q1D, 2, 2, NF);
|
||||
@@ -509,8 +509,8 @@ void SmemPADGTraceApply3D(const int NF,
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
MFEM_SHARED double u0[NBZ][max_D1D][max_D1D];
|
||||
MFEM_SHARED double u1[NBZ][max_D1D][max_D1D];
|
||||
MFEM_FOREACH_THREAD(d1,x,D1D)
|
||||
@@ -659,8 +659,8 @@ void PADGTraceApplyTranspose2D(const int NF,
|
||||
const int VDIM = 1;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, 2, 2, NF);
|
||||
@@ -673,8 +673,8 @@ void PADGTraceApplyTranspose2D(const int NF,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
double u0[max_D1D][VDIM];
|
||||
double u1[max_D1D][VDIM];
|
||||
for (int d = 0; d < D1D; d++)
|
||||
@@ -755,8 +755,8 @@ void PADGTraceApplyTranspose3D(const int NF,
|
||||
const int VDIM = 1;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, Q1D, 2, 2, NF);
|
||||
@@ -769,8 +769,8 @@ void PADGTraceApplyTranspose3D(const int NF,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
double u0[max_D1D][max_D1D][VDIM];
|
||||
double u1[max_D1D][max_D1D][VDIM];
|
||||
for (int d1 = 0; d1 < D1D; d1++)
|
||||
@@ -911,8 +911,8 @@ void SmemPADGTraceApplyTranspose3D(const int NF,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, Q1D, 2, 2, NF);
|
||||
@@ -926,8 +926,8 @@ void SmemPADGTraceApplyTranspose3D(const int NF,
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
MFEM_SHARED double u0[NBZ][max_D1D][max_D1D];
|
||||
MFEM_SHARED double u1[NBZ][max_D1D][max_D1D];
|
||||
MFEM_FOREACH_THREAD(d1,x,D1D)
|
||||
|
||||
@@ -28,8 +28,8 @@ static void EADiffusionAssemble1D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, NE);
|
||||
auto A = Reshape(eadata.ReadWrite(), D1D, D1D, NE);
|
||||
@@ -37,7 +37,7 @@ static void EADiffusionAssemble1D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
double r_Gi[MQ1];
|
||||
double r_Gj[MQ1];
|
||||
for (int q = 0; q < Q1D; q++)
|
||||
@@ -79,8 +79,8 @@ static void EADiffusionAssemble2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, Q1D, 3, NE);
|
||||
@@ -89,8 +89,8 @@ static void EADiffusionAssemble2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
double r_B[MQ1][MD1];
|
||||
double r_G[MQ1][MD1];
|
||||
for (int d = 0; d < D1D; d++)
|
||||
@@ -156,8 +156,8 @@ static void EADiffusionAssemble3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, Q1D, Q1D, 6, NE);
|
||||
@@ -166,8 +166,8 @@ static void EADiffusionAssemble3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
double r_B[MQ1][MD1];
|
||||
double r_G[MQ1][MD1];
|
||||
for (int d = 0; d < D1D; d++)
|
||||
|
||||
@@ -98,8 +98,8 @@ inline void PADiffusionDiagonal2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
// note the different shape for D, if this is a symmetric matrix we only
|
||||
@@ -110,8 +110,8 @@ inline void PADiffusionDiagonal2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
// gradphi \cdot Q \gradphi has four terms
|
||||
double QD0[MQ1][MD1];
|
||||
double QD1[MQ1][MD1];
|
||||
@@ -165,10 +165,10 @@ inline void SmemPADiffusionDiagonal2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
const int max_q1d = T_Q1D ? T_Q1D : DeviceDofQuadLimits::Get().MAX_Q1D;
|
||||
const int max_d1d = T_D1D ? T_D1D : DeviceDofQuadLimits::Get().MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= max_d1d, "");
|
||||
MFEM_VERIFY(Q1D <= max_q1d, "");
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= MD1, "");
|
||||
MFEM_VERIFY(Q1D <= MQ1, "");
|
||||
auto b = Reshape(b_.Read(), Q1D, D1D);
|
||||
auto g = Reshape(g_.Read(), Q1D, D1D);
|
||||
auto D = Reshape(d_.Read(), Q1D*Q1D, symmetric ? 3 : 4, NE);
|
||||
@@ -179,8 +179,8 @@ inline void SmemPADiffusionDiagonal2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_SHARED double BG[2][MQ1*MD1];
|
||||
double (*B)[MD1] = (double (*)[MD1]) (BG+0);
|
||||
double (*G)[MD1] = (double (*)[MD1]) (BG+1);
|
||||
@@ -260,10 +260,10 @@ inline void PADiffusionDiagonal3D(const int NE,
|
||||
constexpr int DIM = 3;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
const int max_q1d = T_Q1D ? T_Q1D : DeviceDofQuadLimits::Get().MAX_Q1D;
|
||||
const int max_d1d = T_D1D ? T_D1D : DeviceDofQuadLimits::Get().MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= max_d1d, "");
|
||||
MFEM_VERIFY(Q1D <= max_q1d, "");
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= MD1, "");
|
||||
MFEM_VERIFY(Q1D <= MQ1, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto Q = Reshape(d.Read(), Q1D*Q1D*Q1D, symmetric ? 6 : 9, NE);
|
||||
@@ -272,8 +272,8 @@ inline void PADiffusionDiagonal3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
double QQD[MQ1][MQ1][MD1];
|
||||
double QDD[MQ1][MD1][MD1];
|
||||
for (int i = 0; i < DIM; ++i)
|
||||
@@ -361,10 +361,10 @@ inline void SmemPADiffusionDiagonal3D(const int NE,
|
||||
constexpr int DIM = 3;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
const int max_q1d = T_Q1D ? T_Q1D : DeviceDofQuadLimits::Get().MAX_Q1D;
|
||||
const int max_d1d = T_D1D ? T_D1D : DeviceDofQuadLimits::Get().MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= max_d1d, "");
|
||||
MFEM_VERIFY(Q1D <= max_q1d, "");
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= MD1, "");
|
||||
MFEM_VERIFY(Q1D <= MQ1, "");
|
||||
auto b = Reshape(b_.Read(), Q1D, D1D);
|
||||
auto g = Reshape(g_.Read(), Q1D, D1D);
|
||||
auto D = Reshape(d_.Read(), Q1D*Q1D*Q1D, symmetric ? 6 : 9, NE);
|
||||
@@ -374,8 +374,8 @@ inline void SmemPADiffusionDiagonal3D(const int NE,
|
||||
const int tidz = MFEM_THREAD_ID(z);
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_SHARED double BG[2][MQ1*MD1];
|
||||
double (*B)[MD1] = (double (*)[MD1]) (BG+0);
|
||||
double (*G)[MD1] = (double (*)[MD1]) (BG+1);
|
||||
@@ -521,8 +521,8 @@ inline void PADiffusionApply2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b_.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g_.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt_.Read(), D1D, Q1D);
|
||||
@@ -535,8 +535,8 @@ inline void PADiffusionApply2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
|
||||
double grad[max_Q1D][max_Q1D][2];
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
@@ -642,10 +642,10 @@ inline void SmemPADiffusionApply2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
const int max_q1d = T_Q1D ? T_Q1D : DeviceDofQuadLimits::Get().MAX_Q1D;
|
||||
const int max_d1d = T_D1D ? T_D1D : DeviceDofQuadLimits::Get().MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= max_d1d, "");
|
||||
MFEM_VERIFY(Q1D <= max_q1d, "");
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= MD1, "");
|
||||
MFEM_VERIFY(Q1D <= MQ1, "");
|
||||
auto b = Reshape(b_.Read(), Q1D, D1D);
|
||||
auto g = Reshape(g_.Read(), Q1D, D1D);
|
||||
auto D = Reshape(d_.Read(), Q1D*Q1D, symmetric ? 3 : 4, NE);
|
||||
@@ -657,8 +657,8 @@ inline void SmemPADiffusionApply2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_SHARED double sBG[2][MQ1*MD1];
|
||||
double (*B)[MD1] = (double (*)[MD1]) (sBG+0);
|
||||
double (*G)[MD1] = (double (*)[MD1]) (sBG+1);
|
||||
@@ -800,8 +800,8 @@ inline void PADiffusionApply3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
@@ -813,8 +813,8 @@ inline void PADiffusionApply3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
double grad[max_Q1D][max_Q1D][max_Q1D][3];
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
@@ -992,10 +992,10 @@ inline void SmemPADiffusionApply3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
const int max_q1d = T_Q1D ? T_Q1D : DeviceDofQuadLimits::Get().MAX_Q1D;
|
||||
const int max_d1d = T_D1D ? T_D1D : DeviceDofQuadLimits::Get().MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= max_d1d, "");
|
||||
MFEM_VERIFY(Q1D <= max_q1d, "");
|
||||
constexpr int M1Q = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int M1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= M1D, "");
|
||||
MFEM_VERIFY(Q1D <= M1Q, "");
|
||||
auto b = Reshape(b_.Read(), Q1D, D1D);
|
||||
auto g = Reshape(g_.Read(), Q1D, D1D);
|
||||
auto d = Reshape(d_.Read(), Q1D, Q1D, Q1D, symmetric ? 6 : 9, NE);
|
||||
@@ -1005,8 +1005,8 @@ inline void SmemPADiffusionApply3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MDQ = (MQ1 > MD1) ? MQ1 : MD1;
|
||||
MFEM_SHARED double sBG[2][MQ1*MD1];
|
||||
double (*B)[MD1] = (double (*)[MD1]) (sBG+0);
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "../bilininteg.hpp"
|
||||
#include "../gridfunc.hpp"
|
||||
#include "../qfunction.hpp"
|
||||
#include "../../mesh/nurbs.hpp"
|
||||
#include "../ceed/integrators/diffusion/diffusion.hpp"
|
||||
#include "bilininteg_diffusion_kernels.hpp"
|
||||
|
||||
@@ -75,29 +74,6 @@ void DiffusionIntegrator::AssemblePA(const FiniteElementSpace &fes)
|
||||
ir->GetWeights(), geom->J, coeff, pa_data);
|
||||
}
|
||||
|
||||
void DiffusionIntegrator::AssembleNURBSPA(const FiniteElementSpace &fes)
|
||||
{
|
||||
fespace = &fes;
|
||||
Mesh *mesh = fes.GetMesh();
|
||||
dim = mesh->Dimension();
|
||||
MFEM_VERIFY(3 == dim, "Only 3D so far");
|
||||
|
||||
numPatches = mesh->NURBSext->GetNP();
|
||||
for (int p=0; p<numPatches; ++p)
|
||||
{
|
||||
AssemblePatchPA(p, fes);
|
||||
}
|
||||
}
|
||||
|
||||
void DiffusionIntegrator::AssemblePatchPA(const int patch,
|
||||
const FiniteElementSpace &fes)
|
||||
{
|
||||
Mesh *mesh = fes.GetMesh();
|
||||
SetupPatchBasisData(mesh, patch);
|
||||
|
||||
SetupPatchPA(patch, mesh); // For full quadrature, unitWeights = false
|
||||
}
|
||||
|
||||
void DiffusionIntegrator::AssembleDiagonalPA(Vector &diag)
|
||||
{
|
||||
if (DeviceCanUseCeed())
|
||||
@@ -139,221 +115,4 @@ void DiffusionIntegrator::AddMultTransposePA(const Vector &x, Vector &y) const
|
||||
}
|
||||
}
|
||||
|
||||
// This version uses full 1D quadrature rules, taking into account the
|
||||
// minimum interaction between basis functions and integration points.
|
||||
void DiffusionIntegrator::AddMultPatchPA(const int patch, const Vector &x,
|
||||
Vector &y) const
|
||||
{
|
||||
MFEM_VERIFY(3 == dim, "Only 3D so far");
|
||||
|
||||
const Array<int>& Q1D = pQ1D[patch];
|
||||
const Array<int>& D1D = pD1D[patch];
|
||||
|
||||
const std::vector<Array2D<double>>& B = pB[patch];
|
||||
const std::vector<Array2D<double>>& G = pG[patch];
|
||||
|
||||
const IntArrayVar2D& minD = pminD[patch];
|
||||
const IntArrayVar2D& maxD = pmaxD[patch];
|
||||
const IntArrayVar2D& minQ = pminQ[patch];
|
||||
const IntArrayVar2D& maxQ = pmaxQ[patch];
|
||||
|
||||
auto X = Reshape(x.Read(), D1D[0], D1D[1], D1D[2]);
|
||||
auto Y = Reshape(y.ReadWrite(), D1D[0], D1D[1], D1D[2]);
|
||||
|
||||
const auto qd = Reshape(pa_data.Read(), Q1D[0]*Q1D[1]*Q1D[2],
|
||||
(symmetric ? 6 : 9));
|
||||
|
||||
// NOTE: the following is adapted from AssemblePatchMatrix_fullQuadrature
|
||||
std::vector<Array3D<double>> grad(dim);
|
||||
// TODO: Can an optimal order of dimensions be determined, for each patch?
|
||||
Array3D<double> gradXY(3, std::max(Q1D[0], D1D[0]), std::max(Q1D[1], D1D[1]));
|
||||
Array2D<double> gradX(3, std::max(Q1D[0], D1D[0]));
|
||||
|
||||
for (int d=0; d<dim; ++d)
|
||||
{
|
||||
grad[d].SetSize(Q1D[0], Q1D[1], Q1D[2]);
|
||||
|
||||
for (int qz = 0; qz < Q1D[2]; ++qz)
|
||||
{
|
||||
for (int qy = 0; qy < Q1D[1]; ++qy)
|
||||
{
|
||||
for (int qx = 0; qx < Q1D[0]; ++qx)
|
||||
{
|
||||
grad[d](qx,qy,qz) = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int dz = 0; dz < D1D[2]; ++dz)
|
||||
{
|
||||
for (int qy = 0; qy < Q1D[1]; ++qy)
|
||||
{
|
||||
for (int qx = 0; qx < Q1D[0]; ++qx)
|
||||
{
|
||||
for (int d=0; d<dim; ++d)
|
||||
{
|
||||
gradXY(d,qx,qy) = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int dy = 0; dy < D1D[1]; ++dy)
|
||||
{
|
||||
for (int qx = 0; qx < Q1D[0]; ++qx)
|
||||
{
|
||||
gradX(0,qx) = 0.0;
|
||||
gradX(1,qx) = 0.0;
|
||||
}
|
||||
for (int dx = 0; dx < D1D[0]; ++dx)
|
||||
{
|
||||
const double s = X(dx,dy,dz);
|
||||
for (int qx = minD[0][dx]; qx <= maxD[0][dx]; ++qx)
|
||||
{
|
||||
gradX(0,qx) += s * B[0](qx,dx);
|
||||
gradX(1,qx) += s * G[0](qx,dx);
|
||||
}
|
||||
}
|
||||
for (int qy = minD[1][dy]; qy <= maxD[1][dy]; ++qy)
|
||||
{
|
||||
const double wy = B[1](qy,dy);
|
||||
const double wDy = G[1](qy,dy);
|
||||
// This full range of qx values is generally necessary.
|
||||
for (int qx = 0; qx < Q1D[0]; ++qx)
|
||||
{
|
||||
const double wx = gradX(0,qx);
|
||||
const double wDx = gradX(1,qx);
|
||||
gradXY(0,qx,qy) += wDx * wy;
|
||||
gradXY(1,qx,qy) += wx * wDy;
|
||||
gradXY(2,qx,qy) += wx * wy;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int qz = minD[2][dz]; qz <= maxD[2][dz]; ++qz)
|
||||
{
|
||||
const double wz = B[2](qz,dz);
|
||||
const double wDz = G[2](qz,dz);
|
||||
for (int qy = 0; qy < Q1D[1]; ++qy)
|
||||
{
|
||||
for (int qx = 0; qx < Q1D[0]; ++qx)
|
||||
{
|
||||
grad[0](qx,qy,qz) += gradXY(0,qx,qy) * wz;
|
||||
grad[1](qx,qy,qz) += gradXY(1,qx,qy) * wz;
|
||||
grad[2](qx,qy,qz) += gradXY(2,qx,qy) * wDz;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int qz = 0; qz < Q1D[2]; ++qz)
|
||||
{
|
||||
for (int qy = 0; qy < Q1D[1]; ++qy)
|
||||
{
|
||||
for (int qx = 0; qx < Q1D[0]; ++qx)
|
||||
{
|
||||
const int q = qx + ((qy + (qz * Q1D[1])) * Q1D[0]);
|
||||
const double O00 = qd(q,0);
|
||||
const double O01 = qd(q,1);
|
||||
const double O02 = qd(q,2);
|
||||
const double O10 = symmetric ? O01 : qd(q,3);
|
||||
const double O11 = symmetric ? qd(q,3) : qd(q,4);
|
||||
const double O12 = symmetric ? qd(q,4) : qd(q,5);
|
||||
const double O20 = symmetric ? O02 : qd(q,6);
|
||||
const double O21 = symmetric ? O12 : qd(q,7);
|
||||
const double O22 = symmetric ? qd(q,5) : qd(q,8);
|
||||
|
||||
const double grad0 = grad[0](qx,qy,qz);
|
||||
const double grad1 = grad[1](qx,qy,qz);
|
||||
const double grad2 = grad[2](qx,qy,qz);
|
||||
|
||||
grad[0](qx,qy,qz) = (O00*grad0)+(O01*grad1)+(O02*grad2);
|
||||
grad[1](qx,qy,qz) = (O10*grad0)+(O11*grad1)+(O12*grad2);
|
||||
grad[2](qx,qy,qz) = (O20*grad0)+(O21*grad1)+(O22*grad2);
|
||||
} // qx
|
||||
} // qy
|
||||
} // qz
|
||||
|
||||
for (int qz = 0; qz < Q1D[2]; ++qz)
|
||||
{
|
||||
for (int dy = 0; dy < D1D[1]; ++dy)
|
||||
{
|
||||
for (int dx = 0; dx < D1D[0]; ++dx)
|
||||
{
|
||||
for (int d=0; d<3; ++d)
|
||||
{
|
||||
gradXY(d,dx,dy) = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int qy = 0; qy < Q1D[1]; ++qy)
|
||||
{
|
||||
for (int dx = 0; dx < D1D[0]; ++dx)
|
||||
{
|
||||
for (int d=0; d<3; ++d)
|
||||
{
|
||||
gradX(d,dx) = 0.0;
|
||||
}
|
||||
}
|
||||
for (int qx = 0; qx < Q1D[0]; ++qx)
|
||||
{
|
||||
const double gX = grad[0](qx,qy,qz);
|
||||
const double gY = grad[1](qx,qy,qz);
|
||||
const double gZ = grad[2](qx,qy,qz);
|
||||
for (int dx = minQ[0][qx]; dx <= maxQ[0][qx]; ++dx)
|
||||
{
|
||||
const double wx = B[0](qx,dx);
|
||||
const double wDx = G[0](qx,dx);
|
||||
gradX(0,dx) += gX * wDx;
|
||||
gradX(1,dx) += gY * wx;
|
||||
gradX(2,dx) += gZ * wx;
|
||||
}
|
||||
}
|
||||
for (int dy = minQ[1][qy]; dy <= maxQ[1][qy]; ++dy)
|
||||
{
|
||||
const double wy = B[1](qy,dy);
|
||||
const double wDy = G[1](qy,dy);
|
||||
for (int dx = 0; dx < D1D[0]; ++dx)
|
||||
{
|
||||
gradXY(0,dx,dy) += gradX(0,dx) * wy;
|
||||
gradXY(1,dx,dy) += gradX(1,dx) * wDy;
|
||||
gradXY(2,dx,dy) += gradX(2,dx) * wy;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int dz = minQ[2][qz]; dz <= maxQ[2][qz]; ++dz)
|
||||
{
|
||||
const double wz = B[2](qz,dz);
|
||||
const double wDz = G[2](qz,dz);
|
||||
for (int dy = 0; dy < D1D[1]; ++dy)
|
||||
{
|
||||
for (int dx = 0; dx < D1D[0]; ++dx)
|
||||
{
|
||||
Y(dx,dy,dz) +=
|
||||
((gradXY(0,dx,dy) * wz) +
|
||||
(gradXY(1,dx,dy) * wz) +
|
||||
(gradXY(2,dx,dy) * wDz));
|
||||
}
|
||||
}
|
||||
} // dz
|
||||
} // qz
|
||||
}
|
||||
|
||||
void DiffusionIntegrator::AddMultNURBSPA(const Vector &x, Vector &y) const
|
||||
{
|
||||
Vector xp, yp;
|
||||
|
||||
for (int p=0; p<numPatches; ++p)
|
||||
{
|
||||
Array<int> vdofs;
|
||||
fespace->GetPatchVDofs(p, vdofs);
|
||||
|
||||
x.GetSubVector(vdofs, xp);
|
||||
yp.SetSize(vdofs.Size());
|
||||
yp = 0.0;
|
||||
|
||||
AddMultPatchPA(p, xp, yp);
|
||||
|
||||
y.AddElementVector(vdofs, yp);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mfem
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -229,9 +229,9 @@ static void PAGradientApply2D(const int NE,
|
||||
const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(TR_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(TR_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, TR_D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, TR_D1D);
|
||||
auto Bt = Reshape(bt.Read(), TE_D1D, Q1D);
|
||||
@@ -245,8 +245,8 @@ static void PAGradientApply2D(const int NE,
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
const int VDIM = 2;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_TE_D1D = T_TE_D1D ? T_TE_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_TE_D1D = T_TE_D1D ? T_TE_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
|
||||
double grad[max_Q1D][max_Q1D][VDIM];
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
@@ -359,9 +359,9 @@ static void PAGradientApply3D(const int NE,
|
||||
const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(TR_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(TR_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, TR_D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, TR_D1D);
|
||||
auto Bt = Reshape(bt.Read(), TE_D1D, Q1D);
|
||||
@@ -375,8 +375,8 @@ static void PAGradientApply3D(const int NE,
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
const int VDIM = 3;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_TE_D1D = T_TE_D1D ? T_TE_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_TE_D1D = T_TE_D1D ? T_TE_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
|
||||
double grad[max_Q1D][max_Q1D][max_Q1D][VDIM];
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
@@ -555,11 +555,11 @@ static void SmemPAGradientApply3D(const int NE,
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
MFEM_VERIFY(TR_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(TR_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(TR_D1D <= Q1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= Q1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
|
||||
auto b = Reshape(b_.Read(), Q1D, TR_D1D);
|
||||
auto g = Reshape(g_.Read(), Q1D, TR_D1D);
|
||||
@@ -575,9 +575,9 @@ static void SmemPAGradientApply3D(const int NE,
|
||||
const int D1DR = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int D1DE = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1R = T_TR_D1D ? T_TR_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MD1E = T_TE_D1D ? T_TE_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1R = T_TR_D1D ? T_TR_D1D : MAX_D1D;
|
||||
constexpr int MD1E = T_TE_D1D ? T_TE_D1D : MAX_D1D;
|
||||
constexpr int MD1 = MD1E > MD1R ? MD1E : MD1R;
|
||||
constexpr int MDQ = MQ1 > MD1 ? MQ1 : MD1;
|
||||
MFEM_SHARED double sBG[2][MQ1*MD1];
|
||||
|
||||
@@ -26,6 +26,9 @@ void PAHcurlMassAssembleDiagonal2D(const int D1D,
|
||||
const Vector &pa_data,
|
||||
Vector &diag)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
auto Bo = Reshape(bo.Read(), Q1D, D1D-1);
|
||||
auto Bc = Reshape(bc.Read(), Q1D, D1D);
|
||||
auto op = Reshape(pa_data.Read(), Q1D, Q1D, symmetric ? 3 : 4, NE);
|
||||
@@ -33,9 +36,6 @@ void PAHcurlMassAssembleDiagonal2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
int osc = 0;
|
||||
|
||||
for (int c = 0; c < VDIM; ++c) // loop over x, y components
|
||||
@@ -83,10 +83,11 @@ void PAHcurlMassAssembleDiagonal3D(const int D1D,
|
||||
const Vector &pa_data,
|
||||
Vector &diag)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: Q1D > MAX_Q1D");
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
auto Bo = Reshape(bo.Read(), Q1D, D1D-1);
|
||||
@@ -96,8 +97,6 @@ void PAHcurlMassAssembleDiagonal3D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
int osc = 0;
|
||||
|
||||
for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
|
||||
@@ -159,6 +158,10 @@ void PAHcurlMassApply2D(const int D1D,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
auto Bo = Reshape(bo.Read(), Q1D, D1D-1);
|
||||
auto Bc = Reshape(bc.Read(), Q1D, D1D);
|
||||
auto Bot = Reshape(bot.Read(), D1D-1, Q1D);
|
||||
@@ -169,10 +172,6 @@ void PAHcurlMassApply2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
double mass[MAX_Q1D][MAX_Q1D][VDIM];
|
||||
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
@@ -289,10 +288,11 @@ void PAHcurlMassApply3D(const int D1D,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: Q1D > MAX_Q1D");
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
auto Bo = Reshape(bo.Read(), Q1D, D1D-1);
|
||||
@@ -305,9 +305,6 @@ void PAHcurlMassApply3D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
double mass[MAX_Q1D][MAX_Q1D][MAX_Q1D][VDIM];
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
@@ -607,6 +604,9 @@ void PACurlCurlAssembleDiagonal2D(const int D1D,
|
||||
const Vector &pa_data,
|
||||
Vector &diag)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
auto Bo = Reshape(bo.Read(), Q1D, D1D-1);
|
||||
auto Gc = Reshape(gc.Read(), Q1D, D1D);
|
||||
auto op = Reshape(pa_data.Read(), Q1D, Q1D, NE);
|
||||
@@ -614,9 +614,6 @@ void PACurlCurlAssembleDiagonal2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
int osc = 0;
|
||||
|
||||
for (int c = 0; c < VDIM; ++c) // loop over x, y components
|
||||
@@ -664,6 +661,9 @@ void PACurlCurlApply2D(const int D1D,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
auto Bo = Reshape(bo.Read(), Q1D, D1D-1);
|
||||
auto Bot = Reshape(bot.Read(), D1D-1, Q1D);
|
||||
@@ -675,10 +675,6 @@ void PACurlCurlApply2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
double curl[MAX_Q1D][MAX_Q1D];
|
||||
|
||||
// curl[qy][qx] will be computed as du_y/dx - du_x/dy
|
||||
@@ -828,6 +824,9 @@ void PAHcurlL2Apply2D(const int D1D,
|
||||
const Vector &x, // trial = H(curl)
|
||||
Vector &y) // test = L2 or H1
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
const int H1 = (D1Dtest == D1D);
|
||||
|
||||
MFEM_VERIFY(y.Size() == NE*D1Dtest*D1Dtest, "Test vector of wrong dimension");
|
||||
@@ -842,10 +841,6 @@ void PAHcurlL2Apply2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
double curl[MAX_Q1D][MAX_Q1D];
|
||||
|
||||
// curl[qy][qx] will be computed as du_y/dx - du_x/dy
|
||||
@@ -944,6 +939,9 @@ void PAHcurlL2ApplyTranspose2D(const int D1D,
|
||||
const Vector &x, // trial = H(curl)
|
||||
Vector &y) // test = L2 or H1
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
const int H1 = (D1Dtest == D1D);
|
||||
|
||||
MFEM_VERIFY(x.Size() == NE*D1Dtest*D1Dtest, "Test vector of wrong dimension");
|
||||
@@ -958,10 +956,6 @@ void PAHcurlL2ApplyTranspose2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
double mass[MAX_Q1D][MAX_Q1D];
|
||||
|
||||
// Zero-order term in L2 or H1 test space
|
||||
|
||||
@@ -59,10 +59,8 @@ inline void SmemPAHcurlMassAssembleDiagonal3D(const int d1d,
|
||||
const Vector &pa_data,
|
||||
Vector &diag)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -74,8 +72,8 @@ inline void SmemPAHcurlMassAssembleDiagonal3D(const int d1d,
|
||||
mfem::forall_3D(NE, Q1D, Q1D, Q1D, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -220,10 +218,8 @@ inline void SmemPAHcurlMassApply3D(const int d1d,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -238,8 +234,8 @@ inline void SmemPAHcurlMassApply3D(const int d1d,
|
||||
mfem::forall_3D(NE, Q1D, Q1D, Q1D, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -445,10 +441,8 @@ inline void PACurlCurlAssembleDiagonal3D(const int d1d,
|
||||
const Vector &pa_data,
|
||||
Vector &diag)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -482,8 +476,8 @@ inline void PACurlCurlAssembleDiagonal3D(const int d1d,
|
||||
// which may be non-symmetric depending on a possibly non-symmetric matrix coefficient.
|
||||
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -641,10 +635,8 @@ inline void SmemPACurlCurlAssembleDiagonal3D(const int d1d,
|
||||
const Vector &pa_data,
|
||||
Vector &diag)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -675,8 +667,8 @@ inline void SmemPACurlCurlAssembleDiagonal3D(const int d1d,
|
||||
// If c = 2, \hat{\nabla}\times\hat{u} reduces to [(u_2)_{x_1}, -(u_2)_{x_0}, 0]
|
||||
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -856,10 +848,8 @@ inline void PACurlCurlApply3D(const int d1d,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -884,8 +874,8 @@ inline void PACurlCurlApply3D(const int d1d,
|
||||
// If c = 2, \hat{\nabla}\times\hat{u} reduces to [(u_2)_{x_1}, -(u_2)_{x_0}, 0]
|
||||
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -1379,10 +1369,8 @@ inline void SmemPACurlCurlApply3D(const int d1d,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -1404,8 +1392,8 @@ inline void SmemPACurlCurlApply3D(const int d1d,
|
||||
auto device_kernel = [=] MFEM_DEVICE (int e)
|
||||
{
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -1750,10 +1738,8 @@ inline void PAHcurlL2Apply3D(const int d1d,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -1778,8 +1764,8 @@ inline void PAHcurlL2Apply3D(const int d1d,
|
||||
// If c = 2, \hat{\nabla}\times\hat{u} reduces to [(u_2)_{x_1}, -(u_2)_{x_0}, 0]
|
||||
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -2121,10 +2107,8 @@ inline void SmemPAHcurlL2Apply3D(const int d1d,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -2139,8 +2123,8 @@ inline void SmemPAHcurlL2Apply3D(const int d1d,
|
||||
{
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int maxCoeffDim = 9;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -2441,10 +2425,8 @@ inline void PAHcurlL2ApplyTranspose3D(const int d1d,
|
||||
Vector &y)
|
||||
{
|
||||
// See PAHcurlL2Apply3D for comments.
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -2460,8 +2442,8 @@ inline void PAHcurlL2ApplyTranspose3D(const int d1d,
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -2809,10 +2791,8 @@ inline void SmemPAHcurlL2ApplyTranspose3D(const int d1d,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -2827,8 +2807,8 @@ inline void SmemPAHcurlL2ApplyTranspose3D(const int d1d,
|
||||
{
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int maxCoeffDim = 9;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
|
||||
@@ -224,10 +224,11 @@ void PAHcurlHdivMassApply2D(const int D1D,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: Q1D > MAX_Q1D");
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
|
||||
constexpr static int VDIM = 2;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
@@ -243,8 +244,6 @@ void PAHcurlHdivMassApply2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
double mass[MAX_Q1D][MAX_Q1D][VDIM];
|
||||
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
@@ -324,7 +323,7 @@ void PAHcurlHdivMassApply2D(const int D1D,
|
||||
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
double massX[DofQuadLimits::HDIV_MAX_D1D];
|
||||
double massX[HDIV_MAX_D1D];
|
||||
for (int dx = 0; dx < D1Dx; ++dx)
|
||||
{
|
||||
massX[dx] = 0.0;
|
||||
@@ -371,10 +370,11 @@ void PAHcurlHdivMassApply3D(const int D1D,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: Q1D > MAX_Q1D");
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
@@ -395,8 +395,6 @@ void PAHcurlHdivMassApply3D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
double mass[MAX_Q1D][MAX_Q1D][MAX_Q1D][VDIM];
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
@@ -509,7 +507,7 @@ void PAHcurlHdivMassApply3D(const int D1D,
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
double massXY[DofQuadLimits::HDIV_MAX_D1D][DofQuadLimits::HDIV_MAX_D1D];
|
||||
double massXY[HDIV_MAX_D1D][HDIV_MAX_D1D];
|
||||
|
||||
osc = 0;
|
||||
for (int c = 0; c < VDIM; ++c) // loop over x, y, z test components
|
||||
@@ -530,7 +528,7 @@ void PAHcurlHdivMassApply3D(const int D1D,
|
||||
}
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
double massX[DofQuadLimits::HDIV_MAX_D1D];
|
||||
double massX[HDIV_MAX_D1D];
|
||||
for (int dx = 0; dx < D1Dx; ++dx)
|
||||
{
|
||||
massX[dx] = 0.0;
|
||||
|
||||
@@ -92,12 +92,10 @@ inline void PAHcurlHdivApply3D(const int d1d,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_D1D_TEST || d1dtest <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1dtest > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_D1D_TEST ||
|
||||
d1dtest <= HCURL_MAX_D1D, "Error: d1dtest > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int D1Dtest = T_D1D_TEST ? T_D1D_TEST : d1dtest;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -122,8 +120,8 @@ inline void PAHcurlHdivApply3D(const int d1d,
|
||||
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int MD1D = T_D1D ? T_D1D :
|
||||
DofQuadLimits::HCURL_MAX_D1D; // Assuming HDIV_MAX_D1D <= HCURL_MAX_D1D
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
HCURL_MAX_D1D; // Assuming HDIV_MAX_D1D <= HCURL_MAX_D1D
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int D1Dtest = T_D1D_TEST ? T_D1D_TEST : d1dtest;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -461,12 +459,10 @@ inline void PAHcurlHdivApplyTranspose3D(const int d1d,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_D1D_TEST || d1dtest <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1dtest > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_D1D_TEST ||
|
||||
d1dtest <= HCURL_MAX_D1D, "Error: d1dtest > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int D1Dtest = T_D1D_TEST ? T_D1D_TEST : d1dtest;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -491,8 +487,8 @@ inline void PAHcurlHdivApplyTranspose3D(const int d1d,
|
||||
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int MD1D = T_D1D ? T_D1D :
|
||||
DofQuadLimits::HCURL_MAX_D1D; // Assuming HDIV_MAX_D1D <= HCURL_MAX_D1D
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
HCURL_MAX_D1D; // Assuming HDIV_MAX_D1D <= HCURL_MAX_D1D
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int D1Dtest = T_D1D_TEST ? T_D1D_TEST : d1dtest;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -176,6 +176,9 @@ void PAHdivMassAssembleDiagonal2D(const int D1D,
|
||||
const Vector &op_,
|
||||
Vector &diag_)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
auto Bc = Reshape(Bc_.Read(), Q1D, D1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, Q1D, symmetric ? 3 : 4, NE);
|
||||
@@ -183,9 +186,6 @@ void PAHdivMassAssembleDiagonal2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HDIV_MAX_Q1D;
|
||||
|
||||
int osc = 0;
|
||||
|
||||
for (int c = 0; c < VDIM; ++c) // loop over x, y components
|
||||
@@ -232,10 +232,8 @@ void PAHdivMassAssembleDiagonal3D(const int D1D,
|
||||
const Vector &op_,
|
||||
Vector &diag_)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HDIV_MAX_D1D,
|
||||
"Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HDIV_MAX_Q1D,
|
||||
"Error: Q1D > HDIV_MAX_Q1D");
|
||||
MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D > HDIV_MAX_Q1D");
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
@@ -256,7 +254,7 @@ void PAHdivMassAssembleDiagonal3D(const int D1D,
|
||||
const int opc = (c == 0) ? 0 : ((c == 1) ? (symmetric ? 3 : 4) :
|
||||
(symmetric ? 5 : 8));
|
||||
|
||||
double mass[DofQuadLimits::HDIV_MAX_Q1D];
|
||||
double mass[HDIV_MAX_Q1D];
|
||||
|
||||
for (int dz = 0; dz < D1Dz; ++dz)
|
||||
{
|
||||
@@ -349,6 +347,10 @@ void PAHdivMassApply2D(const int D1D,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HDIV_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
auto Bc = Reshape(Bc_.Read(), Q1D, D1D);
|
||||
auto Bot = Reshape(Bot_.Read(), D1D-1, Q1D);
|
||||
@@ -359,10 +361,6 @@ void PAHdivMassApply2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HDIV_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HDIV_MAX_Q1D;
|
||||
|
||||
double mass[MAX_Q1D][MAX_Q1D][VDIM];
|
||||
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
@@ -480,10 +478,8 @@ void PAHdivMassApply3D(const int D1D,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HDIV_MAX_D1D,
|
||||
"Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HDIV_MAX_Q1D,
|
||||
"Error: Q1D > HDIV_MAX_Q1D");
|
||||
MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D > HDIV_MAX_Q1D");
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
@@ -496,7 +492,7 @@ void PAHdivMassApply3D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
double mass[DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D][VDIM];
|
||||
double mass[HDIV_MAX_Q1D][HDIV_MAX_Q1D][HDIV_MAX_Q1D][VDIM];
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
@@ -522,7 +518,7 @@ void PAHdivMassApply3D(const int D1D,
|
||||
|
||||
for (int dz = 0; dz < D1Dz; ++dz)
|
||||
{
|
||||
double massXY[DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D];
|
||||
double massXY[HDIV_MAX_Q1D][HDIV_MAX_Q1D];
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
@@ -533,7 +529,7 @@ void PAHdivMassApply3D(const int D1D,
|
||||
|
||||
for (int dy = 0; dy < D1Dy; ++dy)
|
||||
{
|
||||
double massX[DofQuadLimits::HDIV_MAX_Q1D];
|
||||
double massX[HDIV_MAX_Q1D];
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
{
|
||||
massX[qx] = 0.0;
|
||||
@@ -604,7 +600,7 @@ void PAHdivMassApply3D(const int D1D,
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
double massXY[DofQuadLimits::HDIV_MAX_D1D][DofQuadLimits::HDIV_MAX_D1D];
|
||||
double massXY[HDIV_MAX_D1D][HDIV_MAX_D1D];
|
||||
|
||||
osc = 0;
|
||||
|
||||
@@ -623,7 +619,7 @@ void PAHdivMassApply3D(const int D1D,
|
||||
}
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
double massX[DofQuadLimits::HDIV_MAX_D1D];
|
||||
double massX[HDIV_MAX_D1D];
|
||||
for (int dx = 0; dx < D1Dx; ++dx)
|
||||
{
|
||||
massX[dx] = 0;
|
||||
@@ -734,6 +730,9 @@ void PADivDivAssembleDiagonal2D(const int D1D,
|
||||
const Vector &op_,
|
||||
Vector &diag_)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
auto Gc = Reshape(Gc_.Read(), Q1D, D1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, Q1D, NE);
|
||||
@@ -741,9 +740,6 @@ void PADivDivAssembleDiagonal2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HDIV_MAX_Q1D;
|
||||
|
||||
int osc = 0;
|
||||
|
||||
for (int c = 0; c < VDIM; ++c) // loop over x, y components
|
||||
@@ -790,10 +786,8 @@ void PADivDivAssembleDiagonal3D(const int D1D,
|
||||
const Vector &op_,
|
||||
Vector &diag_)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HDIV_MAX_D1D,
|
||||
"Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HDIV_MAX_Q1D,
|
||||
"Error: Q1D > HDIV_MAX_Q1D");
|
||||
MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D > HDIV_MAX_Q1D");
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
@@ -815,7 +809,7 @@ void PADivDivAssembleDiagonal3D(const int D1D,
|
||||
{
|
||||
for (int dy = 0; dy < D1Dy; ++dy)
|
||||
{
|
||||
double a[DofQuadLimits::HDIV_MAX_Q1D];
|
||||
double a[HDIV_MAX_Q1D];
|
||||
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
{
|
||||
@@ -861,6 +855,10 @@ void PADivDivApply2D(const int D1D,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HDIV_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
auto Bot = Reshape(Bot_.Read(), D1D-1, Q1D);
|
||||
auto Gc = Reshape(Gc_.Read(), Q1D, D1D);
|
||||
@@ -871,10 +869,6 @@ void PADivDivApply2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HDIV_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HDIV_MAX_Q1D;
|
||||
|
||||
double div[MAX_Q1D][MAX_Q1D];
|
||||
|
||||
// div[qy][qx] will be computed as du_x/dx + du_y/dy
|
||||
@@ -980,10 +974,8 @@ void PADivDivApply3D(const int D1D,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HDIV_MAX_D1D,
|
||||
"Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HDIV_MAX_Q1D,
|
||||
"Error: Q1D > HDIV_MAX_Q1D");
|
||||
MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D > HDIV_MAX_Q1D");
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
@@ -996,7 +988,7 @@ void PADivDivApply3D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
double div[DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D];
|
||||
double div[HDIV_MAX_Q1D][HDIV_MAX_Q1D][HDIV_MAX_Q1D];
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
@@ -1019,7 +1011,7 @@ void PADivDivApply3D(const int D1D,
|
||||
|
||||
for (int dz = 0; dz < D1Dz; ++dz)
|
||||
{
|
||||
double aXY[DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D];
|
||||
double aXY[HDIV_MAX_Q1D][HDIV_MAX_Q1D];
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
@@ -1030,7 +1022,7 @@ void PADivDivApply3D(const int D1D,
|
||||
|
||||
for (int dy = 0; dy < D1Dy; ++dy)
|
||||
{
|
||||
double aX[DofQuadLimits::HDIV_MAX_Q1D];
|
||||
double aX[HDIV_MAX_Q1D];
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
{
|
||||
aX[qx] = 0.0;
|
||||
@@ -1086,7 +1078,7 @@ void PADivDivApply3D(const int D1D,
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
double aXY[DofQuadLimits::HDIV_MAX_D1D][DofQuadLimits::HDIV_MAX_D1D];
|
||||
double aXY[HDIV_MAX_D1D][HDIV_MAX_D1D];
|
||||
|
||||
osc = 0;
|
||||
|
||||
@@ -1105,7 +1097,7 @@ void PADivDivApply3D(const int D1D,
|
||||
}
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
double aX[DofQuadLimits::HDIV_MAX_D1D];
|
||||
double aX[HDIV_MAX_D1D];
|
||||
for (int dx = 0; dx < D1Dx; ++dx)
|
||||
{
|
||||
aX[dx] = 0;
|
||||
@@ -1215,8 +1207,8 @@ void PAHdivL2AssembleDiagonal_ADAt_2D(const int D1D,
|
||||
// Compute row (rx,ry), assuming all contributions are from
|
||||
// a single element.
|
||||
|
||||
double row[2*DofQuadLimits::HDIV_MAX_D1D*(DofQuadLimits::HDIV_MAX_D1D-1)];
|
||||
double div[DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D];
|
||||
double row[2*HDIV_MAX_D1D*(HDIV_MAX_D1D-1)];
|
||||
double div[HDIV_MAX_Q1D][HDIV_MAX_Q1D];
|
||||
|
||||
for (int i=0; i<2*D1D*(D1D - 1); ++i)
|
||||
{
|
||||
@@ -1239,7 +1231,7 @@ void PAHdivL2AssembleDiagonal_ADAt_2D(const int D1D,
|
||||
const int D1Dy = (c == 1) ? D1D : D1D - 1;
|
||||
const int D1Dx = (c == 0) ? D1D : D1D - 1;
|
||||
|
||||
double aX[DofQuadLimits::HDIV_MAX_D1D];
|
||||
double aX[HDIV_MAX_D1D];
|
||||
for (int dx = 0; dx < D1Dx; ++dx)
|
||||
{
|
||||
aX[dx] = 0;
|
||||
@@ -1289,10 +1281,8 @@ void PAHdivL2AssembleDiagonal_ADAt_3D(const int D1D,
|
||||
const Vector &D_,
|
||||
Vector &diag_)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HDIV_MAX_D1D,
|
||||
"Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HDIV_MAX_Q1D,
|
||||
"Error: Q1D > HDIV_MAX_Q1D");
|
||||
MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D > HDIV_MAX_Q1D");
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
auto L2Bo = Reshape(L2Bo_.Read(), Q1D, L2D1D);
|
||||
@@ -1313,9 +1303,8 @@ void PAHdivL2AssembleDiagonal_ADAt_3D(const int D1D,
|
||||
// Compute row (rx,ry,rz), assuming all contributions are from
|
||||
// a single element.
|
||||
|
||||
double row[3*DofQuadLimits::HDIV_MAX_D1D*(DofQuadLimits::HDIV_MAX_D1D-1)*
|
||||
(DofQuadLimits::HDIV_MAX_D1D-1)];
|
||||
double div[DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D];
|
||||
double row[3*HDIV_MAX_D1D*(HDIV_MAX_D1D-1)*(HDIV_MAX_D1D-1)];
|
||||
double div[HDIV_MAX_Q1D][HDIV_MAX_Q1D][HDIV_MAX_Q1D];
|
||||
|
||||
for (int i=0; i<3*D1D*(D1D - 1)*(D1D - 1); ++i)
|
||||
{
|
||||
@@ -1336,7 +1325,7 @@ void PAHdivL2AssembleDiagonal_ADAt_3D(const int D1D,
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
double aXY[DofQuadLimits::HDIV_MAX_D1D][DofQuadLimits::HDIV_MAX_D1D];
|
||||
double aXY[HDIV_MAX_D1D][HDIV_MAX_D1D];
|
||||
|
||||
int osc = 0;
|
||||
for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
|
||||
@@ -1354,7 +1343,7 @@ void PAHdivL2AssembleDiagonal_ADAt_3D(const int D1D,
|
||||
}
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
double aX[DofQuadLimits::HDIV_MAX_D1D];
|
||||
double aX[HDIV_MAX_D1D];
|
||||
for (int dx = 0; dx < D1Dx; ++dx)
|
||||
{
|
||||
aX[dx] = 0;
|
||||
@@ -1419,6 +1408,10 @@ void PAHdivL2Apply2D(const int D1D,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HDIV_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
auto Gc = Reshape(Gc_.Read(), Q1D, D1D);
|
||||
auto L2Bot = Reshape(L2Bot_.Read(), L2D1D, Q1D);
|
||||
@@ -1428,10 +1421,6 @@ void PAHdivL2Apply2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HDIV_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HDIV_MAX_Q1D;
|
||||
|
||||
double div[MAX_Q1D][MAX_Q1D];
|
||||
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
@@ -1525,6 +1514,10 @@ void PAHdivL2ApplyTranspose2D(const int D1D,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HDIV_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
|
||||
|
||||
auto L2Bo = Reshape(L2Bo_.Read(), Q1D, L2D1D);
|
||||
auto Gct = Reshape(Gct_.Read(), D1D, Q1D);
|
||||
auto Bot = Reshape(Bot_.Read(), D1D-1, Q1D);
|
||||
@@ -1534,10 +1527,6 @@ void PAHdivL2ApplyTranspose2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HDIV_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HDIV_MAX_Q1D;
|
||||
|
||||
double div[MAX_Q1D][MAX_Q1D];
|
||||
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
@@ -1633,10 +1622,8 @@ void PAHdivL2Apply3D(const int D1D,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HDIV_MAX_D1D,
|
||||
"Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HDIV_MAX_Q1D,
|
||||
"Error: Q1D > HDIV_MAX_Q1D");
|
||||
MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D > HDIV_MAX_Q1D");
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
@@ -1648,7 +1635,7 @@ void PAHdivL2Apply3D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
double div[DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D];
|
||||
double div[HDIV_MAX_Q1D][HDIV_MAX_Q1D][HDIV_MAX_Q1D];
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
@@ -1671,7 +1658,7 @@ void PAHdivL2Apply3D(const int D1D,
|
||||
|
||||
for (int dz = 0; dz < D1Dz; ++dz)
|
||||
{
|
||||
double aXY[DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D];
|
||||
double aXY[HDIV_MAX_Q1D][HDIV_MAX_Q1D];
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
@@ -1682,7 +1669,7 @@ void PAHdivL2Apply3D(const int D1D,
|
||||
|
||||
for (int dy = 0; dy < D1Dy; ++dy)
|
||||
{
|
||||
double aX[DofQuadLimits::HDIV_MAX_Q1D];
|
||||
double aX[HDIV_MAX_Q1D];
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
{
|
||||
aX[qx] = 0.0;
|
||||
@@ -1737,7 +1724,7 @@ void PAHdivL2Apply3D(const int D1D,
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
double aXY[DofQuadLimits::HDIV_MAX_D1D][DofQuadLimits::HDIV_MAX_D1D];
|
||||
double aXY[HDIV_MAX_D1D][HDIV_MAX_D1D];
|
||||
|
||||
for (int dy = 0; dy < L2D1D; ++dy)
|
||||
{
|
||||
@@ -1748,7 +1735,7 @@ void PAHdivL2Apply3D(const int D1D,
|
||||
}
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
double aX[DofQuadLimits::HDIV_MAX_D1D];
|
||||
double aX[HDIV_MAX_D1D];
|
||||
for (int dx = 0; dx < L2D1D; ++dx)
|
||||
{
|
||||
aX[dx] = 0;
|
||||
@@ -1796,10 +1783,8 @@ void PAHdivL2ApplyTranspose3D(const int D1D,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HDIV_MAX_D1D,
|
||||
"Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HDIV_MAX_Q1D,
|
||||
"Error: Q1D > HDIV_MAX_Q1D");
|
||||
MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D > HDIV_MAX_Q1D");
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
auto L2Bo = Reshape(L2Bo_.Read(), Q1D, L2D1D);
|
||||
@@ -1811,7 +1796,7 @@ void PAHdivL2ApplyTranspose3D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
double div[DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D];
|
||||
double div[HDIV_MAX_Q1D][HDIV_MAX_Q1D][HDIV_MAX_Q1D];
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
@@ -1826,7 +1811,7 @@ void PAHdivL2ApplyTranspose3D(const int D1D,
|
||||
|
||||
for (int dz = 0; dz < L2D1D; ++dz)
|
||||
{
|
||||
double aXY[DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D];
|
||||
double aXY[HDIV_MAX_Q1D][HDIV_MAX_Q1D];
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
@@ -1837,7 +1822,7 @@ void PAHdivL2ApplyTranspose3D(const int D1D,
|
||||
|
||||
for (int dy = 0; dy < L2D1D; ++dy)
|
||||
{
|
||||
double aX[DofQuadLimits::HDIV_MAX_Q1D];
|
||||
double aX[HDIV_MAX_Q1D];
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
{
|
||||
aX[qx] = 0.0;
|
||||
@@ -1889,7 +1874,7 @@ void PAHdivL2ApplyTranspose3D(const int D1D,
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
double aXY[DofQuadLimits::HDIV_MAX_D1D][DofQuadLimits::HDIV_MAX_D1D];
|
||||
double aXY[HDIV_MAX_D1D][HDIV_MAX_D1D];
|
||||
|
||||
int osc = 0;
|
||||
for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
|
||||
@@ -1907,7 +1892,7 @@ void PAHdivL2ApplyTranspose3D(const int D1D,
|
||||
}
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
double aX[DofQuadLimits::HDIV_MAX_D1D];
|
||||
double aX[HDIV_MAX_D1D];
|
||||
for (int dx = 0; dx < D1Dx; ++dx)
|
||||
{
|
||||
aX[dx] = 0;
|
||||
|
||||
@@ -140,8 +140,8 @@ inline void SmemPAHdivMassApply2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::HDIV_MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::HDIV_MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : HDIV_MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : HDIV_MAX_D1D;
|
||||
constexpr int MDQ = (MQ1 > MD1) ? MQ1 : MD1;
|
||||
|
||||
MFEM_SHARED double smo[MQ1*(MD1-1)];
|
||||
@@ -310,8 +310,8 @@ inline void SmemPAHdivMassApply3D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::HDIV_MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::HDIV_MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : HDIV_MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : HDIV_MAX_D1D;
|
||||
constexpr int MDQ = (MQ1 > MD1) ? MQ1 : MD1;
|
||||
|
||||
MFEM_SHARED double smo[MQ1*(MD1-1)];
|
||||
|
||||
@@ -34,12 +34,11 @@ static void PAHcurlApplyGradient2D(const int c_dofs1D,
|
||||
auto x = Reshape(x_.Read(), c_dofs1D, c_dofs1D, NE);
|
||||
auto y = Reshape(y_.ReadWrite(), 2 * c_dofs1D * o_dofs1D, NE);
|
||||
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
double w[MAX_D1D][MAX_D1D];
|
||||
|
||||
// horizontal part
|
||||
@@ -111,12 +110,11 @@ static void PAHcurlApplyGradient2DBId(const int c_dofs1D,
|
||||
auto x = Reshape(x_.Read(), c_dofs1D, c_dofs1D, NE);
|
||||
auto y = Reshape(y_.ReadWrite(), 2 * c_dofs1D * o_dofs1D, NE);
|
||||
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
double w[MAX_D1D][MAX_D1D];
|
||||
|
||||
// horizontal part
|
||||
@@ -180,12 +178,11 @@ static void PAHcurlApplyGradientTranspose2D(
|
||||
auto x = Reshape(x_.Read(), 2 * c_dofs1D * o_dofs1D, NE);
|
||||
auto y = Reshape(y_.ReadWrite(), c_dofs1D, c_dofs1D, NE);
|
||||
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
double w[MAX_D1D][MAX_D1D];
|
||||
|
||||
// horizontal part (open x, closed y)
|
||||
@@ -256,12 +253,11 @@ static void PAHcurlApplyGradientTranspose2DBId(
|
||||
auto x = Reshape(x_.Read(), 2 * c_dofs1D * o_dofs1D, NE);
|
||||
auto y = Reshape(y_.ReadWrite(), c_dofs1D, c_dofs1D, NE);
|
||||
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
double w[MAX_D1D][MAX_D1D];
|
||||
|
||||
// horizontal part (open x, closed y)
|
||||
@@ -328,12 +324,11 @@ static void PAHcurlApplyGradient3D(const int c_dofs1D,
|
||||
auto x = Reshape(x_.Read(), c_dofs1D, c_dofs1D, c_dofs1D, NE);
|
||||
auto y = Reshape(y_.ReadWrite(), (3 * c_dofs1D * c_dofs1D * o_dofs1D), NE);
|
||||
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
double w1[MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
double w2[MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
|
||||
@@ -516,13 +511,11 @@ static void PAHcurlApplyGradient3DBId(const int c_dofs1D,
|
||||
auto x = Reshape(x_.Read(), c_dofs1D, c_dofs1D, c_dofs1D, NE);
|
||||
auto y = Reshape(y_.ReadWrite(), (3 * c_dofs1D * c_dofs1D * o_dofs1D), NE);
|
||||
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
|
||||
double w1[MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
double w2[MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
|
||||
@@ -685,12 +678,11 @@ static void PAHcurlApplyGradientTranspose3D(
|
||||
auto x = Reshape(x_.Read(), (3 * c_dofs1D * c_dofs1D * o_dofs1D), NE);
|
||||
auto y = Reshape(y_.ReadWrite(), c_dofs1D, c_dofs1D, c_dofs1D, NE);
|
||||
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
double w1[MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
double w2[MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
// ---
|
||||
@@ -871,13 +863,11 @@ static void PAHcurlApplyGradientTranspose3DBId(
|
||||
auto x = Reshape(x_.Read(), (3 * c_dofs1D * c_dofs1D * o_dofs1D), NE);
|
||||
auto y = Reshape(y_.ReadWrite(), c_dofs1D, c_dofs1D, c_dofs1D, NE);
|
||||
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
|
||||
double w1[MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
double w2[MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
// ---
|
||||
@@ -1162,13 +1152,12 @@ static void PAHcurlVecH1IdentityApply2D(const int c_dofs1D,
|
||||
|
||||
auto vk = Reshape(pa_data.Read(), 2, (2 * c_dofs1D * o_dofs1D), NE);
|
||||
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
|
||||
double w[2][MAX_D1D][MAX_D1D];
|
||||
|
||||
// dofs that point parallel to x-axis (open in x, closed in y)
|
||||
@@ -1262,13 +1251,13 @@ static void PAHcurlVecH1IdentityApplyTranspose2D(const int c_dofs1D,
|
||||
|
||||
auto vk = Reshape(pa_data.Read(), 2, (2 * c_dofs1D * o_dofs1D), NE);
|
||||
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
//constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
|
||||
double w[2][MAX_D1D][MAX_D1D];
|
||||
|
||||
// dofs that point parallel to x-axis (open in x, closed in y)
|
||||
@@ -1371,13 +1360,12 @@ static void PAHcurlVecH1IdentityApply3D(const int c_dofs1D,
|
||||
|
||||
auto vk = Reshape(pa_data.Read(), 3, (3 * c_dofs1D * c_dofs1D * o_dofs1D),
|
||||
NE);
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
|
||||
double w1[3][MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
double w2[3][MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
|
||||
@@ -1586,13 +1574,12 @@ static void PAHcurlVecH1IdentityApplyTranspose3D(const int c_dofs1D,
|
||||
auto vk = Reshape(pa_data.Read(), 3, (3 * c_dofs1D * c_dofs1D * o_dofs1D),
|
||||
NE);
|
||||
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
|
||||
double w1[3][MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
double w2[3][MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@ static void EAMassAssemble1D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(basis.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, NE);
|
||||
auto M = Reshape(eadata.ReadWrite(), D1D, D1D, NE);
|
||||
@@ -36,7 +36,7 @@ static void EAMassAssemble1D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
double r_Bi[MQ1];
|
||||
double r_Bj[MQ1];
|
||||
for (int q = 0; q < Q1D; q++)
|
||||
@@ -77,8 +77,8 @@ static void EAMassAssemble2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(basis.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, Q1D, NE);
|
||||
auto M = Reshape(eadata.ReadWrite(), D1D, D1D, D1D, D1D, NE);
|
||||
@@ -86,8 +86,8 @@ static void EAMassAssemble2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
double r_B[MQ1][MD1];
|
||||
for (int d = 0; d < D1D; d++)
|
||||
{
|
||||
@@ -149,8 +149,8 @@ static void EAMassAssemble3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(basis.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, Q1D, Q1D, NE);
|
||||
auto M = Reshape(eadata.ReadWrite(), D1D, D1D, D1D, D1D, D1D, D1D, NE);
|
||||
@@ -158,8 +158,8 @@ static void EAMassAssemble3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int DQ = T_D1D * T_Q1D;
|
||||
|
||||
// For quadratic and lower it's better to use registers but for higher-order you start to
|
||||
|
||||
@@ -25,6 +25,8 @@ static void PAMassAssembleDiagonal1D(const int NE,
|
||||
const int D1D,
|
||||
const int Q1D)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto D = Reshape(d.Read(), Q1D, NE);
|
||||
auto Y = Reshape(y.ReadWrite(), D1D, NE);
|
||||
@@ -32,6 +34,7 @@ static void PAMassAssembleDiagonal1D(const int NE,
|
||||
{
|
||||
for (int dx = 0; dx < D1D; ++dx)
|
||||
{
|
||||
Y(dx, e) = 0.0;
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
{
|
||||
Y(dx, e) += B(qx, dx) * B(qx, dx) * D(qx, e);
|
||||
@@ -195,7 +198,8 @@ void PAMassApply1D_Element(const int e,
|
||||
auto X = ConstDeviceMatrix(x_, D1D, NE);
|
||||
auto Y = DeviceMatrix(y_, D1D, NE);
|
||||
|
||||
double XQ[DofQuadLimits::MAX_Q1D];
|
||||
constexpr int max_Q1D = MAX_Q1D;
|
||||
double XQ[max_Q1D];
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
{
|
||||
XQ[qx] = 0.0;
|
||||
@@ -228,8 +232,8 @@ static void PAMassApply1D(const int NE,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
MFEM_VERIFY(d1d <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(q1d <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(d1d <= MAX_D1D, "");
|
||||
MFEM_VERIFY(q1d <= MAX_Q1D, "");
|
||||
|
||||
const auto B = b_.Read();
|
||||
const auto Bt = bt_.Read();
|
||||
|
||||
@@ -42,8 +42,8 @@ inline void PAMassAssembleDiagonal2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto D = Reshape(d.Read(), Q1D, Q1D, NE);
|
||||
auto Y = Reshape(y.ReadWrite(), D1D, D1D, NE);
|
||||
@@ -51,8 +51,8 @@ inline void PAMassAssembleDiagonal2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
double QD[MQ1][MD1];
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
{
|
||||
@@ -90,10 +90,10 @@ inline void SmemPAMassAssembleDiagonal2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
const int max_q1d = T_Q1D ? T_Q1D : DeviceDofQuadLimits::Get().MAX_Q1D;
|
||||
const int max_d1d = T_D1D ? T_D1D : DeviceDofQuadLimits::Get().MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= max_d1d, "");
|
||||
MFEM_VERIFY(Q1D <= max_q1d, "");
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= MD1, "");
|
||||
MFEM_VERIFY(Q1D <= MQ1, "");
|
||||
auto b = Reshape(b_.Read(), Q1D, D1D);
|
||||
auto D = Reshape(d_.Read(), Q1D, Q1D, NE);
|
||||
auto Y = Reshape(y_.ReadWrite(), D1D, D1D, NE);
|
||||
@@ -103,8 +103,8 @@ inline void SmemPAMassAssembleDiagonal2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_SHARED double B[MQ1][MD1];
|
||||
MFEM_SHARED double QDZ[NBZ][MQ1][MD1];
|
||||
double (*QD)[MD1] = (double (*)[MD1])(QDZ + tidz);
|
||||
@@ -156,8 +156,8 @@ inline void PAMassAssembleDiagonal3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto D = Reshape(d.Read(), Q1D, Q1D, Q1D, NE);
|
||||
auto Y = Reshape(y.ReadWrite(), D1D, D1D, D1D, NE);
|
||||
@@ -165,8 +165,8 @@ inline void PAMassAssembleDiagonal3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
double QQD[MQ1][MQ1][MD1];
|
||||
double QDD[MQ1][MD1][MD1];
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
@@ -226,10 +226,10 @@ inline void SmemPAMassAssembleDiagonal3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
const int max_q1d = T_Q1D ? T_Q1D : DeviceDofQuadLimits::Get().MAX_Q1D;
|
||||
const int max_d1d = T_D1D ? T_D1D : DeviceDofQuadLimits::Get().MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= max_d1d, "");
|
||||
MFEM_VERIFY(Q1D <= max_q1d, "");
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= MD1, "");
|
||||
MFEM_VERIFY(Q1D <= MQ1, "");
|
||||
auto b = Reshape(b_.Read(), Q1D, D1D);
|
||||
auto D = Reshape(d_.Read(), Q1D, Q1D, Q1D, NE);
|
||||
auto Y = Reshape(y_.ReadWrite(), D1D, D1D, D1D, NE);
|
||||
@@ -238,8 +238,8 @@ inline void SmemPAMassAssembleDiagonal3D(const int NE,
|
||||
const int tidz = MFEM_THREAD_ID(z);
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
MFEM_SHARED double B[MQ1][MD1];
|
||||
MFEM_SHARED double QQD[MQ1][MQ1][MD1];
|
||||
MFEM_SHARED double QDD[MQ1][MD1][MD1];
|
||||
@@ -365,8 +365,8 @@ void PAMassApply2D_Element(const int e,
|
||||
}
|
||||
}
|
||||
|
||||
constexpr int max_D1D = DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = MAX_D1D;
|
||||
constexpr int max_Q1D = MAX_Q1D;
|
||||
double sol_xy[max_Q1D][max_Q1D];
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
@@ -447,8 +447,8 @@ void SmemPAMassApply2D_Element(const int e,
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MDQ = (MQ1 > MD1) ? MQ1 : MD1;
|
||||
|
||||
auto b = ConstDeviceMatrix(b_, Q1D, D1D);
|
||||
@@ -592,8 +592,8 @@ void PAMassApply3D_Element(const int e,
|
||||
}
|
||||
}
|
||||
|
||||
constexpr int max_D1D = DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = MAX_D1D;
|
||||
constexpr int max_Q1D = MAX_Q1D;
|
||||
double sol_xyz[max_Q1D][max_Q1D][max_Q1D];
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
@@ -722,8 +722,8 @@ void SmemPAMassApply3D_Element(const int e,
|
||||
{
|
||||
constexpr int D1D = T_D1D ? T_D1D : d1d;
|
||||
constexpr int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MDQ = (MQ1 > MD1) ? MQ1 : MD1;
|
||||
|
||||
auto b = ConstDeviceMatrix(b_, Q1D, D1D);
|
||||
@@ -948,8 +948,8 @@ inline void PAMassApply2D(const int NE,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D ? T_D1D : d1d <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(T_Q1D ? T_Q1D : q1d <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(T_D1D ? T_D1D : d1d <= MAX_D1D, "");
|
||||
MFEM_VERIFY(T_Q1D ? T_Q1D : q1d <= MAX_Q1D, "");
|
||||
|
||||
const auto B = b_.Read();
|
||||
const auto Bt = bt_.Read();
|
||||
@@ -978,10 +978,10 @@ inline void SmemPAMassApply2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
const int max_q1d = T_Q1D ? T_Q1D : DeviceDofQuadLimits::Get().MAX_Q1D;
|
||||
const int max_d1d = T_D1D ? T_D1D : DeviceDofQuadLimits::Get().MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= max_d1d, "");
|
||||
MFEM_VERIFY(Q1D <= max_q1d, "");
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= MD1, "");
|
||||
MFEM_VERIFY(Q1D <= MQ1, "");
|
||||
const auto b = b_.Read();
|
||||
const auto D = d_.Read();
|
||||
const auto x = x_.Read();
|
||||
@@ -1004,8 +1004,8 @@ inline void PAMassApply3D(const int NE,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D ? T_D1D : d1d <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(T_Q1D ? T_Q1D : q1d <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(T_D1D ? T_D1D : d1d <= MAX_D1D, "");
|
||||
MFEM_VERIFY(T_Q1D ? T_Q1D : q1d <= MAX_Q1D, "");
|
||||
|
||||
const auto B = b_.Read();
|
||||
const auto Bt = bt_.Read();
|
||||
@@ -1033,10 +1033,10 @@ inline void SmemPAMassApply3D(const int NE,
|
||||
MFEM_CONTRACT_VAR(bt_);
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
const int max_q1d = T_Q1D ? T_Q1D : DeviceDofQuadLimits::Get().MAX_Q1D;
|
||||
const int max_d1d = T_D1D ? T_D1D : DeviceDofQuadLimits::Get().MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= max_d1d, "");
|
||||
MFEM_VERIFY(Q1D <= max_q1d, "");
|
||||
constexpr int M1Q = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int M1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= M1D, "");
|
||||
MFEM_VERIFY(Q1D <= M1Q, "");
|
||||
auto b = b_.Read();
|
||||
auto d = d_.Read();
|
||||
auto x = x_.Read();
|
||||
|
||||
@@ -128,7 +128,7 @@ void MassIntegrator::AssemblePABoundary(const FiniteElementSpace &fes)
|
||||
|
||||
int map_type = el.GetMapType();
|
||||
dim = el.GetDim(); // Dimension of the boundary element, *not* the mesh
|
||||
ne = fes.GetMesh()->GetNFbyType(FaceType::Boundary);
|
||||
ne = fes.GetMesh()->GetNBE();
|
||||
nq = ir->GetNPoints();
|
||||
face_geom = mesh->GetFaceGeometricFactors(*ir, GeometricFactors::DETERMINANTS,
|
||||
FaceType::Boundary, mt);
|
||||
|
||||
@@ -31,6 +31,10 @@ static void PAHcurlH1Apply2D(const int D1D,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
auto Bc = Reshape(bc.Read(), Q1D, D1D);
|
||||
auto Gc = Reshape(gc.Read(), Q1D, D1D);
|
||||
auto Bot = Reshape(bot.Read(), D1D-1, Q1D);
|
||||
@@ -41,10 +45,6 @@ static void PAHcurlH1Apply2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
double mass[MAX_Q1D][MAX_Q1D][VDIM];
|
||||
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
@@ -155,6 +155,10 @@ static void PAHcurlH1ApplyTranspose2D(const int D1D,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
auto Bc = Reshape(bc.Read(), Q1D, D1D);
|
||||
auto Bo = Reshape(bo.Read(), Q1D, D1D-1);
|
||||
auto Bt = Reshape(bct.Read(), D1D, Q1D);
|
||||
@@ -165,10 +169,6 @@ static void PAHcurlH1ApplyTranspose2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
double mass[MAX_Q1D][MAX_Q1D][VDIM];
|
||||
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
@@ -280,10 +280,11 @@ static void PAHcurlH1Apply3D(const int D1D,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: Q1D > MAX_Q1D");
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
|
||||
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
@@ -297,9 +298,6 @@ static void PAHcurlH1Apply3D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
double mass[MAX_Q1D][MAX_Q1D][MAX_Q1D][VDIM];
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
@@ -472,10 +470,11 @@ static void PAHcurlH1ApplyTranspose3D(const int D1D,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: Q1D > MAX_Q1D");
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
|
||||
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
@@ -489,9 +488,6 @@ static void PAHcurlH1ApplyTranspose3D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
double mass[MAX_Q1D][MAX_Q1D][MAX_Q1D][VDIM];
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
|
||||
@@ -233,8 +233,8 @@ static void PAVectorDiffusionDiagonal2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
// note the different shape for D, this is a (symmetric) matrix so we only
|
||||
@@ -245,8 +245,8 @@ static void PAVectorDiffusionDiagonal2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
// gradphi \cdot Q \gradphi has four terms
|
||||
double QD0[MQ1][MD1];
|
||||
double QD1[MQ1][MD1];
|
||||
@@ -301,10 +301,10 @@ static void PAVectorDiffusionDiagonal3D(const int NE,
|
||||
constexpr int DIM = 3;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
const int max_q1d = T_Q1D ? T_Q1D : DeviceDofQuadLimits::Get().MAX_Q1D;
|
||||
const int max_d1d = T_D1D ? T_D1D : DeviceDofQuadLimits::Get().MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= max_d1d, "");
|
||||
MFEM_VERIFY(Q1D <= max_q1d, "");
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= MD1, "");
|
||||
MFEM_VERIFY(Q1D <= MQ1, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto Q = Reshape(d.Read(), Q1D*Q1D*Q1D, 6, NE);
|
||||
@@ -313,8 +313,8 @@ static void PAVectorDiffusionDiagonal3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
double QQD[MQ1][MQ1][MD1];
|
||||
double QDD[MQ1][MD1][MD1];
|
||||
for (int i = 0; i < DIM; ++i)
|
||||
@@ -442,8 +442,8 @@ void PAVectorDiffusionApply2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
const int VDIM = T_VDIM ? T_VDIM : vdim;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
@@ -456,8 +456,8 @@ void PAVectorDiffusionApply2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
const int VDIM = T_VDIM ? T_VDIM : vdim;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
|
||||
double grad[max_Q1D][max_Q1D][2];
|
||||
for (int c = 0; c < VDIM; c++)
|
||||
@@ -563,8 +563,8 @@ void PAVectorDiffusionApply3D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int VDIM = 3;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
@@ -576,8 +576,8 @@ void PAVectorDiffusionApply3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
for (int c = 0; c < VDIM; ++ c)
|
||||
{
|
||||
double grad[max_Q1D][max_Q1D][max_Q1D][3];
|
||||
|
||||
@@ -170,9 +170,9 @@ static void PADivergenceApply2D(const int NE,
|
||||
const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(TR_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(TR_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, TR_D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, TR_D1D);
|
||||
auto Bt = Reshape(bt.Read(), TE_D1D, Q1D);
|
||||
@@ -186,8 +186,8 @@ static void PADivergenceApply2D(const int NE,
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
const int VDIM = 2;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_TE_D1D = T_TE_D1D ? T_TE_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_TE_D1D = T_TE_D1D ? T_TE_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
|
||||
double grad[max_Q1D][max_Q1D][VDIM];
|
||||
double div[max_Q1D][max_Q1D];
|
||||
@@ -308,9 +308,9 @@ static void PADivergenceApplyTranspose2D(const int NE,
|
||||
const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(TR_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(TR_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto Bt = Reshape(bt.Read(), TR_D1D, Q1D);
|
||||
auto Gt = Reshape(gt.Read(), TR_D1D, Q1D);
|
||||
auto B = Reshape(b.Read(), Q1D, TE_D1D);
|
||||
@@ -324,8 +324,8 @@ static void PADivergenceApplyTranspose2D(const int NE,
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
const int VDIM = 2;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_TR_D1D = T_TR_D1D ? T_TR_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_TR_D1D = T_TR_D1D ? T_TR_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
|
||||
double quadTest[max_Q1D][max_Q1D];
|
||||
double grad[max_Q1D][max_Q1D][VDIM];
|
||||
@@ -424,9 +424,9 @@ static void PADivergenceApply3D(const int NE,
|
||||
const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(TR_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(TR_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, TR_D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, TR_D1D);
|
||||
auto Bt = Reshape(bt.Read(), TE_D1D, Q1D);
|
||||
@@ -440,8 +440,8 @@ static void PADivergenceApply3D(const int NE,
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
const int VDIM = 3;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_TE_D1D = T_TE_D1D ? T_TE_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_TE_D1D = T_TE_D1D ? T_TE_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
|
||||
double grad[max_Q1D][max_Q1D][max_Q1D][VDIM];
|
||||
double div[max_Q1D][max_Q1D][max_Q1D];
|
||||
@@ -607,9 +607,9 @@ static void PADivergenceApplyTranspose3D(const int NE,
|
||||
const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(TR_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(TR_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto Bt = Reshape(bt.Read(), TR_D1D, Q1D);
|
||||
auto Gt = Reshape(gt.Read(), TR_D1D, Q1D);
|
||||
auto B = Reshape(b.Read(), Q1D, TE_D1D);
|
||||
@@ -623,8 +623,8 @@ static void PADivergenceApplyTranspose3D(const int NE,
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
const int VDIM = 3;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_TR_D1D = T_TR_D1D ? T_TR_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_TR_D1D = T_TR_D1D ? T_TR_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
|
||||
double quadTest[max_Q1D][max_Q1D][max_Q1D];
|
||||
double grad[max_Q1D][max_Q1D][max_Q1D][VDIM];
|
||||
@@ -786,9 +786,9 @@ static void SmemPADivergenceApply3D(const int NE,
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
MFEM_VERIFY(TR_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(TR_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
|
||||
auto b = Reshape(b_.Read(), Q1D, TR_D1D);
|
||||
auto g = Reshape(g_.Read(), Q1D, TR_D1D);
|
||||
@@ -804,9 +804,9 @@ static void SmemPADivergenceApply3D(const int NE,
|
||||
const int D1DR = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int D1DE = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1R = T_TR_D1D ? T_TR_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MD1E = T_TE_D1D ? T_TE_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1R = T_TR_D1D ? T_TR_D1D : MAX_D1D;
|
||||
constexpr int MD1E = T_TE_D1D ? T_TE_D1D : MAX_D1D;
|
||||
constexpr int MD1 = MD1E > MD1R ? MD1E : MD1R;
|
||||
constexpr int MDQ = MQ1 > MD1 ? MQ1 : MD1;
|
||||
MFEM_SHARED double sBG[2][MQ1*MD1];
|
||||
|
||||
@@ -118,8 +118,8 @@ static void PAVectorMassAssembleDiagonal2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int VDIM = 2;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(B_.Read(), Q1D, D1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, Q1D, NE);
|
||||
auto y = Reshape(diag_.ReadWrite(), D1D, D1D, VDIM, NE);
|
||||
@@ -127,8 +127,8 @@ static void PAVectorMassAssembleDiagonal2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
|
||||
double temp[max_Q1D][max_D1D];
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
@@ -170,8 +170,8 @@ static void PAVectorMassAssembleDiagonal3D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int VDIM = 3;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(B_.Read(), Q1D, D1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, Q1D, Q1D, NE);
|
||||
auto y = Reshape(diag_.ReadWrite(), D1D, D1D, D1D, VDIM, NE);
|
||||
@@ -180,8 +180,8 @@ static void PAVectorMassAssembleDiagonal3D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d; // nvcc workaround
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
|
||||
double temp[max_Q1D][max_Q1D][max_D1D];
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
@@ -281,8 +281,8 @@ static void PAVectorMassApply2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int VDIM = 2;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(B_.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(Bt_.Read(), D1D, Q1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, Q1D, NE);
|
||||
@@ -293,8 +293,8 @@ static void PAVectorMassApply2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d; // nvcc workaround
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
double sol_xy[max_Q1D][max_Q1D];
|
||||
for (int c = 0; c < VDIM; ++c)
|
||||
{
|
||||
@@ -377,8 +377,8 @@ static void PAVectorMassApply3D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int VDIM = 3;
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(B_.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(Bt_.Read(), D1D, Q1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, Q1D, Q1D, NE);
|
||||
@@ -388,8 +388,8 @@ static void PAVectorMassApply3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
double sol_xyz[max_Q1D][max_Q1D][max_Q1D];
|
||||
for (int c = 0; c < VDIM; ++ c)
|
||||
{
|
||||
|
||||
@@ -38,7 +38,7 @@ static void BLFEvalAssemble2D(const int vdim, const int nbe, const int d,
|
||||
{
|
||||
if (M(e) == 0) { return; } // ignore
|
||||
|
||||
constexpr int Q = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int Q = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
double QQ[Q];
|
||||
|
||||
for (int c = 0; c < vdim; ++c)
|
||||
@@ -92,8 +92,8 @@ static void BLFEvalAssemble3D(const int vdim, const int nbe, const int d,
|
||||
{
|
||||
if (M(e) == 0) { return; } // ignore
|
||||
|
||||
constexpr int Q = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int Q = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int D = T_D1D ? T_D1D : MAX_D1D;
|
||||
|
||||
MFEM_SHARED double sBt[Q*D];
|
||||
MFEM_SHARED double sQQ[Q*Q];
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user