Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e176bb8d06 | ||
|
|
c1509fde91 | ||
|
|
44f25808b9 | ||
|
|
8296bca522 | ||
|
|
d4825be0ca | ||
|
|
ff143322bd | ||
|
|
b08c652314 |
@@ -1,49 +0,0 @@
|
||||
version: '{build}'
|
||||
|
||||
# https://www.appveyor.com/docs/build-environment/#build-worker-images
|
||||
image: Visual Studio 2017
|
||||
|
||||
install:
|
||||
|
||||
# Install MS-MPI
|
||||
- ps: Start-FileDownload 'https://download.microsoft.com/download/B/2/E/B2EB83FE-98C2-4156-834A-E1711E6884FB/MSMpiSetup.exe'
|
||||
- MSMpiSetup.exe -unattend
|
||||
- set PATH=C:\Program Files\Microsoft MPI\Bin;%PATH%
|
||||
|
||||
# Install MS-MPI SDK
|
||||
- ps: Start-FileDownload 'https://download.microsoft.com/download/B/2/E/B2EB83FE-98C2-4156-834A-E1711E6884FB/msmpisdk.msi'
|
||||
- msmpisdk.msi /passive
|
||||
- set PATH=C:\Program Files\Microsoft MPI\Bin;%PATH%
|
||||
|
||||
# Install METIS
|
||||
- ps: Start-FileDownload 'http://glaros.dtc.umn.edu/gkhome/fetch/sw/metis/metis-5.1.0.tar.gz'
|
||||
- 7z x metis-5.1.0.tar.gz -so | 7z x -si -ttar > nul
|
||||
- cd metis-5.1.0
|
||||
- ps: ( get-content "GKlib\gk_arch.h") | % { If ($_.ReadCount -ge 52) {$_ -replace "#ifdef __MSC__","#ifdef DISABLE_THIS_ANCIENT_MSC_CHECK"} Else {$_} } | set-content "GKlib\gk_arch.h"
|
||||
- cmake -H. -Bbuild
|
||||
# -DCMAKE_BUILD_TYPE=Release
|
||||
- cmake --build build
|
||||
- cd ..
|
||||
|
||||
# Install hypre
|
||||
- ps: Start-FileDownload 'https://computation.llnl.gov/project/linear_solvers/download/hypre-2.10.0b.tar.gz'
|
||||
- 7z x hypre-2.10.0b.tar.gz -so | 7z x -si -ttar > nul
|
||||
- cd hypre-2.10.0b
|
||||
- cmake -Hsrc -Bbuild -DMPI_C_INCLUDE_PATH="C:\Program Files (x86)\Microsoft SDKs\MPI\Include" -DMPI_C_LIBRARIES="C:\Program Files (x86)\Microsoft SDKs\MPI\Lib\x86\msmpi.lib" -DMPI_CXX_LIBRARIES="C:\Program Files (x86)\Microsoft SDKs\MPI\Lib\x86\msmpi.lib" -DMPI_CXX_INCLUDE_PATH="C:\Program Files (x86)\Microsoft SDKs\MPI\Include"
|
||||
# - cmake -Hsrc -Bbuild -DCMAKE_BUILD_TYPE=Release -DMPI_C_INCLUDE_PATH="C:\Program Files (x86)\Microsoft SDKs\MPI\Include" -DMPI_C_LIBRARIES="C:\Program Files (x86)\Microsoft SDKs\MPI\Lib\x86\msmpi.lib" -DMPI_CXX_LIBRARIES="C:\Program Files (x86)\Microsoft SDKs\MPI\Lib\x86\msmpi.lib" -DMPI_CXX_INCLUDE_PATH="C:\Program Files (x86)\Microsoft SDKs\MPI\Include"
|
||||
- cmake --build build
|
||||
- cmake --build build --target install
|
||||
- cd ..
|
||||
|
||||
# MFEM
|
||||
before_build:
|
||||
- cmake -H. -DCMAKE_INSTALL_PREFIX=install -Bbuild_parallel -DMFEM_USE_MPI=TRUE -DMFEM_USE_METIS_5=TRUE -DMPI_CXX_LIBRARIES="C:\Program Files (x86)\Microsoft SDKs\MPI\Lib\x86\msmpi.lib" -DMPI_CXX_INCLUDE_PATH="C:\Program Files (x86)\Microsoft SDKs\MPI\Include" -DHYPRE_LIBRARIES=%cd%\hypre-2.10.0b\src\hypre\lib\HYPRE.lib -DHYPRE_INCLUDE_DIRS=%cd%\hypre-2.10.0b\src\hypre\include -DHYPRE_VERSION=21000 -DMETIS_LIBRARIES=%cd%\metis-5.1.0\build\libmetis\Debug\metis.lib -DMETIS_INCLUDE_DIRS=%cd%\metis-5.1.0\include
|
||||
- cmake -H. -DCMAKE_INSTALL_PREFIX=install -Bbuild_serial -DMFEM_USE_MPI=FALSE -DMFEM_USE_METIS_5=TRUE -DMPI_CXX_LIBRARIES="C:\Program Files (x86)\Microsoft SDKs\MPI\Lib\x86\msmpi.lib" -DMPI_CXX_INCLUDE_PATH="C:\Program Files (x86)\Microsoft SDKs\MPI\Include" -DHYPRE_LIBRARIES=%cd%\hypre-2.10.0b\src\hypre\lib\HYPRE.lib -DHYPRE_INCLUDE_DIRS=%cd%\hypre-2.10.0b\src\hypre\include -DHYPRE_VERSION=21000 -DMETIS_LIBRARIES=%cd%\metis-5.1.0\build\libmetis\Debug\metis.lib -DMETIS_INCLUDE_DIRS=%cd%\metis-5.1.0\include
|
||||
|
||||
build_script:
|
||||
- cmake --build build_parallel
|
||||
- cmake --build build_serial
|
||||
|
||||
after_build:
|
||||
# - cmake --build build_parallel --target check
|
||||
- cmake --build build_serial --target check
|
||||
@@ -1,167 +0,0 @@
|
||||
# ------------------------------------------------------------------------------
|
||||
# Ignore files that are generated from the repository sources by either building
|
||||
# the code or running it. These should be the same as the files erased by
|
||||
# `make distclean`.
|
||||
#
|
||||
# Also ignore OS-specific files like .DS_Store on Mac
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Object and library files
|
||||
*.o
|
||||
/libmfem.*
|
||||
|
||||
# CMake generated files
|
||||
CMakeCache.txt
|
||||
CMakeFiles/
|
||||
|
||||
# Backup files
|
||||
*~
|
||||
|
||||
# Default install location
|
||||
/mfem/
|
||||
|
||||
# Generated files in main directory, config/ and docs/
|
||||
/deps.mk
|
||||
config/_config.hpp
|
||||
config/config.mk
|
||||
config/sample-runs-build.log
|
||||
doc/CodeDocumentation.conf
|
||||
doc/CodeDocumentation.html
|
||||
doc/CodeDocumentation
|
||||
|
||||
# Temporary files created by the tests.
|
||||
*.stderr
|
||||
|
||||
# Totalview breakpoint files
|
||||
*.TVD.*breakpoints
|
||||
|
||||
# OS-specific: Mac
|
||||
*.dSYM
|
||||
.DS_Store
|
||||
|
||||
# Example and miniapp binaries and outputs
|
||||
|
||||
examples/ex[1-9]
|
||||
examples/ex[1-9]p
|
||||
examples/ex1[04-9]
|
||||
examples/ex1[0-9]p
|
||||
|
||||
examples/refined.mesh
|
||||
examples/displaced.mesh
|
||||
examples/mesh.*
|
||||
examples/ex5.mesh
|
||||
examples/Example5*
|
||||
examples/Example9*
|
||||
examples/Example15*
|
||||
examples/Example16*
|
||||
examples/sphere_refined.*
|
||||
examples/sol.*
|
||||
examples/sol_u.*
|
||||
examples/sol_p.*
|
||||
examples/ex9.mesh
|
||||
examples/ex9-mesh.*
|
||||
examples/ex9-init.*
|
||||
examples/ex9-final.*
|
||||
examples/deformed.*
|
||||
examples/velocity.*
|
||||
examples/elastic_energy.*
|
||||
examples/mode_*
|
||||
examples/ex16.mesh
|
||||
examples/ex16-mesh.*
|
||||
examples/ex16-init.*
|
||||
examples/ex16-final.*
|
||||
examples/vortex-mesh.*
|
||||
examples/vortex.mesh
|
||||
examples/vortex-?-init.*
|
||||
examples/vortex-?-final.*
|
||||
examples/deformation.*
|
||||
examples/pressure.*
|
||||
|
||||
examples/sundials/ex9
|
||||
examples/sundials/ex1[06]
|
||||
examples/sundials/ex9p
|
||||
examples/sundials/ex1[06]p
|
||||
|
||||
examples/sundials/ex9.mesh
|
||||
examples/sundials/ex9-mesh.*
|
||||
examples/sundials/ex9-init.*
|
||||
examples/sundials/ex9-final.*
|
||||
examples/sundials/Example9*
|
||||
examples/sundials/deformed.*
|
||||
examples/sundials/velocity.*
|
||||
examples/sundials/elastic_energy.*
|
||||
examples/sundials/ex16.mesh
|
||||
examples/sundials/ex16-mesh.*
|
||||
examples/sundials/ex16-init.*
|
||||
examples/sundials/ex16-final.*
|
||||
examples/sundials/Example16*
|
||||
|
||||
examples/petsc/ex[1-69]p
|
||||
examples/petsc/ex10p
|
||||
|
||||
examples/petsc/mesh.*
|
||||
examples/petsc/sol.*
|
||||
examples/petsc/sol_p.*
|
||||
examples/petsc/sol_u.*
|
||||
examples/petsc/Example5*
|
||||
examples/petsc/ex9-mesh.*
|
||||
examples/petsc/ex9-init.*
|
||||
examples/petsc/ex9-final.*
|
||||
examples/petsc/Example9*
|
||||
examples/petsc/deformed.*
|
||||
examples/petsc/velocity.*
|
||||
examples/petsc/elastic_energy.*
|
||||
|
||||
examples/pumi/ex1
|
||||
examples/pumi/ex[126]p
|
||||
|
||||
examples/pumi/refined.mesh
|
||||
examples/pumi/sol.gf
|
||||
examples/pumi/mesh.*
|
||||
examples/pumi/sol.*
|
||||
examples/pumi/displaced.mesh
|
||||
|
||||
miniapps/electromagnetics/volta
|
||||
miniapps/electromagnetics/tesla
|
||||
miniapps/electromagnetics/maxwell
|
||||
miniapps/electromagnetics/joule
|
||||
|
||||
miniapps/electromagnetics/Volta-AMR*
|
||||
miniapps/electromagnetics/Tesla-AMR*
|
||||
miniapps/electromagnetics/Maxwell-Parallel*
|
||||
miniapps/electromagnetics/Joule_*
|
||||
|
||||
miniapps/meshing/mobius-strip
|
||||
miniapps/meshing/klein-bottle
|
||||
miniapps/meshing/mesh-explorer
|
||||
miniapps/meshing/shaper
|
||||
miniapps/meshing/mesh-optimizer
|
||||
miniapps/meshing/pmesh-optimizer
|
||||
|
||||
miniapps/meshing/mobius-strip.mesh
|
||||
miniapps/meshing/klein-bottle.mesh
|
||||
miniapps/meshing/mesh-explorer.mesh
|
||||
miniapps/meshing/partitioning.txt
|
||||
miniapps/meshing/shaper.mesh
|
||||
miniapps/meshing/optimized*
|
||||
miniapps/meshing/perturbed*
|
||||
|
||||
miniapps/performance/ex1
|
||||
miniapps/performance/ex1p
|
||||
|
||||
miniapps/performance/refined.mesh
|
||||
miniapps/performance/mesh.*
|
||||
miniapps/performance/sol.*
|
||||
|
||||
miniapps/tools/display-basis
|
||||
miniapps/tools/load-dc
|
||||
miniapps/tools/convert-dc
|
||||
|
||||
miniapps/nurbs/ex1
|
||||
miniapps/nurbs/ex1p
|
||||
miniapps/nurbs/ex11p
|
||||
miniapps/nurbs/refined.mesh
|
||||
miniapps/nurbs/mesh.*
|
||||
miniapps/nurbs/sol.*
|
||||
miniapps/nurbs/mode_*
|
||||
miniapps/nurbs/Example1*
|
||||
@@ -1,207 +1,55 @@
|
||||
sudo: false
|
||||
|
||||
language: cpp
|
||||
|
||||
matrix:
|
||||
include:
|
||||
#
|
||||
# Linux
|
||||
#
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: DEBUG=YES
|
||||
MPI=NO
|
||||
CODECOV=NO
|
||||
MFEM_TEST_TARGET=check
|
||||
#
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
env: DEBUG=NO
|
||||
MPI=NO
|
||||
CODECOV=NO
|
||||
MFEM_TEST_TARGET=test
|
||||
#
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
packages:
|
||||
# GCC 4.9
|
||||
# - g++-4.9
|
||||
# MPICH
|
||||
- mpich
|
||||
- libmpich-dev
|
||||
# OpenMPI
|
||||
# - openmpi-bin
|
||||
# - libopenmpi-dev
|
||||
env: DEBUG=YES
|
||||
MPI=YES
|
||||
CODECOV=NO
|
||||
MFEM_TEST_TARGET=check
|
||||
NPROCS=2
|
||||
cache:
|
||||
directories:
|
||||
- $TRAVIS_BUILD_DIR/../hypre-2.10.0b/src/hypre/lib
|
||||
- $TRAVIS_BUILD_DIR/../hypre-2.10.0b/src/hypre/include
|
||||
- $TRAVIS_BUILD_DIR/../metis-4.0
|
||||
before_cache:
|
||||
- cd $TRAVIS_BUILD_DIR/../metis-4.0;
|
||||
mv libmetis.a ..; rm -rf *; mv ../libmetis.a .
|
||||
#
|
||||
- os: linux
|
||||
compiler: gcc
|
||||
addons:
|
||||
apt:
|
||||
# sources:
|
||||
# - ubuntu-toolchain-r-test
|
||||
packages:
|
||||
# GCC 4.9
|
||||
# - g++-4.9
|
||||
# MPICH
|
||||
- mpich
|
||||
- libmpich-dev
|
||||
# OpenMPI
|
||||
# - openmpi-bin
|
||||
# - libopenmpi-dev
|
||||
env: DEBUG=NO
|
||||
MPI=YES
|
||||
CODECOV=YES
|
||||
MFEM_TEST_TARGET=test
|
||||
NPROCS=2
|
||||
cache:
|
||||
directories:
|
||||
- $TRAVIS_BUILD_DIR/../hypre-2.10.0b/src/hypre/lib
|
||||
- $TRAVIS_BUILD_DIR/../hypre-2.10.0b/src/hypre/include
|
||||
- $TRAVIS_BUILD_DIR/../metis-4.0
|
||||
before_cache:
|
||||
- cd $TRAVIS_BUILD_DIR/../metis-4.0;
|
||||
mv libmetis.a ..; rm -rf *; mv ../libmetis.a .
|
||||
#
|
||||
# Mac OS X
|
||||
#
|
||||
- os: osx
|
||||
# osx_image: xcode7.3
|
||||
compiler: clang
|
||||
env: DEBUG=YES
|
||||
MPI=NO
|
||||
CODECOV=NO
|
||||
MFEM_TEST_TARGET=check
|
||||
#
|
||||
- os: osx
|
||||
# osx_image: xcode7.3
|
||||
compiler: clang
|
||||
env: DEBUG=NO
|
||||
MPI=NO
|
||||
CODECOV=NO
|
||||
MFEM_TEST_TARGET=test
|
||||
#
|
||||
- os: osx
|
||||
# osx_image: xcode7.3
|
||||
compiler: clang
|
||||
env: DEBUG=YES
|
||||
MPI=YES
|
||||
CODECOV=NO
|
||||
MFEM_TEST_TARGET=check
|
||||
NPROCS=4
|
||||
TMPDIR=/tmp
|
||||
cache:
|
||||
directories:
|
||||
- $TRAVIS_BUILD_DIR/../hypre-2.10.0b/src/hypre/lib
|
||||
- $TRAVIS_BUILD_DIR/../hypre-2.10.0b/src/hypre/include
|
||||
- $TRAVIS_BUILD_DIR/../metis-4.0
|
||||
- $HOME/local-cached
|
||||
before_cache:
|
||||
- cd $TRAVIS_BUILD_DIR/../metis-4.0;
|
||||
mv libmetis.a ..; rm -rf *; mv ../libmetis.a .
|
||||
#
|
||||
- os: osx
|
||||
# osx_image: xcode7.3
|
||||
compiler: clang
|
||||
env: DEBUG=NO
|
||||
MPI=YES
|
||||
CODECOV=YES
|
||||
MFEM_TEST_TARGET=test
|
||||
NPROCS=4
|
||||
TMPDIR=/tmp
|
||||
cache:
|
||||
directories:
|
||||
- $TRAVIS_BUILD_DIR/../hypre-2.10.0b/src/hypre/lib
|
||||
- $TRAVIS_BUILD_DIR/../hypre-2.10.0b/src/hypre/include
|
||||
- $TRAVIS_BUILD_DIR/../metis-4.0
|
||||
- $HOME/local-cached
|
||||
before_cache:
|
||||
- cd $TRAVIS_BUILD_DIR/../metis-4.0;
|
||||
mv libmetis.a ..; rm -rf *; mv ../libmetis.a .
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
env:
|
||||
- DEBUG=YES MPI=YES TMPDIR=/tmp
|
||||
- DEBUG=NO MPI=YES TMPDIR=/tmp
|
||||
- DEBUG=YES MPI=NO
|
||||
- DEBUG=NO MPI=NO
|
||||
|
||||
# Test with GCC on Linux an Clang on Mac
|
||||
matrix:
|
||||
exclude:
|
||||
- compiler: clang
|
||||
os: linux
|
||||
- compiler: gcc
|
||||
os: osx
|
||||
|
||||
before_install:
|
||||
# No addon for brew yet, have to install OSX packages this way.
|
||||
# - if [ $TRAVIS_OS_NAME == "osx" ] && [ $MPI == "YES" ]; then
|
||||
# brew install open-mpi;
|
||||
# fi
|
||||
|
||||
# On Mac OS X, build and cache OpenMPI 2.1.1:
|
||||
- if [ $TRAVIS_OS_NAME == "osx" ] && [ $MPI == "YES" ]; then
|
||||
if [ ! -e $HOME/local-cached/bin/mpicc ]; then
|
||||
mkdir -p $HOME/builds && cd $HOME/builds &&
|
||||
wget https://www.open-mpi.org/software/ompi/v2.1/downloads/openmpi-2.1.1.tar.bz2 &&
|
||||
tar jxf openmpi-2.1.1.tar.bz2 &&
|
||||
mkdir openmpi-build && cd openmpi-build &&
|
||||
../openmpi-2.1.1/configure --prefix=$HOME/local-cached &&
|
||||
make -j3 all && make install;
|
||||
fi;
|
||||
PATH=$HOME/local-cached/bin:$PATH;
|
||||
cd $TRAVIS_BUILD_DIR;
|
||||
fi
|
||||
|
||||
# Update environment to find g++ 4.9 installation first.
|
||||
# - if [ $TRAVIS_OS_NAME == "linux" ]; then
|
||||
# mkdir -p latest-gcc-symlinks;
|
||||
# ln -s /usr/bin/g++-4.9 latest-gcc-symlinks/g++;
|
||||
# ln -s /usr/bin/gcc-4.9 latest-gcc-symlinks/gcc;
|
||||
# ln -s /usr/bin/gcov-4.9 latest-gcc-symlinks/gcov;
|
||||
# export PATH=$PWD/latest-gcc-symlinks:$PATH;
|
||||
# fi
|
||||
|
||||
# Install tool to upload code coverage reports to coveralls.io
|
||||
- if [ "$CODECOV" == "YES" ]; then
|
||||
export PYTHONUSERBASE=$HOME/local;
|
||||
pip install --user cpp-coveralls;
|
||||
pip install --user pyyaml;
|
||||
PATH=$HOME/local/bin:$PATH;
|
||||
fi
|
||||
- if [ $TRAVIS_OS_NAME == "linux" -a "$CXX" == "g++" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi
|
||||
- if [ $TRAVIS_OS_NAME == "linux" ]; then sudo apt-get update; fi || true
|
||||
|
||||
install:
|
||||
# Set MPI compilers, print compiler version
|
||||
- if [ $MPI == "YES" ]; then
|
||||
if [ "$TRAVIS_OS_NAME" == "linux" ]; then
|
||||
export MPICH_CC="$CC";
|
||||
export MPICH_CXX="$CXX";
|
||||
else
|
||||
export OMPI_CC="$CC";
|
||||
export OMPI_CXX="$CXX";
|
||||
mpic++ --showme:version;
|
||||
fi;
|
||||
mpic++ -v;
|
||||
else
|
||||
$CXX -v;
|
||||
fi
|
||||
# g++-4.9
|
||||
- if [ $TRAVIS_OS_NAME == "linux" -a "$CXX" == "g++" ]; then sudo apt-get install -qq g++-4.9; fi
|
||||
- if [ $TRAVIS_OS_NAME == "linux" -a "$CXX" == "g++" ]; then export CXX="g++-4.9"; fi
|
||||
|
||||
# Back out of the mfem directory to install the libraries
|
||||
- cd ..
|
||||
|
||||
# OpenMPI
|
||||
- if [ $TRAVIS_OS_NAME == "linux" ]; then
|
||||
sudo apt-get install openmpi-bin openmpi-common openssh-client openssh-server libopenmpi1.3 libopenmpi-dbg libopenmpi-dev;
|
||||
else
|
||||
travis_wait brew install open-mpi;
|
||||
fi
|
||||
|
||||
# hypre
|
||||
- if [ $MPI == "YES" ]; then
|
||||
if [ ! -e hypre-2.10.0b/src/hypre/lib/libHYPRE.a ]; then
|
||||
wget https://computation.llnl.gov/project/linear_solvers/download/hypre-2.10.0b.tar.gz --no-check-certificate;
|
||||
rm -rf hypre-2.10.0b;
|
||||
tar xvzf hypre-2.10.0b.tar.gz;
|
||||
cd hypre-2.10.0b/src;
|
||||
./configure --disable-fortran --without-fei CC=mpicc CXX=mpic++;
|
||||
make -j3;
|
||||
cd ../..;
|
||||
if [ ! -d hypre-2.10.0b ]; then
|
||||
wget https://computation.llnl.gov/project/linear_solvers/download/hypre-2.10.0b.tar.gz --no-check-certificate;
|
||||
tar xvzf hypre-2.10.0b.tar.gz;
|
||||
cd hypre-2.10.0b/src;
|
||||
./configure --disable-fortran --without-fei CC=mpicc CXX=mpic++;
|
||||
make -j 4;
|
||||
cd ../..;
|
||||
else
|
||||
echo "Reusing cached hypre-2.10.0b/";
|
||||
fi;
|
||||
@@ -210,54 +58,43 @@ install:
|
||||
fi
|
||||
|
||||
# METIS
|
||||
- if [ $MPI == "YES" ]; then
|
||||
if [ ! -e metis-4.0/libmetis.a ]; then
|
||||
wget http://glaros.dtc.umn.edu/gkhome/fetch/sw/metis/OLD/metis-4.0.3.tar.gz;
|
||||
tar xvzf metis-4.0.3.tar.gz;
|
||||
make -j3 -C metis-4.0.3/Lib CC="$CC" OPTFLAGS="-O2";
|
||||
rm -rf metis-4.0;
|
||||
mv metis-4.0.3 metis-4.0;
|
||||
else
|
||||
echo "Reusing cached metis-4.0/";
|
||||
fi;
|
||||
- if [ ! -d metis-4.0 ]; then
|
||||
wget http://glaros.dtc.umn.edu/gkhome/fetch/sw/metis/OLD/metis-4.0.3.tar.gz;
|
||||
tar xvzf metis-4.0.3.tar.gz;
|
||||
cd metis-4.0.3;
|
||||
make -j 4;
|
||||
cd ..;
|
||||
mv metis-4.0.3 metis-4.0;
|
||||
else
|
||||
echo "Reusing cached metis-4.0/";
|
||||
fi
|
||||
|
||||
# # Delete an expired cache here: https://travis-ci.org/mfem/mfem/caches
|
||||
# cache:
|
||||
# directories:
|
||||
# - $TRAVIS_BUILD_DIR/../hypre-2.10.0b
|
||||
# - $TRAVIS_BUILD_DIR/../metis-4.0
|
||||
|
||||
script:
|
||||
# Compiler
|
||||
- if [ $MPI == "YES" ]; then
|
||||
export MYCXX=mpic++;
|
||||
export OMPI_CXX="$CXX";
|
||||
$MYCXX --showme:version;
|
||||
else
|
||||
export MYCXX="$CXX";
|
||||
fi
|
||||
|
||||
# Print the compiler version
|
||||
- $MYCXX -v
|
||||
|
||||
# Set some variables
|
||||
- cd $TRAVIS_BUILD_DIR;
|
||||
CPPFLAGS="";
|
||||
SKIP_TEST_DIRS="";
|
||||
if [ "$CODECOV" == "YES" ]; then
|
||||
CPPFLAGS="--coverage -g";
|
||||
fi;
|
||||
if [ "$CXX" == "clang++" ]; then
|
||||
export MFEM_PERF_SW=clang;
|
||||
fi
|
||||
|
||||
# Configure the library
|
||||
- make config MFEM_USE_MPI=$MPI MFEM_DEBUG=$DEBUG MFEM_CXX="$MYCXX"
|
||||
MFEM_MPI_NP=$NPROCS CPPFLAGS="$CPPFLAGS"
|
||||
# Show the configuration
|
||||
- make info
|
||||
# Build the library
|
||||
- make -j3
|
||||
# Build the examples and the miniapps
|
||||
- make -j3 all
|
||||
# Run tests
|
||||
- make $MFEM_TEST_TARGET SKIP_TEST_DIRS="$SKIP_TEST_DIRS"
|
||||
|
||||
after_success:
|
||||
- if [ "$CODECOV" == "YES" ]; then
|
||||
coveralls --include fem --include general --include linalg --include
|
||||
mesh --exclude /usr --gcov-options '\-lp' --root $TRAVIS_BUILD_DIR;
|
||||
# Build the code and do a quick check (debug mode) or a full tests run (non-debug mode)
|
||||
- if [ $DEBUG == "NO" ]; then
|
||||
export MFEM_TEST_TARGET="test";
|
||||
else
|
||||
export MFEM_TEST_TARGET="check";
|
||||
fi
|
||||
# Build and check/test MFEM, its examples and miniapps
|
||||
- cd $TRAVIS_BUILD_DIR &&
|
||||
make config MFEM_USE_MPI=$MPI MFEM_DEBUG=$DEBUG MFEM_CXX="$MYCXX" &&
|
||||
make info &&
|
||||
make all -j 4 &&
|
||||
make $MFEM_TEST_TARGET
|
||||
|
||||
@@ -8,303 +8,16 @@
|
||||
http://mfem.org
|
||||
|
||||
|
||||
Version 3.4.1 (development)
|
||||
===========================
|
||||
- Added support for reading linear and quadratic 2D quadrilateral and triangular
|
||||
Cubit meshes.
|
||||
|
||||
- The tetrahedral mesh refinement algorithm in serial and in parallel now
|
||||
follows precisely the paper:
|
||||
D. Arnold, A. Mukherjee, and L. Pouly, "Locally Adapted Tetrahedral Meshes
|
||||
Using Bisection", SIAM J. Sci. Comput., 22(2), 431–448.
|
||||
This guarantees that the shape regularity of the elements will be preserved
|
||||
under refinement.
|
||||
|
||||
|
||||
Version 3.4, released on May 29, 2018
|
||||
Development version, not released yet
|
||||
=====================================
|
||||
|
||||
More general and efficient mesh adaptivity
|
||||
------------------------------------------
|
||||
- Added support for PUMI, the Parallel Unstructured Mesh Infrastructure from
|
||||
https://scorec.rpi.edu/pumi. PUMI is an unstructured, distributed mesh data
|
||||
management system that is capable of handling general non-manifold models and
|
||||
effectively supports automated adaptive analysis. PUMI enables for the first
|
||||
time support for parallel unstructured modifications of MFEM meshes.
|
||||
|
||||
- Significantly reduced MPI communication in the construction of the parallel
|
||||
prolongation matrix in ParFiniteElementSpace, for much improved parallel
|
||||
scaling of non-conforming AMR on hundreds of thousands of MPI tasks. The
|
||||
memory footprint of the ParNCMesh class has also been reduced.
|
||||
|
||||
- In FiniteElementSpace, the fully assembled refinement matrix is now replaced
|
||||
by default by a specialized refinement operator. The operator option is both
|
||||
faster and more memory efficient than using the fully assembled matrix. The
|
||||
old approach is still available and can be enabled, if needed, using the new
|
||||
method FiniteElementSpace::SetUpdateOperatorType().
|
||||
|
||||
Discretization improvements
|
||||
---------------------------
|
||||
- Added support for a general "high-order"-to-"low-order refined" transfer of
|
||||
GridFunction and true-dof data from a "high-order" finite element space
|
||||
defined on a coarse mesh, to a "low-order refined" space defined on a refined
|
||||
mesh. The new methods, GetTransferOperator and GetTrueTransferOperator in the
|
||||
FiniteElementSpace classes, work in both serial and parallel and support
|
||||
matrix-based as well as matrix-free transfer operator representations. They
|
||||
use a new method, GetTransferMatrix, in the FiniteElement class similar to
|
||||
GetLocalInterpolation, that allows the coarse FiniteElement to be different
|
||||
from the fine FiniteElement.
|
||||
|
||||
- Added class ComplexOperator, that implements the action of a complex operator
|
||||
through the equivalent 2x2 real formulation. Both symmetric and antisymmetric
|
||||
block structures are supported.
|
||||
|
||||
- Added classes for general block nonlinear finite element operators (deriving
|
||||
from BlockNonlinearForm and ParBlockNonlinearForm) enabling solution of
|
||||
nonlinear systems with multiple unknowns in different function spaces. Such
|
||||
operators have assemble-based action and also support assembly of the gradient
|
||||
operator to enable inversion with Newton iteration.
|
||||
|
||||
- Added variable order NURBS: for each space each knot vector in the mesh can
|
||||
have a different order. The order information is now part of the finite
|
||||
element space header in the NURBS mesh output, so NURBS meshes in the old
|
||||
format need to be updated.
|
||||
|
||||
- In the classes NonlinearForm and ParNonlinearForm, added support for
|
||||
non-conforming AMR meshes; see also the "API changes" section.
|
||||
|
||||
- New specialized time integrators: symplectic integrators of orders 1-4 for
|
||||
systems of first order ODEs derived from a Hamiltonian and generalized-alpha
|
||||
ODE solver for the filtered Navier–Stokes equations with stabilization. See
|
||||
classes SIASolver and GeneralizedAlphaSolver in linalg/ode.hpp.
|
||||
|
||||
- Inherit finite element classes from the new base class TensorBasisElement,
|
||||
whenever the basis can be represented by a tensor product of 1D bases.
|
||||
|
||||
- Added support for elimination of boundary conditions in block matrices.
|
||||
|
||||
New and updated examples and miniapps
|
||||
-------------------------------------
|
||||
- Added a new serial and parallel example (ex19) that solves the quasi-static
|
||||
incompressible hyperelastic equations. The example demonstrates the use of
|
||||
block nonlinear forms as well as custom block preconditioners.
|
||||
|
||||
- Added a new electromagnetics miniapp, Maxwell, for simulating time-domain
|
||||
electromagnetics phenomena as a coupled first order system of equations.
|
||||
|
||||
- A simple local refinement option has been added to the mesh-explorer miniapp
|
||||
(menu option 'r', sub-option 'l') that selects elements for refinement based
|
||||
on their spatial location - see the function 'region()' in the source file.
|
||||
|
||||
- Added a set of miniapps specifically focused on Isogeometric Analysis (IGA) on
|
||||
NURBS meshes in the miniapps/nurbs directory. Currently the directory contains
|
||||
variable order NURBS versions of examples 1, 1p and 11p.
|
||||
|
||||
- Added PUMI versions of examples ex1, ex1p, ex2 and ex6p in a new examples/pumi
|
||||
directory. The new examples demonstrate the PUMI APIs for parallel and serial
|
||||
mesh loading (ex1 and ex1p), applying BCs using classification (ex2), and
|
||||
performing parallel mesh adaptation (ex6p).
|
||||
|
||||
- Added two new miniapps related to DataCollection I/O in miniapps/tools:
|
||||
load-dc.cpp can be used to visualize fields saved via DataCollection classes;
|
||||
convert-dc.cpp demonstrates how to convert between MFEM's different concrete
|
||||
DataCollection options.
|
||||
|
||||
- Example 10p with its SUNDIALS and PETSc versions have been updated to reflect
|
||||
the change in the behavior of the method ParNonlinearForm::GetLocalGradient()
|
||||
(see the "API changes" section) and now works correctly on non-conforming AMR
|
||||
meshes. Example 10 and its SUNDIALS version have also been updated to support
|
||||
non-conforming ARM meshes.
|
||||
|
||||
Miscellaneous
|
||||
-------------
|
||||
- Documented project workflow and provided contribution guidelines in the new
|
||||
top-level file, CONTRIBUTING.md.
|
||||
|
||||
- Added (optional) Conduit Mesh Blueprint support of MFEM data for both in-core
|
||||
and I/O use cases. This includes a new ConduitDataCollection that provides
|
||||
json, simple binary, and HDF5-based I/O. Support requires Conduit >= v0.3.1
|
||||
and VisIt >= v2.13.1 will read the new Data Collection outputs.
|
||||
|
||||
- Added a new developer tool, config/sample-runs.sh, that extracts the sample
|
||||
runs from all examples and miniapps and runs them. Optionally, it can save the
|
||||
output from the execution to files, allowing comparison between different
|
||||
versions and builds of the library.
|
||||
|
||||
- Support for building a shared version of the MFEM library with GNU make.
|
||||
|
||||
- Added a build option, MFEM_USE_EXCEPTIONS=YES, to throw an exception instead
|
||||
of calling abort on mfem errors.
|
||||
|
||||
- When building with the GnuTLS library, switch to using X.509 certificates for
|
||||
secure socket authentication. Support for the previously used OpenPGP keys has
|
||||
been deprecated in GnuTLS 3.5.x and removed in 3.6.0. For secure communication
|
||||
with the visualization tool GLVis, a new set of certificates can be generated
|
||||
using the latest version of the script 'glvis-keygen.sh' from GLVis.
|
||||
|
||||
- Upgraded MFEM to support Axom 0.2.8. Prior versions are no longer supported.
|
||||
|
||||
API changes
|
||||
-----------
|
||||
- Introduced a new enum, Matrix::DiagonalPolicy, that replaces the integer
|
||||
parameters in many methods that perform elimination of rows and/or columns in
|
||||
matrices. Some examples of such methods are:
|
||||
* class SparseMatrix: EliminateRow(), EliminateCol(), EliminateRowCol(), ...
|
||||
* class BilinearForm: EliminateEssentialBC(), EliminateVDofs(), ...
|
||||
* class StaticCondensation: EliminateReducedTrueDofs()
|
||||
* class BlockMatrix: EliminateRowCol()
|
||||
Calling these methods with an explicitly given (integer) constants, will now
|
||||
generate compilation errors, please use one of the new enum constants instead.
|
||||
|
||||
- Modified the virtual method AbstractSparseMatrix::EliminateZeroRows() and its
|
||||
implementations in derived classes, to accept an optional 'threshold'
|
||||
parameter, replacing previously hard-coded threshold values.
|
||||
|
||||
- In the classes NonlinearForm and ParNonlinearForm:
|
||||
* The method GetLocalGradient() no longer imposes boundary conditions. The
|
||||
motivation for the change is that, in the case of non-conforming AMR,
|
||||
performing the elimination at the local level is incorrect - it must be
|
||||
applied at the true-dof level.
|
||||
* The method SetEssentialVDofs() is now deprecated.
|
||||
|
||||
|
||||
Version 3.3.2, released on Nov 10, 2017
|
||||
=======================================
|
||||
|
||||
High-order mesh optimization
|
||||
----------------------------
|
||||
- Added support for mesh optimization via node-movement based on the Target-
|
||||
Matrix Optimization Paradigm (TMOP) developed by P.Knupp et al. A variety of
|
||||
mesh quality metrics, with their first and second derivatives have been
|
||||
implemented. The combination of targets & quality metrics is used to optimize
|
||||
the physical node positions, i.e., they must be as close as possible to the
|
||||
shape, size and/or alignment of their targets. The optimization of arbitrary
|
||||
high-order meshes in 2D, 3D, serial and parallel is supported.
|
||||
|
||||
- The new Mesh Optimizer miniapp can be used to perform mesh optimization with
|
||||
TMOP in serial and parallel versions. The miniapp also demonstrates the use of
|
||||
nonlinear operators and their coupling to Newton methods for solving
|
||||
minimization problems.
|
||||
|
||||
New and improved solvers and preconditioners
|
||||
--------------------------------------------
|
||||
- MFEM is now included in the xSDK project, the Extreme-scale Scientific
|
||||
Software Development Kit, as of xSDK-0.3.0. Various changes were made to
|
||||
comply with xSDK's community policies, https://xsdk.info/policies, including:
|
||||
xSDK-specific options in CMake, support for user-provided MPI communicators,
|
||||
runtime API for version number, and the ability to disable/redirect output.
|
||||
For more details, see general/globals.hpp and in particular the mfem::err and
|
||||
mfem::out streams replacing std::err and std::out respectively.
|
||||
|
||||
- Added (optional) support for the STRUMPACK parallel sparse direct solver and
|
||||
preconditioner. STRUMPACK uses Hierarchically Semi-Separable (HSS) compression
|
||||
in a fully algebraic manner, with interface similar to SuperLU_DIST. See
|
||||
http://portal.nersc.gov/project/sparse/strumpack for more details.
|
||||
|
||||
- Added a block lower triangular preconditioner based (only) on the actions of
|
||||
each block, see class BlockLowerTriangularPreconditioner.
|
||||
|
||||
- Added an optional operator in LOBPCG to projects vectors onto a desired
|
||||
subspace (e.g. divergence-free). Other small changes in LOBPCG include the
|
||||
ability to set the starting vectors and support for relative tolerance.
|
||||
|
||||
- The Newton solver supports an optional scaling factor, that can limit the
|
||||
increment in the Newton step, see e.g. the Mesh Optimizer miniapp.
|
||||
|
||||
- Updated MFEM integration to support the new SUNDIALS 3.0.0 interface.
|
||||
|
||||
New and updated examples and miniapps
|
||||
-------------------------------------
|
||||
- Added a new serial and parallel example (ex18) that solves the transient Euler
|
||||
equations on a periodic domain with explicit time integrators. In the process
|
||||
extended the NonlinearForm class to allow for integrals over faces and
|
||||
exchanging face-neighbor data in parallel.
|
||||
|
||||
- Added a new meshing miniapp, Shaper, that can be used to resolve complicated
|
||||
material interfaces by mesh refinement, e.g. as a tool for initial mesh
|
||||
generation from prescribed "material()" function. Both conforming and
|
||||
non-conforming (isotropic and anisotropic) refinements are supported.
|
||||
|
||||
- Added a new meshing miniapp, Mesh Optimizer, that demonstrates the use of TMOP
|
||||
for mesh optimization (serial and parallel version.)
|
||||
|
||||
- Added SUNDIALS version of Example 16/16p.
|
||||
|
||||
Discretization improvements
|
||||
---------------------------
|
||||
- Added a FindPoints method of the Mesh and ParMesh classes that returns the
|
||||
elements that contain a given set of points, together with the coordinates of
|
||||
the points in the reference space of the corresponding element. In parallel,
|
||||
if a point is shared by multiple processors, only one of them will mark that
|
||||
point as found. Note that the current implementation of this method is not
|
||||
optimal and/or 100% reliable. See the mesh-explorer miniapp for an example.
|
||||
|
||||
- Added a new class InverseElementTransformation, that supports a number of
|
||||
algorithms for inversion of general ElementTransformations. This class can be
|
||||
used as a more flexible and extensible alternative to ElementTransformation's
|
||||
TransformBack method. It is also used in the FindPoints methods as a tunable
|
||||
and customizable inversion algorithm.
|
||||
|
||||
- Memory optimizations in the NCMesh class, which now uses 50% less memory than
|
||||
before. The average cost of an element in a uniformly refined mesh (including
|
||||
the refinement hierarchy, but excluding the temporary face_list and edge_list)
|
||||
- Memory optimizations in the NCMesh class, which now uses 50% less memory.
|
||||
The average cost of an NC element in a uniformly refined mesh (including the
|
||||
refinement hierarchy, but excluding the temporary face_list and edge_list)
|
||||
is now only about 290 bytes. This also makes the class faster.
|
||||
|
||||
- Added the ability to integrate delta functions on the right-hand side (by
|
||||
sampling the test function at the center of the delta coefficient). Currently
|
||||
this is supported in the DomainLFIntegrator, VectorDomainLFIntegrator and
|
||||
VectorFEDomainLFIntegrator classes.
|
||||
|
||||
- Added five new linear interpolators in fem/bilininteg.cpp to compute products
|
||||
of scalar and vector fields or products with arbitrary coefficients.
|
||||
|
||||
- Added matrix coefficient support to CurlCurlIntegrator.
|
||||
|
||||
- Extend the method NodalFiniteElement::Project for VectorCoefficient to work
|
||||
with arbitrary number of vector components.
|
||||
|
||||
Miscellaneous
|
||||
-------------
|
||||
- Added a .gitignore file that ignores all files erased by "make distclean",
|
||||
i.e. the files that can be generated from the source but we don't want to
|
||||
track in the repository, as well as a few platform-specific files.
|
||||
|
||||
- Added Linux, Mac and Windows CI testing on GitHub with Travis CI and Appveyor.
|
||||
|
||||
- Added a new macro, MFEM_VERSION, defined as a single integer of the form
|
||||
(major*100 + minor)*100 + patch. The convention is that an even number
|
||||
(i.e. even patch number) denotes a "release" version, while an odd number
|
||||
denotes a "development" version. See config/config.hpp.in.
|
||||
|
||||
- Added an option for building in parallel without a METIS dependency. This is
|
||||
used for example the Laghos miniapp, https://github.com/CEED/Laghos.
|
||||
|
||||
- Modified the installation layout: all headers, except the master headers
|
||||
(mfem.hpp and mfem-performance.hpp), are installed in <PREFIX>/include/mfem;
|
||||
the master headers are installed in both <PREFIX>/include/mfem and in
|
||||
<PREFIX>/include. The mfem configuration and testing makefiles (config.mk and
|
||||
test.mk) are installed in <PREFIX>/share/mfem, instead of <PREFIX>.
|
||||
|
||||
- Add three more options for MFEM_TIMER_TYPE.
|
||||
|
||||
- Support independent number of digits for cycle and rank in DataCollection.
|
||||
|
||||
- Converted Sidre usage from "asctoolkit" to "axom" namespace.
|
||||
|
||||
- Various small fixes and styling updates.
|
||||
|
||||
API changes
|
||||
-----------
|
||||
- The methods GetCoeff of VectorArrayCoefficient and MatrixArrayCoefficient now
|
||||
return a pointer to Coefficient (instead of reference). Note that NULL pointer
|
||||
is a valid entry for these two classes - it is treated as the zero function.
|
||||
|
||||
- When building with PETSc, the required PETSc version is now 3.8.0. Newer
|
||||
versions may work too, as long as there are no interface changes in PETSc.
|
||||
|
||||
- The class GeometryRefiner now uses the enum in Quadrature1D for its type
|
||||
specification. In particular, this will affect older versions of GLVis. A
|
||||
simple upgrade to the latest version of GLVis should resolve this issue.
|
||||
- Add a block lower triangular preconditioner in using a matrix-free
|
||||
implementation, see class BlockLowerTriangularPreconditioner.
|
||||
|
||||
|
||||
Version 3.3, released on Jan 28, 2017
|
||||
@@ -460,7 +173,7 @@ Improved file output
|
||||
- Added experimental support for an HDF5-based output file format following the
|
||||
Conduit (https://github.com/LLNL/conduit) mesh blueprint specification for
|
||||
visualization and/or restart capability. This functionality is aimed primarily
|
||||
at user of LLNL's axom project (Sidre component) that run problems at extreme
|
||||
at user of LLNL's ASC Toolkit (Sidre component) that run problems at extreme
|
||||
scales. Users desiring a small scale binary format may want to look at the
|
||||
gzstream functionality instead.
|
||||
|
||||
|
||||
@@ -38,14 +38,8 @@ if (NOT CMAKE_CXX_COMPILER)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Project name and version
|
||||
#-------------------------------------------------------------------------------
|
||||
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 3.4.1)
|
||||
project(mfem CXX)
|
||||
set(${PROJECT_NAME}_VERSION 3.3)
|
||||
|
||||
# Prohibit in-source build
|
||||
if (${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR})
|
||||
@@ -53,65 +47,18 @@ if (${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR})
|
||||
"MFEM does not support in-source CMake builds at this time.")
|
||||
endif (${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR})
|
||||
|
||||
# Set xSDK defaults.
|
||||
set(USE_XSDK_DEFAULTS_DEFAULT OFF)
|
||||
set(XSDK_ENABLE_CXX ON)
|
||||
set(XSDK_ENABLE_C OFF)
|
||||
set(XSDK_ENABLE_Fortran OFF)
|
||||
|
||||
# Check if we need to enable C or Fortran.
|
||||
if (CMAKE_VERSION VERSION_LESS 3.2 OR
|
||||
MFEM_USE_CONDUIT OR
|
||||
MFEM_USE_SIDRE OR
|
||||
MFEM_USE_PETSC)
|
||||
if (CMAKE_VERSION VERSION_LESS 3.2 OR MFEM_USE_SIDRE)
|
||||
# This seems to be needed by:
|
||||
# * find_package(BLAS REQUIRED) and
|
||||
# * find_package(HDF5 REQUIRED) needed, in turn, by:
|
||||
# - find_package(AXOM REQUIRED)
|
||||
# * find_package(PETSc REQUIRED)
|
||||
set(XSDK_ENABLE_C ON)
|
||||
endif()
|
||||
if (MFEM_USE_STRUMPACK)
|
||||
# Just needed to find the MPI_Fortran libraries to link with
|
||||
set(XSDK_ENABLE_Fortran ON)
|
||||
endif()
|
||||
|
||||
# Include xSDK default CMake file.
|
||||
include("${CMAKE_CURRENT_SOURCE_DIR}/config/XSDKDefaults.cmake")
|
||||
|
||||
# Enable languages.
|
||||
enable_language(CXX)
|
||||
if (XSDK_ENABLE_C)
|
||||
# - find_package(ATK REQUIRED)
|
||||
enable_language(C)
|
||||
endif()
|
||||
if (XSDK_ENABLE_Fortran)
|
||||
enable_language(Fortran)
|
||||
endif()
|
||||
|
||||
# Suppress warnings about MACOSX_RPATH
|
||||
set(CMAKE_MACOSX_RPATH OFF CACHE BOOL "")
|
||||
|
||||
# CMake needs to know where to find things
|
||||
set(MFEM_CMAKE_PATH ${PROJECT_SOURCE_DIR}/config)
|
||||
set(CMAKE_MODULE_PATH ${MFEM_CMAKE_PATH}/cmake/modules)
|
||||
|
||||
# Load MFEM CMake utilities.
|
||||
include(MfemCmakeUtilities)
|
||||
|
||||
string(TOUPPER "${PROJECT_NAME}" PROJECT_NAME_UC)
|
||||
mfem_version_to_int(${${PROJECT_NAME}_VERSION} ${PROJECT_NAME_UC}_VERSION)
|
||||
set(${PROJECT_NAME_UC}_VERSION_STRING ${${PROJECT_NAME}_VERSION})
|
||||
if (EXISTS ${PROJECT_SOURCE_DIR}/.git)
|
||||
execute_process(
|
||||
COMMAND git describe --all --long --abbrev=40 --dirty --always
|
||||
WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
|
||||
OUTPUT_VARIABLE ${PROJECT_NAME_UC}_GIT_STRING
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
endif()
|
||||
if (NOT ${PROJECT_NAME_UC}_GIT_STRING)
|
||||
set(${PROJECT_NAME_UC}_GIT_STRING "(unknown)")
|
||||
endif()
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Process configuration options
|
||||
#-------------------------------------------------------------------------------
|
||||
@@ -123,23 +70,25 @@ else()
|
||||
set(MFEM_DEBUG OFF)
|
||||
endif()
|
||||
|
||||
# MPI -> hypre; PETSc (optional)
|
||||
# MPI -> hypre, METIS
|
||||
if (MFEM_USE_MPI)
|
||||
find_package(MPI REQUIRED)
|
||||
set(MPI_CXX_INCLUDE_DIRS ${MPI_CXX_INCLUDE_PATH})
|
||||
# Parallel MFEM depends on hypre
|
||||
include_directories(${MPI_CXX_INCLUDE_PATH})
|
||||
# Parallel MFEM depends on hypre and METIS
|
||||
find_package(HYPRE REQUIRED)
|
||||
set(MFEM_HYPRE_VERSION ${HYPRE_VERSION})
|
||||
include_directories(${HYPRE_INCLUDE_DIRS})
|
||||
find_package(METIS REQUIRED)
|
||||
include_directories(${METIS_INCLUDE_DIRS})
|
||||
if (MFEM_USE_PETSC)
|
||||
find_package(PETSc REQUIRED)
|
||||
message(STATUS "Found PETSc version ${PETSC_VERSION}")
|
||||
if (PETSC_VERSION AND (PETSC_VERSION VERSION_LESS 3.8.0))
|
||||
message(FATAL_ERROR "PETSc version >= 3.8.0 is required")
|
||||
if (PETSC_VERSION AND (PETSC_VERSION VERSION_LESS 3.7.5.99))
|
||||
message(FATAL_ERROR "PETSc version >= 3.7.5.99 is required")
|
||||
endif()
|
||||
set(PETSC_INCLUDE_DIRS ${PETSC_INCLUDES})
|
||||
include_directories(${PETSC_INCLUDES})
|
||||
endif()
|
||||
else()
|
||||
set(PKGS_NEED_MPI SUPERLU PETSC STRUMPACK PUMI)
|
||||
set(PKGS_NEED_MPI SUPERLU PETSC)
|
||||
foreach(PKG IN LISTS PKGS_NEED_MPI)
|
||||
if (MFEM_USE_${PKG})
|
||||
message(STATUS "Disabling package ${PKG} - requires MPI")
|
||||
@@ -148,19 +97,17 @@ else()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
if (MFEM_USE_METIS)
|
||||
find_package(METIS REQUIRED)
|
||||
endif()
|
||||
|
||||
# GZSTREAM -> zlib
|
||||
if (MFEM_USE_GZSTREAM)
|
||||
find_package(ZLIB REQUIRED)
|
||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
# Backtrace with libunwind
|
||||
if (MFEM_USE_LIBUNWIND)
|
||||
set(MFEMBacktrace_REQUIRED_PACKAGES "Libunwind" "LIBDL" "CXXABIDemangle")
|
||||
find_package(MFEMBacktrace REQUIRED)
|
||||
include_directories(${LIBUNWIND_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
# BLAS, LAPACK
|
||||
@@ -182,6 +129,7 @@ endif()
|
||||
if (MFEM_USE_SUITESPARSE)
|
||||
find_package(SuiteSparse REQUIRED
|
||||
UMFPACK KLU AMD BTF CHOLMOD COLAMD CAMD CCOLAMD config)
|
||||
include_directories(${SuiteSparse_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
# SUNDIALS
|
||||
@@ -192,82 +140,63 @@ if (MFEM_USE_SUNDIALS)
|
||||
find_package(SUNDIALS REQUIRED
|
||||
NVector_Serial NVector_Parallel NVector_ParHyp CVODE ARKODE KINSOL)
|
||||
endif()
|
||||
include_directories(${SUNDIALS_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
# Mesquite
|
||||
if (MFEM_USE_MESQUITE)
|
||||
find_package(Mesquite REQUIRED)
|
||||
include_directories(${MESQUITE_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
# SuperLU_DIST can only be enabled in parallel
|
||||
# SuperLU_DIST can only be enabled if parallel
|
||||
if (MFEM_USE_SUPERLU)
|
||||
if (MFEM_USE_MPI)
|
||||
find_package(SuperLUDist REQUIRED)
|
||||
include_directories(${SuperLUDist_INCLUDE_DIRS})
|
||||
else()
|
||||
message(FATAL_ERROR " *** SuperLU_DIST requires that MPI be enabled.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# STRUMPACK can only be enabled in parallel
|
||||
if (MFEM_USE_STRUMPACK)
|
||||
if (MFEM_USE_MPI)
|
||||
find_package(STRUMPACK REQUIRED)
|
||||
else()
|
||||
message(FATAL_ERROR " *** STRUMPACK requires that MPI be enabled.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Gecko
|
||||
if (MFEM_USE_GECKO)
|
||||
find_package(Gecko REQUIRED)
|
||||
include_directories(${GECKO_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
# GnuTLS
|
||||
if (MFEM_USE_GNUTLS)
|
||||
find_package(_GnuTLS REQUIRED)
|
||||
include_directories(${GNUTLS_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
# NetCDF
|
||||
if (MFEM_USE_NETCDF)
|
||||
find_package(NetCDF REQUIRED)
|
||||
include_directories(${NETCDF_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
# MPFR
|
||||
if (MFEM_USE_MPFR)
|
||||
find_package(MPFR REQUIRED)
|
||||
endif()
|
||||
|
||||
if (MFEM_USE_CONDUIT)
|
||||
find_package(Conduit REQUIRED conduit relay blueprint )
|
||||
include_directories(${MPFR_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
# Axom/Sidre
|
||||
if (MFEM_USE_SIDRE)
|
||||
find_package(Axom REQUIRED Sidre SLIC axom_utils)
|
||||
endif()
|
||||
|
||||
# PUMI
|
||||
if (MFEM_USE_PUMI)
|
||||
# If PUMI_DIR was specified, only link to that directory,
|
||||
# i.e. don't link to another installation in /usr/lib by mistake
|
||||
find_package(SCOREC 2.1.0 REQUIRED OPTIONAL_COMPONENTS gmi_sim
|
||||
CONFIG PATHS ${PUMI_DIR} NO_DEFAULT_PATH)
|
||||
if (SCOREC_FOUND)
|
||||
# Define a header file with the MFEM_USE_SIMMETRIX preprocessor variable
|
||||
set(MFEM_USE_SIMMETRIX ${SCOREC_gmi_sim_FOUND})
|
||||
set(PUMI_FOUND ${SCOREC_FOUND})
|
||||
get_target_property(PUMI_INCLUDE_DIRS
|
||||
SCOREC::apf INTERFACE_INCLUDE_DIRECTORIES)
|
||||
set(PUMI_LIBRARIES SCOREC::core)
|
||||
if (NOT MFEM_USE_MPI)
|
||||
find_package(ATK REQUIRED Sidre SLIC common)
|
||||
else()
|
||||
find_package(ATK REQUIRED Sidre SPIO SLIC common)
|
||||
endif()
|
||||
include_directories(${ATK_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
# MFEM_TIMER_TYPE
|
||||
if (NOT DEFINED MFEM_TIMER_TYPE)
|
||||
if (APPLE)
|
||||
# use std::clock from <ctime> for UserTime and
|
||||
# use mach_absolute_time from <mach/mach_time.h> for RealTime
|
||||
set(MFEM_TIMER_TYPE 4)
|
||||
set(MFEM_TIMER_TYPE 0) # use std::clock from <ctime>
|
||||
elseif (WIN32)
|
||||
set(MFEM_TIMER_TYPE 3) # QueryPerformanceCounter from <windows.h>
|
||||
else()
|
||||
@@ -281,27 +210,17 @@ if (NOT DEFINED MFEM_TIMER_TYPE)
|
||||
endif()
|
||||
|
||||
# List all possible libraries in order of dependencies.
|
||||
# [METIS < SuiteSparse]:
|
||||
# With newer versions of SuiteSparse which include METIS header using 64-bit
|
||||
# integers, the METIS header (with 32-bit indices, as used by mfem) needs to
|
||||
# be before SuiteSparse.
|
||||
set(MFEM_TPLS MPI_CXX OPENMP BLAS LAPACK METIS HYPRE SuiteSparse SUNDIALS PETSC
|
||||
MESQUITE SuperLUDist STRUMPACK AXOM CONDUIT GECKO GNUTLS NETCDF MPFR PUMI
|
||||
POSIXCLOCKS MFEMBacktrace ZLIB)
|
||||
set(MFEM_TPLS HYPRE OPENMP SUNDIALS MESQUITE SuiteSparse SuperLUDist
|
||||
ParMETIS METIS LAPACK BLAS GECKO GNUTLS NETCDF PETSC MPFR ATK POSIXCLOCKS
|
||||
MFEMBacktrace ZLIB)
|
||||
# Add all *_FOUND libraries in the variable TPL_LIBRARIES.
|
||||
set(TPL_LIBRARIES "")
|
||||
set(TPL_INCLUDE_DIRS "")
|
||||
foreach(TPL IN LISTS MFEM_TPLS)
|
||||
if (${TPL}_FOUND)
|
||||
message(STATUS "MFEM: using package ${TPL}")
|
||||
list(APPEND TPL_LIBRARIES ${${TPL}_LIBRARIES})
|
||||
list(APPEND TPL_INCLUDE_DIRS ${${TPL}_INCLUDE_DIRS})
|
||||
endif()
|
||||
endforeach(TPL)
|
||||
list(REMOVE_DUPLICATES TPL_LIBRARIES)
|
||||
list(REMOVE_DUPLICATES TPL_INCLUDE_DIRS)
|
||||
# message(STATUS "TPL_INCLUDE_DIRS = ${TPL_INCLUDE_DIRS}")
|
||||
include_directories(${TPL_INCLUDE_DIRS})
|
||||
|
||||
if (OPENMP_FOUND)
|
||||
message(STATUS "MFEM: using package OpenMP")
|
||||
@@ -309,8 +228,6 @@ if (OPENMP_FOUND)
|
||||
endif()
|
||||
|
||||
message(STATUS "MFEM build type: CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}")
|
||||
message(STATUS "MFEM version: v${MFEM_VERSION_STRING}")
|
||||
message(STATUS "MFEM git string: ${MFEM_GIT_STRING}")
|
||||
|
||||
# Windows specific
|
||||
set(_USE_MATH_DEFINES ${WIN32})
|
||||
@@ -320,6 +237,7 @@ set(_USE_MATH_DEFINES ${WIN32})
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
# Headers and sources
|
||||
include(MfemCmakeUtilities)
|
||||
set(SOURCES "")
|
||||
set(HEADERS "")
|
||||
set(MFEM_SOURCE_DIRS general linalg mesh fem)
|
||||
@@ -331,30 +249,21 @@ set(MASTER_HEADERS
|
||||
${PROJECT_SOURCE_DIR}/mfem.hpp
|
||||
${PROJECT_SOURCE_DIR}/mfem-performance.hpp)
|
||||
|
||||
set(_lib_path "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON CACHE BOOL "")
|
||||
set(CMAKE_INSTALL_RPATH "${_lib_path}" CACHE PATH "")
|
||||
set(CMAKE_INSTALL_NAME_DIR "${_lib_path}" CACHE PATH "")
|
||||
|
||||
# Declaring the library
|
||||
add_library(mfem ${SOURCES} ${HEADERS} ${MASTER_HEADERS})
|
||||
# message(STATUS "TPL_LIBRARIES = ${TPL_LIBRARIES}")
|
||||
list(REMOVE_DUPLICATES TPL_LIBRARIES)
|
||||
# message(STATUS " TPL_LIBRARIES = ${TPL_LIBRARIES}")
|
||||
if (CMAKE_VERSION VERSION_GREATER 2.8.11)
|
||||
target_link_libraries(mfem PUBLIC ${TPL_LIBRARIES})
|
||||
else()
|
||||
target_link_libraries(mfem ${TPL_LIBRARIES})
|
||||
endif()
|
||||
if (MINGW)
|
||||
target_link_libraries(mfem ws2_32)
|
||||
endif()
|
||||
set_target_properties(mfem PROPERTIES VERSION "${mfem_VERSION}")
|
||||
set_target_properties(mfem PROPERTIES SOVERSION "${mfem_VERSION}")
|
||||
|
||||
# If building out-of-source, define MFEM_BUILD_DIR to point to the build
|
||||
# directory.
|
||||
if (NOT ("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}"))
|
||||
target_compile_definitions(mfem PRIVATE
|
||||
"MFEM_BUILD_DIR=${PROJECT_BINARY_DIR}")
|
||||
"-DMFEM_BUILD_DIR=${PROJECT_BINARY_DIR}")
|
||||
endif()
|
||||
|
||||
# Generate configuration file in the build directory: config/_config.hpp.
|
||||
@@ -372,11 +281,6 @@ if (NOT ("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}"))
|
||||
"// Auto-generated file.
|
||||
#define MFEM_BUILD_DIR ${PROJECT_BINARY_DIR}
|
||||
#include \"${PROJECT_SOURCE_DIR}/${Header}\"
|
||||
")
|
||||
# This version will be installed in the top include directory:
|
||||
file(WRITE "${PROJECT_BINARY_DIR}/InstallHeaders/${Header}"
|
||||
"// Auto-generated file.
|
||||
#include \"mfem/${Header}\"
|
||||
")
|
||||
endforeach()
|
||||
endif()
|
||||
@@ -428,12 +332,12 @@ endif()
|
||||
# Add 'check' target - quick test
|
||||
if (NOT MFEM_USE_MPI)
|
||||
add_custom_target(check
|
||||
${CMAKE_CTEST_COMMAND} -R '^ex1_ser' -C ${CMAKE_CFG_INTDIR}
|
||||
${CMAKE_CTEST_COMMAND} -R ex1_ser -E performance -C ${CMAKE_CFG_INTDIR}
|
||||
USES_TERMINAL)
|
||||
add_dependencies(check ex1)
|
||||
else()
|
||||
add_custom_target(check
|
||||
${CMAKE_CTEST_COMMAND} -R '^ex1p' -C ${CMAKE_CFG_INTDIR}
|
||||
${CMAKE_CTEST_COMMAND} -R ex1p -E performance -C ${CMAKE_CFG_INTDIR}
|
||||
USES_TERMINAL)
|
||||
add_dependencies(check ex1p)
|
||||
endif()
|
||||
@@ -448,6 +352,7 @@ add_subdirectory(doc)
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
message(STATUS "CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}")
|
||||
string(TOUPPER "${PROJECT_NAME}" PROJECT_NAME_UC)
|
||||
set(INSTALL_INCLUDE_DIR include
|
||||
CACHE PATH "Relative path for installing header files.")
|
||||
set(INSTALL_LIB_DIR lib
|
||||
@@ -467,15 +372,11 @@ install(TARGETS ${PROJECT_NAME}
|
||||
DESTINATION ${INSTALL_LIB_DIR})
|
||||
|
||||
# Install the master headers
|
||||
foreach(Header mfem.hpp mfem-performance.hpp)
|
||||
install(FILES ${PROJECT_BINARY_DIR}/InstallHeaders/${Header}
|
||||
DESTINATION ${INSTALL_INCLUDE_DIR})
|
||||
endforeach()
|
||||
install(FILES ${MASTER_HEADERS} DESTINATION ${INSTALL_INCLUDE_DIR}/mfem)
|
||||
install(FILES ${MASTER_HEADERS} DESTINATION ${INSTALL_INCLUDE_DIR})
|
||||
|
||||
# Install the headers; currently, the miniapps headers are excluded
|
||||
install(DIRECTORY ${MFEM_SOURCE_DIRS}
|
||||
DESTINATION ${INSTALL_INCLUDE_DIR}/mfem
|
||||
DESTINATION ${INSTALL_INCLUDE_DIR}
|
||||
FILES_MATCHING PATTERN "*.hpp")
|
||||
|
||||
# Install ${HEADERS}
|
||||
@@ -488,11 +389,11 @@ install(DIRECTORY ${MFEM_SOURCE_DIRS}
|
||||
|
||||
# Install the configuration header files
|
||||
install(FILES ${PROJECT_BINARY_DIR}/config/_config.hpp
|
||||
DESTINATION ${INSTALL_INCLUDE_DIR}/mfem/config
|
||||
DESTINATION ${INSTALL_INCLUDE_DIR}/config
|
||||
RENAME config.hpp)
|
||||
|
||||
install(FILES ${PROJECT_SOURCE_DIR}/config/tconfig.hpp
|
||||
DESTINATION ${INSTALL_INCLUDE_DIR}/mfem/config)
|
||||
DESTINATION ${INSTALL_INCLUDE_DIR}/config)
|
||||
|
||||
# Package the whole thing up nicely
|
||||
include(CMakePackageConfigHelpers)
|
||||
@@ -502,15 +403,11 @@ export(TARGETS ${PROJECT_NAME}
|
||||
FILE "${PROJECT_BINARY_DIR}/MFEMTargets.cmake")
|
||||
|
||||
# Export the package for use from the build-tree (this registers the build-tree
|
||||
# with the CMake user package registry.)
|
||||
# TODO: How do we register the install-tree? Replacing the build-tree?
|
||||
# with a global CMake-registry)
|
||||
export(PACKAGE ${PROJECT_NAME})
|
||||
|
||||
# Extract the include directories required to use MFEM
|
||||
get_target_property(MFEM_TPL_INCLUDE_DIRS mfem INCLUDE_DIRECTORIES)
|
||||
if (NOT MFEM_TPL_INCLUDE_DIRS)
|
||||
set(MFEM_TPL_INCLUDE_DIRS "")
|
||||
endif()
|
||||
|
||||
# This is the build-tree version
|
||||
set(INCLUDE_INSTALL_DIRS ${PROJECT_BINARY_DIR} ${MFEM_TPL_INCLUDE_DIRS})
|
||||
|
||||
@@ -1,538 +0,0 @@
|
||||
<p align="center">
|
||||
<a href="http://mfem.org/"><img alt="mfem" src="http://mfem.org/img/logo-300.png"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/mfem/mfem/blob/master/COPYRIGHT"><img alt="License" src="https://img.shields.io/badge/License-LGPL--2.1-brightgreen.svg"></a>
|
||||
<a href="https://travis-ci.org/mfem/mfem"><img alt="Build Status" src="https://travis-ci.org/mfem/mfem.svg?branch=master"></a>
|
||||
<a href="https://ci.appveyor.com/project/mfem/mfem"><img alt="Build Status" src="https://ci.appveyor.com/api/projects/status/19non9sqm6msi2wy?svg=true"></a>
|
||||
<a href="http://mfem.github.io/doxygen/html/index.html"><img alt="Doxygen" src="https://img.shields.io/badge/code-documented-brightgreen.svg"></a>
|
||||
</p>
|
||||
|
||||
|
||||
# How to Contribute
|
||||
|
||||
The MFEM team welcomes contributions at all levels: bugfixes; code
|
||||
improvements; simplifications; new mesh, discretization or solver
|
||||
capabilities; improved documentation; new examples and miniapps;
|
||||
HPC performance improvements; ...
|
||||
|
||||
Use a pull request (PR) toward the `mfem:master` branch to propose your
|
||||
contribution. If you are planning significant code changes, or have any
|
||||
questions, you can also open an [issue](https://github.com/mfem/mfem/issues)
|
||||
before issuing a PR. We also welcome your [simulation
|
||||
images](http://mfem.org/gallery/), which you can submit via a pull request in
|
||||
[mfem/web](https://github.com/mfem/web).
|
||||
|
||||
See the [Quick Summary](#quick-summary) section for the main highlights of our
|
||||
GitHub workflow. For more details, consult the following sections and refer
|
||||
back to them before issuing pull requests:
|
||||
|
||||
- [Code Overview](#code-overview)
|
||||
- [GitHub Workflow](#github-workflow)
|
||||
- [MFEM Organization](#mfem-organization)
|
||||
- [New Feature Development](#new-feature-development)
|
||||
- [Developer Guidelines](#developer-guidelines)
|
||||
- [Pull Requests](#pull-requests)
|
||||
- [Pull Request Checklist](#pull-request-checklist)
|
||||
- [Master/Next Workflow](#masternext-workflow)
|
||||
- [Releases](#releases)
|
||||
- [Release Checklist](#release-checklist)
|
||||
- [LLNL Workflow](#llnl-workflow)
|
||||
- [Automated Testing](#automated-testing)
|
||||
- [Contact Information](#contact-information)
|
||||
|
||||
Contributing to MFEM requires knowledge of Git and, likely, finite elements. If
|
||||
you are new to Git, see the [GitHub learning
|
||||
resources](https://help.github.com/articles/git-and-github-learning-resources/).
|
||||
To learn more about the finite element method, see our [FEM page](http://mfem.org/fem).
|
||||
|
||||
*By submitting a pull request, you are affirming the [Developer's Certificate of
|
||||
Origin](#developers-certificate-of-origin-11) at the end of this file.*
|
||||
|
||||
|
||||
## Quick Summary
|
||||
|
||||
- We encourage you to [join the MFEM organization](#mfem-organization) and create
|
||||
development branches off `mfem:master`.
|
||||
- Please follow the [developer guidelines](#developer-guidelines), in particular
|
||||
with regards to documentation and code styling.
|
||||
- Pull requests should be issued toward `mfem:master`. Make sure
|
||||
to check the items off the [Pull Request Checklist](#pull-request-checklist).
|
||||
- After approval, MFEM developers merge the PR manually in the [mfem:next branch](#masternext-workflow).
|
||||
- After a week of testing in `mfem:next`, the original PR is merged in `mfem:master`.
|
||||
- We use [milestones](https://github.com/mfem/mfem/milestones) to coordinate the
|
||||
work on different PRs toward a release.
|
||||
- Don't hesitate to [contact us](#contact-information) if you have any questions.
|
||||
|
||||
|
||||
### Code Overview
|
||||
|
||||
- The MFEM library uses object-orient design principles which reflect, in code,
|
||||
the independent mathematical concepts of meshing, linear algebra and finite
|
||||
element spaces and operators.
|
||||
|
||||
- The MFEM source code has the following structure:
|
||||
```
|
||||
.
|
||||
├── config
|
||||
│ └── cmake
|
||||
│ └── modules
|
||||
├── data
|
||||
├── doc
|
||||
│ └── web
|
||||
│ └── examples
|
||||
├── examples
|
||||
│ ├── petsc
|
||||
│ ├── pumi
|
||||
│ └── sundials
|
||||
├── fem
|
||||
├── general
|
||||
├── linalg
|
||||
├── mesh
|
||||
└── miniapps
|
||||
├── common
|
||||
├── electromagnetics
|
||||
├── meshing
|
||||
├── nurbs
|
||||
├── performance
|
||||
└── tools
|
||||
```
|
||||
|
||||
- The main directories are `fem/`, `mesh/` and `linalg/` containing the C++
|
||||
classes implementing the finite element, mesh and linear algebra concepts
|
||||
respectively.
|
||||
|
||||
- The main mesh classes are:
|
||||
+ [`Mesh`](http://mfem.github.io/doxygen/html/classmfem_1_1Mesh.html)
|
||||
+ [`NCMesh`](http://mfem.github.io/doxygen/html/classmfem_1_1NCMesh.html)
|
||||
+ [`Element`](http://mfem.github.io/doxygen/html/classmfem_1_1Element.html)
|
||||
+ [`ElementTransformation`](http://mfem.github.io/doxygen/html/classmfem_1_1ElementTransformation.html)
|
||||
|
||||
- The main finite element classes are:
|
||||
+ [`FiniteElement`](http://mfem.github.io/doxygen/html/classmfem_1_1FiniteElement.html)
|
||||
+ [`FiniteElementCollection`](http://mfem.github.io/doxygen/html/classmfem_1_1FiniteElement.html)
|
||||
+ [`FiniteElementSpace`](http://mfem.github.io/doxygen/html/classmfem_1_1FiniteElementSpace.html)
|
||||
+ [`GridFunction`](http://mfem.github.io/doxygen/html/classmfem_1_1GridFunction.html)
|
||||
+ [`BilinearFormIntegrator`](http://mfem.github.io/doxygen/html/classmfem_1_1BilinearFormIntegrator.html) and [`LinearFormIntegrator`](http://mfem.github.io/doxygen/html/classmfem_1_1LinearFormIntegrator.html)
|
||||
+ [`LinearForm`](http://mfem.github.io/doxygen/html/classmfem_1_1LinearFormIntegrator.html), [`BilinearForm`](http://mfem.github.io/doxygen/html/classmfem_1_1BilinearForm.html) and [`MixedBilinearForm`](http://mfem.github.io/doxygen/html/classmfem_1_1MixedBilinearForm.html)
|
||||
|
||||
- The main linear algebra classes and sources are
|
||||
+ [`Operator`](http://mfem.github.io/doxygen/html/classmfem_1_1Operator.html) and [`BilinearForm`](http://mfem.github.io/doxygen/html/classmfem_1_1BilinearForm.html)
|
||||
+ [`Vector`](http://mfem.github.io/doxygen/html/classmfem_1_1BilinearForm.html) and [`LinearForm`](http://mfem.github.io/doxygen/html/classmfem_1_1LinearForm.html)
|
||||
+ [`DenseMatrix`](http://mfem.github.io/doxygen/html/classmfem_1_1DenseMatrix.html) and [`SparseMatrix`](http://mfem.github.io/doxygen/html/classmfem_1_1SparseMatrix.html)
|
||||
+ Sparse [smoothers](http://mfem.github.io/doxygen/html/sparsesmoothers_8hpp.html) and linear [solvers](http://mfem.github.io/doxygen/html/solvers_8hpp.html)
|
||||
|
||||
- Parallel MPI objects in MFEM inherit their serial counterparts, so a parallel
|
||||
mesh for example is just a serial mesh on each task plus the information on
|
||||
shared geometric entities between different tasks. The parallel source files
|
||||
have a `p` prefix, e.g. `pmesh.cpp` vs. the serial `mesh.cpp`.
|
||||
|
||||
- The main parallel classes are
|
||||
+ [`ParMesh`](http://mfem.github.io/doxygen/html/solvers_8hpp.html)
|
||||
+ [`ParNCMesh`](http://mfem.github.io/doxygen/html/classmfem_1_1ParMesh.html)
|
||||
+ [`ParFiniteElementSpace`](http://mfem.github.io/doxygen/html/classmfem_1_1ParFiniteElementSpace.html)
|
||||
+ [`ParGridFunction`](http://mfem.github.io/doxygen/html/classmfem_1_1ParGridFunction.html)
|
||||
+ [`ParBilinearForm`](http://mfem.github.io/doxygen/html/classmfem_1_1ParBilinearForm.html) and [`ParLinearForm`](http://mfem.github.io/doxygen/html/classmfem_1_1ParLinearForm.html)
|
||||
+ [`HypreParMatrix`](http://mfem.github.io/doxygen/html/classmfem_1_1HypreParMatrix.html) and [`HypreParVector`](http://mfem.github.io/doxygen/html/classmfem_1_1HypreParVector.html)
|
||||
+ [`HypreSolver`](http://mfem.github.io/doxygen/html/classmfem_1_1HypreSolver.html) and other [hypre classes](http://mfem.github.io/doxygen/html/hypre_8hpp.html)
|
||||
|
||||
- The `general/` directory contains C++ classes that serve as utilities for
|
||||
communication, error handling, arrays, (Boolean) tables, timing, etc.
|
||||
|
||||
- The `config/` directory contains build-related files, both for the plain
|
||||
Makefile and the CMake build options.
|
||||
|
||||
- The `doc/` directory contains configuration for the Doxygen code documentation
|
||||
that can either be build locally, or browsed online at
|
||||
http://mfem.github.io/doxygen/html/index.html.
|
||||
|
||||
- The `data/` directory contains a collection of small mesh files, that are used
|
||||
in the simple example codes and more fully-featured mini applications in the
|
||||
`examples/` and `miniapps/` directories.
|
||||
|
||||
- See also the [code overview](http://mfem.org/code-overview/) section on the
|
||||
MFEM website.
|
||||
|
||||
## GitHub Workflow
|
||||
|
||||
The GitHub organization, https://github.com/mfem, is the main developer hub for
|
||||
the MFEM project.
|
||||
|
||||
If you plan to make contributions or will like to stay up-to-date with changes
|
||||
in the code, *we strongly encourage you to [join the MFEM organization](#mfem-organization)*.
|
||||
|
||||
This will simplify the workflow (by providing you additional permissions), and
|
||||
will allow us to reach you directly with project announcements.
|
||||
|
||||
|
||||
### MFEM Organization
|
||||
|
||||
- Before you can start, you need a GitHub account, here are a few suggestions:
|
||||
+ Create the account at: github.com/join.
|
||||
+ For easy identification, please add your name and maybe a picture of you at: https://github.com/settings/profile.
|
||||
+ To receive notification, set a primary email at: https://github.com/settings/emails.
|
||||
+ For password-less pull/push over SSH, add your SSH keys at: https://github.com/settings/keys.
|
||||
|
||||
- [Contact us](#contact-information) for an invitation to join the MFEM GitHub
|
||||
organization.
|
||||
|
||||
- You should receive an invitation email, which you can directly accept.
|
||||
Alternatively, *after logging into GitHub*, you can accept the invitation at
|
||||
the top of https://github.com/mfem.
|
||||
|
||||
- Consider making your membership public by going to https://github.com/orgs/mfem/people
|
||||
and clicking on the organization visibility dropbox next to your name.
|
||||
|
||||
- Project discussions and announcements will be posted at
|
||||
https://github.com/orgs/mfem/teams/everyone.
|
||||
|
||||
- The MFEM source code is in the [mfem](https://github.com/mfem/mfem)
|
||||
repository.
|
||||
|
||||
- The website and corresponding documentation are in the
|
||||
[web](https://github.com/mfem/web) repository.
|
||||
|
||||
- The [PyMFEM](https://github.com/mfem/PyMFEM) repository contains a Python
|
||||
wrapper for MFEM.
|
||||
|
||||
- The [data](https://github.com/mfem/data) repository contains additional
|
||||
(large) datafiles for MFEM.
|
||||
|
||||
|
||||
### New Feature Development
|
||||
|
||||
- A new feature should be important enough that at least one person, the
|
||||
proposer, is willing to work on it and be its champion.
|
||||
|
||||
- The proposer creates a branch for the new feature (with suffix `-dev`), off
|
||||
the `master` branch, or another existing feature branch, for example:
|
||||
|
||||
```
|
||||
# Clone assuming you have setup your ssh keys on GitHub:
|
||||
git clone git@github.com:mfem/mfem.git
|
||||
|
||||
# Alternatively, clone using the "https" protocol:
|
||||
git clone https://github.com/mfem/mfem.git
|
||||
|
||||
# Create a new feature branch starting from "master":
|
||||
git checkout master
|
||||
git pull
|
||||
git checkout -b feature-dev
|
||||
|
||||
# Work on "feature-dev", add local commits
|
||||
# ...
|
||||
|
||||
# (One time only) push the branch to github and setup your local
|
||||
# branch to track the github branch (for "git pull"):
|
||||
git push -u origin feature-dev
|
||||
|
||||
```
|
||||
|
||||
- **We prefer that you create the new feature branch inside the MFEM organization
|
||||
as opposed to in a fork.** This allows everyone in the community to collaborate
|
||||
in one central place.
|
||||
|
||||
- If you prefer to work in your fork, please [enable upstream edits](https://help.github.com/articles/allowing-changes-to-a-pull-request-branch-created-from-a-fork/).
|
||||
|
||||
- Never use the `next` branch to start a new feature branch!
|
||||
|
||||
- The typical feature branch name is `new-feature-dev`, e.g. `pumi-dev`. While
|
||||
not frequent in MFEM, other suffixes are possible, e.g. `-fix`, `-doc`, etc.
|
||||
|
||||
|
||||
### Developer Guidelines
|
||||
|
||||
- *Keep the code lean and as simple as possible*
|
||||
- Well-designed simple code is frequently more general and powerful.
|
||||
- Lean code base is easier to understand by new collaborators.
|
||||
- New features should be added only if they are necessary or generally useful.
|
||||
- Introduction of language constructions not currently used in MFEM should be
|
||||
justified and generally avoided (so we can build on cutting-edge systems).
|
||||
- We prefer basic C++ and the C++03 standard, to keep the code readable by
|
||||
a large audience and to make sure it compiles anywhere.
|
||||
|
||||
- *Keep the code general and reasonably efficient*
|
||||
- Main goal is fast prototyping for research.
|
||||
- When in doubt, generality wins over efficiency.
|
||||
- Respect the needs of different users (current and/or future).
|
||||
|
||||
- *Keep things separate and logically organized*
|
||||
- General usage features go in MFEM (implemented in as much generality as
|
||||
possible), non-general features go into external apps.
|
||||
- Inside MFEM, compartmentalize between linalg, fem, mesh, GLVis, etc.
|
||||
- Contributions that are project-specific or have external dependencies are
|
||||
allowed (if they are of broader interest), but should be `#ifdef`-ed and not
|
||||
change the code by default.
|
||||
|
||||
- Code specifics
|
||||
- All significant new classes, methods and functions have Doxygen-style
|
||||
documentation in source comments.
|
||||
- Consistent code styling is enforced with `make style` in the top-level
|
||||
directory. This requires [Artistic Style](http://astyle.sourceforge.net) (we
|
||||
specifically use version 2.05.1). See also the file `config/mfem.astylerc`.
|
||||
- Use `mfem::out` and `mfem::err` instead of `std::cout` and `std::cerr` in
|
||||
internal library code. (You can use `std` in examples and miniapps.)
|
||||
- When manually resolving conflicts during a merge, make sure to mention the
|
||||
conflicted files in the commit message.
|
||||
|
||||
### Pull Requests
|
||||
|
||||
- When your branch is ready for other developers to review / comment on
|
||||
the code, create a pull request towards `mfem:master`.
|
||||
|
||||
- Pull request typically have titles like:
|
||||
|
||||
`Description [new-feature-dev]`
|
||||
|
||||
for example:
|
||||
|
||||
`Parallel Unstructured Mesh Infrastructure (PUMI) integration [pumi-dev]`
|
||||
|
||||
Note the branch name suffix (in square brackets).
|
||||
|
||||
- Titles may contain a prefix in square brackets to emphasize the type of PR.
|
||||
Common choices are: `[DON'T MERGE]`, `[WIP]` and `[DISCUSS]`, for example:
|
||||
|
||||
`[DISCUSS] Hybridized DG [hdg-dev]`
|
||||
|
||||
- Add a description, appropriate labels and assign yourself to the PR. The MFEM
|
||||
team will add reviewers as appropriate.
|
||||
|
||||
- List outstanding TODO items in the description, see PR #222 for an example.
|
||||
|
||||
- Track the Travis CI and Appveyor [continuous integration](#automated-testing)
|
||||
builds at the end of the PR. These should run clean, so address any errors as
|
||||
soon as possible.
|
||||
|
||||
|
||||
### Pull Request Checklist
|
||||
|
||||
Before a PR can be merged, it should satisfy the following:
|
||||
|
||||
- [ ] Code builds.
|
||||
- [ ] Code passes `make style`.
|
||||
- [ ] Update `CHANGELOG`:
|
||||
- [ ] Is this a new feature users need to be aware of? New or updated example or miniapp?
|
||||
- [ ] Does it make sense to create a new section in the `CHANGELOG` to group with other related features?
|
||||
- [ ] Update `INSTALL`:
|
||||
- [ ] Has a new optional library been added? (*Make sure the external library is licensed under LGPL, not GPL!*)
|
||||
- [ ] Does `make` or `cmake` have a new target?
|
||||
- [ ] Did the requirements or the installation process change? *(rare)*.
|
||||
- [ ] Update `.gitignore`:
|
||||
- [ ] Check if `make distclean; git status` shows any files that are generated from the source but we don't want to track in the repository.
|
||||
- [ ] Add new patterns (just for the new files above) and re-run the above test.
|
||||
- [ ] New examples:
|
||||
- [ ] All sample runs at the top of the example work.
|
||||
- [ ] Update `examples/makefile`:
|
||||
- [ ] Add the example code to the appropriate `SEQ_EXAMPLES` and `PAR_EXAMPLES` variables.
|
||||
- [ ] Add any files generated by it to the `clean` target.
|
||||
- [ ] Add the example binary and any files generated by it to the top-level `.gitignore` file.
|
||||
- [ ] Update `examples/CMakeLists.txt`:
|
||||
- [ ] Add the example code to the `ALL_EXE_SRCS` variable.
|
||||
- [ ] Make sure `THIS_TEST_OPTIONS` is set correctly for the new example.
|
||||
- [ ] List the new example in `doc/CodeDocumentation.dox`.
|
||||
- [ ] Companion pull request for documentation in [mfem/web](https://github.com/mfem/web) repo:
|
||||
- [ ] Update or add example-specific documentation, see e.g. the `src/examples.md`.
|
||||
- [ ] Add the description, labels and screenshots in `src/examples.md` and `src/img`.
|
||||
- [ ] In `examples.md`, list the example under the appropriate categories, add new categories if necessary.
|
||||
- [ ] Add a short description of the example in the "Extensive Examples" section of `features.md`.
|
||||
- [ ] New miniapps:
|
||||
- [ ] All sample runs at the top of the miniapp work.
|
||||
- [ ] Update top-level `makefile` and `makefile` in corresponding miniapp directory.
|
||||
- [ ] Add the miniapp binary and any files generated by it to the top-level `.gitignore` file.
|
||||
- [ ] Update CMake build system:
|
||||
- [ ] Update the `CMakeLists.txt` file in the `miniapps` directory, if the new miniapp is in a new directory.
|
||||
- [ ] Add/update the `CMakeLists.txt` file in the new miniapp directory.
|
||||
- [ ] Consider adding a new test for the new miniapp.
|
||||
- [ ] List the new miniapp in `doc/CodeDocumentation.dox`
|
||||
- [ ] Companion pull request for documentation in [mfem/web](https://github.com/mfem/web) repo:
|
||||
- [ ] Update or add miniapp-specific documentation, see e.g. the `src/meshing.md` and `src/electromagnetics.md` files.
|
||||
- [ ] Add the description, labels and screenshots in `src/examples.md` and `src/img`.
|
||||
- [ ] The miniapps go at the end of the page, and are usually listed only under a specific "Application (PDE)" category.
|
||||
- [ ] Add a short description of the miniapp in the "Extensive Examples" section of `features.md`.
|
||||
- [ ] New capability:
|
||||
- [ ] All significant new classes, methods and functions have Doxygen-style documentation in source comments.
|
||||
- [ ] Consider adding new sample runs in existing examples to highlight the new capability.
|
||||
- [ ] Consider saving cool simulation pictures with the new capability in the Confluence gallery (LLNL only) or submitting them, via pull request, to the gallery section of the `mfem/web` repo.
|
||||
- [ ] If this is a major new feature, consider mentioning in the short summary inside `README` *(rare)*.
|
||||
- [ ] List major new classes in `doc/CodeDocumentation.dox` *(rare)*.
|
||||
- [ ] Update this checklist, if the new pull request affects it.
|
||||
- [ ] (LLNL only) Clone the `tests` repository and run the following tests, see `mfem/tests/README.md`:
|
||||
- [ ] `compilers`
|
||||
- [ ] `memcheck`
|
||||
- [ ] `unit-test`
|
||||
- [ ] `documentation`
|
||||
- [ ] (LLNL only) After merging:
|
||||
- [ ] Regenerate `README.html` files from companion documentation pull requests.
|
||||
- [ ] Update the `baseline` and `compiler` tests, add new tests if necessary.
|
||||
- [ ] Consider updating the script `mfem/tests/sample-runs` (`sample-runs-serial` and `sample-runs-parallel`).
|
||||
|
||||
### Master/Next Workflow
|
||||
|
||||
MFEM uses a `master`/`next`-branch workflow as described below:
|
||||
|
||||
- The `master` branch should always be of release quality and changes should not
|
||||
be merged until they have been fully tested. This branch is protected, and
|
||||
changes can only be made through pull requests.
|
||||
|
||||
- After approval, a pull request is merged manually (by MFEM developers) in the
|
||||
`next` branch for testing and the `in-next` label is added to the PR.
|
||||
This can be done as follows:
|
||||
|
||||
```
|
||||
# Pull the latest version of the "feature-dev" branch
|
||||
git checkout feature-dev
|
||||
git pull
|
||||
|
||||
# Pull the latest version of the "next" branch
|
||||
git checkout next
|
||||
git pull
|
||||
|
||||
# Merge "feature-dev" into "next", resolving conflicts, if necessary.
|
||||
# Use the "--no-ff" flag to create a new commit with merge message.
|
||||
git merge --no-ff feature-dev
|
||||
|
||||
# Push the "next" branch to the server
|
||||
git push
|
||||
```
|
||||
|
||||
- After a week of testing in `next` (excluding bugfixes), both on GitHub, as
|
||||
well as [internally](#tests-at-llnl) at LLNL, the original PR is merged into
|
||||
`master` (provided there are no issues).
|
||||
|
||||
- After the merge, the feature branch is deleted (unless it is a long-term
|
||||
project with periodic PRs).
|
||||
|
||||
- The `next` branch is used just for integrated testing of all PRs approved for
|
||||
merging into `master` to verify that each works individually and that all of
|
||||
them work as a group. This branch can be discarded at any time, though we
|
||||
typically do that only at the end of a [release cycle](#releases).
|
||||
|
||||
|
||||
### Releases
|
||||
|
||||
- Releases are just tags in the `master` branch, e.g. https://github.com/mfem/mfem/releases/tag/v3.3.2,
|
||||
and have a version that ends in an even "patch" number, e.g. `v3.2.2` or
|
||||
`v3.4` (by convention `v3.4` is the same as `v3.4.0`.) Between releases, the
|
||||
version ends in an odd "patch" number, e.g. `v3.3.3`.
|
||||
|
||||
- We use [milestones](https://github.com/mfem/mfem/milestones) to coordinate the
|
||||
work on different PRs toward a release, see for example the
|
||||
[v3.3.2 release](https://github.com/mfem/mfem/milestone/1?closed=1).
|
||||
|
||||
- After a release is complete, the `next` branch is recreated, e.g. as follows
|
||||
(replace `3.3.2` with current release):
|
||||
- Rename the current `next` branch to `next-pre-v3.3.2`.
|
||||
- Create a new `next` branch starting from the `v3.3.2` release.
|
||||
- Local copies of `next` can then be updated with `git checkout -B next origin/next`.
|
||||
|
||||
### Release Checklist
|
||||
|
||||
- [ ] Update the MFEM version in the following files:
|
||||
- [ ] `CHANGELOG`
|
||||
- [ ] `makefile`
|
||||
- [ ] `CMakeLists.txt`
|
||||
- [ ] `doc/CodeDocumentation.conf.in`
|
||||
- [ ] (LLNL only) Make sure all `README.html` files in the source repo are up to date.
|
||||
- [ ] Tag the repository:
|
||||
|
||||
```
|
||||
git tag -a v3.1 -m "Official release v3.1"
|
||||
git push origin v3.1
|
||||
```
|
||||
- [ ] Create the release tarball and push to `mfem/releases`.
|
||||
- [ ] Recreate the `next` branch as described in previous section.
|
||||
- [ ] Update and push documentation to `mfem/doxygen`.
|
||||
- [ ] Update URL shorlinks:
|
||||
- [ ] Create a shortlink at [https://goo.gl/](https://goo.gl/) for the release tarball, e.g. http://mfem.github.io/releases/mfem-3.1.tgz.
|
||||
- [ ] (LLNL only) Add and commit the new shorlink in the `links` and `links-mfem` files of the internal `mfem/downloads` repo.
|
||||
- [ ] Add the new shortlinks to the MFEM packages in `spack`, `homebrew/science`, `VisIt`, etc.
|
||||
- [ ] Update website in `mfem/web` repo:
|
||||
- Update version and shortlinks in `src/index.md` and `src/download.md`.
|
||||
- Use [cloc-1.62.pl](http://cloc.sourceforge.net/) and `ls -lh` to estimate the SLOC and the tarball size in `src/download.md`.
|
||||
|
||||
|
||||
## LLNL Workflow
|
||||
|
||||
- The GitHub `master` and `next` branches are mirrored to the LLNL institutional
|
||||
Bitbucket repository as `gh-master` and `gh-next`.
|
||||
|
||||
- `gh-master` is merged into LLNL's internal `master` through pull requests; write
|
||||
permissions to `master` are restricted to ensure this is the only way in which it
|
||||
gets updated.
|
||||
|
||||
- We never push directly from LLNL to GitHub.
|
||||
|
||||
- Versions of the code on LLNL's internal server, from most to least stable:
|
||||
- MFEM official release on mfem.org -- Most stable, tested in many apps.
|
||||
- `mfem:master` -- Recent development version, guaranteed to work.
|
||||
- `mfem:gh-master` -- Stable development version, passed testing, you can use
|
||||
it to build your code between releases.
|
||||
- `mfem:gh-next` -- Bleeding-edge development version, may be broken, use at
|
||||
your own risk.
|
||||
|
||||
|
||||
## Automated Testing
|
||||
|
||||
MFEM has several levels of automated testing running on GitHub, as well as on
|
||||
local Mac and Linux workstations, and Livermore Computing clusters at LLNL.
|
||||
|
||||
### Linux and Mac smoke tests
|
||||
We use Travis CI to drive the default tests on the `master` and `next`
|
||||
branches. See the `.travis` file and the logs at
|
||||
[https://travis-ci.org/mfem/mfem](https://travis-ci.org/mfem/mfem).
|
||||
|
||||
Testing using Travis CI should be kept lightweight, as there is a 50 minute time
|
||||
constraint on jobs. Two virtual machines are configured - Mac (OS X) and Linux.
|
||||
|
||||
- Tests on the `master` branch are triggered whenever a PR is issued on this branch.
|
||||
- Tests on the `next` branch are currently scheduled to run each night.
|
||||
|
||||
### Windows smoke test
|
||||
We use Appveyor to test building with the MS Visual C++ compiler in a Windows
|
||||
environment, as well as to test the CMake build. See the `.appveyor` file and the
|
||||
build logs at
|
||||
[https://ci.appveyor.com/project/mfem/mfem](https://ci.appveyor.com/project/mfem/mfem).
|
||||
|
||||
CMake is used to generate the MSVC Project files and drive the build. A release
|
||||
and debug build is performed with a simple run of `ex1` to verify the executable.
|
||||
|
||||
### Tests at LLNL
|
||||
At LLNL, we mirror the `master` and `next` branches internally (to `gh-master`
|
||||
and `gh-next`) and run longer nightly tests via cron. On the weekends, a more
|
||||
extensive test is run which extracts and executes all the different sample runs
|
||||
from each example.
|
||||
|
||||
|
||||
## Contact Information
|
||||
|
||||
- Contact the MFEM team by posting to the [GitHub issue tracker](https://github.com/mfem/mfem).
|
||||
Please perform a search to make sure your question has not been answered already.
|
||||
|
||||
- Email communications should be sent to the MFEM developers mailing list,
|
||||
mfem-dev@llnl.gov.
|
||||
|
||||
|
||||
## [Developer's Certificate of Origin 1.1](https://developercertificate.org/)
|
||||
|
||||
By making a contribution to this project, I certify that:
|
||||
|
||||
(a) The contribution was created in whole or in part by me and I have the right
|
||||
to submit it under the open source license indicated in the file; or
|
||||
|
||||
(b) The contribution is based upon previous work that, to the best of my
|
||||
knowledge, is covered under an appropriate open source license and I have
|
||||
the right under that license to submit that work with modifications, whether
|
||||
created in whole or in part by me, under the same open source license
|
||||
(unless I am permitted to submit under a different license), as indicated in
|
||||
the file; or
|
||||
|
||||
(c) The contribution was provided directly to me by some other person who
|
||||
certified (a), (b) or (c) and I have not modified it.
|
||||
|
||||
(d) I understand and agree that this project and the contribution are public and
|
||||
that a record of the contribution (including all personal information I
|
||||
submit with it, including my sign-off) is maintained indefinitely and may be
|
||||
redistributed consistent with this project or the open source license(s)
|
||||
involved.
|
||||
@@ -18,23 +18,14 @@ requires an MPI C++ compiler, as well as the following external libraries:
|
||||
- METIS (a family of multilevel partitioning algorithms)
|
||||
http://glaros.dtc.umn.edu/gkhome/metis/metis/overview
|
||||
|
||||
The METIS dependency can be disabled but that is not generally recommended, see
|
||||
the option MFEM_USE_METIS.
|
||||
|
||||
The library supports two build systems: one based on GNU make, and a second one
|
||||
based on CMake. Both build systems are described below. Some hints for building
|
||||
without GNU make or CMake can be found at the end of this file.
|
||||
|
||||
In addition to the native build systems, MFEM packages are also available in the
|
||||
following package managers:
|
||||
In addition to the native build systems, MFEM packages are also available in
|
||||
the Homebrew/Science, https://github.com/Homebrew/homebrew-science, and the
|
||||
Spack, https://github.com/LLNL/spack, package managers.
|
||||
|
||||
- Spack, https://github.com/spack/spack
|
||||
- OpenHPC, http://openhpc.community
|
||||
- Homebrew/Science, https://github.com/Homebrew/homebrew-science
|
||||
|
||||
We also recommend downloading and building the MFEM-based GLVis visualization
|
||||
tool which can be used to visualize the meshes and solution in MFEM's examples
|
||||
and miniapps. See http://glvis.org and http://mfem.org/building.
|
||||
|
||||
Quick start with GNU make
|
||||
=========================
|
||||
@@ -147,7 +138,7 @@ check the results from all the serial/parallel MFEM examples and miniapps use:
|
||||
|
||||
Note that by default MFEM uses "mpirun -np" in its test runs (this is also what
|
||||
is used in the sample runs of its examples and miniapps). The MPI launcher can
|
||||
be changed by the user as described in the "Specifying an MPI job launcher"
|
||||
be changed by the user as described in the "Specifying a MPI job launcher"
|
||||
section at the end of this file.
|
||||
|
||||
Running all the tests may take a while. Implementation details about the check
|
||||
@@ -159,8 +150,8 @@ An optional installation of the library and the headers can be performed with
|
||||
make install [PREFIX=<dir>]
|
||||
|
||||
The library will be installed in $(PREFIX)/lib, the headers in
|
||||
$(PREFIX)/include, and the configuration makefile (config.mk) in
|
||||
$(PREFIX)/share/mfem. The PREFIX option can also be set during configuration.
|
||||
$(PREFIX)/include, and the configuration makefile (config.mk) in $(PREFIX).
|
||||
The PREFIX option can also be set during configuration.
|
||||
|
||||
Information about the current build configuration can be viewed using
|
||||
|
||||
@@ -190,8 +181,6 @@ examples/ directory.
|
||||
|
||||
Configuration options (GNU make)
|
||||
================================
|
||||
See the configuration file config/defaults.mk for the default settings.
|
||||
|
||||
Compilers:
|
||||
CXX - C++ compiler, serial build
|
||||
MPICXX - MPI C++ compiler, parallel build
|
||||
@@ -202,14 +191,10 @@ Compiler options:
|
||||
CXXFLAGS - If not set, defined based on the above optimized/debug flags
|
||||
CPPFLAGS - Additional compiler options
|
||||
|
||||
Build options:
|
||||
STATIC - Build a static version of the library (YES/NO), default = YES
|
||||
SHARED - Build a shared version of the library (YES/NO), default = NO
|
||||
|
||||
Installation options:
|
||||
PREFIX - Specify the installation directory. The library (libmfem.a) will be
|
||||
installed in $(PREFIX)/lib, the headers in $(PREFIX)/include, and
|
||||
the configuration makefile (config.mk) in $(PREFIX)/share/mfem.
|
||||
the configuration makefile (config.mk) in $(PREFIX).
|
||||
INSTALL - Specify the install program, e.g /usr/bin/install
|
||||
|
||||
MFEM library features/options (GNU make)
|
||||
@@ -218,21 +203,10 @@ MFEM_USE_MPI = YES/NO
|
||||
Choose parallel/serial build. The parallel build requires proper setup of the
|
||||
HYPRE_* and METIS_* library options, see below.
|
||||
|
||||
MFEM_USE_METIS = YES/NO
|
||||
Enable/disable the use of the METIS library. By default, this option is set
|
||||
to the value of MFEM_USE_MPI. If this option is explicitly disabled in a
|
||||
parallel build, then the only parallel partitioning (domain decomposition)
|
||||
option in the library will be Cartesian partitioning with box meshes, and
|
||||
thus most of the parallel examples and miniapps will fail.
|
||||
|
||||
MFEM_DEBUG = YES/NO
|
||||
Choose debug/optimized build. The debug build enables a number of messages
|
||||
and consistency checks that may simplify bug-hunting.
|
||||
|
||||
MFEM_USE_EXCEPTIONS = YES/NO
|
||||
Enable the use of exceptions. In particular, modifies the default bahavior
|
||||
when errors are encountered: throw an exception, instead of aborting.
|
||||
|
||||
MFEM_USE_LIBUNWIND = YES/NO
|
||||
Use libunwind to print a stacktrace whenever mfem_error is raised. The
|
||||
information printed is enough to determine the line numbers where the
|
||||
@@ -257,16 +231,13 @@ MFEM_USE_MEMALLOC = YES/NO
|
||||
Internal MFEM option: enable batch allocation for some small objects.
|
||||
Recommended value is YES.
|
||||
|
||||
MFEM_TIMER_TYPE = 0/1/2/3/4/5/6/NO
|
||||
MFEM_TIMER_TYPE = 0/1/2/3/NO
|
||||
Specify which library functions to use in the class StopWatch used for
|
||||
measuring time. The available options are:
|
||||
0 - use std::clock from <ctime>, standard C++
|
||||
1 - use times from <sys/times.h>
|
||||
2 - use high-resolution POSIX clocks (see option POSIX_CLOCKS_LIB)
|
||||
3 - use QueryPerformanceCounter from <windows.h>
|
||||
4 - use mach_absolute_time from <mach/mach_time.h> + std::clock (Mac)
|
||||
5 - use gettimeofday from <sys/time.h>
|
||||
6 - use MPI_Wtime from <mpi.h>
|
||||
NO - use option 3 if the compiler macro _WIN32 is defined, 0 otherwise
|
||||
|
||||
MFEM_USE_SUNDIALS = YES/NO
|
||||
@@ -290,12 +261,6 @@ MFEM_USE_SUPERLU = YES/NO
|
||||
SuperLURowLocMatrix a distributed CSR matrix class needed by SuperLU. When
|
||||
enabled, this option uses the SUPERLU_* library options, see below.
|
||||
|
||||
MFEM_USE_STRUMPACK = YES/NO
|
||||
Enable MFEM functionality based on the STRUMPACK sparse direct solver and
|
||||
preconditioner through the STRUMPACKSolver and STRUMPACKRowLocMatrix
|
||||
classes. When enabled, this option uses the STRUMPACK_* library options, see
|
||||
below.
|
||||
|
||||
MFEM_USE_GNUTLS = YES/NO
|
||||
Enable secure socket support in class socketstream, using the auxiliary
|
||||
GnuTLS_* classes, based on the GnuTLS library. This option may be useful in
|
||||
@@ -307,9 +272,6 @@ MFEM_USE_GNUTLS = YES/NO
|
||||
the script 'glvis-keygen.sh' in the main GLVis directory can be used to do
|
||||
that:
|
||||
bash glvis-keygen.sh ["Your Name"] ["Your Email"]
|
||||
In MFEM v3.3.2 and earlier, the secure authentication is based on OpenPGP
|
||||
keys, while later versions use X.509 certificates. The latest version of the
|
||||
script 'glvis-keygen.sh' can be used to generate both types of keys.
|
||||
When MFEM_USE_GNUTLS is enabled, the additional build options, GNUTLS_*, are
|
||||
also used, see below.
|
||||
|
||||
@@ -336,13 +298,6 @@ MFEM_USE_SIDRE = YES/NO
|
||||
specification. When enabled, this option requires installation of HDF5 (see
|
||||
also MFEM_USE_NETCDF), Conduit and LLNL's axom project.
|
||||
|
||||
MFEM_USE_CONDUIT = YES/NO
|
||||
Enables support for converting MFEM Mesh and Grid Function objects to and
|
||||
from Conduit Mesh Blueprint Descriptions (https://github.com/LLNL/conduit/)
|
||||
and support for JSON and Binary I/O via Conduit Relay. This option requires
|
||||
an installation of Conduit. If Conduit was built with HDF5 support, it also
|
||||
requires an installation of HDF5 (see also MFEM_USE_NETCDF).
|
||||
|
||||
MFEM_USE_GZSTREAM = YES/NO
|
||||
Enables use of on-the-fly gzip compressed streams. With this feature enabled
|
||||
(YES), MFEM can compress its output files on-the-fly. In addition, it can
|
||||
@@ -353,14 +308,6 @@ MFEM_USE_GZSTREAM = YES/NO
|
||||
able to properly read an input file if it is gzip compressed. In that case,
|
||||
the solution is to uncompress the file with an external tool (such as gunzip)
|
||||
before attempting to use it with MFEM.
|
||||
When enabled, this option uses the ZLIB_* library options, see below.
|
||||
|
||||
MFEM_USE_PUMI = YES/NO
|
||||
Enable the usage of PUMI (https://scorec.rpi.edu/pumi/) in MFEM. The Parallel
|
||||
Unstructured Mesh Infrastructure (PUMI) is an unstructured, distributed mesh
|
||||
data management system that is capable of handling general non-manifold
|
||||
models and effectively supports automated adaptive analysis. PUMI enables
|
||||
support for parallel unstructured mesh modifications in MFEM.
|
||||
|
||||
MFEM_BUILD_TAG = (any value)
|
||||
An optional tag to characterize the build. Exported to config/config.mk.
|
||||
@@ -386,8 +333,8 @@ The specific libraries and their options are:
|
||||
URL: http://www.llnl.gov/CASC/hypre
|
||||
Options: HYPRE_OPT, HYPRE_LIB.
|
||||
|
||||
- METIS, used when MFEM_USE_METIS = YES. If using METIS 5, set
|
||||
MFEM_USE_METIS_5 = YES (default is to use METIS 4).
|
||||
- METIS, required for the parallel build, i.e. when MFEM_USE_MPI = YES. If using
|
||||
METIS 5, set MFEM_USE_METIS_5 = YES (default is to use METIS 4).
|
||||
URL: http://glaros.dtc.umn.edu/gkhome/metis/metis/overview
|
||||
Options: METIS_OPT, METIS_LIB.
|
||||
|
||||
@@ -405,10 +352,7 @@ The specific libraries and their options are:
|
||||
Option: POSIX_CLOCKS_LIB (default = -lrt).
|
||||
|
||||
- SUNDIALS (optional), used when MFEM_USE_SUNDIALS = YES.
|
||||
Beginning with MFEM v3.3, SUNDIALS v2.7.0 is supported.
|
||||
Beginning with MFEM v3.3.2, SUNDIALS v3.0.0 is also supported.
|
||||
If MFEM_USE_MPI is enabled, we expect that SUNDIALS is built with support for
|
||||
both MPI and hypre.
|
||||
In parallel we expect that SUNDIALS is built with support for MPI and hypre.
|
||||
URL: http://computation.llnl.gov/projects/sundials/sundials-software
|
||||
Options: SUNDIALS_OPT, SUNDIALS_LIB.
|
||||
|
||||
@@ -427,14 +371,6 @@ The specific libraries and their options are:
|
||||
URL: http://crd-legacy.lbl.gov/~xiaoye/SuperLU
|
||||
Options: SUPERLU_OPT, SUPERLU_LIB.
|
||||
|
||||
- STRUMPACK (optional), used when MFEM_USE_STRUMPACK = YES. Note that STRUMPACK
|
||||
requires the PT-Scotch and Scalapack libraries as well as ParMETIS, which
|
||||
includes METIS 5 in its distribution.
|
||||
The support for STRUMPACK was added in MFEM v3.3.2 and it requires STRUMPACK
|
||||
2.0.0 or later.
|
||||
URL: http://portal.nersc.gov/project/sparse/strumpack
|
||||
Options: STRUMPACK_OPT, STRUMPACK_LIB.
|
||||
|
||||
- GnuTLS (optional), used when MFEM_USE_GNUTLS = YES. On most Linux systems,
|
||||
GnuTLS is available as a development package, e.g. gnutls-devel. On Mac OS X,
|
||||
one can get the library through the Homebrew package manager (http://brew.sh).
|
||||
@@ -448,7 +384,7 @@ The specific libraries and their options are:
|
||||
URL: www.unidata.ucar.edu/software/netcdf
|
||||
Options: NETCDF_OPT, NETCDF_LIB.
|
||||
|
||||
- PETSc (optional), used when MFEM_USE_PETSC = YES. Version 3.8 or higher of
|
||||
- PETSc (optional), used when MFEM_USE_PETSC = YES. Version 3.8 or higher of
|
||||
the PETSC dev branch is required. The MFEM and PETSc builds can share common
|
||||
libraries, e.g., hypre and SUNDIALS. Here's an example configuration, assuming
|
||||
PETSc has been cloned on the same level as mfem and hypre:
|
||||
@@ -465,16 +401,6 @@ The specific libraries and their options are:
|
||||
https://support.hdfgroup.org/HDF5 (HDF5)
|
||||
Options: SIDRE_OPT, SIDRE_LIB.
|
||||
|
||||
- Conduit, used when MFEM_USE_CONDUIT = YES. Direct Conduit Mesh Blueprint
|
||||
support requires Conduit >= v0.3.1 and VisIt >= v2.13.1 to read the output.
|
||||
URL: https://github.com/LLNL/conduit (Conduit)
|
||||
https://support.hdfgroup.org/HDF5 (HDF5)
|
||||
Options: CONDUIT_OPT, CONDUIT_LIB.
|
||||
|
||||
- PUMI, used when MFEM_USE_PUMI = YES.
|
||||
URL: https://scorec.rpi.edu/pumi
|
||||
Options: PUMI_OPT, PUMI_LIB.
|
||||
|
||||
- MPFR (optional), used when MFEM_USE_MPFR = YES.
|
||||
URL: http://mpfr.org, it depends on the GMP library: https://gmplib.org
|
||||
Options: MPFR_OPT, MPFR_LIB.
|
||||
@@ -485,11 +411,6 @@ The specific libraries and their options are:
|
||||
URL: http://www.nongnu.org/libunwind
|
||||
Options: LIBUNWIND_OPT, LIBUNWIND_LIB.
|
||||
|
||||
- ZLIB (optional), used when MFEM_USE_GZSTREAM = YES, or when MFEM_USE_NETCDF =
|
||||
YES (in the default settings for NETCDF_OPT and NETCDF_LIB).
|
||||
URL: https://zlib.net
|
||||
Options: ZLIB_OPT, ZLIB_LIB.
|
||||
|
||||
|
||||
Building with CMake
|
||||
===================
|
||||
@@ -521,12 +442,6 @@ Debug and optimization options are controlled through the CMake variable
|
||||
CMAKE_BUILD_TYPE which can be set to standard values like "Debug", and "Release"
|
||||
(default).
|
||||
|
||||
To use a specific generator use the "-G <generator>" option of cmake:
|
||||
|
||||
cmake <mfem-source-dir> -G "Xcode"
|
||||
cmake <mfem-source-dir> -G "Visual Studio 12 2013"
|
||||
cmake <mfem-source-dir> -G "MinGW Makefiles"
|
||||
|
||||
With CMake it is possible to build MFEM as a shared library using the standard
|
||||
CMake option -DBUILD_SHARED_LIBS=1.
|
||||
|
||||
@@ -534,30 +449,15 @@ Once configured, the library can be built simply with (assuming a UNIX type
|
||||
system, where the default is to generate "UNIX Makefiles")
|
||||
|
||||
make -j 4
|
||||
or
|
||||
cmake --build .
|
||||
or
|
||||
cmake --build . --config Release [Visual Studio, Xcode]
|
||||
|
||||
The build can be quick-tested by running
|
||||
|
||||
make check
|
||||
or
|
||||
cmake --build . --target check
|
||||
or
|
||||
cmake --build . --config Release --target check [Visual Studio, Xcode]
|
||||
|
||||
which will simply compile and run Example 1/1p. For more extensive tests that
|
||||
check the results from all the serial/parallel MFEM examples and miniapps use:
|
||||
|
||||
make exec -j 4
|
||||
make test
|
||||
or
|
||||
cmake --build . --target exec
|
||||
cmake --build . --target test
|
||||
or
|
||||
cmake --build . --config Release --target exec [Visual Studio, Xcode]
|
||||
cmake --build . --config Release --target RUN_TESTS [Visual Studio, Xcode]
|
||||
|
||||
Note that running all the tests may take a while.
|
||||
|
||||
@@ -565,11 +465,6 @@ Installation prefix can be configured by setting the standard CMake variable
|
||||
CMAKE_INSTALL_PREFIX. To install the library, use
|
||||
|
||||
make install
|
||||
or
|
||||
cmake --build . --target install
|
||||
or
|
||||
cmake --build . --config Release --target install [Xcode]
|
||||
cmake --build . --config Release --target INSTALL [Visual Studio]
|
||||
|
||||
The library will be installed in <PREFIX>/lib, the headers in <PREFIX>/include,
|
||||
and the configuration CMake files in <PREFIX>/lib/cmake/mfem.
|
||||
@@ -577,8 +472,6 @@ and the configuration CMake files in <PREFIX>/lib/cmake/mfem.
|
||||
|
||||
Configuration variables (CMake)
|
||||
===============================
|
||||
See the configuration file config/defaults.cmake for the default settings.
|
||||
|
||||
Non-standard CMake variables for compilers:
|
||||
CXX - If set, overwrite the auto-detected C++ compiler, serial build
|
||||
MPICXX - If set, overwrite the auto-detected MPI C++ compiler, parallel build
|
||||
@@ -592,7 +485,6 @@ The following options are equivalent to the GNU make options with the same name:
|
||||
[see "MFEM library features/options (GNU make)" above]
|
||||
|
||||
MFEM_USE_MPI
|
||||
MFEM_USE_METIS - Set to ${MFEM_USE_MPI}, can be overwritten.
|
||||
MFEM_USE_LIBUNWIND
|
||||
MFEM_USE_LAPACK
|
||||
MFEM_THREAD_SAFE
|
||||
@@ -602,12 +494,10 @@ MFEM_TIMER_TYPE - Set automatically, can be overwritten.
|
||||
MFEM_USE_MESQUITE
|
||||
MFEM_USE_SUITESPARSE
|
||||
MFEM_USE_SUPERLU
|
||||
MFEM_USE_STRUMPACK
|
||||
MFEM_USE_GNUTLS
|
||||
MFEM_USE_NETCDF
|
||||
MFEM_USE_MPFR
|
||||
MFEM_USE_GZSTREAM
|
||||
MFEM_USE_PUMI
|
||||
|
||||
The following options are CMake specific:
|
||||
|
||||
@@ -646,14 +536,13 @@ The CMake build system adds auto-detection for the following packages/libraries:
|
||||
- METIS - The option MFEM_USE_METIS_5 is auto-detected.
|
||||
- MESQUITE
|
||||
- SuiteSparse
|
||||
- SuperLUDist, STRUMPACK
|
||||
- SuperLUDist
|
||||
- ParMETIS
|
||||
- GNUTLS - Extends the built-in CMake support, to search GNUTLS_DIR as well.
|
||||
- NETCDF
|
||||
- MPFR
|
||||
- LIBUNWIND
|
||||
- POSIXCLOCKS
|
||||
- PUMI
|
||||
|
||||
The following built-in CMake packages are also used:
|
||||
|
||||
@@ -669,15 +558,15 @@ Before using another build system (e.g. Visual Studio) it is necessary to create
|
||||
a proper configuration header file, config/config.hpp, using the template from
|
||||
config/config.hpp.in:
|
||||
|
||||
cp config/config.hpp.in config/_config.hpp
|
||||
cp config/config.hpp.in config/config.hpp
|
||||
|
||||
The file config/_config.hpp can then be edited to enable desired options. The
|
||||
The file config/config.hpp can then be edited to enable desired options. The
|
||||
MFEM library is simply a combination of all object files obtained by compiling
|
||||
the .cpp source files in the source directories: general, linalg, mesh, and fem.
|
||||
|
||||
|
||||
Specifying an MPI job launcher
|
||||
==============================
|
||||
Specifying a MPI job launcher
|
||||
=============================
|
||||
By default, MFEM will use 'mpirun -np #' to launch any of its parallel tests or
|
||||
miniapps, where # is the number of MPI tasks. An alternate MPI launcher can be
|
||||
provided by setting the MFEM_MPIEXEC and MFEM_MPIEXEC_NP config variables.
|
||||
|
||||
@@ -12,15 +12,11 @@ to enable the research and development of scalable finite element discretization
|
||||
and solver algorithms through general finite element abstractions, accurate and
|
||||
flexible visualization, and tight integration with the hypre library.
|
||||
|
||||
* For building instructions, see the file INSTALL, or type "make help".
|
||||
For building instructions, see the file INSTALL, or type "make help". Copyright
|
||||
information and licensing restrictions can be found in the file COPYRIGHT.
|
||||
|
||||
* Copyright and licensing information can be found in the file COPYRIGHT.
|
||||
|
||||
* The best starting point for new users interested in MFEM's features is the
|
||||
interactive documentation in examples/README.html.
|
||||
|
||||
* Developers interested in contributing to the library, should read the
|
||||
instructions and documentation in the CONTRIBUTING.md file.
|
||||
The best starting point for new users interested in MFEM's features is the
|
||||
interactive documentation in examples/README.html.
|
||||
|
||||
Conceptually, MFEM can be viewed as a finite element toolbox that provides the
|
||||
building blocks for developing finite element algorithms in a manner similar to
|
||||
@@ -60,8 +56,7 @@ time integrators, etc.
|
||||
For examples of using MFEM, see the examples/ and miniapps/ directories, as well
|
||||
as the OpenGL visualization tool GLVis which is available at http://glvis.org.
|
||||
|
||||
This project is released under the LGPL v2.1 license with static linking
|
||||
exception. See files COPYRIGHT and LICENSE file for full details.
|
||||
This project is released under the LGPL v2.1 license. See LICENSE file for full
|
||||
details.
|
||||
|
||||
LLNL Release Number: LLNL-CODE-443211
|
||||
DOI: 10.11578/dc.20171025.1248
|
||||
|
||||
@@ -1,182 +0,0 @@
|
||||
##################################################################################
|
||||
#
|
||||
# Set defaults for XSDK CMake projects
|
||||
#
|
||||
##################################################################################
|
||||
|
||||
#
|
||||
# This module implements standard behavior for XSDK CMake projects. The main
|
||||
# thing it does in XSDK mode (i.e. USE_XSDK_DEFAULTS=TRUE) is to print out
|
||||
# when the env vars CC, CXX, FC and compiler flags CFLAGS, CXXFLAGS, and
|
||||
# FFLAGS/FCFLAGS are used to select the compilers and compiler flags (raw
|
||||
# CMake does this silently) and to set BUILD_SHARED_LIBS=TRUE and
|
||||
# CMAKE_BUILD_TYPE=DEBUG by default. It does not implement *all* of the
|
||||
# standard XSDK configuration parameters. The parent CMake project must do
|
||||
# that.
|
||||
#
|
||||
# Note that when USE_XSDK_DEFAULTS=TRUE, then the Fortran flags will be read
|
||||
# from either of the env vars FFLAGS or FCFLAGS. If both are set, but are the
|
||||
# same, then FFLAGS it used (which is the same as FCFLAGS). However, if both
|
||||
# are set but are not equal, then a FATAL_ERROR is raised and CMake configure
|
||||
# processing is stopped.
|
||||
#
|
||||
# To be used in a parent project, this module must be included after
|
||||
#
|
||||
# PROJECT(${PROJECT_NAME} NONE)
|
||||
#
|
||||
# is called but before the compilers are defined and processed using:
|
||||
#
|
||||
# ENABLE_LANGUAGE(<LANG>)
|
||||
#
|
||||
# For example, one would do:
|
||||
#
|
||||
# PROJECT(${PROJECT_NAME} NONE)
|
||||
# ...
|
||||
# SET(USE_XSDK_DEFAULTS_DEFAULT TRUE) # Set to false if desired
|
||||
# INCLUDE("${CMAKE_CURRENT_SOURCE_DIR}/stdk/XSDKDefaults.cmake")
|
||||
# ...
|
||||
# ENABLE_LANGUAGE(C)
|
||||
# ENABLE_LANGUAGE(C++)
|
||||
# ENABLE_LANGUAGE(Fortran)
|
||||
#
|
||||
# The variable `USE_XSDK_DEFAULTS_DEFAULT` is used as the default for the
|
||||
# cache var `USE_XSDK_DEFAULTS`. That way, a project can decide if it wants
|
||||
# XSDK defaults turned on or off by default and users can independently decide
|
||||
# if they want the CMake project to use standard XSDK behavior or raw CMake
|
||||
# behavior.
|
||||
#
|
||||
# By default, the XSDKDefaults.cmake module assumes that the project will need
|
||||
# C, C++, and Fortran. If any language is not needed then, set
|
||||
# XSDK_ENABLE_C=OFF, XSDK_ENABLE_CXX=OFF, or XSDK_ENABLE_Fortran=OFF *before*
|
||||
# including this module. Note, these variables are *not* cache vars because a
|
||||
# project either does or does not have C, C++ or Fortran source files, the
|
||||
# user has nothing to do with this so there is no need for cache vars. The
|
||||
# parent CMake project just needs to tell XSDKDefault.cmake what languages is
|
||||
# needs or does not need.
|
||||
#
|
||||
# For example, if the parent CMake project only needs C, then it would do:
|
||||
#
|
||||
# PROJECT(${PROJECT_NAME} NONE)'
|
||||
# ...
|
||||
# SET(USE_XSDK_DEFAULTS_DEFAULT TRUE)
|
||||
# SET(XSDK_ENABLE_CXX OFF)
|
||||
# SET(XSDK_ENABLE_Fortran OFF)
|
||||
# INCLUDE("${CMAKE_CURRENT_SOURCE_DIR}/stdk/XSDKDefaults.cmake")
|
||||
# ...
|
||||
# ENABLE_LANGAUGE(C)
|
||||
#
|
||||
# This module code will announce when it sets any variables.
|
||||
#
|
||||
|
||||
#
|
||||
# Helper functions
|
||||
#
|
||||
|
||||
IF (NOT COMMAND PRINT_VAR)
|
||||
FUNCTION(PRINT_VAR VAR_NAME)
|
||||
MESSAGE("-- " "${VAR_NAME} = '${${VAR_NAME}}'")
|
||||
ENDFUNCTION()
|
||||
ENDIF()
|
||||
|
||||
IF (NOT COMMAND SET_DEFAULT)
|
||||
MACRO(SET_DEFAULT VAR)
|
||||
IF ("${${VAR}}" STREQUAL "")
|
||||
SET(${VAR} ${ARGN})
|
||||
ENDIF()
|
||||
ENDMACRO()
|
||||
ENDIF()
|
||||
|
||||
#
|
||||
# XSDKDefaults.cmake control variables
|
||||
#
|
||||
|
||||
# USE_XSDK_DEFAULTS
|
||||
IF ("${USE_XSDK_DEFAULTS_DEFAULT}" STREQUAL "")
|
||||
SET(USE_XSDK_DEFAULTS_DEFAULT FALSE)
|
||||
ENDIF()
|
||||
SET(USE_XSDK_DEFAULTS ${USE_XSDK_DEFAULTS_DEFAULT} CACHE BOOL
|
||||
"Use XSDK defaults and behavior.")
|
||||
PRINT_VAR(USE_XSDK_DEFAULTS)
|
||||
|
||||
SET_DEFAULT(XSDK_ENABLE_C TRUE)
|
||||
SET_DEFAULT(XSDK_ENABLE_CXX TRUE)
|
||||
SET_DEFAULT(XSDK_ENABLE_Fortran TRUE)
|
||||
|
||||
# Handle the compiler and flags for a language
|
||||
MACRO(XSDK_HANDLE_LANG_DEFAULTS CMAKE_LANG_NAME ENV_LANG_NAME
|
||||
ENV_LANG_FLAGS_NAMES
|
||||
)
|
||||
|
||||
# Announce using env var ${ENV_LANG_NAME}
|
||||
IF (NOT "$ENV{${ENV_LANG_NAME}}" STREQUAL "" AND
|
||||
"${CMAKE_${CMAKE_LANG_NAME}_COMPILER}" STREQUAL ""
|
||||
)
|
||||
MESSAGE("-- " "XSDK: Setting CMAKE_${CMAKE_LANG_NAME}_COMPILER from env var"
|
||||
" ${ENV_LANG_NAME}='$ENV{${ENV_LANG_NAME}}'!")
|
||||
SET(CMAKE_${CMAKE_LANG_NAME}_COMPILER "$ENV{${ENV_LANG_NAME}}" CACHE FILEPATH
|
||||
"XSDK: Set by default from env var ${ENV_LANG_NAME}")
|
||||
ENDIF()
|
||||
|
||||
# Announce using env var ${ENV_LANG_FLAGS_NAME}
|
||||
FOREACH(ENV_LANG_FLAGS_NAME ${ENV_LANG_FLAGS_NAMES})
|
||||
IF (NOT "$ENV{${ENV_LANG_FLAGS_NAME}}" STREQUAL "" AND
|
||||
"${CMAKE_${CMAKE_LANG_NAME}_FLAGS}" STREQUAL ""
|
||||
)
|
||||
MESSAGE("-- " "XSDK: Setting CMAKE_${CMAKE_LANG_NAME}_FLAGS from env var"
|
||||
" ${ENV_LANG_FLAGS_NAME}='$ENV{${ENV_LANG_FLAGS_NAME}}'!")
|
||||
SET(CMAKE_${CMAKE_LANG_NAME}_FLAGS "$ENV{${ENV_LANG_FLAGS_NAME}} " CACHE STRING
|
||||
"XSDK: Set by default from env var ${ENV_LANG_FLAGS_NAME}")
|
||||
# NOTE: CMake adds the space after $ENV{${ENV_LANG_FLAGS_NAME}} so we
|
||||
# duplicate that here!
|
||||
ENDIF()
|
||||
ENDFOREACH()
|
||||
|
||||
ENDMACRO()
|
||||
|
||||
|
||||
#
|
||||
# Set XSDK Defaults
|
||||
#
|
||||
|
||||
# Set default compilers and flags
|
||||
IF (USE_XSDK_DEFAULTS)
|
||||
|
||||
# Handle env vars for languages C, C++, and Fortran
|
||||
|
||||
IF (XSDK_ENABLE_C)
|
||||
XSDK_HANDLE_LANG_DEFAULTS(C CC CFLAGS)
|
||||
ENDIF()
|
||||
|
||||
IF (XSDK_ENABLE_CXX)
|
||||
XSDK_HANDLE_LANG_DEFAULTS(CXX CXX CXXFLAGS)
|
||||
ENDIF()
|
||||
|
||||
IF (XSDK_ENABLE_Fortran)
|
||||
SET(ENV_FFLAGS "$ENV{FFLAGS}")
|
||||
SET(ENV_FCFLAGS "$ENV{FCFLAGS}")
|
||||
IF (
|
||||
(NOT "${ENV_FFLAGS}" STREQUAL "") AND (NOT "${ENV_FCFLAGS}" STREQUAL "")
|
||||
AND
|
||||
("${CMAKE_Fortran_FLAGS}" STREQUAL "")
|
||||
)
|
||||
IF (NOT "${ENV_FFLAGS}" STREQUAL "${ENV_FCFLAGS}")
|
||||
MESSAGE(FATAL_ERROR "Error, env vars FFLAGS='${ENV_FFLAGS}' and"
|
||||
" FCFLAGS='${ENV_FCFLAGS}' are both set in the env but are not equal!")
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
XSDK_HANDLE_LANG_DEFAULTS(Fortran FC "FFLAGS;FCFLAGS")
|
||||
ENDIF()
|
||||
|
||||
# Set XSDK defaults for other CMake variables
|
||||
|
||||
IF ("${BUILD_SHARED_LIBS}" STREQUAL "")
|
||||
MESSAGE("-- " "XSDK: Setting default BUILD_SHARED_LIBS=TRUE")
|
||||
SET(BUILD_SHARED_LIBS TRUE CACHE BOOL "Set by default in XSDK mode")
|
||||
ENDIF()
|
||||
|
||||
IF ("${CMAKE_BUILD_TYPE}" STREQUAL "")
|
||||
MESSAGE("-- " "XSDK: Setting default CMAKE_BUILD_TYPE=DEBUG")
|
||||
SET(CMAKE_BUILD_TYPE DEBUG CACHE STRING "Set by default in XSDK mode")
|
||||
ENDIF()
|
||||
|
||||
ENDIF()
|
||||
@@ -12,42 +12,31 @@
|
||||
include(${CMAKE_CURRENT_LIST_DIR}/MFEMConfigVersion.cmake)
|
||||
|
||||
set(MFEM_VERSION ${PACKAGE_VERSION})
|
||||
set(MFEM_VERSION_INT @MFEM_VERSION@)
|
||||
set(MFEM_GIT_STRING "@MFEM_GIT_STRING@")
|
||||
|
||||
set(MFEM_USE_MPI @MFEM_USE_MPI@)
|
||||
set(MFEM_USE_METIS @MFEM_USE_METIS@)
|
||||
set(MFEM_USE_METIS_5 @MFEM_USE_METIS_5@)
|
||||
set(MFEM_DEBUG @MFEM_DEBUG@)
|
||||
set(MFEM_USE_EXCEPTIONS @MFEM_USE_EXCEPTIONS@)
|
||||
set(MFEM_USE_GZSTREAM @MFEM_USE_GZSTREAM@)
|
||||
set(MFEM_USE_LIBUNWIND @MFEM_USE_LIBUNWIND@)
|
||||
set(MFEM_USE_LAPACK @MFEM_USE_LAPACK@)
|
||||
set(MFEM_THREAD_SAFE @MFEM_THREAD_SAFE@)
|
||||
set(MFEM_USE_OPENMP @MFEM_USE_OPENMP@)
|
||||
set(MFEM_USE_MEMALLOC @MFEM_USE_MEMALLOC@)
|
||||
set(MFEM_TIMER_TYPE @MFEM_TIMER_TYPE@)
|
||||
set(MFEM_USE_SUNDIALS @MFEM_USE_SUNDIALS@)
|
||||
set(MFEM_USE_MESQUITE @MFEM_USE_MESQUITE@)
|
||||
set(MFEM_USE_SUITESPARSE @MFEM_USE_SUITESPARSE@)
|
||||
set(MFEM_USE_SUPERLU @MFEM_USE_SUPERLU@)
|
||||
set(MFEM_USE_STRUMPACK @MFEM_USE_STRUMPACK@)
|
||||
set(MFEM_USE_GECKO @MFEM_USE_GECKO@)
|
||||
set(MFEM_USE_GNUTLS @MFEM_USE_GNUTLS@)
|
||||
set(MFEM_USE_NETCDF @MFEM_USE_NETCDF@)
|
||||
set(MFEM_USE_PETSC @MFEM_USE_PETSC@)
|
||||
set(MFEM_USE_MPFR @MFEM_USE_MPFR@)
|
||||
set(MFEM_USE_SIDRE @MFEM_USE_SIDRE@)
|
||||
set(MFEM_USE_CONDUIT @MFEM_USE_CONDUIT@)
|
||||
set(MFEM_USE_PUMI @MFEM_USE_PUMI@)
|
||||
|
||||
set(MFEM_CXX_COMPILER "@CMAKE_CXX_COMPILER@")
|
||||
set(MFEM_CXX_FLAGS "@CMAKE_CXX_FLAGS@")
|
||||
|
||||
@PACKAGE_INIT@
|
||||
|
||||
set(MFEM_INCLUDE_DIRS "@PACKAGE_INCLUDE_INSTALL_DIRS@")
|
||||
foreach (dir ${MFEM_INCLUDE_DIRS})
|
||||
message("DIR = ${dir}")
|
||||
|
||||
set_and_check(MFEM_INCLUDE_DIR "${dir}")
|
||||
endforeach (dir "${MFEM_INCLUDE_DIRS}")
|
||||
|
||||
|
||||
@@ -12,27 +12,6 @@
|
||||
#ifndef MFEM_CONFIG_HEADER
|
||||
#define MFEM_CONFIG_HEADER
|
||||
|
||||
// MFEM version: integer of the form: (major*100 + minor)*100 + patch.
|
||||
#cmakedefine MFEM_VERSION @MFEM_VERSION@
|
||||
|
||||
// MFEM version string of the form "3.3" or "3.3.1".
|
||||
#cmakedefine MFEM_VERSION_STRING "@MFEM_VERSION_STRING@"
|
||||
|
||||
// MFEM version type, see the MFEM_VERSION_TYPE_* constants below.
|
||||
#define MFEM_VERSION_TYPE ((MFEM_VERSION)%2)
|
||||
|
||||
// MFEM version type constants.
|
||||
#define MFEM_VERSION_TYPE_RELEASE 0
|
||||
#define MFEM_VERSION_TYPE_DEVELOPMENT 1
|
||||
|
||||
// Separate MFEM version numbers for major, minor, and patch.
|
||||
#define MFEM_VERSION_MAJOR ((MFEM_VERSION)/10000)
|
||||
#define MFEM_VERSION_MINOR (((MFEM_VERSION)/100)%100)
|
||||
#define MFEM_VERSION_PATCH ((MFEM_VERSION)%100)
|
||||
|
||||
// Description of the git commit used to build MFEM.
|
||||
#cmakedefine MFEM_GIT_STRING "@MFEM_GIT_STRING@"
|
||||
|
||||
// Build the parallel MFEM library.
|
||||
// Requires an MPI compiler, and the libraries HYPRE and METIS.
|
||||
#cmakedefine MFEM_USE_MPI
|
||||
@@ -40,18 +19,12 @@
|
||||
// Enable debug checks in MFEM.
|
||||
#cmakedefine MFEM_DEBUG
|
||||
|
||||
// Throw an exception on errors.
|
||||
#cmakedefine MFEM_USE_EXCEPTIONS
|
||||
|
||||
// Enable gzstream in MFEM.
|
||||
#cmakedefine MFEM_USE_GZSTREAM
|
||||
|
||||
// Enable backtraces for mfem_error through libunwind.
|
||||
#cmakedefine MFEM_USE_LIBUNWIND
|
||||
|
||||
// Enable MFEM features that use the METIS library (parallel MFEM).
|
||||
#cmakedefine MFEM_USE_METIS
|
||||
|
||||
// Enable this option if linking with METIS version 5 (parallel MFEM).
|
||||
#cmakedefine MFEM_USE_METIS_5
|
||||
|
||||
@@ -74,9 +47,6 @@
|
||||
// Enable MFEM functionality based on the SuperLU_DIST library.
|
||||
#cmakedefine MFEM_USE_SUPERLU
|
||||
|
||||
// Enable MFEM functionality based on the STRUMPACK library.
|
||||
#cmakedefine MFEM_USE_STRUMPACK
|
||||
|
||||
// Internal MFEM option: enable group/batch allocation for some small objects.
|
||||
#cmakedefine MFEM_USE_MEMALLOC
|
||||
|
||||
@@ -95,14 +65,12 @@
|
||||
// Enable MFEM functionality based on the Sidre library
|
||||
#cmakedefine MFEM_USE_SIDRE
|
||||
|
||||
// Enable MFEM functionality based on Conduit
|
||||
#cmakedefine MFEM_USE_CONDUIT
|
||||
|
||||
// Enable MFEM functionality based on the PUMI library
|
||||
#cmakedefine MFEM_USE_PUMI
|
||||
|
||||
// Which library functions to use in class StopWatch for measuring time.
|
||||
// For a list of the available options, see INSTALL.
|
||||
// The available options are:
|
||||
// 0 - use std::clock from <ctime>
|
||||
// 1 - use times from <sys/times.h>
|
||||
// 2 - use high-resolution POSIX clocks
|
||||
// 3 - use QueryPerformanceCounter from <windows.h>
|
||||
// If not defined, an option is selected automatically.
|
||||
#define MFEM_TIMER_TYPE @MFEM_TIMER_TYPE@
|
||||
|
||||
@@ -113,11 +81,4 @@
|
||||
// Macro needed to get defines like M_PI from <cmath>. (Visual Studio C++ only?)
|
||||
#cmakedefine _USE_MATH_DEFINES
|
||||
|
||||
// Version of HYPRE used for building MFEM.
|
||||
#cmakedefine MFEM_HYPRE_VERSION @MFEM_HYPRE_VERSION@
|
||||
|
||||
// Macro defined when PUMI is built with support for the Simmetrix SimModSuite
|
||||
// library.
|
||||
#cmakedefine MFEM_USE_SIMMETRIX
|
||||
|
||||
#endif // MFEM_CONFIG_HEADER
|
||||
|
||||
@@ -10,14 +10,15 @@
|
||||
# Software Foundation) version 2.1 dated February 1999.
|
||||
|
||||
# Defines the following variables:
|
||||
# - AXOM_FOUND
|
||||
# - AXOM_LIBRARIES
|
||||
# - AXOM_INCLUDE_DIRS
|
||||
# - ATK_FOUND
|
||||
# - ATK_LIBRARIES
|
||||
# - ATK_INCLUDE_DIRS
|
||||
|
||||
include(MfemCmakeUtilities)
|
||||
# Note: components are enabled based on the find_package() parameters.
|
||||
mfem_find_package(Axom AXOM AXOM_DIR "include" "" "lib" ""
|
||||
"Paths to headers required by Axom." "Libraries required by Axom."
|
||||
mfem_find_package(ATK ATK ATK_DIR "include" "" "lib" ""
|
||||
"Paths to headers required by ATK." "Libraries required by ATK."
|
||||
ADD_COMPONENT Sidre "include" sidre/sidre.hpp "lib" sidre
|
||||
ADD_COMPONENT SPIO "include" spio/IOManager.hpp "lib" spio
|
||||
ADD_COMPONENT SLIC "include" slic/slic.hpp "lib" slic
|
||||
ADD_COMPONENT axom_utils "include" axom_utils/Utilities.hpp "lib" axom_utils)
|
||||
ADD_COMPONENT common "include" common/ATKMacros.hpp "lib" common)
|
||||
@@ -14,22 +14,9 @@
|
||||
# - CONDUIT_LIBRARIES
|
||||
# - CONDUIT_INCLUDE_DIRS
|
||||
|
||||
# check to see if relay requires hdf5, if so make sure to set HDF5
|
||||
# as a required dep
|
||||
if(EXISTS ${CONDUIT_DIR}/include/conduit/conduit_relay_hdf5.hpp)
|
||||
message(STATUS "Conduit Relay HDF5 Support is ENABLED")
|
||||
# we only need HDF5 if Conduit was built with HDF5 support
|
||||
set(Conduit_REQUIRED_PACKAGES "HDF5" CACHE STRING
|
||||
"Additional packages required by Conduit.")
|
||||
else()
|
||||
message(STATUS "Conduit Relay HDF5 Support is DISABLED")
|
||||
endif()
|
||||
|
||||
include(MfemCmakeUtilities)
|
||||
mfem_find_package(Conduit CONDUIT CONDUIT_DIR
|
||||
"include;include/conduit" conduit.hpp "lib" conduit
|
||||
"Paths to headers required by Conduit." "Libraries required by Conduit."
|
||||
ADD_COMPONENT relay
|
||||
"include;include/conduit" conduit_relay.hpp "lib" conduit_relay
|
||||
ADD_COMPONENT blueprint
|
||||
"include;include/conduit" conduit_blueprint.hpp "lib" conduit_blueprint)
|
||||
"include;include/conduit" conduit_relay.hpp "lib" conduit_relay)
|
||||
|
||||
@@ -13,23 +13,7 @@
|
||||
# - HYPRE_FOUND
|
||||
# - HYPRE_LIBRARIES
|
||||
# - HYPRE_INCLUDE_DIRS
|
||||
# - HYPRE_VERSION
|
||||
|
||||
include(MfemCmakeUtilities)
|
||||
mfem_find_package(HYPRE HYPRE HYPRE_DIR "include" "HYPRE.h" "lib" "HYPRE"
|
||||
"Paths to headers required by HYPRE." "Libraries required by HYPRE.")
|
||||
|
||||
if (HYPRE_FOUND AND (NOT HYPRE_VERSION))
|
||||
try_run(HYPRE_VERSION_RUN_RESULT HYPRE_VERSION_COMPILE_RESULT
|
||||
${CMAKE_CURRENT_BINARY_DIR}/config
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/config/get_hypre_version.cpp
|
||||
CMAKE_FLAGS -DINCLUDE_DIRECTORIES:STRING=${HYPRE_INCLUDE_DIRS}
|
||||
RUN_OUTPUT_VARIABLE HYPRE_VERSION_OUTPUT)
|
||||
if ((HYPRE_VERSION_RUN_RESULT EQUAL 0) AND HYPRE_VERSION_OUTPUT)
|
||||
string(STRIP "${HYPRE_VERSION_OUTPUT}" HYPRE_VERSION)
|
||||
set(HYPRE_VERSION ${HYPRE_VERSION} CACHE STRING "HYPRE version." FORCE)
|
||||
message(STATUS "Found HYPRE version ${HYPRE_VERSION}")
|
||||
else()
|
||||
message(FATAL_ERROR "Unable to determine HYPRE version.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
# Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at the
|
||||
# Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights reserved.
|
||||
# See file COPYRIGHT for details.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability see http://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Lesser General Public License (as published by the Free
|
||||
# Software Foundation) version 2.1 dated February 1999.
|
||||
|
||||
# Sets the following variables:
|
||||
# - STRUMPACK_FOUND
|
||||
# - STRUMPACK_INCLUDE_DIRS
|
||||
# - STRUMPACK_LIBRARIES
|
||||
|
||||
include(MfemCmakeUtilities)
|
||||
mfem_find_package(STRUMPACK STRUMPACK STRUMPACK_DIR
|
||||
"include" "StrumpackSparseSolverMPIDist.hpp"
|
||||
"lib" "strumpack;strumpack_sparse" # add NAMES_PER_DIR?
|
||||
"Paths to headers required by STRUMPACK."
|
||||
"Libraries required by STRUMPACK."
|
||||
CHECK_BUILD STRUMPACK_VERSION_OK TRUE
|
||||
"
|
||||
#include <StrumpackSparseSolverMPIDist.hpp>
|
||||
using namespace strumpack;
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
MPI_Init(&argc, &argv);
|
||||
MPI_Comm comm = MPI_COMM_WORLD;
|
||||
StrumpackSparseSolverMPIDist<double,int> solver(comm, argc, argv, false);
|
||||
solver.options().set_from_command_line();
|
||||
return 0;
|
||||
}
|
||||
"
|
||||
)
|
||||
@@ -1,29 +0,0 @@
|
||||
# Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at the
|
||||
# Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights reserved.
|
||||
# See file COPYRIGHT for details.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability see http://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Lesser General Public License (as published by the Free
|
||||
# Software Foundation) version 2.1 dated February 1999.
|
||||
|
||||
# Sets the following variables:
|
||||
# - Scotch_FOUND
|
||||
# - Scotch_INCLUDE_DIRS
|
||||
# - Scotch_LIBRARIES
|
||||
|
||||
include(MfemCmakeUtilities)
|
||||
mfem_find_package(Scotch Scotch Scotch_DIR "" "" "" ""
|
||||
"Paths to headers required by Scotch."
|
||||
"Libraries required by Scotch."
|
||||
ADD_COMPONENT "scotch" "include" scotch.h "lib" scotch
|
||||
ADD_COMPONENT "scotcherr" "" "" "lib" scotcherr
|
||||
ADD_COMPONENT "scotcherrexit" "" "" "lib" scotcherrexit
|
||||
ADD_COMPONENT "scotchmetis" "include" "metis.h" "lib" scotchmetis
|
||||
ADD_COMPONENT "ptscotch" "include" ptscotch.h "lib" ptscotch
|
||||
ADD_COMPONENT "ptscotcherr" "" "" "lib" ptscotcherr
|
||||
ADD_COMPONENT "ptscotcherrexit" "" "" "lib" ptscotcherrexit
|
||||
ADD_COMPONENT "ptscotchparmetis" "include" "parmetis.h" "lib" ptscotchparmetis
|
||||
)
|
||||
@@ -9,30 +9,6 @@
|
||||
# terms of the GNU Lesser General Public License (as published by the Free
|
||||
# Software Foundation) version 2.1 dated February 1999.
|
||||
|
||||
# Function that converts a version string of the form 'major[.minor[.patch]]' to
|
||||
# the integer ((major * 100) + minor) * 100 + patch.
|
||||
function(mfem_version_to_int VersionString VersionIntVar)
|
||||
if ("${VersionString}" MATCHES "^([0-9]+)(.*)$")
|
||||
set(Major "${CMAKE_MATCH_1}")
|
||||
set(MinorPatchString "${CMAKE_MATCH_2}")
|
||||
else()
|
||||
set(Major 0)
|
||||
endif()
|
||||
if ("${MinorPatchString}" MATCHES "^\\.([0-9]+)(.*)$")
|
||||
set(Minor "${CMAKE_MATCH_1}")
|
||||
set(PatchString "${CMAKE_MATCH_2}")
|
||||
else()
|
||||
set(Minor 0)
|
||||
endif()
|
||||
if ("${PatchString}" MATCHES "^\\.([0-9]+)(.*)$")
|
||||
set(Patch "${CMAKE_MATCH_1}")
|
||||
else()
|
||||
set(Patch 0)
|
||||
endif()
|
||||
math(EXPR VersionInt "(${Major}*100+${Minor})*100+${Patch}")
|
||||
set(${VersionIntVar} ${VersionInt} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# A handy function to add the current source directory to a local
|
||||
# filename. To be used for creating a list of sources.
|
||||
function(convert_filenames_to_full_paths NAMES)
|
||||
@@ -74,8 +50,10 @@ function(add_mfem_examples EXE_SRCS)
|
||||
|
||||
string(REPLACE ".cpp" "" EXE_NAME "${EXE_PREFIX}${SRC_FILENAME}")
|
||||
add_executable(${EXE_NAME} ${SRC_FILE})
|
||||
add_dependencies(${MFEM_ALL_EXAMPLES_TARGET_NAME} ${EXE_NAME})
|
||||
if (EXE_NEEDED_BY)
|
||||
# If given a prefix, don't add the example to the list of examples to build.
|
||||
if (NOT EXE_PREFIX)
|
||||
add_dependencies(${MFEM_ALL_EXAMPLES_TARGET_NAME} ${EXE_NAME})
|
||||
elseif (EXE_NEEDED_BY)
|
||||
add_dependencies(${EXE_NEEDED_BY} ${EXE_NAME})
|
||||
endif()
|
||||
add_dependencies(${EXE_NAME}
|
||||
@@ -83,8 +61,7 @@ function(add_mfem_examples EXE_SRCS)
|
||||
|
||||
target_link_libraries(${EXE_NAME} mfem)
|
||||
if (MFEM_USE_MPI)
|
||||
# Not needed: (mfem already links with MPI_CXX_LIBRARIES)
|
||||
# target_link_libraries(${EXE_NAME} ${MPI_CXX_LIBRARIES})
|
||||
target_link_libraries(${EXE_NAME} ${MPI_CXX_LIBRARIES})
|
||||
|
||||
# Language-specific include directories:
|
||||
if (MPI_CXX_INCLUDE_PATH)
|
||||
@@ -155,7 +132,6 @@ function(add_mfem_miniapp MFEM_EXE_NAME)
|
||||
|
||||
# Handle the MPI separately
|
||||
if (MFEM_USE_MPI)
|
||||
# Add MPI_CXX_LIBRARIES, in case this target does not link with mfem.
|
||||
if(CMAKE_VERSION VERSION_GREATER 2.8.11)
|
||||
target_link_libraries(${MFEM_EXE_NAME} PRIVATE ${MPI_CXX_LIBRARIES})
|
||||
else()
|
||||
@@ -183,26 +159,26 @@ function(mfem_find_component Prefix DirVar IncSuffixes Header LibSuffixes Lib
|
||||
|
||||
if (Lib)
|
||||
if (${DirVar} OR EnvDirVar)
|
||||
find_library(${Prefix}_LIBRARY ${Lib}
|
||||
find_library(${Prefix}_LIBRARIES ${Lib}
|
||||
HINTS ${${DirVar}} ENV ${DirVar}
|
||||
PATH_SUFFIXES ${LibSuffixes}
|
||||
NO_DEFAULT_PATH
|
||||
DOC "${LibDoc}")
|
||||
endif()
|
||||
find_library(${Prefix}_LIBRARY ${Lib}
|
||||
find_library(${Prefix}_LIBRARIES ${Lib}
|
||||
PATH_SUFFIXES ${LibSuffixes}
|
||||
DOC "${LibDoc}")
|
||||
endif()
|
||||
|
||||
if (Header)
|
||||
if (${DirVar} OR EnvDirVar)
|
||||
find_path(${Prefix}_INCLUDE_DIR ${Header}
|
||||
find_path(${Prefix}_INCLUDE_DIRS ${Header}
|
||||
HINTS ${${DirVar}} ENV ${DirVar}
|
||||
PATH_SUFFIXES ${IncSuffixes}
|
||||
NO_DEFAULT_PATH
|
||||
DOC "${IncDoc}")
|
||||
endif()
|
||||
find_path(${Prefix}_INCLUDE_DIR ${Header}
|
||||
find_path(${Prefix}_INCLUDE_DIRS ${Header}
|
||||
PATH_SUFFIXES ${IncSuffixes}
|
||||
DOC "${IncDoc}")
|
||||
endif()
|
||||
@@ -214,9 +190,8 @@ endfunction(mfem_find_component)
|
||||
# successful, optionally checks building (compile + link) one or more given
|
||||
# code snippets. Additionally, a list of required/optional/alternative
|
||||
# packages (given by ${Name}_REQUIRED_PACKAGES) are searched for and added to
|
||||
# the ${Prefix}_INCLUDE_DIRS and ${Prefix}_LIBRARIES lists. The variable
|
||||
# ${Name}_REQUIRED_LIBRARIES can be set to spcecify any additional libraries
|
||||
# that are needed. This function defines the following CACHE variables:
|
||||
# the ${Prefix}_INCLUDE_DIRS and ${Prefix}_LIBRARIES lists. The function
|
||||
# defines the following CACHE variables:
|
||||
#
|
||||
# ${Prefix}_FOUND
|
||||
# ${Prefix}_INCLUDE_DIRS
|
||||
@@ -255,14 +230,12 @@ function(mfem_find_package Name Prefix DirVar IncSuffixes Header LibSuffixes
|
||||
mfem_find_component("${Prefix}" "${DirVar}" "${IncSuffixes}" "${Header}"
|
||||
"${LibSuffixes}" "${Lib}" "${IncDoc}" "${LibDoc}")
|
||||
|
||||
if (((NOT Lib) OR ${Prefix}_LIBRARY) AND
|
||||
((NOT Header) OR ${Prefix}_INCLUDE_DIR))
|
||||
if (((NOT Lib) OR ${Prefix}_LIBRARIES) AND
|
||||
((NOT Header) OR ${Prefix}_INCLUDE_DIRS))
|
||||
set(Found TRUE)
|
||||
else()
|
||||
set(Found FALSE)
|
||||
endif()
|
||||
set(${Prefix}_LIBRARIES ${${Prefix}_LIBRARY})
|
||||
set(${Prefix}_INCLUDE_DIRS ${${Prefix}_INCLUDE_DIR})
|
||||
|
||||
set(ReqVars "")
|
||||
|
||||
@@ -301,22 +274,25 @@ function(mfem_find_package Name Prefix DirVar IncSuffixes Header LibSuffixes
|
||||
"${CompLibSuffixes}" "${CompLib}" "" "")
|
||||
if (CompRequired)
|
||||
if (CompLib)
|
||||
list(APPEND ReqVars ${FullPrefix}_LIBRARY)
|
||||
list(APPEND ReqVars ${FullPrefix}_LIBRARIES)
|
||||
endif()
|
||||
if (CompHeader)
|
||||
list(APPEND ReqVars ${FullPrefix}_INCLUDE_DIR)
|
||||
list(APPEND ReqVars ${FullPrefix}_INCLUDE_DIRS)
|
||||
endif()
|
||||
endif(CompRequired)
|
||||
if (((NOT CompLib) OR ${FullPrefix}_LIBRARY) AND
|
||||
((NOT CompHeader) OR ${FullPrefix}_INCLUDE_DIR))
|
||||
if (((NOT CompLib) OR ${FullPrefix}_LIBRARIES) AND
|
||||
((NOT CompHeader) OR ${FullPrefix}_INCLUDE_DIRS))
|
||||
# Component found
|
||||
list(APPEND ${Prefix}_LIBRARIES ${${FullPrefix}_LIBRARY})
|
||||
list(APPEND ${Prefix}_INCLUDE_DIRS ${${FullPrefix}_INCLUDE_DIR})
|
||||
set(${FullPrefix}_FOUND TRUE CACHE BOOL
|
||||
"${Name}/${CompPrefix} was found." FORCE)
|
||||
list(APPEND ${Prefix}_LIBRARIES ${${FullPrefix}_LIBRARIES})
|
||||
list(APPEND ${Prefix}_INCLUDE_DIRS ${${FullPrefix}_INCLUDE_DIRS})
|
||||
if (NOT ${Name}_FIND_QUIETLY)
|
||||
# message(STATUS "${Name}: ${CompPrefix}: found")
|
||||
message(STATUS
|
||||
"${Name}: ${CompPrefix}: ${${FullPrefix}_LIBRARY}")
|
||||
"${Name}: ${CompPrefix}: ${${FullPrefix}_LIBRARIES}")
|
||||
# message(STATUS
|
||||
# "${Name}: ${CompPrefix}: ${${FullPrefix}_INCLUDE_DIR}")
|
||||
# "${Name}: ${CompPrefix}: ${${FullPrefix}_INCLUDE_DIRS}")
|
||||
endif()
|
||||
else()
|
||||
# Let FindPackageHandleStandardArgs() handle errors
|
||||
@@ -369,8 +345,6 @@ function(mfem_find_package Name Prefix DirVar IncSuffixes Header LibSuffixes
|
||||
if (NOT ${Name}_FIND_QUIETLY)
|
||||
message(STATUS "${Name}: trying alternative package: ${ReqPackM}")
|
||||
endif()
|
||||
# Do not add ${Required} here, since that will prevent other potential
|
||||
# alternative packages from being found.
|
||||
find_package(${ReqPack} ${Quiet} COMPONENTS ${PackComps})
|
||||
string(TOUPPER ${ReqPack} ReqPACK)
|
||||
if (${ReqPack}_FOUND)
|
||||
@@ -384,7 +358,7 @@ function(mfem_find_package Name Prefix DirVar IncSuffixes Header LibSuffixes
|
||||
endif()
|
||||
elseif (Alternative)
|
||||
set(Alternative FALSE)
|
||||
elseif (Found)
|
||||
else()
|
||||
if (NOT ${Name}_FIND_QUIETLY)
|
||||
if (Required)
|
||||
message(STATUS "${Name}: looking for required package: ${ReqPackM}")
|
||||
@@ -394,139 +368,23 @@ function(mfem_find_package Name Prefix DirVar IncSuffixes Header LibSuffixes
|
||||
endif()
|
||||
string(TOUPPER ${ReqPack} ReqPACK)
|
||||
if (NOT (${ReqPack}_FOUND OR ${ReqPACK}_FOUND))
|
||||
if (NOT ${ReqPack}_TARGET_NAMES)
|
||||
find_package(${ReqPack} ${Required} ${Quiet} COMPONENTS ${PackComps})
|
||||
else()
|
||||
foreach(_target ${ReqPack} ${${ReqPack}_TARGET_NAMES})
|
||||
# Do not use ${Required} here:
|
||||
find_package(${_target} NAMES ${_target} ${ReqPack} ${Quiet}
|
||||
COMPONENTS ${PackComps})
|
||||
string(TOUPPER ${_target} _TARGET)
|
||||
if (${_target}_FOUND OR ${_TARGET}_FOUND)
|
||||
set(${ReqPack}_FOUND TRUE)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
if (${Required} AND NOT ${ReqPack}_FOUND)
|
||||
message(FATAL_ERROR " *** Required package ${ReqPack} not found."
|
||||
"Checked target names: ${ReqPack} ${${ReqPack}_TARGET_NAMES}")
|
||||
endif()
|
||||
endif()
|
||||
find_package(${ReqPack} ${Required} ${Quiet} COMPONENTS ${PackComps})
|
||||
endif()
|
||||
if (Required AND NOT (${ReqPack}_FOUND OR ${ReqPACK}_FOUND))
|
||||
message(FATAL_ERROR " --------- INTERNAL ERROR")
|
||||
endif()
|
||||
if ("${ReqPack}" STREQUAL "MPI" AND MPI_CXX_FOUND)
|
||||
if ("${ReqPack}" STREQUAL "MPI")
|
||||
list(APPEND ${Prefix}_LIBRARIES ${MPI_CXX_LIBRARIES})
|
||||
list(APPEND ${Prefix}_INCLUDE_DIRS ${MPI_CXX_INCLUDE_PATH})
|
||||
elseif (${ReqPack}_FOUND OR ${ReqPACK}_FOUND)
|
||||
else()
|
||||
if (${ReqPack}_FOUND)
|
||||
set(_Pack ${ReqPack})
|
||||
else()
|
||||
set(_Pack ${ReqPACK})
|
||||
list(APPEND ${Prefix}_LIBRARIES ${${ReqPack}_LIBRARIES})
|
||||
list(APPEND ${Prefix}_INCLUDE_DIRS ${${ReqPack}_INCLUDE_DIRS})
|
||||
elseif (${ReqPACK}_FOUND)
|
||||
list(APPEND ${Prefix}_LIBRARIES ${${ReqPACK}_LIBRARIES})
|
||||
list(APPEND ${Prefix}_INCLUDE_DIRS ${${ReqPACK}_INCLUDE_DIRS})
|
||||
endif()
|
||||
set(_Pack_LIBS)
|
||||
set(_Pack_INCS)
|
||||
# - ${_Pack}_CONFIG is defined by find_package() when a config file was
|
||||
# loaded
|
||||
# - If ${ReqPack}_TARGET_NAMES is defined, use target mode
|
||||
if (NOT ((DEFINED ${_Pack}_CONFIG) OR
|
||||
(DEFINED ${ReqPack}_TARGET_NAMES)))
|
||||
# Defined variables expected:
|
||||
# - ${ReqPack}_LIB_VARS, optional, default: ${_Pack}_LIBRARIES
|
||||
# - ${ReqPack}_INCLUDE_VARS, optional, default: ${_Pack}_INCLUDE_DIRS
|
||||
set(_lib_vars ${${ReqPack}_LIB_VARS})
|
||||
if (NOT _lib_vars)
|
||||
set(_lib_vars ${_Pack}_LIBRARIES)
|
||||
endif()
|
||||
foreach (_var ${_lib_vars})
|
||||
if (${_var})
|
||||
list(APPEND _Pack_LIBS ${${_var}})
|
||||
endif()
|
||||
endforeach()
|
||||
# Includes
|
||||
set(_inc_vars ${${ReqPack}_INCLUDE_VARS})
|
||||
if (NOT _inc_vars)
|
||||
set(_inc_vars ${_Pack}_INCLUDE_DIRS)
|
||||
endif()
|
||||
foreach (_include ${_inc_vars})
|
||||
# message(STATUS "${Name}: ${ReqPack}: ${_include}")
|
||||
if (${_include})
|
||||
list(APPEND _Pack_INCS ${${_include}})
|
||||
endif()
|
||||
endforeach()
|
||||
else()
|
||||
# Target mode: check for a valid target:
|
||||
# - an entry in the variable ${ReqPack}_TARGET_NAMES (optional)
|
||||
# - ${_Pack}
|
||||
# Other optional variables:
|
||||
# - ${ReqPack}_IMPORT_CONFIG, default value: "RELEASE"
|
||||
# - ${ReqPack}_TARGET_FORCE, default value: "FALSE"
|
||||
set(TargetName)
|
||||
foreach (_target ${${ReqPack}_TARGET_NAMES} ${_Pack})
|
||||
if (TARGET ${_target})
|
||||
set(TargetName ${_target})
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
if ("${TargetName}" STREQUAL "")
|
||||
message(FATAL_ERROR " *** ${ReqPack}: unknown target. "
|
||||
"Please set ${ReqPack}_TARGET_NAMES.")
|
||||
endif()
|
||||
get_target_property(IsImported ${TargetName} IMPORTED)
|
||||
if (IsImported)
|
||||
set(ImportConfig ${${ReqPack}_IMPORT_CONFIG})
|
||||
if (NOT ImportConfig)
|
||||
set(ImportConfig RELEASE)
|
||||
endif()
|
||||
get_target_property(ImpConfigs ${TargetName} IMPORTED_CONFIGURATIONS)
|
||||
list(FIND ImpConfigs ${ImportConfig} _Index)
|
||||
if (_Index EQUAL -1)
|
||||
message(FATAL_ERROR " *** ${ReqPack}: configuration "
|
||||
"${ImportConfig} not found. Set ${ReqPack}_IMPORT_CONFIG "
|
||||
"from the list: ${ImpConfigs}.")
|
||||
endif()
|
||||
endif()
|
||||
# Set _Pack_LIBS
|
||||
if (NOT IsImported OR ${ReqPack}_TARGET_FORCE)
|
||||
# Set _Pack_LIBS to be the target itself
|
||||
set(_Pack_LIBS ${TargetName})
|
||||
if (NOT ${Name}_FIND_QUIETLY)
|
||||
message(STATUS "Found ${ReqPack}: ${_Pack_LIBS} (target)")
|
||||
endif()
|
||||
else()
|
||||
# Set _Pack_LIBS from the target properties for ImportConfig
|
||||
foreach (_prop IMPORTED_LOCATION_${ImportConfig}
|
||||
IMPORTED_LINK_INTERFACE_LIBRARIES_${ImportConfig})
|
||||
get_target_property(_value ${TargetName} ${_prop})
|
||||
if (_value)
|
||||
list(APPEND _Pack_LIBS ${_value})
|
||||
endif()
|
||||
endforeach()
|
||||
if (NOT ${Name}_FIND_QUIETLY)
|
||||
message(STATUS
|
||||
"Imported ${ReqPack}[${ImportConfig}]: ${_Pack_LIBS}")
|
||||
endif()
|
||||
endif()
|
||||
# Set _Pack_INCS
|
||||
foreach (_prop INCLUDE_DIRECTORIES)
|
||||
get_target_property(_value ${TargetName} ${_prop})
|
||||
if (_value)
|
||||
list(APPEND _Pack_INCS ${_value})
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
# _Pack_LIBS and _Pack_INCS should be fully defined here
|
||||
list(APPEND ${Prefix}_LIBRARIES ${_Pack_LIBS})
|
||||
list(APPEND ${Prefix}_INCLUDE_DIRS ${_Pack_INCS})
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if (Found AND ${Name}_REQUIRED_LIBRARIES)
|
||||
list(APPEND ${Prefix}_LIBRARIES ${${Name}_REQUIRED_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if (NOT ("${${Prefix}_INCLUDE_DIRS}" STREQUAL ""))
|
||||
list(INSERT ReqVars 0 ${Prefix}_INCLUDE_DIRS)
|
||||
set(ReqHeaders 1)
|
||||
@@ -543,6 +401,12 @@ function(mfem_find_package Name Prefix DirVar IncSuffixes Header LibSuffixes
|
||||
if (ReqHeaders)
|
||||
list(REMOVE_DUPLICATES ${Prefix}_INCLUDE_DIRS)
|
||||
endif()
|
||||
# Write the updated values to the cache.
|
||||
set(${Prefix}_LIBRARIES ${${Prefix}_LIBRARIES} CACHE STRING
|
||||
"${LibDoc}" FORCE)
|
||||
set(${Prefix}_INCLUDE_DIRS ${${Prefix}_INCLUDE_DIRS} CACHE STRING
|
||||
"${IncDoc}" FORCE)
|
||||
set(${Prefix}_FOUND TRUE CACHE BOOL "${Name} was found." FORCE)
|
||||
|
||||
# Check for optional "CHECK_BUILD" arguments.
|
||||
set(I 9) # 9 is the number of required arguments
|
||||
@@ -560,10 +424,6 @@ function(mfem_find_package Name Prefix DirVar IncSuffixes Header LibSuffixes
|
||||
set(CMAKE_REQUIRED_QUIET ${${Name}_FIND_QUIETLY})
|
||||
check_cxx_source_compiles("${TestSrc}" ${TestVar})
|
||||
if (TestReq)
|
||||
if (NOT ${TestVar})
|
||||
set(Found FALSE)
|
||||
unset(${TestVar} CACHE)
|
||||
endif()
|
||||
list(APPEND ReqVars ${TestVar})
|
||||
endif()
|
||||
elseif("${ARGV${I}}" STREQUAL "ADD_COMPONENT")
|
||||
@@ -574,35 +434,22 @@ function(mfem_find_package Name Prefix DirVar IncSuffixes Header LibSuffixes
|
||||
endif()
|
||||
math(EXPR I "${I}+1")
|
||||
endwhile()
|
||||
else()
|
||||
set(${Prefix}_FOUND FALSE CACHE BOOL "${Name} was not found." FORCE)
|
||||
endif()
|
||||
if ("_x_${ReqVars}" STREQUAL "_x_")
|
||||
set(${Prefix}_FOUND ${Found})
|
||||
set(ReqVars ${Prefix}_FOUND)
|
||||
endif()
|
||||
# foreach(ReqVar ${ReqVars})
|
||||
# message(STATUS " *** ${ReqVar}=${${ReqVar}}")
|
||||
# get_property(IsCached CACHE ${ReqVar} PROPERTY "VALUE" SET)
|
||||
# if (IsCached)
|
||||
# get_property(CachedVal CACHE ${ReqVar} PROPERTY "VALUE")
|
||||
# message(STATUS " *** ${ReqVar}[cached]=${CachedVal}")
|
||||
# endif()
|
||||
# message(STATUS "${ReqVar}=${${ReqVar}}")
|
||||
# endforeach()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(${Name}
|
||||
" *** ${Name} not found. Please set ${DirVar}." ${ReqVars})
|
||||
|
||||
string(TOUPPER ${Name} UName)
|
||||
if (${UName}_FOUND)
|
||||
# Write the ${Prefix}_* variables to the cache.
|
||||
set(${Prefix}_LIBRARIES ${${Prefix}_LIBRARIES} CACHE STRING
|
||||
"${LibDoc}" FORCE)
|
||||
set(${Prefix}_INCLUDE_DIRS ${${Prefix}_INCLUDE_DIRS} CACHE STRING
|
||||
"${IncDoc}" FORCE)
|
||||
set(${Prefix}_FOUND TRUE CACHE BOOL "${Name} was found." FORCE)
|
||||
if (ReqHeaders AND (NOT ${Name}_FIND_QUIETLY))
|
||||
message(STATUS "${Prefix}_INCLUDE_DIRS=${${Prefix}_INCLUDE_DIRS}")
|
||||
endif()
|
||||
if (Found AND ReqLibs AND ReqHeaders AND (NOT ${Name}_FIND_QUIETLY))
|
||||
message(STATUS "${Prefix}_INCLUDE_DIRS=${${Prefix}_INCLUDE_DIRS}")
|
||||
endif()
|
||||
|
||||
endfunction(mfem_find_package)
|
||||
|
||||
@@ -30,13 +30,7 @@
|
||||
#ifdef MFEM_USE_SUPERLU
|
||||
#error Building with SuperLU_DIST (MFEM_USE_SUPERLU=YES) requires MPI (MFEM_USE_MPI=YES)
|
||||
#endif
|
||||
#ifdef MFEM_USE_STRUMPACK
|
||||
#error Building with STRUMPACK (MFEM_USE_STRUMPACK=YES) requires MPI (MFEM_USE_MPI=YES)
|
||||
#endif
|
||||
#ifdef MFEM_USE_PETSC
|
||||
#error Building with PETSc (MFEM_USE_PETSC=YES) requires MPI (MFEM_USE_MPI=YES)
|
||||
#endif
|
||||
#ifdef MFEM_USE_PUMI
|
||||
#error Building with PUMI (MFEM_USE_PUMI=YES) requires MPI (MFEM_USE_MPI=YES)
|
||||
#endif
|
||||
#endif // MFEM_USE_MPI not defined
|
||||
|
||||
@@ -12,27 +12,6 @@
|
||||
#ifndef MFEM_CONFIG_HEADER
|
||||
#define MFEM_CONFIG_HEADER
|
||||
|
||||
// MFEM version: integer of the form: (major*100 + minor)*100 + patch.
|
||||
// #define MFEM_VERSION @MFEM_VERSION@
|
||||
|
||||
// MFEM version string of the form "3.3" or "3.3.1".
|
||||
// #define MFEM_VERSION_STRING "@MFEM_VERSION_STRING@"
|
||||
|
||||
// MFEM version type, see the MFEM_VERSION_TYPE_* constants below.
|
||||
#define MFEM_VERSION_TYPE ((MFEM_VERSION)%2)
|
||||
|
||||
// MFEM version type constants.
|
||||
#define MFEM_VERSION_TYPE_RELEASE 0
|
||||
#define MFEM_VERSION_TYPE_DEVELOPMENT 1
|
||||
|
||||
// Separate MFEM version numbers for major, minor, and patch.
|
||||
#define MFEM_VERSION_MAJOR ((MFEM_VERSION)/10000)
|
||||
#define MFEM_VERSION_MINOR (((MFEM_VERSION)/100)%100)
|
||||
#define MFEM_VERSION_PATCH ((MFEM_VERSION)%100)
|
||||
|
||||
// Description of the git commit used to build MFEM.
|
||||
// #define MFEM_GIT_STRING "@MFEM_GIT_STRING@"
|
||||
|
||||
// Build the parallel MFEM library.
|
||||
// Requires an MPI compiler, and the libraries HYPRE and METIS.
|
||||
// #define MFEM_USE_MPI
|
||||
@@ -40,18 +19,12 @@
|
||||
// Enable debug checks in MFEM.
|
||||
// #define MFEM_DEBUG
|
||||
|
||||
// Throw an exception on errors.
|
||||
// #define MFEM_USE_EXCEPTIONS
|
||||
|
||||
// Enable gzstream in MFEM.
|
||||
// #define MFEM_USE_GZSTREAM
|
||||
|
||||
// Enable backtraces for mfem_error through libunwind.
|
||||
// #define MFEM_USE_LIBUNWIND
|
||||
|
||||
// Enable MFEM features that use the METIS library (parallel MFEM).
|
||||
// #define MFEM_USE_METIS
|
||||
|
||||
// Enable this option if linking with METIS version 5 (parallel MFEM).
|
||||
// #define MFEM_USE_METIS_5
|
||||
|
||||
@@ -69,7 +42,11 @@
|
||||
// #define MFEM_USE_MEMALLOC
|
||||
|
||||
// Which library functions to use in class StopWatch for measuring time.
|
||||
// For a list of the available options, see INSTALL.
|
||||
// The available options are:
|
||||
// 0 - use std::clock from <ctime>
|
||||
// 1 - use times from <sys/times.h>
|
||||
// 2 - use high-resolution POSIX clocks
|
||||
// 3 - use QueryPerformanceCounter from <windows.h>
|
||||
// If not defined, an option is selected automatically.
|
||||
// #define MFEM_TIMER_TYPE @MFEM_TIMER_TYPE@
|
||||
|
||||
@@ -85,9 +62,6 @@
|
||||
// Enable MFEM functionality based on the SuperLU library.
|
||||
// #define MFEM_USE_SUPERLU
|
||||
|
||||
// Enable MFEM functionality based on the STRUMPACK library.
|
||||
// #define MFEM_USE_STRUMPACK
|
||||
|
||||
// Enable functionality based on the Gecko library
|
||||
// #define MFEM_USE_GECKO
|
||||
|
||||
@@ -97,9 +71,6 @@
|
||||
// Enable Sidre support
|
||||
// #define MFEM_USE_SIDRE
|
||||
|
||||
// Enable Conduit support
|
||||
// #define MFEM_USE_CONDUIT
|
||||
|
||||
// Enable functionality based on the NetCDF library (reading CUBIT files)
|
||||
// #define MFEM_USE_NETCDF
|
||||
|
||||
@@ -109,20 +80,10 @@
|
||||
// Enable functionality based on the MPFR library.
|
||||
// #define MFEM_USE_MPFR
|
||||
|
||||
// Enable MFEM functionality based on the PUMI library
|
||||
// #define MFEM_USE_PUMI
|
||||
|
||||
// Windows specific options
|
||||
#ifdef _WIN32
|
||||
// Macro needed to get defines like M_PI from <cmath>. (Visual Studio C++ only?)
|
||||
#define _USE_MATH_DEFINES
|
||||
#endif
|
||||
|
||||
// Version of HYPRE used for building MFEM.
|
||||
// #define MFEM_HYPRE_VERSION @MFEM_HYPRE_VERSION@
|
||||
|
||||
// Macro defined when PUMI is built with support for the Simmetrix SimModSuite
|
||||
// library.
|
||||
// #define MFEM_USE_SIMMETRIX
|
||||
|
||||
#endif // MFEM_CONFIG_HEADER
|
||||
|
||||
@@ -10,14 +10,9 @@
|
||||
# Software Foundation) version 2.1 dated February 1999.
|
||||
|
||||
# Variables corresponding to defines in config.hpp (YES, NO, or value)
|
||||
MFEM_VERSION = @MFEM_VERSION@
|
||||
MFEM_VERSION_STRING = @MFEM_VERSION_STRING@
|
||||
MFEM_GIT_STRING = @MFEM_GIT_STRING@
|
||||
MFEM_USE_MPI = @MFEM_USE_MPI@
|
||||
MFEM_USE_METIS = @MFEM_USE_METIS@
|
||||
MFEM_USE_METIS_5 = @MFEM_USE_METIS_5@
|
||||
MFEM_DEBUG = @MFEM_DEBUG@
|
||||
MFEM_USE_EXCEPTIONS = @MFEM_USE_EXCEPTIONS@
|
||||
MFEM_USE_GZSTREAM = @MFEM_USE_GZSTREAM@
|
||||
MFEM_USE_LIBUNWIND = @MFEM_USE_LIBUNWIND@
|
||||
MFEM_USE_LAPACK = @MFEM_USE_LAPACK@
|
||||
@@ -29,15 +24,12 @@ MFEM_USE_SUNDIALS = @MFEM_USE_SUNDIALS@
|
||||
MFEM_USE_MESQUITE = @MFEM_USE_MESQUITE@
|
||||
MFEM_USE_SUITESPARSE = @MFEM_USE_SUITESPARSE@
|
||||
MFEM_USE_SUPERLU = @MFEM_USE_SUPERLU@
|
||||
MFEM_USE_STRUMPACK = @MFEM_USE_STRUMPACK@
|
||||
MFEM_USE_GECKO = @MFEM_USE_GECKO@
|
||||
MFEM_USE_GNUTLS = @MFEM_USE_GNUTLS@
|
||||
MFEM_USE_NETCDF = @MFEM_USE_NETCDF@
|
||||
MFEM_USE_PETSC = @MFEM_USE_PETSC@
|
||||
MFEM_USE_MPFR = @MFEM_USE_MPFR@
|
||||
MFEM_USE_SIDRE = @MFEM_USE_SIDRE@
|
||||
MFEM_USE_CONDUIT = @MFEM_USE_CONDUIT@
|
||||
MFEM_USE_PUMI = @MFEM_USE_PUMI@
|
||||
|
||||
# Compiler, compile options, and link options
|
||||
MFEM_CXX = @MFEM_CXX@
|
||||
@@ -45,25 +37,17 @@ MFEM_CPPFLAGS = @MFEM_CPPFLAGS@
|
||||
MFEM_CXXFLAGS = @MFEM_CXXFLAGS@
|
||||
MFEM_TPLFLAGS = @MFEM_TPLFLAGS@
|
||||
MFEM_INCFLAGS = @MFEM_INCFLAGS@
|
||||
MFEM_PICFLAG = @MFEM_PICFLAG@
|
||||
MFEM_FLAGS = @MFEM_FLAGS@
|
||||
MFEM_EXT_LIBS = @MFEM_EXT_LIBS@
|
||||
MFEM_LIBS = @MFEM_LIBS@
|
||||
MFEM_LIB_FILE = @MFEM_LIB_FILE@
|
||||
MFEM_STATIC = @MFEM_STATIC@
|
||||
MFEM_SHARED = @MFEM_SHARED@
|
||||
MFEM_BUILD_TAG = @MFEM_BUILD_TAG@
|
||||
MFEM_PREFIX = @MFEM_PREFIX@
|
||||
MFEM_INC_DIR = @MFEM_INC_DIR@
|
||||
MFEM_LIB_DIR = @MFEM_LIB_DIR@
|
||||
|
||||
# Location of test.mk
|
||||
MFEM_TEST_MK = @MFEM_TEST_MK@
|
||||
|
||||
# Command used to launch MPI jobs
|
||||
MFEM_MPIEXEC = @MFEM_MPIEXEC@
|
||||
MFEM_MPIEXEC_NP = @MFEM_MPIEXEC_NP@
|
||||
MFEM_MPI_NP = @MFEM_MPI_NP@
|
||||
|
||||
# Optional extra configuration
|
||||
@MFEM_CONFIG_EXTRA@
|
||||
|
||||
@@ -18,10 +18,8 @@ if (NOT CMAKE_BUILD_TYPE)
|
||||
"Build type: Debug, Release, RelWithDebInfo, or MinSizeRel." FORCE)
|
||||
endif()
|
||||
|
||||
# MFEM options. Set to mimic the default "defaults.mk" file.
|
||||
# MFEM options. Set to mimic the default "default.mk" file.
|
||||
option(MFEM_USE_MPI "Enable MPI parallel build" OFF)
|
||||
option(MFEM_USE_METIS "Enable METIS usage" ${MFEM_USE_MPI})
|
||||
option(MFEM_USE_EXCEPTIONS "Enable the use of exceptions" OFF)
|
||||
option(MFEM_USE_GZSTREAM "Enable gzstream for compressed data streams." OFF)
|
||||
option(MFEM_USE_LIBUNWIND "Enable backtrace for errors." OFF)
|
||||
option(MFEM_USE_LAPACK "Enable LAPACK usage" OFF)
|
||||
@@ -32,21 +30,17 @@ option(MFEM_USE_SUNDIALS "Enable SUNDIALS usage" OFF)
|
||||
option(MFEM_USE_MESQUITE "Enable MESQUITE usage" OFF)
|
||||
option(MFEM_USE_SUITESPARSE "Enable SuiteSparse usage" OFF)
|
||||
option(MFEM_USE_SUPERLU "Enable SuperLU_DIST usage" OFF)
|
||||
option(MFEM_USE_STRUMPACK "Enable STRUMPACK usage" OFF)
|
||||
option(MFEM_USE_GECKO "Enable GECKO usage" OFF)
|
||||
option(MFEM_USE_GNUTLS "Enable GNUTLS usage" OFF)
|
||||
option(MFEM_USE_NETCDF "Enable NETCDF usage" OFF)
|
||||
option(MFEM_USE_PETSC "Enable PETSc support." OFF)
|
||||
option(MFEM_USE_MPFR "Enable MPFR usage." OFF)
|
||||
option(MFEM_USE_SIDRE "Enable Axom/Sidre usage" OFF)
|
||||
option(MFEM_USE_CONDUIT "Enable Conduit usage" OFF)
|
||||
option(MFEM_USE_PUMI "Enable PUMI" OFF)
|
||||
option(MFEM_USE_SIDRE "Enable ATK/Sidre usage" OFF)
|
||||
|
||||
# Allow a user to disable testing, examples, and/or miniapps at CONFIGURE TIME
|
||||
# if they don't want/need them (e.g. if MFEM is "just a dependency" and all they
|
||||
# need is the library, building all that stuff adds unnecessary overhead). Note
|
||||
# that the examples or miniapps can always be built using the targets 'examples'
|
||||
# or 'miniapps', respectively.
|
||||
# need is the library, building all that stuff adds unnecessary overhead). To
|
||||
# match "makefile" behavior, they are all enabled by default.
|
||||
option(MFEM_ENABLE_TESTING "Enable the ctest framework for testing" ON)
|
||||
option(MFEM_ENABLE_EXAMPLES "Build all of the examples" OFF)
|
||||
option(MFEM_ENABLE_MINIAPPS "Build all of the miniapps" OFF)
|
||||
@@ -72,7 +66,7 @@ set(METIS_DIR "${MFEM_DIR}/../metis-4.0" CACHE PATH "Path to the METIS library."
|
||||
|
||||
set(LIBUNWIND_DIR "" CACHE PATH "Path to Libunwind.")
|
||||
|
||||
set(SUNDIALS_DIR "${MFEM_DIR}/../sundials-3.0.0" CACHE PATH
|
||||
set(SUNDIALS_DIR "${MFEM_DIR}/../sundials-2.7.0" CACHE PATH
|
||||
"Path to the SUNDIALS library.")
|
||||
# The following may be necessary, if SUNDIALS was built with KLU:
|
||||
# set(SUNDIALS_REQUIRED_PACKAGES "SuiteSparse/KLU/AMD/BTF/COLAMD/config"
|
||||
@@ -97,32 +91,6 @@ set(SuperLUDist_DIR "${MFEM_DIR}/../SuperLU_DIST_5.1.0" CACHE PATH
|
||||
set(SuperLUDist_REQUIRED_PACKAGES "MPI" "BLAS" "ParMETIS" CACHE STRING
|
||||
"Additional packages required by SuperLU_DIST.")
|
||||
|
||||
set(STRUMPACK_DIR "${MFEM_DIR}/../STRUMPACK-build" CACHE PATH
|
||||
"Path to the STRUMPACK library.")
|
||||
# STRUMPACK may also depend on "OpenMP", depending on how it was compiled.
|
||||
set(STRUMPACK_REQUIRED_PACKAGES "MPI" "MPI_Fortran" "ParMETIS" "METIS"
|
||||
"ScaLAPACK" "Scotch/ptscotch/ptscotcherr/scotch/scotcherr" CACHE STRING
|
||||
"Additional packages required by STRUMPACK.")
|
||||
# If the MPI package does not find all required Fortran libraries:
|
||||
# set(STRUMPACK_REQUIRED_LIBRARIES "gfortran" "mpi_mpifh" CACHE STRING
|
||||
# "Additional libraries required by STRUMPACK.")
|
||||
|
||||
# The Scotch library, required by STRUMPACK
|
||||
set(Scotch_DIR "${MFEM_DIR}/../scotch_6.0.4" CACHE PATH
|
||||
"Path to the Scotch and PT-Scotch libraries.")
|
||||
set(Scotch_REQUIRED_PACKAGES "Threads" CACHE STRING
|
||||
"Additional packages required by Scotch.")
|
||||
# Tell the "Threads" package/module to prefer pthreads.
|
||||
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
|
||||
set(Threads_LIB_VARS CMAKE_THREAD_LIBS_INIT)
|
||||
|
||||
# The ScaLAPACK library, required by STRUMPACK
|
||||
set(ScaLAPACK_DIR "${MFEM_DIR}/../scalapack-2.0.2/lib/cmake/scalapack-2.0.2"
|
||||
CACHE PATH "Path to the configuration file scalapack-config.cmake")
|
||||
set(ScaLAPACK_TARGET_NAMES scalapack)
|
||||
# set(ScaLAPACK_TARGET_FORCE)
|
||||
# set(ScaLAPACK_IMPORT_CONFIG DEBUG)
|
||||
|
||||
set(GECKO_DIR "${MFEM_DIR}/../gecko" CACHE PATH "Path to the Gecko library.")
|
||||
|
||||
set(GNUTLS_DIR "" CACHE PATH "Path to the GnuTLS library.")
|
||||
@@ -134,20 +102,19 @@ set(NetCDF_REQUIRED_PACKAGES "" CACHE STRING
|
||||
|
||||
set(PETSC_DIR "${MFEM_DIR}/../petsc" CACHE PATH
|
||||
"Path to the PETSc main directory.")
|
||||
set(PETSC_ARCH "arch-linux2-c-debug" CACHE STRING "PETSc build architecture.")
|
||||
set(PETSC_ARCH "arch-linux2-c-debug" CACHE PATH "PETSc build architecture.")
|
||||
|
||||
set(MPFR_DIR "" CACHE PATH "Path to the MPFR library.")
|
||||
|
||||
set(CONDUIT_DIR "${MFEM_DIR}/../conduit" CACHE PATH
|
||||
"Path to the Conduit library.")
|
||||
set(Conduit_REQUIRED_PACKAGES "HDF5" CACHE STRING
|
||||
"Additional packages required by Conduit.")
|
||||
|
||||
set(AXOM_DIR "${MFEM_DIR}/../axom" CACHE PATH "Path to the Axom library.")
|
||||
set(ATK_DIR "${MFEM_DIR}/../asctoolkit" CACHE PATH "Path to the ATK library.")
|
||||
# May need to add "Boost" as requirement.
|
||||
set(Axom_REQUIRED_PACKAGES "Conduit/relay" CACHE STRING
|
||||
"Additional packages required by Axom.")
|
||||
|
||||
set(PUMI_DIR "${MFEM_DIR}/../pumi-2.1.0" CACHE STRING
|
||||
"Directory where PUMI is installed")
|
||||
set(ATK_REQUIRED_PACKAGES "Conduit/relay" CACHE STRING
|
||||
"Additional packages required by ATK.")
|
||||
|
||||
set(BLAS_INCLUDE_DIRS "" CACHE STRING "Path to BLAS headers.")
|
||||
set(BLAS_LIBRARIES "" CACHE STRING "The BLAS library.")
|
||||
|
||||
@@ -30,36 +30,15 @@ PREFIX = ./mfem
|
||||
# Install program
|
||||
INSTALL = /usr/bin/install
|
||||
|
||||
STATIC = YES
|
||||
SHARED = NO
|
||||
|
||||
ifneq ($(NOTMAC),)
|
||||
AR = ar
|
||||
ARFLAGS = cruv
|
||||
RANLIB = ranlib
|
||||
PICFLAG = -fPIC
|
||||
SO_EXT = so
|
||||
SO_VER = so.$(MFEM_VERSION_STRING)
|
||||
BUILD_SOFLAGS = -shared -Wl,-soname,libmfem.$(SO_VER)
|
||||
BUILD_RPATH = -Wl,-rpath,$(BUILD_REAL_DIR)
|
||||
INSTALL_SOFLAGS = $(BUILD_SOFLAGS)
|
||||
INSTALL_RPATH = -Wl,-rpath,@MFEM_LIB_DIR@
|
||||
else
|
||||
# Silence "has no symbols" warnings on Mac OS X
|
||||
AR = ar
|
||||
ARFLAGS = Scruv
|
||||
RANLIB = ranlib -no_warning_for_no_symbols
|
||||
PICFLAG = -fPIC
|
||||
SO_EXT = dylib
|
||||
SO_VER = $(MFEM_VERSION_STRING).dylib
|
||||
MAKE_SOFLAGS = -Wl,-dylib,-install_name,$(1)/libmfem.$(SO_VER),\
|
||||
-compatibility_version,$(MFEM_VERSION_STRING),\
|
||||
-current_version,$(MFEM_VERSION_STRING),\
|
||||
-undefined,dynamic_lookup
|
||||
BUILD_SOFLAGS = $(subst $1 ,,$(call MAKE_SOFLAGS,$(BUILD_REAL_DIR)))
|
||||
BUILD_RPATH = -Wl,-undefined,dynamic_lookup
|
||||
INSTALL_SOFLAGS = $(subst $1 ,,$(call MAKE_SOFLAGS,$(MFEM_LIB_DIR)))
|
||||
INSTALL_RPATH = -Wl,-undefined,dynamic_lookup
|
||||
endif
|
||||
|
||||
# Set CXXFLAGS to overwrite the default selection of DEBUG_FLAGS/OPTIM_FLAGS
|
||||
@@ -75,44 +54,31 @@ endif
|
||||
# Command used to launch MPI jobs
|
||||
MFEM_MPIEXEC = mpirun
|
||||
MFEM_MPIEXEC_NP = -np
|
||||
# Number of mpi tasks for parallel jobs
|
||||
MFEM_MPI_NP = 4
|
||||
|
||||
# MFEM configuration options: YES/NO values, which are exported to config.mk and
|
||||
# config.hpp. The values below are the defaults for generating the actual values
|
||||
# in config.mk and config.hpp.
|
||||
|
||||
MFEM_USE_MPI = NO
|
||||
MFEM_USE_METIS = $(MFEM_USE_MPI)
|
||||
MFEM_USE_METIS_5 = NO
|
||||
MFEM_DEBUG = NO
|
||||
MFEM_USE_EXCEPTIONS = NO
|
||||
MFEM_USE_GZSTREAM = NO
|
||||
MFEM_USE_LIBUNWIND = NO
|
||||
MFEM_USE_LAPACK = NO
|
||||
MFEM_THREAD_SAFE = NO
|
||||
MFEM_USE_OPENMP = NO
|
||||
MFEM_USE_MEMALLOC = YES
|
||||
MFEM_TIMER_TYPE = $(if $(NOTMAC),2,4)
|
||||
MFEM_TIMER_TYPE = $(if $(NOTMAC),2,0)
|
||||
MFEM_USE_SUNDIALS = NO
|
||||
MFEM_USE_MESQUITE = NO
|
||||
MFEM_USE_SUITESPARSE = NO
|
||||
MFEM_USE_SUPERLU = NO
|
||||
MFEM_USE_STRUMPACK = NO
|
||||
MFEM_USE_GECKO = NO
|
||||
MFEM_USE_GNUTLS = NO
|
||||
MFEM_USE_NETCDF = NO
|
||||
MFEM_USE_PETSC = NO
|
||||
MFEM_USE_MPFR = NO
|
||||
MFEM_USE_SIDRE = NO
|
||||
MFEM_USE_CONDUIT = NO
|
||||
MFEM_USE_PUMI = NO
|
||||
|
||||
# Compile and link options for zlib.
|
||||
ZLIB_DIR =
|
||||
ZLIB_OPT = $(if $(ZLIB_DIR),-I$(ZLIB_DIR)/include)
|
||||
ZLIB_LIB = $(if $(ZLIB_DIR),$(ZLIB_RPATH) -L$(ZLIB_DIR)/lib ,)-lz
|
||||
ZLIB_RPATH = -Wl,-rpath,$(ZLIB_DIR)/lib
|
||||
|
||||
LIBUNWIND_OPT = -g
|
||||
LIBUNWIND_LIB = $(if $(NOTMAC),-lunwind -ldl,)
|
||||
@@ -123,7 +89,7 @@ HYPRE_OPT = -I$(HYPRE_DIR)/include
|
||||
HYPRE_LIB = -L$(HYPRE_DIR)/lib -lHYPRE
|
||||
|
||||
# METIS library configuration
|
||||
ifeq ($(MFEM_USE_SUPERLU)$(MFEM_USE_STRUMPACK),NONO)
|
||||
ifeq ($(MFEM_USE_SUPERLU),NO)
|
||||
ifeq ($(MFEM_USE_METIS_5),NO)
|
||||
METIS_DIR = @MFEM_DIR@/../metis-4.0
|
||||
METIS_OPT =
|
||||
@@ -134,7 +100,7 @@ ifeq ($(MFEM_USE_SUPERLU)$(MFEM_USE_STRUMPACK),NONO)
|
||||
METIS_LIB = -L$(METIS_DIR)/lib -lmetis
|
||||
endif
|
||||
else
|
||||
# ParMETIS: currently needed by SuperLU or STRUMPACK. We assume that METIS 5
|
||||
# ParMETIS currently needed only with SuperLU. We assume that METIS 5
|
||||
# (included with ParMETIS) is installed in the same location.
|
||||
METIS_DIR = @MFEM_DIR@/../parmetis-4.0.3
|
||||
METIS_OPT = -I$(METIS_DIR)/include
|
||||
@@ -154,10 +120,10 @@ OPENMP_LIB =
|
||||
POSIX_CLOCKS_LIB = -lrt
|
||||
|
||||
# SUNDIALS library configuration
|
||||
SUNDIALS_DIR = @MFEM_DIR@/../sundials-3.0.0
|
||||
SUNDIALS_DIR = @MFEM_DIR@/../sundials-2.7.0
|
||||
SUNDIALS_OPT = -I$(SUNDIALS_DIR)/include
|
||||
SUNDIALS_LIB = -Wl,-rpath,$(SUNDIALS_DIR)/lib -L$(SUNDIALS_DIR)/lib\
|
||||
-lsundials_arkode -lsundials_cvode -lsundials_nvecserial -lsundials_kinsol
|
||||
-lsundials_arkode -lsundials_cvode -lsundials_nvecserial -lsundials_kinsol
|
||||
|
||||
ifeq ($(MFEM_USE_MPI),YES)
|
||||
SUNDIALS_LIB += -lsundials_nvecparhyp -lsundials_nvecparallel
|
||||
@@ -174,41 +140,14 @@ MESQUITE_LIB = -L$(MESQUITE_DIR)/lib -lmesquite
|
||||
LIB_RT = $(if $(NOTMAC),-lrt,)
|
||||
SUITESPARSE_DIR = @MFEM_DIR@/../SuiteSparse
|
||||
SUITESPARSE_OPT = -I$(SUITESPARSE_DIR)/include
|
||||
SUITESPARSE_LIB = -Wl,-rpath,$(SUITESPARSE_DIR)/lib -L$(SUITESPARSE_DIR)/lib\
|
||||
-lklu -lbtf -lumfpack -lcholmod -lcolamd -lamd -lcamd -lccolamd\
|
||||
-lsuitesparseconfig $(LIB_RT) $(METIS_LIB) $(LAPACK_LIB)
|
||||
SUITESPARSE_LIB = -L$(SUITESPARSE_DIR)/lib -lklu -lbtf -lumfpack -lcholmod\
|
||||
-lcolamd -lamd -lcamd -lccolamd -lsuitesparseconfig $(LIB_RT) $(METIS_LIB)\
|
||||
$(LAPACK_LIB)
|
||||
|
||||
# SuperLU library configuration
|
||||
SUPERLU_DIR = @MFEM_DIR@/../SuperLU_DIST_5.1.0
|
||||
SUPERLU_OPT = -I$(SUPERLU_DIR)/SRC
|
||||
SUPERLU_LIB = -Wl,-rpath,$(SUPERLU_DIR)/SRC -L$(SUPERLU_DIR)/SRC -lsuperlu_dist
|
||||
|
||||
# SCOTCH library configuration (required by STRUMPACK)
|
||||
SCOTCH_DIR = @MFEM_DIR@/../scotch_6.0.4
|
||||
SCOTCH_OPT = -I$(SCOTCH_DIR)/include
|
||||
SCOTCH_LIB = -L$(SCOTCH_DIR)/lib -lptscotch -lptscotcherr -lscotch -lscotcherr\
|
||||
-lpthread
|
||||
|
||||
# SCALAPACK library configuration (required by STRUMPACK)
|
||||
SCALAPACK_DIR = @MFEM_DIR@/../scalapack-2.0.2
|
||||
SCALAPACK_OPT = -I$(SCALAPACK_DIR)/SRC
|
||||
SCALAPACK_LIB = -L$(SCALAPACK_DIR)/lib -lscalapack $(LAPACK_LIB)
|
||||
|
||||
# MPI Fortran library, needed e.g. by STRUMPACK
|
||||
# MPICH:
|
||||
MPI_FORTRAN_LIB = -lmpifort
|
||||
# OpenMPI:
|
||||
# MPI_FORTRAN_LIB = -lmpi_mpifh
|
||||
# Additional Fortan library:
|
||||
# MPI_FORTRAN_LIB += -lgfortran
|
||||
|
||||
# STRUMPACK library configuration
|
||||
STRUMPACK_DIR = @MFEM_DIR@/../STRUMPACK-build
|
||||
STRUMPACK_OPT = -I$(STRUMPACK_DIR)/include $(SCOTCH_OPT)
|
||||
# If STRUMPACK was build with OpenMP support, the following may be need:
|
||||
# STRUMPACK_OPT += $(OPENMP_OPT)
|
||||
STRUMPACK_LIB = -L$(STRUMPACK_DIR)/lib -lstrumpack $(MPI_FORTRAN_LIB)\
|
||||
$(SCOTCH_LIB) $(SCALAPACK_LIB)
|
||||
SUPERLU_LIB = -L$(SUPERLU_DIR)/SRC -lsuperlu_dist
|
||||
|
||||
# Gecko library configuration
|
||||
GECKO_DIR = @MFEM_DIR@/../gecko
|
||||
@@ -220,64 +159,43 @@ GNUTLS_OPT =
|
||||
GNUTLS_LIB = -lgnutls
|
||||
|
||||
# NetCDF library configuration
|
||||
NETCDF_DIR = $(HOME)/local
|
||||
HDF5_DIR = $(HOME)/local
|
||||
NETCDF_OPT = -I$(NETCDF_DIR)/include -I$(HDF5_DIR)/include $(ZLIB_OPT)
|
||||
NETCDF_LIB = -Wl,-rpath,$(NETCDF_DIR)/lib -L$(NETCDF_DIR)/lib\
|
||||
-Wl,-rpath,$(HDF5_DIR)/lib -L$(HDF5_DIR)/lib\
|
||||
-lnetcdf -lhdf5_hl -lhdf5 $(ZLIB_LIB)
|
||||
NETCDF_DIR = $(HOME)/local
|
||||
HDF5_DIR = $(HOME)/local
|
||||
ZLIB_DIR = $(HOME)/local
|
||||
NETCDF_OPT = -I$(NETCDF_DIR)/include
|
||||
NETCDF_LIB = -L$(NETCDF_DIR)/lib -lnetcdf -L$(HDF5_DIR)/lib -lhdf5_hl -lhdf5\
|
||||
-L$(ZLIB_DIR)/lib -lz
|
||||
|
||||
# PETSc library configuration (version greater or equal to 3.8 or the dev branch)
|
||||
PETSC_ARCH := arch-linux2-c-debug
|
||||
PETSC_DIR := $(MFEM_DIR)/../petsc/$(PETSC_ARCH)
|
||||
PETSC_VARS := $(PETSC_DIR)/lib/petsc/conf/petscvariables
|
||||
PETSC_FOUND := $(if $(wildcard $(PETSC_VARS)),YES,)
|
||||
PETSC_INC_VAR = PETSC_CC_INCLUDES
|
||||
PETSC_LIB_VAR = PETSC_EXTERNAL_LIB_BASIC
|
||||
ifeq ($(PETSC_FOUND),YES)
|
||||
PETSC_OPT := $(shell sed -n "s/$(PETSC_INC_VAR) = *//p" $(PETSC_VARS))
|
||||
PETSC_LIB := $(shell sed -n "s/$(PETSC_LIB_VAR) = *//p" $(PETSC_VARS))
|
||||
PETSC_LIB := -Wl,-rpath,$(abspath $(PETSC_DIR))/lib\
|
||||
-L$(abspath $(PETSC_DIR))/lib -lpetsc $(PETSC_LIB)
|
||||
ifeq ($(MFEM_USE_PETSC),YES)
|
||||
PETSC_DIR := $(MFEM_DIR)/../petsc/arch-linux2-c-debug
|
||||
PETSC_PC := $(PETSC_DIR)/lib/pkgconfig/PETSc.pc
|
||||
$(if $(wildcard $(PETSC_PC)),,$(error PETSc config not found - $(PETSC_PC)))
|
||||
PETSC_OPT := $(shell sed -n "s/Cflags: *//p" $(PETSC_PC))
|
||||
PETSC_LIB := $(shell sed -n "s/Libs.*: *//p" $(PETSC_PC))
|
||||
PETSC_LIB := -Wl,-rpath -Wl,$(abspath $(PETSC_DIR))/lib $(PETSC_LIB)
|
||||
endif
|
||||
|
||||
# MPFR library configuration
|
||||
MPFR_OPT =
|
||||
MPFR_LIB = -lmpfr
|
||||
|
||||
# Conduit and required libraries configuration
|
||||
CONDUIT_DIR = @MFEM_DIR@/../conduit
|
||||
CONDUIT_OPT = -I$(CONDUIT_DIR)/include/conduit
|
||||
CONDUIT_LIB = \
|
||||
-Wl,-rpath,$(CONDUIT_DIR)/lib -L$(CONDUIT_DIR)/lib \
|
||||
-lconduit -lconduit_relay -lconduit_blueprint -ldl
|
||||
|
||||
# Check if Conduit was built with hdf5 support, by looking
|
||||
# for the relay hdf5 header
|
||||
CONDUIT_HDF5_HEADER=$(CONDUIT_DIR)/include/conduit/conduit_relay_hdf5.hpp
|
||||
ifneq (,$(wildcard $(CONDUIT_HDF5_HEADER)))
|
||||
CONDUIT_OPT += -I$(HDF5_DIR)/include
|
||||
CONDUIT_LIB += -Wl,-rpath,$(HDF5_DIR)/lib -L$(HDF5_DIR)/lib \
|
||||
-lhdf5 $(ZLIB_LIB)
|
||||
endif
|
||||
|
||||
# Sidre and required libraries configuration
|
||||
# Be sure to check the HDF5_DIR (set above) is correct
|
||||
SIDRE_DIR = @MFEM_DIR@/../axom
|
||||
SIDRE_DIR = @MFEM_DIR@/../asctoolkit
|
||||
CONDUIT_DIR = @MFEM_DIR@/../conduit
|
||||
SIDRE_OPT = -I$(SIDRE_DIR)/include -I$(CONDUIT_DIR)/include/conduit\
|
||||
-I$(HDF5_DIR)/include
|
||||
SIDRE_LIB = \
|
||||
-Wl,-rpath,$(SIDRE_DIR)/lib -L$(SIDRE_DIR)/lib \
|
||||
-Wl,-rpath,$(CONDUIT_DIR)/lib -L$(CONDUIT_DIR)/lib \
|
||||
-Wl,-rpath,$(HDF5_DIR)/lib -L$(HDF5_DIR)/lib \
|
||||
-lsidre -lslic -laxom_utils -lconduit -lconduit_relay -lhdf5 $(ZLIB_LIB) -ldl
|
||||
SIDRE_LIB = -L$(SIDRE_DIR)/lib \
|
||||
-L$(CONDUIT_DIR)/lib \
|
||||
-Wl,-rpath -Wl,$(CONDUIT_DIR)/lib \
|
||||
-L$(HDF5_DIR)/lib\
|
||||
-Wl,-rpath -Wl,$(HDF5_DIR)/lib \
|
||||
-lsidre -lslic -lcommon -lconduit -lconduit_relay -lhdf5 -lz -ldl
|
||||
|
||||
# PUMI
|
||||
# Note that PUMI_DIR is needed -- it is used to check for gmi_sim.h
|
||||
PUMI_DIR = @MFEM_DIR@/../pumi-2.1.0
|
||||
PUMI_OPT = -I$(PUMI_DIR)/include
|
||||
PUMI_LIB = -L$(PUMI_DIR)/lib -lpumi -lcrv -lma -lmds -lapf -lpcu -lgmi -lparma\
|
||||
-llion -lmth -lapf_zoltan -lspr
|
||||
ifeq ($(MFEM_USE_MPI),YES)
|
||||
SIDRE_LIB += -lspio -lcommon
|
||||
endif
|
||||
|
||||
# If YES, enable some informational messages
|
||||
VERBOSE = NO
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
|
||||
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
|
||||
// reserved. See file COPYRIGHT for details.
|
||||
//
|
||||
// This file is part of the MFEM library. For more information and source code
|
||||
// availability see http://mfem.org.
|
||||
//
|
||||
// MFEM is free software; you can redistribute it and/or modify it under the
|
||||
// terms of the GNU Lesser General Public License (as published by the Free
|
||||
// Software Foundation) version 2.1 dated February 1999.
|
||||
|
||||
#include "HYPRE_config.h"
|
||||
#include <cstdio>
|
||||
|
||||
#ifdef HYPRE_RELEASE_VERSION
|
||||
#define HYPRE_VERSION_STRING HYPRE_RELEASE_VERSION
|
||||
#elif defined(HYPRE_PACKAGE_VERSION)
|
||||
#define HYPRE_VERSION_STRING HYPRE_PACKAGE_VERSION
|
||||
#endif
|
||||
|
||||
// Macros to expand a macro as a string
|
||||
#define STR_EXPAND(s) #s
|
||||
#define STR(s) STR_EXPAND(s)
|
||||
|
||||
// Convert the HYPRE_RELEASE_VERSION macro (string) to integer.
|
||||
// Examples: "2.10.0b" --> 21000, "2.11.2" --> 21102
|
||||
int main()
|
||||
{
|
||||
#ifdef HYPRE_VERSION_STRING
|
||||
const char *ptr = STR(HYPRE_VERSION_STRING);
|
||||
if (*ptr == '"') { ptr++; }
|
||||
int version = 0;
|
||||
for (int i = 0; i < 3; i++, ptr++)
|
||||
{
|
||||
int pv = 0;
|
||||
for (char d; d = *ptr, '0' <= d && d <= '9'; ptr++)
|
||||
{
|
||||
pv = 10*pv + (d - '0');
|
||||
if (pv >= 100) { return 1; }
|
||||
}
|
||||
version = 100*version + pv;
|
||||
}
|
||||
printf("%i\n", version);
|
||||
return 0;
|
||||
#else
|
||||
return 2;
|
||||
#endif
|
||||
}
|
||||
@@ -31,44 +31,17 @@ CONFIG_HPP = _config.hpp
|
||||
CONFIG_MK = config.mk
|
||||
|
||||
.SUFFIXES:
|
||||
.PHONY: all get-hypre-version header config-mk
|
||||
.PHONY: all header config-mk
|
||||
|
||||
all: header config-mk
|
||||
|
||||
MPI = $(MFEM_USE_MPI:NO=)
|
||||
GHV = get_hypre_version
|
||||
GHV_FLAGS = $(subst @MFEM_DIR@,$(if $(MFEM_DIR),$(MFEM_DIR),..),$(HYPRE_OPT))
|
||||
SMX = $(if $(MFEM_USE_PUMI:NO=),MFEM_USE_SIMMETRIX)
|
||||
SMX_PATH = $(PUMI_DIR)/include/gmi_sim.h
|
||||
SMX_FILE = $(subst @MFEM_DIR@,$(if $(MFEM_DIR),$(MFEM_DIR),..),$(SMX_PATH))
|
||||
|
||||
$(GHV): $(SRC)$(GHV).cpp
|
||||
$(call mfem-info, Determining HYPRE version ...)
|
||||
$(MFEM_CXX) ${GHV_FLAGS} $(SRC)$(GHV).cpp -o $(GHV)
|
||||
$(GHV).out: $(GHV)
|
||||
./$(GHV) > $(GHV).out
|
||||
.INTERMEDIATE: $(GHV) $(GHV).out
|
||||
|
||||
get-hypre-version: $(GHV).out
|
||||
$(eval MFEM_HYPRE_VERSION:=$(shell cat $(GHV).out))
|
||||
$(if $(MFEM_HYPRE_VERSION),$(eval export MFEM_HYPRE_VERSION)\
|
||||
$(info HYPRE version: $(MFEM_HYPRE_VERSION)),\
|
||||
$(error Unable to determine HYPRE version))
|
||||
|
||||
check-smx:
|
||||
$(call mfem-info, Checking for Simmetrix header [$(SMX_FILE)] ...)
|
||||
$(eval MFEM_USE_SIMMETRIX:=$(if $(wildcard $(SMX_FILE)),YES,NO))
|
||||
$(call mfem-info, MFEM_USE_SIMMETRIX = $(MFEM_USE_SIMMETRIX))
|
||||
$(eval export MFEM_USE_SIMMETRIX)
|
||||
|
||||
header: $(if $(MPI),get-hypre-version,) $(if $(SMX),check-smx)
|
||||
header:
|
||||
$(call mfem-info, Writing $(CONFIG_HPP) ...)
|
||||
@set -- && \
|
||||
for def in $${MFEM_DEFINES} $(if $(MPI),MFEM_HYPRE_VERSION) $(SMX); do \
|
||||
for def in $${MFEM_DEFINES}; do \
|
||||
eval var=\$$$$def && \
|
||||
if [ "NO" != "$${var}" ]; then \
|
||||
set -- "$$@" -e "s|// \(#define $${def} \)|\1|" && \
|
||||
set -- "$$@" -e "s|// \(#define $${def}\)$$|\1|" && \
|
||||
set -- "$$@" -e "s|// \(#define $${def}\)|\1|" && \
|
||||
set -- "$$@" -e "s#@$${def}@#$${var}#g"; \
|
||||
fi; \
|
||||
done && \
|
||||
@@ -89,4 +62,4 @@ config-mk:
|
||||
sed "$$@" $(SRC)config.mk.in > $(CONFIG_MK)
|
||||
|
||||
clean:
|
||||
rm -f $(CONFIG_HPP) $(CONFIG_MK) sample-runs-build.log
|
||||
rm -f $(CONFIG_HPP) $(CONFIG_MK)
|
||||
|
||||
@@ -1,525 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at the
|
||||
# Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights reserved.
|
||||
# See file COPYRIGHT for details.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability see http://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Lesser General Public License (as published by the Free
|
||||
# Software Foundation) version 2.1 dated February 1999.
|
||||
|
||||
make="${MAKE:-make}"
|
||||
mpiexec="${MPIEXEC:-mpirun}"
|
||||
mpiexec_np="${MPIEXEC_NP:--np}"
|
||||
run_prefix=""
|
||||
run_vg="valgrind --leak-check=full --show-reachable=yes --track-origins=yes"
|
||||
run_suffix="-no-vis"
|
||||
skip_gen_meshes="yes"
|
||||
cur_dir="${PWD}"
|
||||
mfem_dir="$(cd "$(dirname "$0")"/.. && pwd)"
|
||||
mfem_build_dir=""
|
||||
build_log=""
|
||||
output_dir=""
|
||||
output_sfx=".out"
|
||||
# The group format is: '"group-name" "group-summary-title" "group-directory"
|
||||
# "group-source-patterns"'
|
||||
groups_serial=(
|
||||
'"examples"
|
||||
"Examples:"
|
||||
"examples"
|
||||
"ex{,1}[0-9].cpp"'
|
||||
# "ex1.cpp"'
|
||||
'"sundials"
|
||||
"SUNDIALS examples:"
|
||||
"examples/sundials"
|
||||
"ex{9,10,16}.cpp"'
|
||||
'"performance"
|
||||
"Performance miniapps:"
|
||||
"miniapps/performance"
|
||||
"ex1.cpp"'
|
||||
# ""'
|
||||
'"meshing"
|
||||
"Meshing miniapps:"
|
||||
"miniapps/meshing"
|
||||
"mobius-strip.cpp klein-bottle.cpp mesh-optimizer.cpp"'
|
||||
)
|
||||
# Parallel groups
|
||||
groups_parallel=(
|
||||
'"examples"
|
||||
"Examples:"
|
||||
"examples"
|
||||
"ex{,1}[0-9]p.cpp"'
|
||||
# "ex1p.cpp"'
|
||||
'"sundials"
|
||||
"SUNDIALS examples:"
|
||||
"examples/sundials"
|
||||
"ex{9,10,16}p.cpp"'
|
||||
'"petsc"
|
||||
"PETSc examples:"
|
||||
"examples/petsc"
|
||||
"ex{,1}[0-9]p.cpp"'
|
||||
'"performance"
|
||||
"Performance miniapps:"
|
||||
"miniapps/performance"
|
||||
"ex1p.cpp"'
|
||||
# ""'
|
||||
'"meshing"
|
||||
"Meshing miniapps:"
|
||||
"miniapps/meshing"
|
||||
"pmesh-optimizer.cpp"'
|
||||
'"electromagnetics"
|
||||
"Electromagnetics miniapps:"
|
||||
"miniapps/electromagnetics"
|
||||
"joule.cpp"'
|
||||
# "{volta,tesla,joule}.cpp"' # todo: multiline sample runs
|
||||
)
|
||||
# All groups serial + parallel runs mixed in the same group:
|
||||
groups_all=(
|
||||
'"examples"
|
||||
"Examples:"
|
||||
"examples"
|
||||
"ex\"{,1}[0-9]\"{,p}.cpp"'
|
||||
'"sundials"
|
||||
"SUNDIALS examples:"
|
||||
"examples/sundials"
|
||||
"ex\"{9,10,16}\"{,p}.cpp"'
|
||||
'"petsc"
|
||||
"PETSc examples:"
|
||||
"examples/petsc"
|
||||
"ex{,1}[0-9]p.cpp"'
|
||||
'"performance"
|
||||
"Performance miniapps:"
|
||||
"miniapps/performance"
|
||||
"ex1{,p}.cpp"'
|
||||
'"meshing"
|
||||
"Meshing miniapps:"
|
||||
"miniapps/meshing"
|
||||
"mobius-strip.cpp klein-bottle.cpp {,p}mesh-optimizer.cpp"'
|
||||
'"electromagnetics"
|
||||
"Electromagnetics miniapps:"
|
||||
"miniapps/electromagnetics"
|
||||
"joule.cpp"'
|
||||
# "{volta,tesla,joule}.cpp"' # todo: multiline sample runs
|
||||
)
|
||||
make_all="all"
|
||||
base_timeformat=$'real: %3Rs user: %3Us sys: %3Ss %%cpu: %P'
|
||||
# separator
|
||||
sep='----------------------------------------------------------------'
|
||||
|
||||
# Command line parameters:
|
||||
opt_help="no"
|
||||
opt_show="no"
|
||||
mfem_config="MFEM_USE_MPI=NO MFEM_DEBUG=NO"
|
||||
groups=()
|
||||
group_name=""
|
||||
group_title=""
|
||||
valgrind="no"
|
||||
make_j="-j $(getconf _NPROCESSORS_ONLN)"
|
||||
color="no"
|
||||
built="no"
|
||||
timing="no"
|
||||
|
||||
# Read the sample runs from the source "$1" and put them in the array variable
|
||||
# "runs".
|
||||
function extract_sample_runs()
|
||||
{
|
||||
local old_IFS="${IFS}" sruns="" pruns=""
|
||||
local src="$1"
|
||||
if [ "${src}" == "" ]; then runs=(); return 1; fi
|
||||
local app=${src%.cpp}
|
||||
local vg_app="${app}"
|
||||
if [ "${valgrind}" == "yes" ]; then vg_app="${run_vg} ${app}"; fi
|
||||
# parallel sample runs are lines matching "^//.* mpirun .* ${app}" with
|
||||
# everything in front of "mpirun" removed:
|
||||
pruns=`grep "^//.* mpirun .* ${app}" "${src}" |
|
||||
sed -e "s/.* mpirun \(.*\) ${app}/${mpiexec} \1 ${app}/g" \
|
||||
-e "s/ -np\(.*\) ${app}/ ${mpiexec_np}\1 ${vg_app}/g"`
|
||||
# serial sample runs are lines that are not parallel sample runs and matching
|
||||
# "^//.* ${app}" with everything in front of "${app}" removed:
|
||||
sruns=`grep -v "^//.* mpirun .* ${app}" "${src}" |
|
||||
grep "^//.* ${app}" |
|
||||
sed -e "s/.* ${app}/${vg_app}/g"`
|
||||
runs="${sruns}${pruns}"
|
||||
if [ "$skip_gen_meshes" == "yes" ]; then
|
||||
runs=`printf "%s" "$runs" | grep -v ".* -m .*\.gen"`
|
||||
fi
|
||||
IFS=$'\n'
|
||||
runs=(${runs})
|
||||
IFS="${old_IFS}"
|
||||
}
|
||||
|
||||
# Echo usage information
|
||||
function help_message()
|
||||
{
|
||||
cat <<EOF
|
||||
|
||||
$0 [options]
|
||||
|
||||
Options:
|
||||
-h|-help Print this usage information and exit
|
||||
-p|-par Build the parallel MFEM library + examples + miniapps.
|
||||
The default is to build the serial MFEM library + examples +
|
||||
miniapps. The build can be customized by setting the variable
|
||||
'mfem_config' or by building separately and using '-b'
|
||||
-g <dir> <pattern>
|
||||
Specify explicitly a group (dir + file pattern) to run; This
|
||||
option can be used multiple times to define multiple groups
|
||||
-v Enable valgrind
|
||||
-o <dir> [${output_dir:-"<empty>: output goes to stdout"}]
|
||||
If not empty, save output to files inside <dir>
|
||||
-j <np> [${make_j}] Specify the number of jobs to use for building
|
||||
-c|-color Always use colors for the status messages: OK, FAILED, etc
|
||||
-b|-built Do NOT rebuild the library and the executables
|
||||
-t|-time Measure and print execution time for each sample run
|
||||
-s|-show Show all configured sample runs and exit
|
||||
-n Dry run: replace "\$sample_run" with "echo \$sample_run"
|
||||
<var>=<value>
|
||||
Set a shell script varible; see below for valid variables
|
||||
* Any other parameter is treated as <mfem_dir>
|
||||
<mfem_dir> [${mfem_dir}] is the MFEM source directory
|
||||
|
||||
This script tests all the sample runs listed in the begining comments of
|
||||
MFEM's serial or parallel example and miniapp codes. The list of sample runs
|
||||
is auto-generated and can be viewed with the -s|-show option.
|
||||
|
||||
The following shell script variables can be set with <var>=<value>:
|
||||
output_dir [${output_dir}]
|
||||
Same as '-o': if not empty, save output to files in that directory
|
||||
output_sfx [${output_sfx}]
|
||||
Suffix to append to the output files
|
||||
mfem_config [${mfem_config}]
|
||||
Set MFEM configuration options
|
||||
make [${make}], mpiexec [${mpiexec}], mpiexec_np [${mpiexec_np}]
|
||||
Their values can also set using the respective uppercase environment
|
||||
variable
|
||||
mfem_build_dir [${mfem_build_dir}]
|
||||
Set this variable to something different from <mfem_dir> to use an
|
||||
out-of-source build
|
||||
|
||||
For other valid variables, see the script source.
|
||||
|
||||
The following environment variables, if non-empty, are used:
|
||||
MAKE, MPIEXEC, MPIEXEC_NP
|
||||
|
||||
Example usage:
|
||||
$0 -s [ Show all configured sample runs ]
|
||||
$0 -o baseline [ Serial build; run and save all built sample runs ]
|
||||
$0 -p -o baseline [ Parallel build; run and save all sample runs ]
|
||||
$0 -b -g examples ex8.cpp [ Use the existing build; run ex8 sample runs ]
|
||||
|
||||
EOF
|
||||
}
|
||||
|
||||
function show_runs()
|
||||
{
|
||||
echo "${sep}"
|
||||
for group_params in "${groups[@]}"; do
|
||||
eval params=(${group_params})
|
||||
name="${params[0]}"
|
||||
title="${params[1]}"
|
||||
group_dir="${mfem_dir}/${params[2]}"
|
||||
pattern="${params[3]}"
|
||||
printf "group name: [%s]\n" "${name}"
|
||||
printf "summary title: [%s]\n" "${title}"
|
||||
printf "directory: [%s]\n" "${group_dir}"
|
||||
printf "pattern: [%s]\n" "${pattern}"
|
||||
cd "${cur_dir}"; cd "${group_dir}" || exit 1
|
||||
eval sources=(${pattern})
|
||||
eval sources=("${sources[@]}")
|
||||
printf "sources: (%s)\n" "${sources[*]}"
|
||||
printf "sample runs:\n"
|
||||
for src in "${sources[@]}"; do
|
||||
extract_sample_runs "${src}"
|
||||
for run in "${runs[@]}"; do
|
||||
printf " %s\n" "${run}"
|
||||
done
|
||||
done
|
||||
echo "${sep}"
|
||||
done
|
||||
}
|
||||
|
||||
# Process command line parameters
|
||||
while [ $# -gt 0 ]; do
|
||||
|
||||
case "$1" in
|
||||
-h|-help)
|
||||
opt_help="yes"
|
||||
;;
|
||||
-p|-parallel)
|
||||
mfem_config="MFEM_USE_MPI=YES MFEM_DEBUG=NO"
|
||||
;;
|
||||
-g)
|
||||
gbasename="$(basename "$2")"
|
||||
gname="${group_name:-${gbasename}}"
|
||||
gtitle="${group_title:-"Group <${gbasename}>:"}"
|
||||
test_group="\"${gname}\" \"${gtitle}\" \"$2\" \"$3\""
|
||||
groups=("${groups[@]}" "${test_group}")
|
||||
shift 2
|
||||
;;
|
||||
-v)
|
||||
valgrind="yes"
|
||||
;;
|
||||
-o)
|
||||
shift
|
||||
output_dir="$1"
|
||||
;;
|
||||
-j)
|
||||
shift
|
||||
make_j="-j $1"
|
||||
;;
|
||||
-c|-color)
|
||||
color="yes"
|
||||
;;
|
||||
-b|-built)
|
||||
built="yes"
|
||||
;;
|
||||
-t|-time)
|
||||
timing="yes"
|
||||
;;
|
||||
-s|-show)
|
||||
opt_show="yes"
|
||||
;;
|
||||
-n)
|
||||
run_prefix="echo"
|
||||
;;
|
||||
*=*)
|
||||
eval $1
|
||||
;;
|
||||
*)
|
||||
mfem_dir="$1"
|
||||
;;
|
||||
esac
|
||||
|
||||
shift
|
||||
done # while ...
|
||||
|
||||
mfem_build_dir="${mfem_build_dir:-${mfem_dir}}"
|
||||
|
||||
build_log="${build_log:-${mfem_build_dir}/config/sample-runs-build.log}"
|
||||
|
||||
if [ 0 -eq ${#groups[*]} ]; then
|
||||
groups=("${groups_all[@]}")
|
||||
# These can be used as command line arguments:
|
||||
# 'groups=("${groups_serial[@]}")'
|
||||
# 'groups=("${groups_parallel[@]}")'
|
||||
fi
|
||||
|
||||
if [ "${opt_help}" == "yes" ]; then
|
||||
help_message
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ "${opt_show}" == "yes" ]; then
|
||||
show_runs
|
||||
exit
|
||||
fi
|
||||
|
||||
# Setup colors
|
||||
if [ -t 1 ] && [ -z "${output_dir}" ] || [ "${color}" == "yes" ]; then
|
||||
red='\033[0;31m'
|
||||
green='\033[0;32m'
|
||||
yellow='\033[0;33m'
|
||||
magenta='\033[0;35m'
|
||||
cyan='\033[0;36m'
|
||||
none='\033[0m'
|
||||
else
|
||||
red=
|
||||
green=
|
||||
yellow=
|
||||
magenta=
|
||||
cyan=
|
||||
none=
|
||||
fi
|
||||
|
||||
# Run the given command, saving the rune time in the variable "timer".
|
||||
function timed_run()
|
||||
{
|
||||
timer="$({ time "$@" 1>&3 2>&4; } 2>&1)"
|
||||
} 3>&1 4>&2
|
||||
|
||||
# This function is used to execute the sample runs
|
||||
function go()
|
||||
{
|
||||
local cmd=("$@")
|
||||
local res=""
|
||||
echo $sep
|
||||
echo "<${group}>" "${cmd[@]}"
|
||||
echo $sep
|
||||
if [ "${timing}" == "yes" ]; then
|
||||
timed_run "${cmd[@]}"
|
||||
else
|
||||
"${cmd[@]}"
|
||||
fi
|
||||
if [ "$?" -eq 0 ]; then
|
||||
res="${green} OK ${none}"
|
||||
else
|
||||
res="${red}FAILED${none}"
|
||||
fi
|
||||
printf "[${res}] <${group}> ${cmd[*]}\n"
|
||||
if [ "${timing}" == "yes" ]; then
|
||||
printf "Run time: %s\n" "${timer}"
|
||||
timer=(${timer})
|
||||
timer="${timer[1]}"
|
||||
printf -v line "[$res](%8s) ${cmd[*]}" "$timer"
|
||||
summary=("${summary[@]}" "$line")
|
||||
else
|
||||
summary=("${summary[@]}" "[${res}] ${cmd[*]}")
|
||||
fi
|
||||
echo $sep
|
||||
}
|
||||
|
||||
# This function is used to run a group of sample runs (in the same directory)
|
||||
function go_group()
|
||||
{
|
||||
local res=""
|
||||
if [ $# -eq 0 ]; then return 0; fi
|
||||
local group_output_dir="" output_file="" output=""
|
||||
if [ ! -z "$output_dir" ]; then
|
||||
group_output_dir="${output_dir}/${group_dir}"
|
||||
mkdir -p "${group_output_dir}" || exit 1
|
||||
fi
|
||||
for src in "$@"; do
|
||||
cd "${mfem_dir}/${group_dir}" || exit 1
|
||||
extract_sample_runs "${src}" || continue
|
||||
[ "${#runs[@]}" -eq 0 ] && continue
|
||||
cd "${mfem_build_dir}/${group_dir}" || exit 1
|
||||
if [ ! -x "${src%.cpp}" ]; then
|
||||
res="${magenta} SKIP ${none}"
|
||||
echo $sep
|
||||
printf "[${res}] <${group}> <${src}>\n"
|
||||
echo $sep
|
||||
summary=("${summary[@]}" "[${res}] <${src}>")
|
||||
continue
|
||||
fi
|
||||
if [ ! -z "$output_dir" ]; then
|
||||
output_file="${group_output_dir}/${src}${output_sfx}"
|
||||
: > "${output_file}"
|
||||
output=">> \"${output_file}\" 2>&1"
|
||||
fi
|
||||
for run in "${runs[@]}"; do
|
||||
if [ "${run}" == "" ]; then continue; fi
|
||||
eval go \${run_prefix} \${run} \${run_suffix} $output
|
||||
done
|
||||
done
|
||||
${make} clean-exec
|
||||
}
|
||||
|
||||
# Make sure $mfem_dir exists and we can cd into it
|
||||
cd "$mfem_dir" || exit 1
|
||||
# Make sure $mfem_dir is an absolute path
|
||||
mfem_dir="$PWD"
|
||||
cd "${cur_dir}"
|
||||
if [ "${built}" == "no" ]; then
|
||||
mkdir -p "${mfem_build_dir}" || exit 1
|
||||
fi
|
||||
# Make sure $mfem_build_dir exists and we can cd into it
|
||||
cd "${mfem_build_dir}" || exit 1
|
||||
# Make sure $mfem_build_dir is an absolute path
|
||||
mfem_build_dir="$PWD"
|
||||
# Setup 'output_dir'
|
||||
if [ ! -z "$output_dir" ]; then
|
||||
cd "${cur_dir}"
|
||||
mkdir -p "${output_dir}" && cd "${output_dir}" || exit 1
|
||||
output_dir="$PWD"
|
||||
echo "Sending output to files in: [${output_dir}]"
|
||||
echo "Using suffix: [${output_sfx}]"
|
||||
fi
|
||||
|
||||
TIMEFORMAT="${base_timeformat}"
|
||||
|
||||
function set_echo_log()
|
||||
{
|
||||
local dirname=`dirname "$1"`
|
||||
cd "${cur_dir}"
|
||||
mkdir -p "${dirname}" && cd "${dirname}" || exit 1
|
||||
echo_log="$PWD"/`basename "$1"`
|
||||
}
|
||||
|
||||
# Echo the given command line; then run it sending all output to $echo_log
|
||||
function echo_run()
|
||||
{
|
||||
echo " $@"
|
||||
{ echo " $@"; echo "$sep";
|
||||
"$@"
|
||||
echo "$sep"; } >> "$echo_log" 2>&1
|
||||
}
|
||||
|
||||
# Function that builds the mfem library, examples and miniapps
|
||||
function build_all()
|
||||
{
|
||||
printf "Building MFEM with all examples and miniapps:\n"
|
||||
set_echo_log "${build_log}"
|
||||
echo " ### build log: [$echo_log]"
|
||||
{ echo "$sep"; echo " MFEM build log"; echo "$sep"; } > "$echo_log"
|
||||
echo_run cd "${mfem_build_dir}"
|
||||
if [ "${mfem_dir}" != "${mfem_build_dir}" ]; then
|
||||
echo_run ${make} -f "${mfem_dir}"/makefile config
|
||||
fi
|
||||
# Don't use 'make distclean' as it will delete the default $build_log
|
||||
echo_run ${make} clean || exit 1
|
||||
echo_run ${make} config ${mfem_config} || exit 1
|
||||
echo_run ${make} ${make_j} || exit 1
|
||||
echo_run ${make} ${make_all} ${make_j} || exit 1
|
||||
}
|
||||
|
||||
# Function that runs all sample runs, given by the array variable "groups".
|
||||
function all_go()
|
||||
{
|
||||
for group_params in "${groups[@]}"; do
|
||||
eval params=(${group_params})
|
||||
group="${params[0]}"
|
||||
group_dir="${params[2]}"
|
||||
cd "${mfem_dir}/${group_dir}" || exit 1
|
||||
eval sources=(${params[3]})
|
||||
eval sources=("${sources[@]}")
|
||||
summary=("${summary[@]}" "${params[1]}")
|
||||
go_group "${sources[@]}"
|
||||
done
|
||||
|
||||
printf "Summary:\n--------\n"
|
||||
for line in "${summary[@]}"; do
|
||||
printf "${line}\n"
|
||||
done
|
||||
}
|
||||
|
||||
function main()
|
||||
{
|
||||
# Build all mfem examples and miniapps
|
||||
if [ "${built}" == "no" ]; then
|
||||
if [ "${timing}" == "yes" ]; then
|
||||
timed_run build_all
|
||||
printf "Build time: %s\n" "${timer}"
|
||||
else
|
||||
build_all
|
||||
fi
|
||||
fi
|
||||
|
||||
summary=()
|
||||
PATH=.:$PATH
|
||||
|
||||
# Print the MFEM configuration info
|
||||
cd "${mfem_build_dir}"
|
||||
echo "$sep"
|
||||
echo "MFEM configuration"
|
||||
echo "$sep"
|
||||
${make} info
|
||||
echo "$sep"
|
||||
|
||||
# Run all sample runs.
|
||||
if [ "${timing}" == "yes" ]; then
|
||||
timed_run all_go
|
||||
printf "Total run time: %s\n" "${timer}"
|
||||
else
|
||||
all_go
|
||||
fi
|
||||
echo
|
||||
}
|
||||
|
||||
output=""
|
||||
if [ ! -z "$output_dir" ]; then
|
||||
output=">> \"${output_dir}/main${output_sfx}\" 2>&1"
|
||||
fi
|
||||
eval main $output
|
||||
@@ -10,49 +10,14 @@
|
||||
# Software Foundation) version 2.1 dated February 1999.
|
||||
|
||||
# Utilities for the "make test" and "make check" targets.
|
||||
|
||||
# Colors used below:
|
||||
# green '\033[0;32m'
|
||||
# red '\033[0;31m'
|
||||
# yellow '\033[0;33m'
|
||||
# no color '\033[0m'
|
||||
COLOR_PRINT = if [ -t 1 ]; then \
|
||||
printf $(1)$(2)'\033[0m'$(3); else printf $(2)$(3); fi
|
||||
PRINT_OK = $(call COLOR_PRINT,'\033[0;32m',OK," ($$1 $$2)\n")
|
||||
PRINT_FAILED = $(call COLOR_PRINT,'\033[0;31m',FAILED," ($$1 $$2)\n")
|
||||
PRINT_SKIP = $(call COLOR_PRINT,'\033[0;33m',SKIP,"\n")
|
||||
|
||||
# Timing support
|
||||
define TIMECMD_detect
|
||||
timecmd=$$(which time 2> /dev/null);
|
||||
if [ -n "$$timecmd" ]; then
|
||||
if $$timecmd --version > /dev/null 2>&1; then
|
||||
echo "$$timecmd" GNU; else echo "$$timecmd" NOTGNU; fi;
|
||||
else timecmd=$$(command -v time);
|
||||
if [ "$$timecmd" = time ]; then
|
||||
echo "$$timecmd" BASH; else echo X NONE; fi;
|
||||
fi
|
||||
endef
|
||||
define TIMECMD.GNU
|
||||
export TIME='%es %MkB %x'; \
|
||||
set -- $$($(1) $(SHELL) -c "$(2)" 2>&1); while [ "$$#" -gt 3 ]; do shift; done
|
||||
endef
|
||||
define TIMECMD.NOTGNU
|
||||
set -- $$($(1) -l $(SHELL) -c "$(2)" 2>&1; echo $$?); \
|
||||
set -- "$$1"s "$$(($$7/1024))"kB "$${60}"
|
||||
endef
|
||||
define TIMECMD.BASH
|
||||
TIMEFORMAT=$$'%3Rs'; \
|
||||
set -- $$({ time $(2); } 2>&1; echo $$?); set -- "$$1" "" "$$2"
|
||||
endef
|
||||
define TIMECMD.NONE
|
||||
$(2); set -- "" "" "$$?"
|
||||
endef
|
||||
TIMECMD := $(shell $(TIMECMD_detect))
|
||||
TIMEFUN := TIMECMD.$(word 2,$(TIMECMD))
|
||||
TIMECMD := $(word 1,$(TIMECMD))
|
||||
# Sample use of the timing macro: (returns shell commands as text)
|
||||
# $(call $(TIMEFUN),$(TIMECMD),$(MY_SHELL_COMMANDS))
|
||||
PRINT_OK = $(call COLOR_PRINT,'\033[0;32m',OK,"\n")
|
||||
PRINT_FAILED = $(call COLOR_PRINT,'\033[0;31m',FAILED,"\n")
|
||||
|
||||
ifneq (,$(filter test%,$(MAKECMDGOALS)))
|
||||
MAKEFLAGS += -k
|
||||
@@ -60,20 +25,16 @@ endif
|
||||
# Test runs of the examples/miniapps with parameters - check exit code
|
||||
mfem-test = \
|
||||
printf " $(3) [$(2) $(1) ... ]: "; \
|
||||
$(call $(TIMEFUN),$(TIMECMD),$(2) ./$(1) -no-vis $(4) > $(1).stderr 2>&1); \
|
||||
if [ "$$3" = 0 ]; \
|
||||
then $(PRINT_OK); else $(PRINT_FAILED); cat $(1).stderr; fi; \
|
||||
rm -f $(1).stderr; exit $$3
|
||||
if ($(2) ./$(1) -no-vis $(4) > /dev/null); \
|
||||
then $(PRINT_OK); else $(PRINT_FAILED); exit 1; fi
|
||||
|
||||
# Test runs of the examples/miniapps - check exit code and if a file exists
|
||||
mfem-test-file = \
|
||||
printf " $(3) [$(2) $(1) ... ]: "; \
|
||||
$(call $(TIMEFUN),$(TIMECMD),$(2) ./$(1) -no-vis > $(1).stderr 2>&1); \
|
||||
if [ "$$3" = 0 ] && [ -e $(4) ]; \
|
||||
then $(PRINT_OK); else $(PRINT_FAILED); cat $(1).stderr; fi; \
|
||||
rm -f $(1).stderr; exit $$3
|
||||
if ($(2) ./$(1) -no-vis > /dev/null) && [ -e $(4) ]; \
|
||||
then $(PRINT_OK); else $(PRINT_FAILED); exit 1; fi
|
||||
|
||||
.PHONY: test test-par-YES test-par-NO test-ser test-par test-clean test-print
|
||||
.PHONY: test test-par-YES test-par-NO
|
||||
|
||||
# What sets of tests to run in serial and parallel
|
||||
test-par-YES: $(PAR_$(MFEM_TESTS):=-test-par) $(SEQ_$(MFEM_TESTS):=-test-seq)
|
||||
@@ -81,12 +42,3 @@ test-par-NO: $(SEQ_$(MFEM_TESTS):=-test-seq)
|
||||
test-ser: test-par-NO
|
||||
test-par: test-par-YES
|
||||
test: all test-par-$(MFEM_USE_MPI) clean-exec
|
||||
test-clean: ; @rm -f *.stderr
|
||||
test-print: mfem-test=printf " $(3) [$(2) ./$(1) -no-vis $(if $(4),$(4) )]\n"
|
||||
test-print: mfem-test-file=printf " $(3) [$(2) ./$(1) -no-vis ]\n"
|
||||
test-print: test-par-$(MFEM_USE_MPI)
|
||||
ifeq ($(MAKECMDGOALS),test-print)
|
||||
.PHONY: $(PAR_$(MFEM_TESTS)) $(SEQ_$(MFEM_TESTS))
|
||||
endif
|
||||
|
||||
clean-exec: test-clean
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
MFEM mesh v1.1
|
||||
|
||||
#
|
||||
# MFEM Geometry Types (see mesh/geom.hpp):
|
||||
#
|
||||
# POINT = 0
|
||||
# SEGMENT = 1
|
||||
# TRIANGLE = 2
|
||||
# SQUARE = 3
|
||||
# TETRAHEDRON = 4
|
||||
# CUBE = 5
|
||||
#
|
||||
|
||||
dimension
|
||||
2
|
||||
|
||||
elements
|
||||
17
|
||||
1 3 0 23 30 26
|
||||
1 3 26 30 25 21
|
||||
1 3 30 24 22 25
|
||||
1 3 23 18 24 30
|
||||
1 3 18 1 19 22
|
||||
1 3 22 19 10 20
|
||||
1 3 31 27 20 28
|
||||
1 3 25 22 27 31
|
||||
1 3 21 25 31 29
|
||||
1 3 29 31 28 9
|
||||
1 3 1 2 11 10
|
||||
1 3 2 3 12 11
|
||||
1 3 3 4 13 12
|
||||
2 3 4 5 14 13
|
||||
2 3 5 6 15 14
|
||||
2 3 6 7 16 15
|
||||
2 3 7 8 17 16
|
||||
|
||||
boundary
|
||||
25
|
||||
3 1 0 23
|
||||
1 1 26 0
|
||||
1 1 21 26
|
||||
3 1 23 18
|
||||
3 1 18 1
|
||||
3 1 10 20
|
||||
3 1 20 28
|
||||
1 1 29 21
|
||||
3 1 28 9
|
||||
1 1 9 29
|
||||
3 1 1 2
|
||||
3 1 11 10
|
||||
3 1 2 3
|
||||
3 1 12 11
|
||||
3 1 3 4
|
||||
3 1 13 12
|
||||
3 1 4 5
|
||||
3 1 14 13
|
||||
3 1 5 6
|
||||
3 1 15 14
|
||||
3 1 6 7
|
||||
3 1 16 15
|
||||
3 1 7 8
|
||||
2 1 8 17
|
||||
3 1 17 16
|
||||
|
||||
vertex_parents
|
||||
14
|
||||
18 0 1
|
||||
19 1 10
|
||||
20 9 10
|
||||
21 0 9
|
||||
22 18 20
|
||||
23 0 18
|
||||
24 18 22
|
||||
25 21 22
|
||||
26 0 21
|
||||
27 20 22
|
||||
28 9 20
|
||||
29 9 21
|
||||
30 23 25
|
||||
31 25 28
|
||||
|
||||
coarse_elements
|
||||
3
|
||||
3 0 3 2 1
|
||||
3 8 7 6 9
|
||||
3 17 4 5 18
|
||||
|
||||
vertices
|
||||
32
|
||||
2
|
||||
0 0
|
||||
1 0
|
||||
2 0
|
||||
3 0
|
||||
4 0
|
||||
5 0
|
||||
6 0
|
||||
7 0
|
||||
8 0
|
||||
0 1
|
||||
1 1
|
||||
2 1
|
||||
3 1
|
||||
4 1
|
||||
5 1
|
||||
6 1
|
||||
7 1
|
||||
8 1
|
||||
0.5 0
|
||||
1 0.5
|
||||
0.5 1
|
||||
0 0.5
|
||||
0.5 0.5
|
||||
0.25 0
|
||||
0.5 0.25
|
||||
0.25 0.5
|
||||
0 0.25
|
||||
0.5 0.75
|
||||
0.25 1
|
||||
0 0.75
|
||||
0.25 0.25
|
||||
0.25 0.75
|
||||
@@ -1,218 +0,0 @@
|
||||
MFEM mesh v1.0
|
||||
|
||||
dimension
|
||||
2
|
||||
|
||||
elements
|
||||
74
|
||||
2 3 0 1 2 3
|
||||
2 3 1 5 6 2
|
||||
2 3 5 8 9 6
|
||||
2 3 8 11 12 9
|
||||
2 3 11 14 15 12
|
||||
2 3 14 17 18 15
|
||||
2 3 17 20 21 18
|
||||
2 3 20 23 24 21
|
||||
2 3 23 26 27 24
|
||||
2 3 26 29 30 27
|
||||
2 3 29 32 33 30
|
||||
2 3 32 35 36 33
|
||||
2 3 35 38 39 36
|
||||
2 3 38 41 42 39
|
||||
2 3 41 44 45 42
|
||||
2 3 44 47 48 45
|
||||
2 3 47 50 51 48
|
||||
2 3 50 53 54 51
|
||||
2 3 53 56 57 54
|
||||
2 3 56 59 60 57
|
||||
2 3 59 62 63 60
|
||||
2 3 62 65 66 63
|
||||
2 3 65 68 69 66
|
||||
2 3 68 71 72 69
|
||||
2 3 71 74 75 72
|
||||
1 2 2 3 4
|
||||
1 2 6 2 7
|
||||
1 2 9 6 10
|
||||
1 2 12 9 13
|
||||
1 2 15 12 16
|
||||
1 2 18 15 19
|
||||
1 2 21 18 22
|
||||
1 2 24 21 25
|
||||
1 2 27 24 28
|
||||
1 2 30 27 31
|
||||
1 2 33 30 34
|
||||
1 2 36 33 37
|
||||
1 2 39 36 40
|
||||
1 2 42 39 43
|
||||
1 2 45 42 46
|
||||
1 2 48 45 49
|
||||
1 2 51 48 52
|
||||
1 2 54 51 55
|
||||
1 2 57 54 58
|
||||
1 2 60 57 61
|
||||
1 2 63 60 64
|
||||
1 2 66 63 67
|
||||
1 2 69 66 70
|
||||
1 2 72 69 73
|
||||
1 2 75 72 76
|
||||
1 2 2 4 7
|
||||
1 2 6 7 10
|
||||
1 2 9 10 13
|
||||
1 2 12 13 16
|
||||
1 2 15 16 19
|
||||
1 2 18 19 22
|
||||
1 2 21 22 25
|
||||
1 2 24 25 28
|
||||
1 2 27 28 31
|
||||
1 2 30 31 34
|
||||
1 2 33 34 37
|
||||
1 2 36 37 40
|
||||
1 2 39 40 43
|
||||
1 2 42 43 46
|
||||
1 2 45 46 49
|
||||
1 2 48 49 52
|
||||
1 2 51 52 55
|
||||
1 2 54 55 58
|
||||
1 2 57 58 61
|
||||
1 2 60 61 64
|
||||
1 2 63 64 67
|
||||
1 2 66 67 70
|
||||
1 2 69 70 73
|
||||
1 2 72 73 76
|
||||
|
||||
boundary
|
||||
53
|
||||
1 1 0 1
|
||||
1 1 1 5
|
||||
1 1 5 8
|
||||
1 1 8 11
|
||||
1 1 11 14
|
||||
1 1 14 17
|
||||
1 1 17 20
|
||||
1 1 20 23
|
||||
1 1 23 26
|
||||
1 1 26 29
|
||||
1 1 29 32
|
||||
1 1 32 35
|
||||
1 1 35 38
|
||||
1 1 38 41
|
||||
1 1 41 44
|
||||
1 1 44 47
|
||||
1 1 47 50
|
||||
1 1 50 53
|
||||
1 1 53 56
|
||||
1 1 56 59
|
||||
1 1 59 62
|
||||
1 1 62 65
|
||||
1 1 65 68
|
||||
1 1 68 71
|
||||
1 1 71 74
|
||||
1 1 74 75
|
||||
1 1 75 76
|
||||
1 1 76 73
|
||||
1 1 73 70
|
||||
1 1 70 67
|
||||
1 1 67 64
|
||||
1 1 64 61
|
||||
1 1 61 58
|
||||
1 1 58 55
|
||||
1 1 55 52
|
||||
1 1 52 49
|
||||
1 1 49 46
|
||||
1 1 46 43
|
||||
1 1 43 40
|
||||
1 1 40 37
|
||||
1 1 37 34
|
||||
1 1 34 31
|
||||
1 1 31 28
|
||||
1 1 28 25
|
||||
1 1 25 22
|
||||
1 1 22 19
|
||||
1 1 19 16
|
||||
1 1 16 13
|
||||
1 1 13 10
|
||||
1 1 10 7
|
||||
1 1 7 4
|
||||
1 1 4 3
|
||||
1 1 3 0
|
||||
|
||||
vertices
|
||||
77
|
||||
2
|
||||
3.9788735773 0.0
|
||||
3.84329674785 1.02980825986
|
||||
2.88247256089 0.772356194895
|
||||
2.98415518297 0.0
|
||||
1.97241688113 0.259673608685
|
||||
3.44580559639 1.98943678865
|
||||
2.58435419729 1.49207759149
|
||||
1.83799993026 0.761324498753
|
||||
2.81348848799 2.81348848799
|
||||
2.11011636599 2.11011636599
|
||||
1.57832632157 1.21109238238
|
||||
1.98943678865 3.44580559639
|
||||
1.49207759149 2.58435419729
|
||||
1.21109238238 1.57832632157
|
||||
1.02980825986 3.84329674785
|
||||
0.772356194895 2.88247256089
|
||||
0.761324498753 1.83799993026
|
||||
2.43635739532e-16 3.9788735773
|
||||
1.82726804649e-16 2.98415518297
|
||||
0.259673608685 1.97241688113
|
||||
-1.02980825986 3.84329674785
|
||||
-0.772356194895 2.88247256089
|
||||
-0.259673608685 1.97241688113
|
||||
-1.98943678865 3.44580559639
|
||||
-1.49207759149 2.58435419729
|
||||
-0.761324498753 1.83799993026
|
||||
-2.81348848799 2.81348848799
|
||||
-2.11011636599 2.11011636599
|
||||
-1.21109238238 1.57832632157
|
||||
-3.44580559639 1.98943678865
|
||||
-2.58435419729 1.49207759149
|
||||
-1.57832632157 1.21109238238
|
||||
-3.84329674785 1.02980825986
|
||||
-2.88247256089 0.772356194895
|
||||
-1.83799993026 0.761324498753
|
||||
-3.9788735773 4.87271479065e-16
|
||||
-2.98415518297 3.65453609299e-16
|
||||
-1.97241688113 0.259673608685
|
||||
-3.84329674785 -1.02980825986
|
||||
-2.88247256089 -0.772356194895
|
||||
-1.97241688113 -0.259673608685
|
||||
-3.44580559639 -1.98943678865
|
||||
-2.58435419729 -1.49207759149
|
||||
-1.83799993026 -0.761324498753
|
||||
-2.81348848799 -2.81348848799
|
||||
-2.11011636599 -2.11011636599
|
||||
-1.57832632157 -1.21109238238
|
||||
-1.98943678865 -3.44580559639
|
||||
-1.49207759149 -2.58435419729
|
||||
-1.21109238238 -1.57832632157
|
||||
-1.02980825986 -3.84329674785
|
||||
-0.772356194895 -2.88247256089
|
||||
-0.761324498753 -1.83799993026
|
||||
-7.30907218597e-16 -3.9788735773
|
||||
-5.48180413948e-16 -2.98415518297
|
||||
-0.259673608685 -1.97241688113
|
||||
1.02980825986 -3.84329674785
|
||||
0.772356194895 -2.88247256089
|
||||
0.259673608685 -1.97241688113
|
||||
1.98943678865 -3.44580559639
|
||||
1.49207759149 -2.58435419729
|
||||
0.761324498753 -1.83799993026
|
||||
2.81348848799 -2.81348848799
|
||||
2.11011636599 -2.11011636599
|
||||
1.21109238238 -1.57832632157
|
||||
3.44580559639 -1.98943678865
|
||||
2.58435419729 -1.49207759149
|
||||
1.57832632157 -1.21109238238
|
||||
3.84329674785 -1.02980825986
|
||||
2.88247256089 -0.772356194895
|
||||
1.83799993026 -0.761324498753
|
||||
3.9788735773 -9.7454295813e-16
|
||||
2.98415518297 -7.30907218597e-16
|
||||
1.97241688113 -0.259673608685
|
||||
3.84329674785 1.02980825986
|
||||
2.88247256089 0.772356194895
|
||||
1.97241688113 0.259673608685
|
||||
@@ -1,74 +0,0 @@
|
||||
MFEM mesh v1.0
|
||||
|
||||
dimension
|
||||
2
|
||||
|
||||
elements
|
||||
20
|
||||
2 3 0 1 2 3
|
||||
2 3 1 5 6 2
|
||||
2 3 5 8 9 6
|
||||
2 3 8 11 12 9
|
||||
2 3 11 14 15 12
|
||||
2 3 14 17 18 15
|
||||
2 3 17 20 21 18
|
||||
1 2 2 3 4
|
||||
1 2 6 2 7
|
||||
1 2 9 6 10
|
||||
1 2 12 9 13
|
||||
1 2 15 12 16
|
||||
1 2 18 15 19
|
||||
1 2 21 18 22
|
||||
1 2 2 4 7
|
||||
1 2 6 7 10
|
||||
1 2 9 10 13
|
||||
1 2 12 13 16
|
||||
1 2 15 16 19
|
||||
1 2 18 19 22
|
||||
|
||||
boundary
|
||||
17
|
||||
1 1 0 1
|
||||
1 1 1 5
|
||||
1 1 5 8
|
||||
1 1 8 11
|
||||
1 1 11 14
|
||||
1 1 14 17
|
||||
1 1 17 20
|
||||
1 1 20 21
|
||||
1 1 21 22
|
||||
1 1 22 19
|
||||
1 1 19 16
|
||||
1 1 16 13
|
||||
1 1 13 10
|
||||
1 1 10 7
|
||||
1 1 7 4
|
||||
1 1 4 3
|
||||
1 1 3 0
|
||||
|
||||
vertices
|
||||
23
|
||||
2
|
||||
1.11408460164 0.0
|
||||
0.557042300822 0.964825566988
|
||||
0.417781725616 0.723619175241
|
||||
0.835563451232 0.0
|
||||
0.482412783494 0.278521150411
|
||||
-0.557042300822 0.964825566988
|
||||
-0.417781725616 0.723619175241
|
||||
3.41090035345e-17 0.557042300822
|
||||
-1.11408460164 1.36436014138e-16
|
||||
-0.835563451232 1.02327010604e-16
|
||||
-0.482412783494 0.278521150411
|
||||
-0.557042300822 -0.964825566988
|
||||
-0.417781725616 -0.723619175241
|
||||
-0.482412783494 -0.278521150411
|
||||
0.557042300822 -0.964825566988
|
||||
0.417781725616 -0.723619175241
|
||||
-1.02327010604e-16 -0.557042300822
|
||||
1.11408460164 -2.72872028276e-16
|
||||
0.835563451232 -2.04654021207e-16
|
||||
0.482412783494 -0.278521150411
|
||||
0.557042300822 0.964825566988
|
||||
0.417781725616 0.723619175241
|
||||
0.482412783494 0.278521150411
|
||||
@@ -1,924 +0,0 @@
|
||||
#Title:circInSquare.py
|
||||
#Author:T. M. McManus
|
||||
#Date:10-7-18
|
||||
#Purpose: Fill a circular sector with triangles and a bounding region,
|
||||
#defined by 3 nodes, with quads. Then reflect/preserve QuadI twice to
|
||||
#create a complete disc bounded in a square.
|
||||
|
||||
import scipy as sp
|
||||
import argparse
|
||||
import sys
|
||||
import subprocess
|
||||
import time
|
||||
|
||||
parser=argparse.ArgumentParser(description='Fill a circular sector with triangles and a bounding region,\
|
||||
defined by 3 nodes, with quads. Then reflect/preserve QuadI twice to create a complete disc bounded in a square.'
|
||||
,epilog='Sample run: python circInSquare.py -r 1 -e 2 -n 8 -g ../../../glvis/glvis')
|
||||
|
||||
parser.add_argument('-r','--circRad', nargs='?',const=1, default = 1.0, type=float, help='Radius of circle')
|
||||
parser.add_argument('-e','--edgeLength', nargs='?',const=1,default=2.0,type=float,help='Edge-length of bounding square')
|
||||
parser.add_argument('-n','--numEdges',nargs='?',const=1,default=6,type=int,help='n-gon approximation of internal circle')
|
||||
parser.add_argument('-o','--outputFile',nargs='?',const=1,default='circInSquare', help='Output file name.')
|
||||
parser.add_argument('-g','--glvis',nargs='?',const=1,default='',type=str,help='Abs. or rel. path of glvis binary.')
|
||||
args=parser.parse_args()
|
||||
|
||||
r=args.circRad
|
||||
edgeLength=args.edgeLength
|
||||
numEdges=args.numEdges
|
||||
outputName=args.outputFile
|
||||
glvis=args.glvis
|
||||
|
||||
visMesh=False;
|
||||
|
||||
if glvis!='':
|
||||
visMesh=True
|
||||
|
||||
if r >= edgeLength:
|
||||
print("Circle radius must be less than bounding square edge length")
|
||||
sys.exit(1)
|
||||
|
||||
if sp.mod(numEdges,2) != 0:
|
||||
print("Currently this mixed element generator only supports an even numbers of edges.")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
#The basic idea:
|
||||
#1. Construct topology for regions
|
||||
#2. Combine topologies
|
||||
#3. Construct boundary
|
||||
#4. Construct geometry for regions
|
||||
#5. Combine geometries
|
||||
#6. Output
|
||||
|
||||
def eleMatCirc(numEdges):
|
||||
|
||||
nNodesSeq=sp.zeros([numEdges])
|
||||
nNodesSeq[0]=3
|
||||
if numEdges != 1:
|
||||
for n in range(1,numEdges):
|
||||
nNodesSeq[n]=nNodesSeq[n-1]+(2+n)
|
||||
|
||||
numCircNodesTot =int(((numEdges+1)*(numEdges+2))/2)
|
||||
|
||||
b=range(numCircNodesTot)
|
||||
row_size=1
|
||||
A=sp.zeros([numEdges+1,numEdges+1])
|
||||
start=0;stop=1;
|
||||
for m in range(numEdges+1):
|
||||
if m==0:
|
||||
A[m,range(m+1)]=b[0:1]
|
||||
start=0
|
||||
stop=1
|
||||
else:
|
||||
start=stop
|
||||
stop=stop+m+1
|
||||
A[m,range(m+1)]=b[start:stop]
|
||||
|
||||
M=sp.ones([numEdges**2,5])
|
||||
m_row=0
|
||||
for m in range(numEdges):
|
||||
if m==0:
|
||||
M[0,:]=[1,2,0,1,2]
|
||||
m_row+=1
|
||||
else:
|
||||
holder=sp.size(sp.nonzero(A[m,:]))
|
||||
for n in range(holder):
|
||||
if n!=holder-1:
|
||||
M[m_row,:]=[1,2,A[m,n],A[m,n+1],A[m+1,n+1]]
|
||||
m_row+=1
|
||||
M[m_row,:]=[1,2,A[m,n],A[m+1,n],A[m+1,n+1]]
|
||||
m_row+=1
|
||||
else:
|
||||
M[m_row,:]=[1,2,A[m,n],A[m+1,n],A[m+1,n+1]]
|
||||
m_row+=1
|
||||
|
||||
return M.astype(int),numCircNodesTot
|
||||
|
||||
def eleMatQuad(numEdges):
|
||||
S0=numEdges*(numEdges+1)/(2.0)
|
||||
A=sp.linspace(S0,(S0+(numEdges+1)**2)-1,(numEdges+1)**2)
|
||||
A=A.reshape([numEdges+1,numEdges+1])
|
||||
quadNode=sp.delete(A,-1,1)
|
||||
quadNode=sp.delete(quadNode,-1,0)
|
||||
quadNode=quadNode.flatten()
|
||||
M=sp.zeros([numEdges**2,6])
|
||||
for n in range(numEdges**2):
|
||||
M[n,:]=[2,3,quadNode[n],quadNode[n]+1,quadNode[n]+numEdges+2,quadNode[n]+numEdges+1]
|
||||
return M.astype(int)
|
||||
|
||||
def boundMatTot(numEdges):
|
||||
triS1=sp.zeros(numEdges+1)
|
||||
triS3=sp.zeros(numEdges+1)
|
||||
quadS1=sp.zeros(numEdges)
|
||||
quadS2=sp.zeros(numEdges-1)
|
||||
quadS3=sp.zeros(numEdges)
|
||||
|
||||
triS1[0]=0;
|
||||
triS3[0]=0;
|
||||
for n in range(1,numEdges+1):
|
||||
triS1[n]=triS1[n-1]+n
|
||||
triS3[n]=triS1[n]+n
|
||||
ref1=triS3
|
||||
|
||||
triS3=sp.flipud(triS3)
|
||||
quadS1[0]=triS1[-1]+numEdges+1
|
||||
quadS3[0]=triS1[-1]+2*numEdges+1
|
||||
|
||||
for n in range(1,numEdges):
|
||||
quadS1[n]=quadS1[n-1]+(numEdges+1)
|
||||
quadS3[n]=quadS3[n-1]+(numEdges+1)
|
||||
ref2=quadS3
|
||||
xAxisRootRef=sp.concatenate([triS1.copy(),quadS1],axis=0)
|
||||
quadS3=sp.flipud(quadS3)
|
||||
quadS2=range(int(quadS1[-1]+1),int(quadS3[0]),1)
|
||||
STOT=sp.concatenate([triS1,quadS1,quadS2,quadS3,triS3],axis=0)
|
||||
|
||||
filler=sp.zeros(1)
|
||||
filler[0]=quadS3[0]
|
||||
fillerFirst=sp.zeros(1)
|
||||
fillerFirst[0]=quadS1[-1]
|
||||
sTotRef=sp.concatenate([triS1,quadS1,quadS2,filler],axis=0)
|
||||
newsTotRef=sp.concatenate([fillerFirst,quadS2,filler],axis=0)
|
||||
boundMat=sp.zeros([STOT.size-1,4])
|
||||
boundMatRef=sp.zeros([sTotRef.size-1,4])
|
||||
new_boundMat_ref=sp.zeros([newsTotRef.size-1,4])
|
||||
|
||||
for n in range(STOT.size-1):
|
||||
boundMat[n,:]=[1,1,STOT[n],STOT[n+1]]
|
||||
for n in range(sTotRef.size-1):
|
||||
boundMatRef[n,:]=[1,1,sTotRef[n],sTotRef[n+1]]
|
||||
for n in range(newsTotRef.size-1):
|
||||
new_boundMat_ref[n,:]=[1,1,newsTotRef[n],newsTotRef[n+1]]
|
||||
|
||||
ref=sp.concatenate([ref1,ref2],axis=0).astype(int)
|
||||
return boundMat.astype(int),ref,boundMatRef.astype(int),xAxisRootRef.astype(int),new_boundMat_ref.astype(int)
|
||||
|
||||
def vertMatCirc(numEdges):
|
||||
r_o=sp.linspace(0,r,numEdges+1)
|
||||
counter=0
|
||||
vertMat=sp.zeros([numCircNodesTot,2])
|
||||
for m in range(numEdges+1):
|
||||
theta=sp.linspace(0,sp.pi/2.0,m+1)
|
||||
for n in range(sp.size(theta)):
|
||||
vertMat[counter,:]=[r_o[m]*sp.cos(theta[n]),r_o[m]*sp.sin(theta[n])]
|
||||
counter+=1
|
||||
return vertMat
|
||||
|
||||
def vertMatQuad(numEdges):
|
||||
|
||||
theta=sp.linspace(0,sp.pi/2.0,numEdges+1)
|
||||
AX=sp.zeros([numEdges+1,numEdges+1])
|
||||
AY=sp.zeros([numEdges+1,numEdges+1])
|
||||
AX[0,:]=r*sp.cos(theta)
|
||||
AY[0,:]=r*sp.sin(theta)
|
||||
|
||||
vertLinSpace=sp.linspace(0,edgeLength,(numEdges/2)+1)
|
||||
horzLineSpace=sp.linspace(edgeLength,0,(numEdges/2)+1)
|
||||
|
||||
#Assigning node locations along the boundary
|
||||
vertCount=0
|
||||
horzCount=1
|
||||
for n in range(numEdges+1):
|
||||
if n < (numEdges/2):
|
||||
AX[-1,n]=edgeLength
|
||||
AY[-1,n]=vertLinSpace[vertCount]
|
||||
vertCount+=1
|
||||
elif n == int(numEdges/2):
|
||||
AX[-1,n]=edgeLength
|
||||
AY[-1,n]=edgeLength
|
||||
else:
|
||||
AX[-1,n]=horzLineSpace[horzCount]
|
||||
AY[-1,n]=edgeLength
|
||||
horzCount+=1
|
||||
|
||||
#Linearly spacing nodes between the inner/outer boundaries
|
||||
#One could then smooth this via r-based adaptivity
|
||||
for col in range(numEdges+1):
|
||||
for row in range(1,numEdges):
|
||||
AX[row,col]=sp.linspace(AX[0,col],AX[-1,col],numEdges+1)[row]
|
||||
AY[row,col]=sp.linspace(AY[0,col],AY[-1,col],numEdges+1)[row]
|
||||
|
||||
AX=sp.delete(AX,0,0)
|
||||
AY=sp.delete(AY,0,0)
|
||||
AX=AX.flatten()
|
||||
AY=AY.flatten()
|
||||
AX_reshape = AX.flatten()
|
||||
|
||||
numQuadNodesTot=numEdges*(numEdges+1)
|
||||
vertMat=sp.zeros([numQuadNodesTot,2])
|
||||
for n in range(numQuadNodesTot):
|
||||
vertMat[n,:]=[AX[n],AY[n]]
|
||||
return vertMat
|
||||
|
||||
def orient(A):
|
||||
aOrient=sp.zeros([A.shape[0],A.shape[1]])
|
||||
triCounter=0
|
||||
quadCounter=0
|
||||
#Determine the number of triangle and quad elments in the given element matrix
|
||||
for n in range(A.shape[0]):
|
||||
if A[n,1]==2:
|
||||
triCounter+=1
|
||||
else:
|
||||
quadCounter+=1
|
||||
edgeMatTotal=sp.zeros([3*triCounter+4*quadCounter,2])
|
||||
counter=0
|
||||
for n in range(A.shape[0]):
|
||||
detected=0
|
||||
if A[n,1]==2:
|
||||
for m in range(edgeMatTotal.shape[0]):
|
||||
if detected != 1:
|
||||
if edgeMatTotal[m,0]==A[n,2] and edgeMatTotal[m,1]==A[n,3]:
|
||||
aOrient[n,:]=[1,2,A[n,2],A[n,4],A[n,3],0]
|
||||
detected=1
|
||||
#print("reorder:[{} {} {}] to [{} {} {}]".format(A[n,2],A[n,3],A[n,4],int(aOrient[n,2]),int(aOrient[n,3]),int(aOrient[n,4])))
|
||||
elif edgeMatTotal[m,0]==A[n,4] and edgeMatTotal[m,1]==A[n,2]:
|
||||
aOrient[n,:]=[1,2,A[n,2],A[n,4],A[n,3],0]
|
||||
detected=1
|
||||
else:
|
||||
aOrient[n,:]=A[n,:]
|
||||
|
||||
edgeMatTotal[counter,:]=[aOrient[n,2],aOrient[n,3]]
|
||||
counter+=1
|
||||
edgeMatTotal[counter,:]=[aOrient[n,3],aOrient[n,4]]
|
||||
counter+=1
|
||||
edgeMatTotal[counter,:]=[aOrient[n,4],aOrient[n,2]]
|
||||
counter+=1
|
||||
else:
|
||||
for m in range(edgeMatTotal.shape[0]):
|
||||
if detected != 1:
|
||||
if edgeMatTotal[m,0]==A[n,2] and edgeMatTotal[m,1]==A[n,3]:
|
||||
aOrient[n,:]=[2,3,A[n,2],A[n,5],A[n,4],A[n,3]]
|
||||
detected=1
|
||||
#print("reorder:[{} {} {} {}] to [{} {} {} {}]".format(A[n,2],A[n,3],A[n,4],A[n,5],int(aOrient[n,2]),int(aOrient[n,3]),int(aOrient[n,4]),int(aOrient[n,5])))
|
||||
elif edgeMatTotal[m,0]==A[n,5] and edgeMatTotal[m,1]==A[n,2]:
|
||||
aOrient[n,:]=[2,3,A[n,2],A[n,5],A[n,4],A[n,3]]
|
||||
detected=1
|
||||
else:
|
||||
aOrient[n,:]=A[n,:]
|
||||
edgeMatTotal[counter,:]=[aOrient[n,2],aOrient[n,3]]
|
||||
counter+=1
|
||||
edgeMatTotal[counter,:]=[aOrient[n,3],aOrient[n,4]]
|
||||
counter+=1
|
||||
edgeMatTotal[counter,:]=[aOrient[n,4],aOrient[n,5]]
|
||||
counter+=1
|
||||
edgeMatTotal[counter,:]=[aOrient[n,5],aOrient[n,2]]
|
||||
counter+=1
|
||||
return aOrient.astype(int)
|
||||
|
||||
def gVis(_glvis,_meshFile):
|
||||
|
||||
if(_glvis==''):
|
||||
print("Failure: Set glvis location via -g switch")
|
||||
sys.exit(1)
|
||||
|
||||
colFuncFileName=_meshFile.replace('.mesh','.gf')
|
||||
glvsScriptFileName=_meshFile.replace('.mesh','.glvs')
|
||||
imageFileName=_meshFile.replace('.mesh','.png')
|
||||
|
||||
#Create Coloring Function for mesh
|
||||
_colFuncCommand=_glvis+ ' -m '+ _meshFile +' -sc -k q'
|
||||
args=_colFuncCommand.split()
|
||||
p=subprocess.Popen(args)#Create 'GLVis_coloring.gf'
|
||||
|
||||
_renameCommand='mv GLVis_coloring.gf {}'.format(colFuncFileName)
|
||||
args=_renameCommand.split()
|
||||
p=subprocess.Popen(args)
|
||||
|
||||
#Glvis script template
|
||||
f=open(glvsScriptFileName,'w')
|
||||
f.write('window 0 0 800 800\n'+'\n')
|
||||
f.write('solution {} {}\n'.format(_meshFile,colFuncFileName)+'\n')
|
||||
f.write('{\n'+'perspective off\n'+'zoom 1.5\n'+'keys gAeeRM\n'+'solution {} {} screenshot {}\n'.format(_meshFile,colFuncFileName,imageFileName)+'keys q\n'+'}\n')
|
||||
f.close()
|
||||
|
||||
_runGlvisCommand=_glvis+' -run {}'.format(glvsScriptFileName)
|
||||
args=_runGlvisCommand.split()
|
||||
p=subprocess.Popen(args)
|
||||
p.wait()
|
||||
|
||||
return 0
|
||||
def quadInterDof(_edge,_linEleMat,_linVertMatRound):
|
||||
_state=False
|
||||
for n in range(_linEleMat.shape[0]):
|
||||
if _linEleMat[n,1]==3:
|
||||
if sp.any(_edge[0]==_linEleMat[n,2:6]) and sp.any(_edge[1]==_linEleMat[n,2:6]):
|
||||
print("{} is possibly in {}".format(_edge,_linEleMat[n,2:6]))
|
||||
_n1Loc=sp.where(_edge[0]==_linEleMat[n,2:6])[0][0]
|
||||
_n2Loc=sp.where(_edge[1]==_linEleMat[n,2:6])[0][0]
|
||||
if _n1Loc==sp.mod(_n2Loc+1,4) or _n1Loc==sp.mod(_n2Loc-1,4):
|
||||
_state=True
|
||||
xcent=(_linVertMatRound[_linEleMat[n,2],0]+_linVertMatRound[_linEleMat[n,3],0]+_linVertMatRound[_linEleMat[n,4],0]+_linVertMatRound[_linEleMat[n,5],0])/4.0
|
||||
ycent=(_linVertMatRound[_linEleMat[n,2],1]+_linVertMatRound[_linEleMat[n,3],1]+_linVertMatRound[_linEleMat[n,4],1]+_linVertMatRound[_linEleMat[n,5],1])/4.0
|
||||
_interDof=sp.zeros(2)
|
||||
_interDof[0]=sp.round_((_linVertMatRound[_edge[0],0]+_linVertMatRound[_edge[1],0]+xcent)/3.0,5)
|
||||
_interDof[1]=sp.round_((_linVertMatRound[_edge[0],1]+_linVertMatRound[_edge[1],1]+ycent)/3.0,5)
|
||||
print("dof loc is {},{}".format(_interDof[0],_interDof[1]))
|
||||
return(_state,_interDof[0],_interDof[1])
|
||||
|
||||
return(_state,0,0)
|
||||
|
||||
[eleMatTriHolder,numCircNodesTot]=eleMatCirc(numEdges) #Construct tri element matrix for the region inside circular sector
|
||||
eleMatQuadHolder=eleMatQuad(numEdges) #Construct quad element matrix for region outside the circular sector
|
||||
|
||||
#Combining eleMatTriHolder and eleMatQuadHolder
|
||||
linEleMat=sp.zeros([eleMatTriHolder.shape[0]+eleMatQuadHolder.shape[0],6])
|
||||
counter=0
|
||||
for n in range(eleMatTriHolder.shape[0]):
|
||||
linEleMat[n,[0,1,2,3,4]]=eleMatTriHolder[n,:]
|
||||
counter+=1
|
||||
for n in range(eleMatQuadHolder.shape[0]):
|
||||
linEleMat[counter+n,:]=eleMatQuadHolder[n,:]
|
||||
|
||||
linEleMat=linEleMat.astype(int)
|
||||
linBoundMat=boundMatTot(numEdges)[0] #Construct the boundary
|
||||
vertMatCircHolder = vertMatCirc(numEdges) #Construct vertex matrix for triang region
|
||||
vertMatQuadHolder = vertMatQuad(numEdges) #Construct vertex matrix for the quad region
|
||||
|
||||
|
||||
#Combining the two vertex matrices in Quadrant I (q1)
|
||||
linVertMat=sp.zeros([vertMatCircHolder.shape[0]+vertMatQuadHolder.shape[0],2])
|
||||
counter=0
|
||||
for n in range(vertMatCircHolder.shape[0]):
|
||||
linVertMat[n,:]=vertMatCircHolder[n,:]
|
||||
counter+=1
|
||||
for n in range(vertMatQuadHolder.shape[0]):
|
||||
linVertMat[counter+n,:]=vertMatQuadHolder[n,:]
|
||||
|
||||
#Outputting P1/Q1 mesh to a .mesh file
|
||||
g=open(outputName+'Lin.mesh','w')
|
||||
g.write('MFEM mesh v1.0\n'+'\n')
|
||||
g.write('dimension\n'+'2\n'+'\n')
|
||||
g.write('elements\n'+'{}\n'.format(linEleMat.shape[0]))
|
||||
for n in range(linEleMat.shape[0]):
|
||||
if linEleMat[n,1]==2:
|
||||
g.write('{} {} {} {} {}\n'.format(linEleMat[n,0],linEleMat[n,1],linEleMat[n,2],linEleMat[n,3],linEleMat[n,4]))
|
||||
else:
|
||||
g.write('{} {} {} {} {} {}\n'.format(linEleMat[n,0],linEleMat[n,1],linEleMat[n,2],linEleMat[n,3],linEleMat[n,4],linEleMat[n,5]))
|
||||
g.write('\n'+'boundary\n'+'{}\n'.format(linBoundMat.shape[0]))
|
||||
for n in range(linBoundMat.shape[0]):
|
||||
g.write('{} {} {} {}\n'.format(linBoundMat[n,0],linBoundMat[n,1],linBoundMat[n,2],linBoundMat[n,3]))
|
||||
g.write('\n'+'vertices\n'+'{}\n'.format(linVertMat.shape[0])+'2\n')
|
||||
for n in range(linVertMat.shape[0]):
|
||||
g.write('{} {}\n'.format(linVertMat[n,0],linVertMat[n,1]))
|
||||
g.close()
|
||||
|
||||
if(visMesh==True):
|
||||
gVis(glvis,outputName+'Lin.mesh')
|
||||
|
||||
#Quadratic (P2/Q2) Element Generation
|
||||
|
||||
#1.)Create Edge list from previously generated linear elements
|
||||
edgeMat=sp.zeros([3*eleMatTriHolder.shape[0]+4*eleMatQuadHolder.shape[0],2])
|
||||
linEleMat=orient(linEleMat)#Make sure that element orientation is in agreement with MFEM requirements
|
||||
|
||||
counter=0
|
||||
for n in range(linEleMat.shape[0]):
|
||||
if linEleMat[n,1]==2:
|
||||
edgeMat[counter,:]=[linEleMat[n,2],linEleMat[n,3]]
|
||||
counter+=1
|
||||
edgeMat[counter,:]=[linEleMat[n,3],linEleMat[n,4]]
|
||||
counter+=1
|
||||
edgeMat[counter,:]=[linEleMat[n,4],linEleMat[n,2]]
|
||||
counter+=1
|
||||
else:
|
||||
edgeMat[counter,:]=[linEleMat[n,2],linEleMat[n,3]]
|
||||
counter+=1
|
||||
edgeMat[counter,:]=[linEleMat[n,3],linEleMat[n,4]]
|
||||
counter+=1
|
||||
edgeMat[counter,:]=[linEleMat[n,4],linEleMat[n,5]]
|
||||
counter+=1
|
||||
edgeMat[counter,:]=[linEleMat[n,5],linEleMat[n,2]]
|
||||
counter+=1
|
||||
|
||||
#Remove duplicates
|
||||
holder=[]
|
||||
for n in range(edgeMat.shape[0]):
|
||||
counter=0
|
||||
for m in range(edgeMat.shape[0]):
|
||||
if edgeMat[n,0]==edgeMat[m,0] and edgeMat[n,1]==edgeMat[m,1] and m!=n:
|
||||
holder.append([n,m])
|
||||
elif edgeMat[n,1]==edgeMat[m,0] and edgeMat[n,0]==edgeMat[m,1] and m!=n:
|
||||
holder.append([n,m])
|
||||
|
||||
removeIndices=sp.zeros(len(holder))
|
||||
for n in range(len(holder)):
|
||||
if holder[n][0]>holder[n][1]:
|
||||
removeIndices[n]=holder[n][0]
|
||||
else:
|
||||
removeIndices[n]=holder[n][1]
|
||||
removeIndices=sp.unique(removeIndices).astype(int)
|
||||
edgeMat=sp.delete(edgeMat,removeIndices,0)
|
||||
edgeMat=edgeMat.astype(int)
|
||||
|
||||
edgeDofMat=sp.zeros([edgeMat.shape[0],2])#These will be the new DoFs that appear after the Element Vertices within the .mesh file
|
||||
linVertMatRound=sp.round_(linVertMat,5)
|
||||
|
||||
counter=0
|
||||
|
||||
for n in edgeMat:
|
||||
if linVertMatRound[n[0],1] == linVertMatRound[n[1],1]:
|
||||
xmid=(linVertMatRound[n[0],0]+linVertMatRound[n[1],0])/2.0
|
||||
ymid=linVertMatRound[n[0],1]
|
||||
edgeDofMat[counter,:]=[xmid,ymid]
|
||||
elif linVertMatRound[n[0],0] == linVertMatRound[n[1],0]:
|
||||
xmid=linVertMatRound[n[0],0]
|
||||
ymid=(linVertMatRound[n[0],1]+linVertMatRound[n[1],1])/2.0
|
||||
edgeDofMat[counter,:]=[xmid,ymid]
|
||||
else:
|
||||
r0=sp.sqrt(linVertMatRound[n[0],0]**2+linVertMatRound[n[0],1]**2)
|
||||
r1=sp.sqrt(linVertMatRound[n[1],0]**2+linVertMatRound[n[1],1]**2)
|
||||
rmid = (r0+r1)/2.0 #should not be needed
|
||||
xmidOld=(linVertMatRound[n[0],0]+linVertMatRound[n[1],0])/2.0
|
||||
ymidOld=(linVertMatRound[n[0],1]+linVertMatRound[n[1],1])/2.0
|
||||
midtheta=sp.arctan(ymidOld/xmidOld)
|
||||
xmid=rmid*sp.cos(midtheta)
|
||||
ymid=rmid*sp.sin(midtheta)
|
||||
edgeDofMat[counter,:]=[xmid,ymid]
|
||||
counter+=1
|
||||
edgeDofMat = sp.round_(edgeDofMat,5)
|
||||
|
||||
#Determine midpoints of all Q1 elements:
|
||||
quadCentroidLoc=sp.zeros([eleMatQuadHolder.shape[0],2])
|
||||
for n in range(eleMatQuadHolder.shape[0]):
|
||||
quadCentroidLoc[n,0]=(linVertMatRound[eleMatQuadHolder[n,2],0]+linVertMatRound[eleMatQuadHolder[n,3],0]+linVertMatRound[eleMatQuadHolder[n,4],0]+linVertMatRound[eleMatQuadHolder[n,5],0])/4.0
|
||||
quadCentroidLoc[n,1]=(linVertMatRound[eleMatQuadHolder[n,2],1]+linVertMatRound[eleMatQuadHolder[n,3],1]+linVertMatRound[eleMatQuadHolder[n,4],1]+linVertMatRound[eleMatQuadHolder[n,5],1])/4.0
|
||||
|
||||
quadCentroidLoc = sp.round_(quadCentroidLoc,5)
|
||||
|
||||
#3.)Populate nodes section
|
||||
g=open(outputName+'Quad.mesh','w')
|
||||
g.write('MFEM mesh v1.0\n'+'\n')
|
||||
g.write('dimension\n'+'2\n'+'\n')
|
||||
g.write('elements\n'+'{}\n'.format(linEleMat.shape[0]))
|
||||
for n in range(linEleMat.shape[0]):
|
||||
if linEleMat[n,1]==2:
|
||||
g.write('{} {} {} {} {}\n'.format(linEleMat[n,0],linEleMat[n,1],linEleMat[n,2],linEleMat[n,3],linEleMat[n,4]))
|
||||
else:
|
||||
g.write('{} {} {} {} {} {}\n'.format(linEleMat[n,0],linEleMat[n,1],linEleMat[n,2],linEleMat[n,3],linEleMat[n,4],linEleMat[n,5]))
|
||||
g.write('\n'+'boundary\n'+'{}\n'.format(linBoundMat.shape[0]))
|
||||
for n in range(linBoundMat.shape[0]):
|
||||
g.write('{} {} {} {}\n'.format(linBoundMat[n,0],linBoundMat[n,1],linBoundMat[n,2],linBoundMat[n,3]))
|
||||
g.write('\n'+'vertices\n'+'{}\n'.format(linVertMat.shape[0]))
|
||||
g.write('\n'+'nodes'+'\n'+'FiniteElementSpace'+'\n'+'FiniteElementCollection: H1_2D_P2'+'\n'+'VDim: 2'+'\n'+'Ordering: 1' +'\n\n')
|
||||
for n in range(linVertMatRound.shape[0]):
|
||||
g.write('{} {}\n'.format(linVertMatRound[n,0],linVertMatRound[n,1]))
|
||||
for n in range(edgeDofMat.shape[0]):
|
||||
g.write('{} {}\n'.format(edgeDofMat[n,0],edgeDofMat[n,1]))
|
||||
for n in range(quadCentroidLoc.shape[0]):
|
||||
g.write('{} {}\n'.format(quadCentroidLoc[n,0],quadCentroidLoc[n,1]))
|
||||
g.close()
|
||||
|
||||
if(visMesh==True):
|
||||
gVis(glvis,outputName+'Quad.mesh')
|
||||
|
||||
#Cubic (P3/Q3) Element Generation
|
||||
|
||||
cubeDofMat=sp.zeros([2*edgeMat.shape[0],2])#These will be the new DoFs that appear after the Element Vertices within the .mesh file
|
||||
|
||||
counter=0
|
||||
for n in edgeMat: #Here DoF ordering matters.
|
||||
if linVertMatRound[n[0],1] == linVertMatRound[n[1],1]:
|
||||
xmid=(linVertMatRound[n[0],0]+linVertMatRound[n[1],0])/2.0
|
||||
ymid=linVertMatRound[n[0],1]
|
||||
xmid1=(linVertMatRound[n[0],0]+xmid)/2.0
|
||||
ymid1=linVertMatRound[n[0],1]
|
||||
xmid2=(linVertMatRound[n[1],0]+xmid)/2.0
|
||||
ymid2=linVertMatRound[n[0],1]
|
||||
if n[0] > n[1]:
|
||||
cubeDofMat[counter,:]=[xmid2,ymid2]
|
||||
counter+=1
|
||||
cubeDofMat[counter,:]=[xmid1,ymid1]
|
||||
counter+=1
|
||||
else:
|
||||
cubeDofMat[counter,:]=[xmid1,ymid1]
|
||||
counter+=1
|
||||
cubeDofMat[counter,:]=[xmid2,ymid2]
|
||||
counter+=1
|
||||
|
||||
elif linVertMatRound[n[0],0] == linVertMatRound[n[1],0]:
|
||||
xmid=linVertMatRound[n[0],0]
|
||||
ymid=(linVertMatRound[n[0],1]+linVertMatRound[n[1],1])/2.0
|
||||
xmid1=linVertMatRound[n[0],0]
|
||||
ymid1=(linVertMatRound[n[0],1]+ymid)/2.0
|
||||
xmid2=linVertMatRound[n[0],0]
|
||||
ymid2=(linVertMatRound[n[1],1]+ymid)/2.0
|
||||
if n[0] > n[1]:
|
||||
cubeDofMat[counter,:]=[xmid2,ymid2]
|
||||
counter+=1
|
||||
cubeDofMat[counter,:]=[xmid1,ymid1]
|
||||
counter+=1
|
||||
else:
|
||||
cubeDofMat[counter,:]=[xmid1,ymid1]
|
||||
counter+=1
|
||||
cubeDofMat[counter,:]=[xmid2,ymid2]
|
||||
counter+=1
|
||||
else:
|
||||
r0=sp.sqrt(linVertMatRound[n[0],0]**2+linVertMatRound[n[0],1]**2)
|
||||
r1=sp.sqrt(linVertMatRound[n[1],0]**2+linVertMatRound[n[1],1]**2)
|
||||
rmid = (r0+r1)/2.0 #should not be needed
|
||||
xmidOld=(linVertMatRound[n[0],0]+linVertMatRound[n[1],0])/2.0
|
||||
ymidOld=(linVertMatRound[n[0],1]+linVertMatRound[n[1],1])/2.0
|
||||
midtheta=sp.arctan(ymidOld/xmidOld)
|
||||
xmid=rmid*sp.cos(midtheta)
|
||||
ymid=rmid*sp.sin(midtheta)
|
||||
xmid1=(linVertMatRound[n[0],0]+xmid)/2.0
|
||||
ymid1=(linVertMatRound[n[0],1]+ymid)/2.0
|
||||
xmid2=(linVertMatRound[n[1],0]+xmid)/2.0
|
||||
ymid2=(linVertMatRound[n[1],1]+ymid)/2.0
|
||||
if n[0] > n[1]:
|
||||
cubeDofMat[counter,:]=[xmid2,ymid2]
|
||||
counter+=1
|
||||
cubeDofMat[counter,:]=[xmid1,ymid1]
|
||||
counter+=1
|
||||
else:
|
||||
cubeDofMat[counter,:]=[xmid1,ymid1]
|
||||
counter+=1
|
||||
cubeDofMat[counter,:]=[xmid2,ymid2]
|
||||
counter+=1
|
||||
|
||||
cubeDofMat = sp.round_(cubeDofMat,5)
|
||||
|
||||
triCentroidLoc=sp.zeros([eleMatTriHolder.shape[0],2])
|
||||
|
||||
for n in range(eleMatTriHolder.shape[0]):
|
||||
triCentroidLoc[n,0]=(linVertMatRound[eleMatTriHolder[n,2],0]+linVertMatRound[eleMatTriHolder[n,3],0]+linVertMatRound[eleMatTriHolder[n,4],0])/3.0
|
||||
triCentroidLoc[n,1]=(linVertMatRound[eleMatTriHolder[n,2],1]+linVertMatRound[eleMatTriHolder[n,3],1]+linVertMatRound[eleMatTriHolder[n,4],1])/3.0
|
||||
|
||||
quadCentroidLocCubic=sp.zeros([4*eleMatQuadHolder.shape[0],2])
|
||||
|
||||
counter=0
|
||||
for n in range(eleMatQuadHolder.shape[0]):
|
||||
xcent=quadCentroidLoc[n,0];ycent=quadCentroidLoc[n,1]
|
||||
a=eleMatQuadHolder[n,2:6]
|
||||
aMinIndex=sp.where(a[:]==a.min())[0][0]
|
||||
dof0=0.5*sp.array([xcent+linVertMatRound[a[aMinIndex],0],ycent+linVertMatRound[a[aMinIndex],1]])
|
||||
quadCentroidLocCubic[counter,:]=dof0
|
||||
counter+=1
|
||||
if aMinIndex==0:
|
||||
aLeft=-1
|
||||
aRight=1
|
||||
aLast=2
|
||||
else:
|
||||
aLeft=aMinIndex-1
|
||||
aRight=aMinIndex+1
|
||||
aLast=sp.delete(a,[aMinIndex,aLeft,aRight])[0]
|
||||
edge1=[a[aMinIndex], a[aLeft]]
|
||||
edge2=[a[aMinIndex], a[aRight]]
|
||||
edge1Index=0
|
||||
edge2Index=0
|
||||
edgeCounter=0
|
||||
for edge in edgeMat:
|
||||
if(edge[0]==edge1[0] and edge[1]==edge1[1]) or (edge[1]==edge1[0] and edge[0]==edge1[1]):
|
||||
edge1Index=edgeCounter
|
||||
if(edge[0]==edge2[0] and edge[1]==edge2[1]) or (edge[1]==edge2[0] and edge[0]==edge2[1]):
|
||||
edge2Index=edgeCounter
|
||||
edgeCounter+=1
|
||||
|
||||
if (edge1Index > edge2Index):
|
||||
dof1=0.5*sp.array([xcent+linVertMatRound[a[aLeft],0],ycent+linVertMatRound[a[aLeft],1]])
|
||||
quadCentroidLocCubic[counter,:]=dof1
|
||||
counter+=1
|
||||
dof2=0.5*sp.array([xcent+linVertMatRound[a[aRight],0],ycent+linVertMatRound[a[aRight],1]])
|
||||
quadCentroidLocCubic[counter,:]=dof2
|
||||
counter+=1
|
||||
dof3=0.5*sp.array([xcent+linVertMatRound[a[aLast],0],ycent+linVertMatRound[a[aLast],1]])
|
||||
quadCentroidLocCubic[counter,:]=dof3
|
||||
counter+=1
|
||||
else:
|
||||
dof1=0.5*sp.array([xcent+linVertMatRound[a[aRight],0],ycent+linVertMatRound[a[aRight],1]])
|
||||
quadCentroidLocCubic[counter,:]=dof1
|
||||
counter+=1
|
||||
dof2=0.5*sp.array([xcent+linVertMatRound[a[aLeft],0],ycent+linVertMatRound[a[aLeft],1]])
|
||||
quadCentroidLocCubic[counter,:]=dof2
|
||||
counter+=1
|
||||
dof3=0.5*sp.array([xcent+linVertMatRound[a[aLast],0],ycent+linVertMatRound[a[aLast],1]])
|
||||
quadCentroidLocCubic[counter,:]=dof3
|
||||
counter+=1
|
||||
|
||||
truCentroidLoc=sp.round_(triCentroidLoc,5)
|
||||
|
||||
#3.)Populate nodes section
|
||||
g=open(outputName+'Cub.mesh','w')
|
||||
g.write('MFEM mesh v1.0\n'+'\n')
|
||||
g.write('dimension\n'+'2\n'+'\n')
|
||||
g.write('elements\n'+'{}\n'.format(linEleMat.shape[0]))
|
||||
for n in range(linEleMat.shape[0]):
|
||||
if linEleMat[n,1]==2:
|
||||
g.write('{} {} {} {} {}\n'.format(linEleMat[n,0],linEleMat[n,1],linEleMat[n,2],linEleMat[n,3],linEleMat[n,4]))
|
||||
else:
|
||||
g.write('{} {} {} {} {} {}\n'.format(linEleMat[n,0],linEleMat[n,1],linEleMat[n,2],linEleMat[n,3],linEleMat[n,4],linEleMat[n,5]))
|
||||
g.write('\n'+'boundary\n'+'{}\n'.format(linBoundMat.shape[0]))
|
||||
for n in range(linBoundMat.shape[0]):
|
||||
g.write('{} {} {} {}\n'.format(linBoundMat[n,0],linBoundMat[n,1],linBoundMat[n,2],linBoundMat[n,3]))
|
||||
g.write('\n'+'vertices\n'+'{}\n'.format(linVertMat.shape[0]))
|
||||
g.write('\n'+'nodes'+'\n'+'FiniteElementSpace'+'\n'+'FiniteElementCollection: H1_2D_P3'+'\n'+'VDim: 2'+'\n'+'Ordering: 1' +'\n\n')
|
||||
for n in range(linVertMatRound.shape[0]):
|
||||
g.write('{} {}\n'.format(linVertMatRound[n,0],linVertMatRound[n,1]))
|
||||
for n in range(cubeDofMat.shape[0]):
|
||||
g.write('{} {}\n'.format(cubeDofMat[n,0],cubeDofMat[n,1]))
|
||||
for n in range(triCentroidLoc.shape[0]):
|
||||
g.write('{} {}\n'.format(triCentroidLoc[n,0],triCentroidLoc[n,1]))
|
||||
for n in range(quadCentroidLocCubic.shape[0]):
|
||||
g.write('{} {}\n'.format(quadCentroidLocCubic[n,0],quadCentroidLocCubic[n,1]))
|
||||
g.close()
|
||||
|
||||
if(visMesh==True):
|
||||
gVis(glvis,outputName+'Cub.mesh')
|
||||
#raw_input()
|
||||
#'Reflecting' topology about one of its edges and append it to itself
|
||||
upperPlaneEleMat = sp.zeros([2*linEleMat.shape[0],6])
|
||||
for n in range(linEleMat.shape[0]):
|
||||
upperPlaneEleMat[n,:]=linEleMat[n,:]
|
||||
|
||||
#Create ele_mat_holder.shape[0]x2 matrix for mapping
|
||||
refEdge=boundMatTot(numEdges)[1]
|
||||
q1NumNodes=linVertMat.shape[0]
|
||||
|
||||
mapping = sp.zeros([q1NumNodes])
|
||||
counter=0
|
||||
for n in range(q1NumNodes):
|
||||
if (sp.any(refEdge == n)):
|
||||
mapping[n]=n
|
||||
else:
|
||||
mapping[n]=counter+q1NumNodes
|
||||
counter+=1
|
||||
|
||||
mapping=mapping.astype(int)
|
||||
#Implement mapping
|
||||
|
||||
counter=0
|
||||
for n in range(linEleMat.shape[0],2*linEleMat.shape[0]):
|
||||
upperPlaneEleMat[n,0]=linEleMat[counter,0]
|
||||
upperPlaneEleMat[n,1]=linEleMat[counter,1]
|
||||
upperPlaneEleMat[n,2]=mapping[linEleMat[counter,2]]
|
||||
upperPlaneEleMat[n,3]=mapping[linEleMat[counter,3]]
|
||||
upperPlaneEleMat[n,4]=mapping[linEleMat[counter,4]]
|
||||
upperPlaneEleMat[n,5]=mapping[linEleMat[counter,5]]
|
||||
counter+=1
|
||||
|
||||
upperPlaneEleMat = upperPlaneEleMat.astype(int)
|
||||
|
||||
#Reflecting boundary matrix
|
||||
origBound=boundMatTot(numEdges)[2]
|
||||
upperPlaneBoundMat=sp.zeros([2*origBound.shape[0],4])
|
||||
for n in range(origBound.shape[0]):
|
||||
upperPlaneBoundMat[n,:]=origBound[n,:]
|
||||
counter=0
|
||||
newOrigBound=origBound.copy()
|
||||
newOrigBound[:,2]=sp.flipud(origBound[:,3])
|
||||
newOrigBound[:,3]=sp.flipud(origBound[:,2])
|
||||
for n in range(newOrigBound.shape[0],upperPlaneBoundMat.shape[0]):
|
||||
upperPlaneBoundMat[n,0]=newOrigBound[counter,0]
|
||||
upperPlaneBoundMat[n,1]=newOrigBound[counter,1]
|
||||
upperPlaneBoundMat[n,2]=mapping[newOrigBound[counter,2]]
|
||||
upperPlaneBoundMat[n,3]=mapping[newOrigBound[counter,3]]
|
||||
counter+=1
|
||||
upperPlaneBoundMat=upperPlaneBoundMat.astype(int)
|
||||
|
||||
#Reflecting vertex matrix about the y-axis and appending it to itself
|
||||
upperPlaneNumNodes=q1NumNodes+(q1NumNodes-refEdge.shape[0])
|
||||
upperPlaneVertMat = sp.zeros([upperPlaneNumNodes,2])
|
||||
for n in range(linVertMat.shape[0]):
|
||||
upperPlaneVertMat[n,:]=linVertMat[n,:]
|
||||
counter=0
|
||||
for n in range(linVertMat.shape[0],upperPlaneNumNodes):
|
||||
upperPlaneVertMat[n,0]=-1.0*linVertMat[sp.where(mapping==n)[0][0],0]
|
||||
upperPlaneVertMat[n,1]=linVertMat[sp.where(mapping==n)[0][0],1]
|
||||
counter+=1
|
||||
|
||||
upperPlaneEleMat=orient(upperPlaneEleMat)
|
||||
g=open(outputName+'UpperPlaneLin.mesh','w')
|
||||
g.write('MFEM mesh v1.0\n'+'\n')
|
||||
g.write('dimension\n'+'2\n'+'\n')
|
||||
g.write('elements\n'+'{}\n'.format(upperPlaneEleMat.shape[0]))
|
||||
for n in range(upperPlaneEleMat.shape[0]):
|
||||
if upperPlaneEleMat[n,1]==2:
|
||||
g.write('{} {} {} {} {}\n'.format(upperPlaneEleMat[n,0],upperPlaneEleMat[n,1],upperPlaneEleMat[n,2],upperPlaneEleMat[n,3],upperPlaneEleMat[n,4]))
|
||||
else:
|
||||
g.write('{} {} {} {} {} {}\n'.format(upperPlaneEleMat[n,0],upperPlaneEleMat[n,1],upperPlaneEleMat[n,2],upperPlaneEleMat[n,3],upperPlaneEleMat[n,4],upperPlaneEleMat[n,5]))
|
||||
g.write('\n'+'boundary\n'+'{}\n'.format(upperPlaneBoundMat.shape[0]))
|
||||
for n in range(upperPlaneBoundMat.shape[0]):
|
||||
g.write('{} {} {} {}\n'.format(upperPlaneBoundMat[n,0],upperPlaneBoundMat[n,1],upperPlaneBoundMat[n,2],upperPlaneBoundMat[n,3]))
|
||||
g.write('\n'+'vertices\n'+'{}\n'.format(upperPlaneVertMat.shape[0])+'2\n')
|
||||
for n in range(upperPlaneVertMat.shape[0]):
|
||||
g.write('{} {}\n'.format(upperPlaneVertMat[n,0],upperPlaneVertMat[n,1]))
|
||||
g.close()
|
||||
|
||||
if(visMesh==True):
|
||||
gVis(glvis,outputName+'UpperPlaneLin.mesh')
|
||||
|
||||
#'Reflecting' topology about one of its edges and append it to itself
|
||||
wholePlaneEleMat = sp.zeros([2*upperPlaneEleMat.shape[0],6])
|
||||
for n in range(upperPlaneEleMat.shape[0]):
|
||||
wholePlaneEleMat[n,:]=upperPlaneEleMat[n,:]
|
||||
|
||||
quad1Edge=boundMatTot(numEdges)[3]
|
||||
newRefEdge=sp.zeros(2*quad1Edge.shape[0]-1)
|
||||
for n in range(quad1Edge.shape[0]):
|
||||
newRefEdge[n]=quad1Edge[n]
|
||||
counter=0
|
||||
for n in range(quad1Edge.shape[0],newRefEdge.shape[0]):
|
||||
newRefEdge[n]=mapping[quad1Edge[counter]]
|
||||
counter+=1
|
||||
newRefEdge=sp.unique(newRefEdge)
|
||||
newRefEdge=newRefEdge.astype(int)
|
||||
newTotNumNodes=upperPlaneVertMat.shape[0]
|
||||
|
||||
newMapping=sp.zeros([newTotNumNodes])
|
||||
counter=0
|
||||
for n in range(newTotNumNodes):
|
||||
if (sp.any(newRefEdge == n)):
|
||||
newMapping[n]=n
|
||||
else:
|
||||
newMapping[n]=counter+newTotNumNodes
|
||||
counter+=1
|
||||
newMapping=newMapping.astype(int)
|
||||
|
||||
counter=0
|
||||
for n in range(upperPlaneEleMat.shape[0],2*upperPlaneEleMat.shape[0]):
|
||||
wholePlaneEleMat[n,0]=upperPlaneEleMat[counter,0]
|
||||
wholePlaneEleMat[n,1]=upperPlaneEleMat[counter,1]
|
||||
wholePlaneEleMat[n,2]=newMapping[upperPlaneEleMat[counter,2]]
|
||||
wholePlaneEleMat[n,3]=newMapping[upperPlaneEleMat[counter,3]]
|
||||
wholePlaneEleMat[n,4]=newMapping[upperPlaneEleMat[counter,4]]
|
||||
wholePlaneEleMat[n,5]=newMapping[upperPlaneEleMat[counter,5]]
|
||||
counter+=1
|
||||
|
||||
wholePlaneEleMat=wholePlaneEleMat.astype(int)
|
||||
|
||||
#Reflecting boundary matrix
|
||||
newOrigBoundQuad1=boundMatTot(numEdges)[4]
|
||||
newFirstBoundMatHolder=sp.zeros([2*newOrigBoundQuad1.shape[0],4])
|
||||
for n in range(newOrigBoundQuad1.shape[0]):
|
||||
newFirstBoundMatHolder[n,:]=newOrigBoundQuad1[n,:]
|
||||
|
||||
newNewOrigBoundQuad1=newOrigBoundQuad1.copy()
|
||||
newNewOrigBoundQuad1[:,2]=sp.flipud(newOrigBoundQuad1[:,3])
|
||||
newNewOrigBoundQuad1[:,3]=sp.flipud(newOrigBoundQuad1[:,2])
|
||||
counter=0
|
||||
for n in range(newOrigBoundQuad1.shape[0],newFirstBoundMatHolder.shape[0]):
|
||||
newFirstBoundMatHolder[n,0]=newNewOrigBoundQuad1[counter,0]
|
||||
newFirstBoundMatHolder[n,1]=newNewOrigBoundQuad1[counter,1]
|
||||
newFirstBoundMatHolder[n,2]=mapping[newNewOrigBoundQuad1[counter,2]]
|
||||
newFirstBoundMatHolder[n,3]=mapping[newNewOrigBoundQuad1[counter,3]]
|
||||
counter+=1
|
||||
|
||||
upperQuadMat=newFirstBoundMatHolder.copy()
|
||||
wholePlaneBoundMat=sp.zeros([2*upperQuadMat.shape[0],4])
|
||||
for n in range(upperQuadMat.shape[0]):
|
||||
wholePlaneBoundMat[n,:]=upperQuadMat[n,:]
|
||||
|
||||
counter=0
|
||||
newNewOrigBound=upperQuadMat.copy()
|
||||
newNewOrigBound[:,2]=sp.flipud(upperQuadMat[:,3])
|
||||
newNewOrigBound[:,3]=sp.flipud(upperQuadMat[:,2])
|
||||
newNewOrigBound=newNewOrigBound.astype(int)
|
||||
for n in range(newNewOrigBound.shape[0],wholePlaneBoundMat.shape[0]):
|
||||
wholePlaneBoundMat[n,0]=newNewOrigBound[counter,0]
|
||||
wholePlaneBoundMat[n,1]=newNewOrigBound[counter,1]
|
||||
wholePlaneBoundMat[n,2]=newMapping[newNewOrigBound[counter,2]]
|
||||
wholePlaneBoundMat[n,3]=newMapping[newNewOrigBound[counter,3]]
|
||||
counter+=1
|
||||
wholePlaneBoundMat=wholePlaneBoundMat.astype(int)
|
||||
|
||||
wholePlaneNumNodes=newTotNumNodes+(newTotNumNodes-newRefEdge.shape[0])
|
||||
wholePlaneVertMat = sp.zeros([wholePlaneNumNodes,2])
|
||||
for n in range(upperPlaneVertMat.shape[0]):
|
||||
wholePlaneVertMat[n,:]=upperPlaneVertMat[n,:]
|
||||
counter=0
|
||||
for n in range(upperPlaneVertMat.shape[0],wholePlaneNumNodes):
|
||||
wholePlaneVertMat[n,0]=upperPlaneVertMat[sp.where(newMapping==n)[0][0],0]
|
||||
wholePlaneVertMat[n,1]=-1.0*upperPlaneVertMat[sp.where(newMapping==n)[0][0],1]
|
||||
counter+=1
|
||||
|
||||
g=open(outputName+'WholePlaneLin.mesh','w')
|
||||
g.write('MFEM mesh v1.0\n'+'\n')
|
||||
g.write('dimension\n'+'2\n'+'\n')
|
||||
g.write('elements\n'+'{}\n'.format(wholePlaneEleMat.shape[0]))
|
||||
for n in range(wholePlaneEleMat.shape[0]):
|
||||
if wholePlaneEleMat[n,1]==2:
|
||||
g.write('{} {} {} {} {}\n'.format(wholePlaneEleMat[n,0],wholePlaneEleMat[n,1],wholePlaneEleMat[n,2],wholePlaneEleMat[n,3],wholePlaneEleMat[n,4]))
|
||||
else:
|
||||
g.write('{} {} {} {} {} {}\n'.format(wholePlaneEleMat[n,0],wholePlaneEleMat[n,1],wholePlaneEleMat[n,2],wholePlaneEleMat[n,3],wholePlaneEleMat[n,4],wholePlaneEleMat[n,5]))
|
||||
g.write('\n'+'boundary\n'+'{}\n'.format(wholePlaneBoundMat.shape[0]))
|
||||
for n in range(wholePlaneBoundMat.shape[0]):
|
||||
g.write('{} {} {} {}\n'.format(wholePlaneBoundMat[n,0],wholePlaneBoundMat[n,1],wholePlaneBoundMat[n,2],wholePlaneBoundMat[n,3]))
|
||||
g.write('\n'+'vertices\n'+'{}\n'.format(wholePlaneVertMat.shape[0])+'2\n')
|
||||
for n in range(wholePlaneVertMat.shape[0]):
|
||||
g.write('{} {}\n'.format(wholePlaneVertMat[n,0],wholePlaneVertMat[n,1]))
|
||||
g.close()
|
||||
|
||||
if(visMesh==True):
|
||||
gVis(glvis,outputName+'WholePlaneLin.mesh')
|
||||
|
||||
#1.)Create Edge list from elements
|
||||
wholePlaneEleMat=orient(wholePlaneEleMat)
|
||||
triCounter=0;quadCounter=0;
|
||||
for n in range(wholePlaneEleMat.shape[0]):
|
||||
if wholePlaneEleMat[n,1]==2:
|
||||
triCounter+=1
|
||||
else:
|
||||
quadCounter+=1
|
||||
edgeMat=sp.zeros([3*triCounter+4*quadCounter,2])
|
||||
counter=0
|
||||
for n in range(wholePlaneEleMat.shape[0]):
|
||||
if wholePlaneEleMat[n,1]==2:
|
||||
edgeMat[counter,:]=[wholePlaneEleMat[n,2],wholePlaneEleMat[n,3]]
|
||||
counter+=1
|
||||
edgeMat[counter,:]=[wholePlaneEleMat[n,3],wholePlaneEleMat[n,4]]
|
||||
counter+=1
|
||||
edgeMat[counter,:]=[wholePlaneEleMat[n,4],wholePlaneEleMat[n,2]]
|
||||
counter+=1
|
||||
else:
|
||||
edgeMat[counter,:]=[wholePlaneEleMat[n,2],wholePlaneEleMat[n,3]]
|
||||
counter+=1
|
||||
edgeMat[counter,:]=[wholePlaneEleMat[n,3],wholePlaneEleMat[n,4]]
|
||||
counter+=1
|
||||
edgeMat[counter,:]=[wholePlaneEleMat[n,4],wholePlaneEleMat[n,5]]
|
||||
counter+=1
|
||||
edgeMat[counter,:]=[wholePlaneEleMat[n,5],wholePlaneEleMat[n,2]]
|
||||
counter+=1
|
||||
|
||||
#Remove duplicates
|
||||
holder=[]
|
||||
for n in range(edgeMat.shape[0]):
|
||||
counter=0
|
||||
for m in range(edgeMat.shape[0]):
|
||||
if edgeMat[n,0]==edgeMat[m,0] and edgeMat[n,1]==edgeMat[m,1] and m!=n:
|
||||
holder.append([n,m])
|
||||
elif edgeMat[n,1]==edgeMat[m,0] and edgeMat[n,0]==edgeMat[m,1] and m!=n:
|
||||
holder.append([n,m])
|
||||
removeIndices=sp.zeros(len(holder))
|
||||
for n in range(len(holder)):
|
||||
if holder[n][0]>holder[n][1]:
|
||||
removeIndices[n]=holder[n][0]
|
||||
else:
|
||||
removeIndices[n]=holder[n][1]
|
||||
removeIndices=sp.unique(removeIndices).astype(int)
|
||||
edgeMat=sp.delete(edgeMat,removeIndices,0)
|
||||
edgeMat=edgeMat.astype(int)
|
||||
|
||||
edgeDofMat=sp.zeros([edgeMat.shape[0],2])
|
||||
|
||||
wholePlaneVertMatRound=sp.round_(wholePlaneVertMat,5)
|
||||
|
||||
counter=0
|
||||
for n in edgeMat:
|
||||
if wholePlaneVertMatRound[n[0],1] == wholePlaneVertMatRound[n[1],1]:
|
||||
xmid=(wholePlaneVertMatRound[n[0],0]+wholePlaneVertMatRound[n[1],0])/2.0
|
||||
ymid=wholePlaneVertMatRound[n[0],1]
|
||||
edgeDofMat[counter,:]=[xmid,ymid]
|
||||
elif wholePlaneVertMatRound[n[0],0] == wholePlaneVertMatRound[n[1],0]:
|
||||
xmid=wholePlaneVertMatRound[n[0],0]
|
||||
ymid=(wholePlaneVertMatRound[n[0],1]+wholePlaneVertMatRound[n[1],1])/2.0
|
||||
edgeDofMat[counter,:]=[xmid,ymid]
|
||||
else:
|
||||
r0=sp.sqrt(wholePlaneVertMatRound[n[0],0]**2+wholePlaneVertMatRound[n[0],1]**2)
|
||||
r1=sp.sqrt(wholePlaneVertMatRound[n[1],0]**2+wholePlaneVertMatRound[n[1],1]**2)
|
||||
rmid = (r0+r1)/2.0 #should not be needed
|
||||
xmidOld=(wholePlaneVertMatRound[n[0],0]+wholePlaneVertMatRound[n[1],0])/2.0
|
||||
ymidOld=(wholePlaneVertMatRound[n[0],1]+wholePlaneVertMatRound[n[1],1])/2.0
|
||||
midtheta=sp.arctan2(ymidOld,xmidOld)
|
||||
xmid=rmid*sp.cos(midtheta)
|
||||
ymid=rmid*sp.sin(midtheta)
|
||||
edgeDofMat[counter,:]=[xmid,ymid]
|
||||
counter+=1
|
||||
edgeDofMat = sp.round_(edgeDofMat,5)
|
||||
|
||||
#2.)Create correct dof locations
|
||||
#Determine midpoints of all quads:
|
||||
quadCentroidLoc=sp.zeros([quadCounter,2])
|
||||
counter=0
|
||||
for n in range(wholePlaneEleMat.shape[0]):
|
||||
if wholePlaneEleMat[n,1]==3:
|
||||
quadCentroidLoc[counter,0]=(wholePlaneVertMatRound[wholePlaneEleMat[n,2],0]+wholePlaneVertMatRound[wholePlaneEleMat[n,3],0]+wholePlaneVertMatRound[wholePlaneEleMat[n,4],0]+wholePlaneVertMatRound[wholePlaneEleMat[n,5],0])/4.0
|
||||
quadCentroidLoc[counter,1]=(wholePlaneVertMatRound[wholePlaneEleMat[n,2],1]+wholePlaneVertMatRound[wholePlaneEleMat[n,3],1]+wholePlaneVertMatRound[wholePlaneEleMat[n,4],1]+wholePlaneVertMatRound[wholePlaneEleMat[n,5],1])/4.0
|
||||
counter+=1
|
||||
|
||||
quadCentroidLoc = sp.round_(quadCentroidLoc,5)
|
||||
|
||||
#3.)Populate nodes section
|
||||
g=open(outputName+'WholePlaneQuad.mesh','w')
|
||||
g.write('MFEM mesh v1.0\n'+'\n')
|
||||
g.write('dimension\n'+'2\n'+'\n')
|
||||
g.write('elements\n'+'{}\n'.format(wholePlaneEleMat.shape[0]))
|
||||
for n in range(wholePlaneEleMat.shape[0]):
|
||||
if wholePlaneEleMat[n,1]==2:
|
||||
g.write('{} {} {} {} {}\n'.format(wholePlaneEleMat[n,0],wholePlaneEleMat[n,1],wholePlaneEleMat[n,2],wholePlaneEleMat[n,3],wholePlaneEleMat[n,4]))
|
||||
else:
|
||||
g.write('{} {} {} {} {} {}\n'.format(wholePlaneEleMat[n,0],wholePlaneEleMat[n,1],wholePlaneEleMat[n,2],wholePlaneEleMat[n,3],wholePlaneEleMat[n,4],wholePlaneEleMat[n,5]))
|
||||
g.write('\n'+'boundary\n'+'{}\n'.format(wholePlaneBoundMat.shape[0]))
|
||||
for n in range(wholePlaneBoundMat.shape[0]):
|
||||
g.write('{} {} {} {}\n'.format(wholePlaneBoundMat[n,0],wholePlaneBoundMat[n,1],wholePlaneBoundMat[n,2],wholePlaneBoundMat[n,3]))
|
||||
g.write('\n'+'vertices\n'+'{}\n'.format(wholePlaneVertMat.shape[0]))
|
||||
g.write('\n'+'nodes'+'\n'+'FiniteElementSpace'+'\n'+'FiniteElementCollection: H1_2D_P2'+'\n'+'VDim: 2'+'\n'+'Ordering: 1' +'\n\n')
|
||||
for n in range(wholePlaneVertMatRound.shape[0]):
|
||||
g.write('{} {}\n'.format(wholePlaneVertMatRound[n,0],wholePlaneVertMatRound[n,1]))
|
||||
for n in range(edgeDofMat.shape[0]):
|
||||
g.write('{} {}\n'.format(edgeDofMat[n,0],edgeDofMat[n,1]))
|
||||
for n in range(quadCentroidLoc.shape[0]):
|
||||
g.write('{} {}\n'.format(quadCentroidLoc[n,0],quadCentroidLoc[n,1]))
|
||||
g.close()
|
||||
|
||||
if(visMesh==True):
|
||||
gVis(glvis,outputName+'WholePlaneQuad.mesh')
|
||||
@@ -1,264 +0,0 @@
|
||||
MFEM mesh v1.0
|
||||
|
||||
dimension
|
||||
2
|
||||
|
||||
elements
|
||||
128
|
||||
1 2 0 1 2
|
||||
1 2 1 2 4
|
||||
1 2 1 3 4
|
||||
1 2 2 4 5
|
||||
1 2 3 4 7
|
||||
1 2 3 6 7
|
||||
1 2 4 5 8
|
||||
1 2 4 7 8
|
||||
1 2 5 8 9
|
||||
1 2 6 7 11
|
||||
1 2 6 10 11
|
||||
1 2 7 8 12
|
||||
1 2 7 11 12
|
||||
1 2 8 9 13
|
||||
1 2 8 12 13
|
||||
1 2 9 13 14
|
||||
2 3 10 15 16 11
|
||||
2 3 11 16 17 12
|
||||
2 3 12 17 18 13
|
||||
2 3 13 18 19 14
|
||||
2 3 15 20 21 16
|
||||
2 3 16 21 22 17
|
||||
2 3 17 22 23 18
|
||||
2 3 18 23 24 19
|
||||
2 3 20 25 26 21
|
||||
2 3 21 26 27 22
|
||||
2 3 22 27 28 23
|
||||
2 3 23 28 29 24
|
||||
2 3 25 30 31 26
|
||||
2 3 26 31 32 27
|
||||
2 3 27 32 33 28
|
||||
2 3 28 33 34 29
|
||||
1 2 0 35 2
|
||||
1 2 35 2 37
|
||||
1 2 35 36 37
|
||||
1 2 2 37 5
|
||||
1 2 36 37 39
|
||||
1 2 36 38 39
|
||||
1 2 37 5 40
|
||||
1 2 37 39 40
|
||||
1 2 5 40 9
|
||||
1 2 38 39 42
|
||||
1 2 38 41 42
|
||||
1 2 39 40 43
|
||||
1 2 39 42 43
|
||||
1 2 40 9 44
|
||||
1 2 40 43 44
|
||||
1 2 9 44 14
|
||||
2 3 41 45 46 42
|
||||
2 3 42 46 47 43
|
||||
2 3 43 47 48 44
|
||||
2 3 44 48 19 14
|
||||
2 3 45 49 50 46
|
||||
2 3 46 50 51 47
|
||||
2 3 47 51 52 48
|
||||
2 3 48 52 24 19
|
||||
2 3 49 53 54 50
|
||||
2 3 50 54 55 51
|
||||
2 3 51 55 56 52
|
||||
2 3 52 56 29 24
|
||||
2 3 53 57 58 54
|
||||
2 3 54 58 59 55
|
||||
2 3 55 59 60 56
|
||||
2 3 56 60 34 29
|
||||
1 2 0 1 61
|
||||
1 2 1 61 62
|
||||
1 2 1 3 62
|
||||
1 2 61 62 63
|
||||
1 2 3 62 64
|
||||
1 2 3 6 64
|
||||
1 2 62 63 65
|
||||
1 2 62 64 65
|
||||
1 2 63 65 66
|
||||
1 2 6 64 67
|
||||
1 2 6 10 67
|
||||
1 2 64 65 68
|
||||
1 2 64 67 68
|
||||
1 2 65 66 69
|
||||
1 2 65 68 69
|
||||
1 2 66 69 70
|
||||
2 3 10 15 71 67
|
||||
2 3 67 71 72 68
|
||||
2 3 68 72 73 69
|
||||
2 3 69 73 74 70
|
||||
2 3 15 20 75 71
|
||||
2 3 71 75 76 72
|
||||
2 3 72 76 77 73
|
||||
2 3 73 77 78 74
|
||||
2 3 20 25 79 75
|
||||
2 3 75 79 80 76
|
||||
2 3 76 80 81 77
|
||||
2 3 77 81 82 78
|
||||
2 3 25 30 83 79
|
||||
2 3 79 83 84 80
|
||||
2 3 80 84 85 81
|
||||
2 3 81 85 86 82
|
||||
1 2 0 35 61
|
||||
1 2 35 61 87
|
||||
1 2 35 36 87
|
||||
1 2 61 87 63
|
||||
1 2 36 87 88
|
||||
1 2 36 38 88
|
||||
1 2 87 63 89
|
||||
1 2 87 88 89
|
||||
1 2 63 89 66
|
||||
1 2 38 88 90
|
||||
1 2 38 41 90
|
||||
1 2 88 89 91
|
||||
1 2 88 90 91
|
||||
1 2 89 66 92
|
||||
1 2 89 91 92
|
||||
1 2 66 92 70
|
||||
2 3 41 45 93 90
|
||||
2 3 90 93 94 91
|
||||
2 3 91 94 95 92
|
||||
2 3 92 95 74 70
|
||||
2 3 45 49 96 93
|
||||
2 3 93 96 97 94
|
||||
2 3 94 97 98 95
|
||||
2 3 95 98 78 74
|
||||
2 3 49 53 99 96
|
||||
2 3 96 99 100 97
|
||||
2 3 97 100 101 98
|
||||
2 3 98 101 82 78
|
||||
2 3 53 102 103 99
|
||||
2 3 99 103 104 100
|
||||
2 3 100 104 105 101
|
||||
2 3 101 105 86 82
|
||||
|
||||
boundary
|
||||
16
|
||||
1 1 30 31
|
||||
1 1 31 32
|
||||
1 1 32 33
|
||||
1 1 33 34
|
||||
1 1 34 60
|
||||
1 1 60 59
|
||||
1 1 59 58
|
||||
1 1 58 57
|
||||
1 1 102 103
|
||||
1 1 103 104
|
||||
1 1 104 105
|
||||
1 1 105 86
|
||||
1 1 86 85
|
||||
1 1 85 84
|
||||
1 1 84 83
|
||||
1 1 83 30
|
||||
|
||||
vertices
|
||||
106
|
||||
2
|
||||
0.0 0.0
|
||||
0.125 0.0
|
||||
7.65404249467e-18 0.125
|
||||
0.25 0.0
|
||||
0.176776695297 0.176776695297
|
||||
1.53080849893e-17 0.25
|
||||
0.375 0.0
|
||||
0.324759526419 0.1875
|
||||
0.1875 0.324759526419
|
||||
2.2962127484e-17 0.375
|
||||
0.5 0.0
|
||||
0.461939766256 0.191341716183
|
||||
0.353553390593 0.353553390593
|
||||
0.191341716183 0.461939766256
|
||||
3.06161699787e-17 0.5
|
||||
0.625 0.0
|
||||
0.596454824692 0.268506287137
|
||||
0.515165042945 0.515165042945
|
||||
0.268506287137 0.596454824692
|
||||
2.2962127484e-17 0.625
|
||||
0.75 0.0
|
||||
0.730969883128 0.345670858091
|
||||
0.676776695297 0.676776695297
|
||||
0.345670858091 0.730969883128
|
||||
1.53080849893e-17 0.75
|
||||
0.875 0.0
|
||||
0.865484941564 0.422835429046
|
||||
0.838388347648 0.838388347648
|
||||
0.422835429046 0.865484941564
|
||||
7.65404249467e-18 0.875
|
||||
1.0 0.0
|
||||
1.0 0.5
|
||||
1.0 1.0
|
||||
0.5 1.0
|
||||
0.0 1.0
|
||||
-0.125 0.0
|
||||
-0.25 0.0
|
||||
-0.176776695297 0.176776695297
|
||||
-0.375 0.0
|
||||
-0.324759526419 0.1875
|
||||
-0.1875 0.324759526419
|
||||
-0.5 0.0
|
||||
-0.461939766256 0.191341716183
|
||||
-0.353553390593 0.353553390593
|
||||
-0.191341716183 0.461939766256
|
||||
-0.625 0.0
|
||||
-0.596454824692 0.268506287137
|
||||
-0.515165042945 0.515165042945
|
||||
-0.268506287137 0.596454824692
|
||||
-0.75 0.0
|
||||
-0.730969883128 0.345670858091
|
||||
-0.676776695297 0.676776695297
|
||||
-0.345670858091 0.730969883128
|
||||
-0.875 0.0
|
||||
-0.865484941564 0.422835429046
|
||||
-0.838388347648 0.838388347648
|
||||
-0.422835429046 0.865484941564
|
||||
-1.0 0.0
|
||||
-1.0 0.5
|
||||
-1.0 1.0
|
||||
-0.5 1.0
|
||||
7.65404249467e-18 -0.125
|
||||
0.176776695297 -0.176776695297
|
||||
1.53080849893e-17 -0.25
|
||||
0.324759526419 -0.1875
|
||||
0.1875 -0.324759526419
|
||||
2.2962127484e-17 -0.375
|
||||
0.461939766256 -0.191341716183
|
||||
0.353553390593 -0.353553390593
|
||||
0.191341716183 -0.461939766256
|
||||
3.06161699787e-17 -0.5
|
||||
0.596454824692 -0.268506287137
|
||||
0.515165042945 -0.515165042945
|
||||
0.268506287137 -0.596454824692
|
||||
2.2962127484e-17 -0.625
|
||||
0.730969883128 -0.345670858091
|
||||
0.676776695297 -0.676776695297
|
||||
0.345670858091 -0.730969883128
|
||||
1.53080849893e-17 -0.75
|
||||
0.865484941564 -0.422835429046
|
||||
0.838388347648 -0.838388347648
|
||||
0.422835429046 -0.865484941564
|
||||
7.65404249467e-18 -0.875
|
||||
1.0 -0.5
|
||||
1.0 -1.0
|
||||
0.5 -1.0
|
||||
0.0 -1.0
|
||||
-0.176776695297 -0.176776695297
|
||||
-0.324759526419 -0.1875
|
||||
-0.1875 -0.324759526419
|
||||
-0.461939766256 -0.191341716183
|
||||
-0.353553390593 -0.353553390593
|
||||
-0.191341716183 -0.461939766256
|
||||
-0.596454824692 -0.268506287137
|
||||
-0.515165042945 -0.515165042945
|
||||
-0.268506287137 -0.596454824692
|
||||
-0.730969883128 -0.345670858091
|
||||
-0.676776695297 -0.676776695297
|
||||
-0.345670858091 -0.730969883128
|
||||
-0.865484941564 -0.422835429046
|
||||
-0.838388347648 -0.838388347648
|
||||
-0.422835429046 -0.865484941564
|
||||
-1.0 -0.0
|
||||
-1.0 -0.5
|
||||
-1.0 -1.0
|
||||
-0.5 -1.0
|
||||
@@ -1,72 +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
|
||||
#
|
||||
|
||||
dimension
|
||||
2
|
||||
|
||||
elements
|
||||
17
|
||||
1 2 0 1 2
|
||||
1 2 0 2 3
|
||||
1 2 0 3 4
|
||||
2 3 0 4 5 6
|
||||
2 3 0 6 7 1
|
||||
1 2 7 8 1
|
||||
1 2 1 8 9
|
||||
2 3 1 9 10 2
|
||||
1 2 2 10 11
|
||||
2 3 2 11 12 3
|
||||
1 2 3 12 13
|
||||
2 3 3 13 14 4
|
||||
1 2 4 14 15
|
||||
1 2 4 15 5
|
||||
1 2 5 16 6
|
||||
1 2 6 16 17
|
||||
1 2 6 17 7
|
||||
|
||||
boundary
|
||||
12
|
||||
1 1 7 8
|
||||
1 1 8 9
|
||||
1 1 9 10
|
||||
1 1 10 11
|
||||
1 1 11 12
|
||||
1 1 12 13
|
||||
1 1 13 14
|
||||
1 1 14 15
|
||||
1 1 15 5
|
||||
1 1 5 16
|
||||
1 1 16 17
|
||||
1 1 17 7
|
||||
|
||||
vertices
|
||||
18
|
||||
2
|
||||
0 0
|
||||
1 0
|
||||
0.5 0.866025
|
||||
-0.5 0.866025
|
||||
-1 0
|
||||
-1 -1
|
||||
0 -1
|
||||
1 -1
|
||||
1.866025 -0.5
|
||||
1.866025 0.5
|
||||
1.366025 1.366025
|
||||
0.5 1.866025
|
||||
-0.5 1.866025
|
||||
-1.366025 1.366025
|
||||
-1.866025 0.5
|
||||
-1.866025 -0.5
|
||||
-0.5 -1.866025
|
||||
0.5 -1.866025
|
||||
@@ -1,362 +0,0 @@
|
||||
MFEM mesh v1.0
|
||||
|
||||
dimension
|
||||
2
|
||||
|
||||
elements
|
||||
154
|
||||
2 3 0 1 2 3
|
||||
2 3 1 5 6 2
|
||||
2 3 5 8 9 6
|
||||
2 3 8 11 12 9
|
||||
2 3 11 14 15 12
|
||||
2 3 14 17 18 15
|
||||
2 3 17 20 21 18
|
||||
2 3 20 23 24 21
|
||||
2 3 23 26 27 24
|
||||
2 3 26 29 30 27
|
||||
2 3 29 32 33 30
|
||||
2 3 32 35 36 33
|
||||
2 3 35 38 39 36
|
||||
2 3 38 41 42 39
|
||||
2 3 41 44 45 42
|
||||
2 3 44 47 48 45
|
||||
2 3 47 50 51 48
|
||||
2 3 50 53 54 51
|
||||
2 3 53 56 57 54
|
||||
2 3 56 59 60 57
|
||||
2 3 59 62 63 60
|
||||
2 3 62 65 66 63
|
||||
2 3 65 68 69 66
|
||||
2 3 68 71 72 69
|
||||
2 3 71 74 75 72
|
||||
2 3 74 77 78 75
|
||||
1 2 2 3 4
|
||||
1 2 6 2 7
|
||||
1 2 9 6 10
|
||||
1 2 12 9 13
|
||||
1 2 15 12 16
|
||||
1 2 18 15 19
|
||||
1 2 21 18 22
|
||||
1 2 24 21 25
|
||||
1 2 27 24 28
|
||||
1 2 30 27 31
|
||||
1 2 33 30 34
|
||||
1 2 36 33 37
|
||||
1 2 39 36 40
|
||||
1 2 42 39 43
|
||||
1 2 45 42 46
|
||||
1 2 48 45 49
|
||||
1 2 51 48 52
|
||||
1 2 54 51 55
|
||||
1 2 57 54 58
|
||||
1 2 60 57 61
|
||||
1 2 63 60 64
|
||||
1 2 66 63 67
|
||||
1 2 69 66 70
|
||||
1 2 72 69 73
|
||||
1 2 75 72 76
|
||||
1 2 78 75 79
|
||||
1 2 2 4 7
|
||||
1 2 6 7 10
|
||||
1 2 9 10 13
|
||||
1 2 12 13 16
|
||||
1 2 15 16 19
|
||||
1 2 18 19 22
|
||||
1 2 21 22 25
|
||||
1 2 24 25 28
|
||||
1 2 27 28 31
|
||||
1 2 30 31 34
|
||||
1 2 33 34 37
|
||||
1 2 36 37 40
|
||||
1 2 39 40 43
|
||||
1 2 42 43 46
|
||||
1 2 45 46 49
|
||||
1 2 48 49 52
|
||||
1 2 51 52 55
|
||||
1 2 54 55 58
|
||||
1 2 57 58 61
|
||||
1 2 60 61 64
|
||||
1 2 63 64 67
|
||||
1 2 66 67 70
|
||||
1 2 69 70 73
|
||||
1 2 72 73 76
|
||||
1 2 75 76 79
|
||||
2 3 80 81 82 83
|
||||
2 3 81 84 85 82
|
||||
2 3 84 86 87 85
|
||||
2 3 86 88 89 87
|
||||
2 3 88 90 91 89
|
||||
2 3 90 92 93 91
|
||||
2 3 92 94 95 93
|
||||
2 3 94 96 97 95
|
||||
2 3 96 98 99 97
|
||||
2 3 98 100 101 99
|
||||
2 3 100 102 103 101
|
||||
2 3 102 104 105 103
|
||||
2 3 104 106 107 105
|
||||
2 3 106 108 109 107
|
||||
2 3 108 110 111 109
|
||||
2 3 110 112 113 111
|
||||
2 3 112 114 115 113
|
||||
2 3 114 116 117 115
|
||||
2 3 116 118 119 117
|
||||
2 3 118 120 121 119
|
||||
2 3 120 122 123 121
|
||||
2 3 122 124 125 123
|
||||
2 3 124 126 127 125
|
||||
2 3 126 128 129 127
|
||||
2 3 128 130 131 129
|
||||
2 3 130 132 133 131
|
||||
1 2 82 83 4
|
||||
1 2 85 82 7
|
||||
1 2 87 85 10
|
||||
1 2 89 87 13
|
||||
1 2 91 89 16
|
||||
1 2 93 91 19
|
||||
1 2 95 93 22
|
||||
1 2 97 95 25
|
||||
1 2 99 97 28
|
||||
1 2 101 99 31
|
||||
1 2 103 101 34
|
||||
1 2 105 103 37
|
||||
1 2 107 105 40
|
||||
1 2 109 107 43
|
||||
1 2 111 109 46
|
||||
1 2 113 111 49
|
||||
1 2 115 113 52
|
||||
1 2 117 115 55
|
||||
1 2 119 117 58
|
||||
1 2 121 119 61
|
||||
1 2 123 121 64
|
||||
1 2 125 123 67
|
||||
1 2 127 125 70
|
||||
1 2 129 127 73
|
||||
1 2 131 129 76
|
||||
1 2 133 131 79
|
||||
1 2 82 4 7
|
||||
1 2 85 7 10
|
||||
1 2 87 10 13
|
||||
1 2 89 13 16
|
||||
1 2 91 16 19
|
||||
1 2 93 19 22
|
||||
1 2 95 22 25
|
||||
1 2 97 25 28
|
||||
1 2 99 28 31
|
||||
1 2 101 31 34
|
||||
1 2 103 34 37
|
||||
1 2 105 37 40
|
||||
1 2 107 40 43
|
||||
1 2 109 43 46
|
||||
1 2 111 46 49
|
||||
1 2 113 49 52
|
||||
1 2 115 52 55
|
||||
1 2 117 55 58
|
||||
1 2 119 58 61
|
||||
1 2 121 61 64
|
||||
1 2 123 64 67
|
||||
1 2 125 67 70
|
||||
1 2 127 70 73
|
||||
1 2 129 73 76
|
||||
1 2 131 76 79
|
||||
|
||||
boundary
|
||||
60
|
||||
1 1 0 1
|
||||
1 1 1 5
|
||||
1 1 5 8
|
||||
1 1 8 11
|
||||
1 1 11 14
|
||||
1 1 14 17
|
||||
1 1 17 20
|
||||
1 1 20 23
|
||||
1 1 23 26
|
||||
1 1 26 29
|
||||
1 1 29 32
|
||||
1 1 32 35
|
||||
1 1 35 38
|
||||
1 1 38 41
|
||||
1 1 41 44
|
||||
1 1 44 47
|
||||
1 1 47 50
|
||||
1 1 50 53
|
||||
1 1 53 56
|
||||
1 1 56 59
|
||||
1 1 59 62
|
||||
1 1 62 65
|
||||
1 1 65 68
|
||||
1 1 68 71
|
||||
1 1 71 74
|
||||
1 1 74 77
|
||||
1 1 77 78
|
||||
1 1 78 79
|
||||
1 1 79 133
|
||||
1 1 133 132
|
||||
1 1 132 130
|
||||
1 1 130 128
|
||||
1 1 128 126
|
||||
1 1 126 124
|
||||
1 1 124 122
|
||||
1 1 122 120
|
||||
1 1 120 118
|
||||
1 1 118 116
|
||||
1 1 116 114
|
||||
1 1 114 112
|
||||
1 1 112 110
|
||||
1 1 110 108
|
||||
1 1 108 106
|
||||
1 1 106 104
|
||||
1 1 104 102
|
||||
1 1 102 100
|
||||
1 1 100 98
|
||||
1 1 98 96
|
||||
1 1 96 94
|
||||
1 1 94 92
|
||||
1 1 92 90
|
||||
1 1 90 88
|
||||
1 1 88 86
|
||||
1 1 86 84
|
||||
1 1 84 81
|
||||
1 1 81 80
|
||||
1 1 80 83
|
||||
1 1 83 4
|
||||
1 1 4 3
|
||||
1 1 3 0
|
||||
|
||||
vertices
|
||||
134
|
||||
2
|
||||
0.0 0.0
|
||||
1.0 0.0
|
||||
1.0 1.0
|
||||
0.0 1.0
|
||||
0.5 1.86602540378
|
||||
2.0 0.0
|
||||
2.0 1.0
|
||||
1.5 1.86602540378
|
||||
3.0 0.0
|
||||
3.0 1.0
|
||||
2.5 1.86602540378
|
||||
4.0 0.0
|
||||
4.0 1.0
|
||||
3.5 1.86602540378
|
||||
5.0 0.0
|
||||
5.0 1.0
|
||||
4.5 1.86602540378
|
||||
6.0 0.0
|
||||
6.0 1.0
|
||||
5.5 1.86602540378
|
||||
7.0 0.0
|
||||
7.0 1.0
|
||||
6.5 1.86602540378
|
||||
8.0 0.0
|
||||
8.0 1.0
|
||||
7.5 1.86602540378
|
||||
9.0 0.0
|
||||
9.0 1.0
|
||||
8.5 1.86602540378
|
||||
10.0 0.0
|
||||
10.0 1.0
|
||||
9.5 1.86602540378
|
||||
11.0 0.0
|
||||
11.0 1.0
|
||||
10.5 1.86602540378
|
||||
12.0 0.0
|
||||
12.0 1.0
|
||||
11.5 1.86602540378
|
||||
13.0 0.0
|
||||
13.0 1.0
|
||||
12.5 1.86602540378
|
||||
14.0 0.0
|
||||
14.0 1.0
|
||||
13.5 1.86602540378
|
||||
15.0 0.0
|
||||
15.0 1.0
|
||||
14.5 1.86602540378
|
||||
16.0 0.0
|
||||
16.0 1.0
|
||||
15.5 1.86602540378
|
||||
17.0 0.0
|
||||
17.0 1.0
|
||||
16.5 1.86602540378
|
||||
18.0 0.0
|
||||
18.0 1.0
|
||||
17.5 1.86602540378
|
||||
19.0 0.0
|
||||
19.0 1.0
|
||||
18.5 1.86602540378
|
||||
20.0 0.0
|
||||
20.0 1.0
|
||||
19.5 1.86602540378
|
||||
21.0 0.0
|
||||
21.0 1.0
|
||||
20.5 1.86602540378
|
||||
22.0 0.0
|
||||
22.0 1.0
|
||||
21.5 1.86602540378
|
||||
23.0 0.0
|
||||
23.0 1.0
|
||||
22.5 1.86602540378
|
||||
24.0 0.0
|
||||
24.0 1.0
|
||||
23.5 1.86602540378
|
||||
25.0 0.0
|
||||
25.0 1.0
|
||||
24.5 1.86602540378
|
||||
26.0 0.0
|
||||
26.0 1.0
|
||||
25.5 1.86602540378
|
||||
0.0 3.73205080757
|
||||
1.0 3.73205080757
|
||||
1.0 2.73205080757
|
||||
0.0 2.73205080757
|
||||
2.0 3.73205080757
|
||||
2.0 2.73205080757
|
||||
3.0 3.73205080757
|
||||
3.0 2.73205080757
|
||||
4.0 3.73205080757
|
||||
4.0 2.73205080757
|
||||
5.0 3.73205080757
|
||||
5.0 2.73205080757
|
||||
6.0 3.73205080757
|
||||
6.0 2.73205080757
|
||||
7.0 3.73205080757
|
||||
7.0 2.73205080757
|
||||
8.0 3.73205080757
|
||||
8.0 2.73205080757
|
||||
9.0 3.73205080757
|
||||
9.0 2.73205080757
|
||||
10.0 3.73205080757
|
||||
10.0 2.73205080757
|
||||
11.0 3.73205080757
|
||||
11.0 2.73205080757
|
||||
12.0 3.73205080757
|
||||
12.0 2.73205080757
|
||||
13.0 3.73205080757
|
||||
13.0 2.73205080757
|
||||
14.0 3.73205080757
|
||||
14.0 2.73205080757
|
||||
15.0 3.73205080757
|
||||
15.0 2.73205080757
|
||||
16.0 3.73205080757
|
||||
16.0 2.73205080757
|
||||
17.0 3.73205080757
|
||||
17.0 2.73205080757
|
||||
18.0 3.73205080757
|
||||
18.0 2.73205080757
|
||||
19.0 3.73205080757
|
||||
19.0 2.73205080757
|
||||
20.0 3.73205080757
|
||||
20.0 2.73205080757
|
||||
21.0 3.73205080757
|
||||
21.0 2.73205080757
|
||||
22.0 3.73205080757
|
||||
22.0 2.73205080757
|
||||
23.0 3.73205080757
|
||||
23.0 2.73205080757
|
||||
24.0 3.73205080757
|
||||
24.0 2.73205080757
|
||||
25.0 3.73205080757
|
||||
25.0 2.73205080757
|
||||
26.0 3.73205080757
|
||||
26.0 2.73205080757
|
||||
@@ -1,66 +0,0 @@
|
||||
MFEM mesh v1.0
|
||||
|
||||
dimension
|
||||
2
|
||||
|
||||
elements
|
||||
17
|
||||
2 3 0 1 2 3
|
||||
2 3 1 5 6 2
|
||||
2 3 5 8 9 6
|
||||
2 3 8 11 12 9
|
||||
2 3 11 14 15 12
|
||||
2 3 14 17 18 15
|
||||
1 2 2 3 4
|
||||
1 2 6 2 7
|
||||
1 2 9 6 10
|
||||
1 2 12 9 13
|
||||
1 2 15 12 16
|
||||
1 2 18 15 19
|
||||
1 2 2 4 7
|
||||
1 2 6 7 10
|
||||
1 2 9 10 13
|
||||
1 2 12 13 16
|
||||
1 2 15 16 19
|
||||
|
||||
boundary
|
||||
15
|
||||
1 1 0 1
|
||||
1 1 1 5
|
||||
1 1 5 8
|
||||
1 1 8 11
|
||||
1 1 11 14
|
||||
1 1 14 17
|
||||
1 1 17 18
|
||||
1 1 18 19
|
||||
1 1 19 16
|
||||
1 1 16 13
|
||||
1 1 13 10
|
||||
1 1 10 7
|
||||
1 1 7 4
|
||||
1 1 4 3
|
||||
1 1 3 0
|
||||
|
||||
vertices
|
||||
20
|
||||
2
|
||||
0.0 0.0
|
||||
1.0 0.0
|
||||
1.0 1.0
|
||||
0.0 1.0
|
||||
0.5 1.86602540378
|
||||
2.0 0.0
|
||||
2.0 1.0
|
||||
1.5 1.86602540378
|
||||
3.0 0.0
|
||||
3.0 1.0
|
||||
2.5 1.86602540378
|
||||
4.0 0.0
|
||||
4.0 1.0
|
||||
3.5 1.86602540378
|
||||
5.0 0.0
|
||||
5.0 1.0
|
||||
4.5 1.86602540378
|
||||
6.0 0.0
|
||||
6.0 1.0
|
||||
5.5 1.86602540378
|
||||
@@ -1,45 +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
|
||||
#
|
||||
|
||||
dimension
|
||||
2
|
||||
|
||||
elements
|
||||
5
|
||||
1 2 0 1 2
|
||||
1 2 0 2 3
|
||||
1 2 0 3 4
|
||||
2 3 0 4 5 6
|
||||
2 3 0 6 7 1
|
||||
|
||||
boundary
|
||||
7
|
||||
1 1 1 2
|
||||
1 1 2 3
|
||||
1 1 3 4
|
||||
1 1 4 5
|
||||
1 1 5 6
|
||||
1 1 6 7
|
||||
1 1 7 1
|
||||
|
||||
vertices
|
||||
8
|
||||
2
|
||||
0 0
|
||||
1 0
|
||||
0.5 0.866025
|
||||
-0.5 0.866025
|
||||
-1 0
|
||||
-1 -1
|
||||
0 -1
|
||||
1 -1
|
||||
@@ -1,45 +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
|
||||
#
|
||||
|
||||
dimension
|
||||
2
|
||||
|
||||
elements
|
||||
5
|
||||
1 2 0 1 2
|
||||
1 2 0 2 3
|
||||
1 2 0 5 6
|
||||
2 3 0 3 4 5
|
||||
2 3 0 6 7 1
|
||||
|
||||
boundary
|
||||
7
|
||||
1 1 1 2
|
||||
1 1 2 3
|
||||
1 1 3 4
|
||||
1 1 4 5
|
||||
1 1 5 6
|
||||
1 1 6 7
|
||||
1 1 7 1
|
||||
|
||||
vertices
|
||||
8
|
||||
2
|
||||
0 0
|
||||
0.866025 0.5
|
||||
0 1
|
||||
-0.866025 0.5
|
||||
-1.366025 -0.36602500
|
||||
-0.5 -0.866025
|
||||
0.5 -0.866025
|
||||
1.366025 -0.36602500
|
||||
@@ -1,57 +0,0 @@
|
||||
MFEM mesh v1.0
|
||||
|
||||
dimension
|
||||
2
|
||||
|
||||
elements
|
||||
16
|
||||
1 2 0 1 2
|
||||
1 2 1 2 4
|
||||
1 2 1 3 4
|
||||
1 2 2 4 5
|
||||
1 2 3 4 7
|
||||
1 2 3 6 7
|
||||
1 2 4 5 8
|
||||
1 2 4 7 8
|
||||
1 2 5 8 9
|
||||
1 2 6 7 11
|
||||
1 2 6 10 11
|
||||
1 2 7 8 12
|
||||
1 2 7 11 12
|
||||
1 2 8 9 13
|
||||
1 2 8 12 13
|
||||
1 2 9 13 14
|
||||
|
||||
boundary
|
||||
12
|
||||
1 1 0 1
|
||||
1 1 1 3
|
||||
1 1 3 6
|
||||
1 1 6 10
|
||||
1 1 10 11
|
||||
1 1 11 12
|
||||
1 1 12 13
|
||||
1 1 13 14
|
||||
1 1 14 9
|
||||
1 1 9 5
|
||||
1 1 5 2
|
||||
1 1 2 0
|
||||
|
||||
vertices
|
||||
15
|
||||
2
|
||||
0.0 0.0
|
||||
0.25 0.0
|
||||
1.53080849893e-17 0.25
|
||||
0.5 0.0
|
||||
0.353553390593 0.353553390593
|
||||
3.06161699787e-17 0.5
|
||||
0.75 0.0
|
||||
0.649519052838 0.375
|
||||
0.375 0.649519052838
|
||||
4.5924254968e-17 0.75
|
||||
1.0 0.0
|
||||
0.923879532511 0.382683432365
|
||||
0.707106781187 0.707106781187
|
||||
0.382683432365 0.923879532511
|
||||
6.12323399574e-17 1.0
|
||||
@@ -1,147 +0,0 @@
|
||||
MFEM mesh v1.0
|
||||
|
||||
dimension
|
||||
2
|
||||
|
||||
elements
|
||||
64
|
||||
1 2 0 1 2
|
||||
1 2 1 2 4
|
||||
1 2 1 3 4
|
||||
1 2 2 4 5
|
||||
1 2 3 4 7
|
||||
1 2 3 6 7
|
||||
1 2 4 5 8
|
||||
1 2 4 7 8
|
||||
1 2 5 8 9
|
||||
1 2 6 7 11
|
||||
1 2 6 10 11
|
||||
1 2 7 8 12
|
||||
1 2 7 11 12
|
||||
1 2 8 9 13
|
||||
1 2 8 12 13
|
||||
1 2 9 13 14
|
||||
1 2 10 11 16
|
||||
1 2 10 15 16
|
||||
1 2 11 12 17
|
||||
1 2 11 16 17
|
||||
1 2 12 13 18
|
||||
1 2 12 17 18
|
||||
1 2 13 14 19
|
||||
1 2 13 18 19
|
||||
1 2 14 19 20
|
||||
1 2 15 16 22
|
||||
1 2 15 21 22
|
||||
1 2 16 17 23
|
||||
1 2 16 22 23
|
||||
1 2 17 18 24
|
||||
1 2 17 23 24
|
||||
1 2 18 19 25
|
||||
1 2 18 24 25
|
||||
1 2 19 20 26
|
||||
1 2 19 25 26
|
||||
1 2 20 26 27
|
||||
1 2 21 22 29
|
||||
1 2 21 28 29
|
||||
1 2 22 23 30
|
||||
1 2 22 29 30
|
||||
1 2 23 24 31
|
||||
1 2 23 30 31
|
||||
1 2 24 25 32
|
||||
1 2 24 31 32
|
||||
1 2 25 26 33
|
||||
1 2 25 32 33
|
||||
1 2 26 27 34
|
||||
1 2 26 33 34
|
||||
1 2 27 34 35
|
||||
1 2 28 29 37
|
||||
1 2 28 36 37
|
||||
1 2 29 30 38
|
||||
1 2 29 37 38
|
||||
1 2 30 31 39
|
||||
1 2 30 38 39
|
||||
1 2 31 32 40
|
||||
1 2 31 39 40
|
||||
1 2 32 33 41
|
||||
1 2 32 40 41
|
||||
1 2 33 34 42
|
||||
1 2 33 41 42
|
||||
1 2 34 35 43
|
||||
1 2 34 42 43
|
||||
1 2 35 43 44
|
||||
|
||||
boundary
|
||||
24
|
||||
1 1 0 1
|
||||
1 1 1 3
|
||||
1 1 3 6
|
||||
1 1 6 10
|
||||
1 1 10 15
|
||||
1 1 15 21
|
||||
1 1 21 28
|
||||
1 1 28 36
|
||||
1 1 36 37
|
||||
1 1 37 38
|
||||
1 1 38 39
|
||||
1 1 39 40
|
||||
1 1 40 41
|
||||
1 1 41 42
|
||||
1 1 42 43
|
||||
1 1 43 44
|
||||
1 1 44 35
|
||||
1 1 35 27
|
||||
1 1 27 20
|
||||
1 1 20 14
|
||||
1 1 14 9
|
||||
1 1 9 5
|
||||
1 1 5 2
|
||||
1 1 2 0
|
||||
|
||||
vertices
|
||||
45
|
||||
2
|
||||
0.0 0.0
|
||||
0.125 0.0
|
||||
7.65404249467e-18 0.125
|
||||
0.25 0.0
|
||||
0.176776695297 0.176776695297
|
||||
1.53080849893e-17 0.25
|
||||
0.375 0.0
|
||||
0.324759526419 0.1875
|
||||
0.1875 0.324759526419
|
||||
2.2962127484e-17 0.375
|
||||
0.5 0.0
|
||||
0.461939766256 0.191341716183
|
||||
0.353553390593 0.353553390593
|
||||
0.191341716183 0.461939766256
|
||||
3.06161699787e-17 0.5
|
||||
0.625 0.0
|
||||
0.594410322684 0.193135621484
|
||||
0.505635621484 0.367365782683
|
||||
0.367365782683 0.505635621484
|
||||
0.193135621484 0.594410322684
|
||||
3.82702124734e-17 0.625
|
||||
0.75 0.0
|
||||
0.724444369717 0.194114283827
|
||||
0.649519052838 0.375
|
||||
0.53033008589 0.53033008589
|
||||
0.375 0.649519052838
|
||||
0.194114283827 0.724444369717
|
||||
4.5924254968e-17 0.75
|
||||
0.875 0.0
|
||||
0.853061923159 0.194705817212
|
||||
0.788347759415 0.379648271728
|
||||
0.68410254716 0.545553576626
|
||||
0.545553576626 0.68410254716
|
||||
0.379648271728 0.788347759415
|
||||
0.194705817212 0.853061923159
|
||||
5.35782974627e-17 0.875
|
||||
1.0 0.0
|
||||
0.980785280403 0.195090322016
|
||||
0.923879532511 0.382683432365
|
||||
0.831469612303 0.55557023302
|
||||
0.707106781187 0.707106781187
|
||||
0.55557023302 0.831469612303
|
||||
0.382683432365 0.923879532511
|
||||
0.195090322016 0.980785280403
|
||||
6.12323399574e-17 1.0
|
||||
@@ -1,73 +0,0 @@
|
||||
MFEM mesh v1.0
|
||||
|
||||
dimension
|
||||
2
|
||||
|
||||
elements
|
||||
8
|
||||
1 2 0 1 2
|
||||
1 2 1 4 2
|
||||
1 2 1 3 4
|
||||
1 2 4 5 2
|
||||
2 3 3 6 7 4
|
||||
2 3 8 5 4 7
|
||||
2 3 6 9 10 7
|
||||
2 3 11 8 7 10
|
||||
|
||||
boundary
|
||||
10
|
||||
1 1 0 1
|
||||
1 1 1 3
|
||||
1 1 3 6
|
||||
1 1 6 9
|
||||
1 1 9 10
|
||||
1 1 10 11
|
||||
1 1 11 8
|
||||
1 1 8 5
|
||||
1 1 5 2
|
||||
1 1 2 0
|
||||
|
||||
vertices
|
||||
12
|
||||
|
||||
nodes
|
||||
FiniteElementSpace
|
||||
FiniteElementCollection: Quadratic
|
||||
VDim: 2
|
||||
Ordering: 1
|
||||
|
||||
0.0 0.0
|
||||
0.5 0.0
|
||||
0.0 0.5
|
||||
1.0 0.0
|
||||
0.70711 0.70711
|
||||
0.0 1.0
|
||||
1.5 0.0
|
||||
1.35355 1.35355
|
||||
0.0 1.5
|
||||
2.0 0.0
|
||||
2.0 2.0
|
||||
0.0 2.0
|
||||
0.25 0.0
|
||||
0.35355 0.35355
|
||||
0.0 0.25
|
||||
0.64714 0.37909
|
||||
0.37909 0.64714
|
||||
0.75 0.0
|
||||
0.92388 0.38269
|
||||
0.38269 0.92388
|
||||
0.0 0.75
|
||||
1.25 0.0
|
||||
1.54238 0.73161
|
||||
1.03033 1.03033
|
||||
0.0 1.25
|
||||
0.73161 1.54238
|
||||
1.75 0.0
|
||||
2.0 1.0
|
||||
1.67678 1.67678
|
||||
0.0 1.75
|
||||
1.0 2.0
|
||||
1.14017 0.51516
|
||||
0.51516 1.14017
|
||||
1.71339 0.83839
|
||||
0.83839 1.71339
|
||||
@@ -1,567 +0,0 @@
|
||||
MFEM mesh v1.0
|
||||
|
||||
dimension
|
||||
2
|
||||
|
||||
elements
|
||||
128
|
||||
1 2 0 1 2
|
||||
1 2 1 4 2
|
||||
1 2 1 3 4
|
||||
1 2 2 4 5
|
||||
1 2 3 7 4
|
||||
1 2 3 6 7
|
||||
1 2 4 8 5
|
||||
1 2 4 7 8
|
||||
1 2 5 8 9
|
||||
1 2 6 11 7
|
||||
1 2 6 10 11
|
||||
1 2 7 12 8
|
||||
1 2 7 11 12
|
||||
1 2 8 13 9
|
||||
1 2 8 12 13
|
||||
1 2 9 13 14
|
||||
2 3 10 15 16 11
|
||||
2 3 11 16 17 12
|
||||
2 3 12 17 18 13
|
||||
2 3 13 18 19 14
|
||||
2 3 15 20 21 16
|
||||
2 3 16 21 22 17
|
||||
2 3 17 22 23 18
|
||||
2 3 18 23 24 19
|
||||
2 3 20 25 26 21
|
||||
2 3 21 26 27 22
|
||||
2 3 22 27 28 23
|
||||
2 3 23 28 29 24
|
||||
2 3 25 30 31 26
|
||||
2 3 26 31 32 27
|
||||
2 3 27 32 33 28
|
||||
2 3 28 33 34 29
|
||||
1 2 0 2 35
|
||||
1 2 35 2 37
|
||||
1 2 35 37 36
|
||||
1 2 2 5 37
|
||||
1 2 36 37 39
|
||||
1 2 36 39 38
|
||||
1 2 37 5 40
|
||||
1 2 37 40 39
|
||||
1 2 5 9 40
|
||||
1 2 38 39 42
|
||||
1 2 38 42 41
|
||||
1 2 39 40 43
|
||||
1 2 39 43 42
|
||||
1 2 40 9 44
|
||||
1 2 40 44 43
|
||||
1 2 9 14 44
|
||||
2 3 41 42 46 45
|
||||
2 3 42 43 47 46
|
||||
2 3 43 44 48 47
|
||||
2 3 44 14 19 48
|
||||
2 3 45 46 50 49
|
||||
2 3 46 47 51 50
|
||||
2 3 47 48 52 51
|
||||
2 3 48 19 24 52
|
||||
2 3 49 50 54 53
|
||||
2 3 50 51 55 54
|
||||
2 3 51 52 56 55
|
||||
2 3 52 24 29 56
|
||||
2 3 53 54 58 57
|
||||
2 3 54 55 59 58
|
||||
2 3 55 56 60 59
|
||||
2 3 56 29 34 60
|
||||
1 2 0 61 1
|
||||
1 2 1 61 62
|
||||
1 2 1 62 3
|
||||
1 2 61 63 62
|
||||
1 2 3 62 64
|
||||
1 2 3 64 6
|
||||
1 2 62 63 65
|
||||
1 2 62 65 64
|
||||
1 2 63 66 65
|
||||
1 2 6 64 67
|
||||
1 2 6 67 10
|
||||
1 2 64 65 68
|
||||
1 2 64 68 67
|
||||
1 2 65 66 69
|
||||
1 2 65 69 68
|
||||
1 2 66 70 69
|
||||
2 3 10 67 71 15
|
||||
2 3 67 68 72 71
|
||||
2 3 68 69 73 72
|
||||
2 3 69 70 74 73
|
||||
2 3 15 71 75 20
|
||||
2 3 71 72 76 75
|
||||
2 3 72 73 77 76
|
||||
2 3 73 74 78 77
|
||||
2 3 20 75 79 25
|
||||
2 3 75 76 80 79
|
||||
2 3 76 77 81 80
|
||||
2 3 77 78 82 81
|
||||
2 3 25 79 83 30
|
||||
2 3 79 80 84 83
|
||||
2 3 80 81 85 84
|
||||
2 3 81 82 86 85
|
||||
1 2 0 35 61
|
||||
1 2 35 87 61
|
||||
1 2 35 36 87
|
||||
1 2 61 87 63
|
||||
1 2 36 88 87
|
||||
1 2 36 38 88
|
||||
1 2 87 89 63
|
||||
1 2 87 88 89
|
||||
1 2 63 89 66
|
||||
1 2 38 90 88
|
||||
1 2 38 41 90
|
||||
1 2 88 91 89
|
||||
1 2 88 90 91
|
||||
1 2 89 92 66
|
||||
1 2 89 91 92
|
||||
1 2 66 92 70
|
||||
2 3 41 45 93 90
|
||||
2 3 90 93 94 91
|
||||
2 3 91 94 95 92
|
||||
2 3 92 95 74 70
|
||||
2 3 45 49 96 93
|
||||
2 3 93 96 97 94
|
||||
2 3 94 97 98 95
|
||||
2 3 95 98 78 74
|
||||
2 3 49 53 99 96
|
||||
2 3 96 99 100 97
|
||||
2 3 97 100 101 98
|
||||
2 3 98 101 82 78
|
||||
2 3 53 102 103 99
|
||||
2 3 99 103 104 100
|
||||
2 3 100 104 105 101
|
||||
2 3 101 105 86 82
|
||||
|
||||
boundary
|
||||
16
|
||||
1 1 30 31
|
||||
1 1 31 32
|
||||
1 1 32 33
|
||||
1 1 33 34
|
||||
1 1 34 60
|
||||
1 1 60 59
|
||||
1 1 59 58
|
||||
1 1 58 57
|
||||
1 1 102 103
|
||||
1 1 103 104
|
||||
1 1 104 105
|
||||
1 1 105 86
|
||||
1 1 86 85
|
||||
1 1 85 84
|
||||
1 1 84 83
|
||||
1 1 83 30
|
||||
|
||||
vertices
|
||||
106
|
||||
|
||||
nodes
|
||||
FiniteElementSpace
|
||||
FiniteElementCollection: H1_2D_P2
|
||||
VDim: 2
|
||||
Ordering: 1
|
||||
|
||||
0.0 0.0
|
||||
0.25 0.0
|
||||
0.0 0.25
|
||||
0.5 0.0
|
||||
0.35355 0.35355
|
||||
0.0 0.5
|
||||
0.75 0.0
|
||||
0.64952 0.375
|
||||
0.375 0.64952
|
||||
0.0 0.75
|
||||
1.0 0.0
|
||||
0.92388 0.38268
|
||||
0.70711 0.70711
|
||||
0.38268 0.92388
|
||||
0.0 1.0
|
||||
1.25 0.0
|
||||
1.19291 0.53701
|
||||
1.03033 1.03033
|
||||
0.53701 1.19291
|
||||
0.0 1.25
|
||||
1.5 0.0
|
||||
1.46194 0.69134
|
||||
1.35355 1.35355
|
||||
0.69134 1.46194
|
||||
0.0 1.5
|
||||
1.75 0.0
|
||||
1.73097 0.84567
|
||||
1.67678 1.67678
|
||||
0.84567 1.73097
|
||||
0.0 1.75
|
||||
2.0 0.0
|
||||
2.0 1.0
|
||||
2.0 2.0
|
||||
1.0 2.0
|
||||
0.0 2.0
|
||||
-0.25 0.0
|
||||
-0.5 0.0
|
||||
-0.35355 0.35355
|
||||
-0.75 0.0
|
||||
-0.64952 0.375
|
||||
-0.375 0.64952
|
||||
-1.0 0.0
|
||||
-0.92388 0.38268
|
||||
-0.70711 0.70711
|
||||
-0.38268 0.92388
|
||||
-1.25 0.0
|
||||
-1.19291 0.53701
|
||||
-1.03033 1.03033
|
||||
-0.53701 1.19291
|
||||
-1.5 0.0
|
||||
-1.46194 0.69134
|
||||
-1.35355 1.35355
|
||||
-0.69134 1.46194
|
||||
-1.75 0.0
|
||||
-1.73097 0.84567
|
||||
-1.67678 1.67678
|
||||
-0.84567 1.73097
|
||||
-2.0 0.0
|
||||
-2.0 1.0
|
||||
-2.0 2.0
|
||||
-1.0 2.0
|
||||
0.0 -0.25
|
||||
0.35355 -0.35355
|
||||
0.0 -0.5
|
||||
0.64952 -0.375
|
||||
0.375 -0.64952
|
||||
0.0 -0.75
|
||||
0.92388 -0.38268
|
||||
0.70711 -0.70711
|
||||
0.38268 -0.92388
|
||||
0.0 -1.0
|
||||
1.19291 -0.53701
|
||||
1.03033 -1.03033
|
||||
0.53701 -1.19291
|
||||
0.0 -1.25
|
||||
1.46194 -0.69134
|
||||
1.35355 -1.35355
|
||||
0.69134 -1.46194
|
||||
0.0 -1.5
|
||||
1.73097 -0.84567
|
||||
1.67678 -1.67678
|
||||
0.84567 -1.73097
|
||||
0.0 -1.75
|
||||
2.0 -1.0
|
||||
2.0 -2.0
|
||||
1.0 -2.0
|
||||
0.0 -2.0
|
||||
-0.35355 -0.35355
|
||||
-0.64952 -0.375
|
||||
-0.375 -0.64952
|
||||
-0.92388 -0.38268
|
||||
-0.70711 -0.70711
|
||||
-0.38268 -0.92388
|
||||
-1.19291 -0.53701
|
||||
-1.03033 -1.03033
|
||||
-0.53701 -1.19291
|
||||
-1.46194 -0.69134
|
||||
-1.35355 -1.35355
|
||||
-0.69134 -1.46194
|
||||
-1.73097 -0.84567
|
||||
-1.67678 -1.67678
|
||||
-0.84567 -1.73097
|
||||
-2.0 -0.0
|
||||
-2.0 -1.0
|
||||
-2.0 -2.0
|
||||
-1.0 -2.0
|
||||
0.125 0.0
|
||||
0.17678 0.17678
|
||||
0.0 0.125
|
||||
0.32357 0.18954
|
||||
0.18954 0.32357
|
||||
0.375 0.0
|
||||
0.46194 0.19134
|
||||
0.19134 0.46194
|
||||
0.0 0.375
|
||||
0.59418 0.19384
|
||||
0.50569 0.36729
|
||||
0.625 0.0
|
||||
0.72444 0.19411
|
||||
0.36729 0.50569
|
||||
0.19384 0.59418
|
||||
0.53033 0.53033
|
||||
0.19411 0.72444
|
||||
0.0 0.625
|
||||
0.85299 0.19501
|
||||
0.78835 0.37964
|
||||
0.875 0.0
|
||||
0.98079 0.19509
|
||||
0.68405 0.54563
|
||||
0.54563 0.68405
|
||||
0.83147 0.55557
|
||||
0.37964 0.78835
|
||||
0.19501 0.85299
|
||||
0.55557 0.83147
|
||||
0.19509 0.98079
|
||||
0.0 0.875
|
||||
1.125 0.0
|
||||
1.24928 0.27462
|
||||
1.05851 0.4599
|
||||
1.13007 0.79668
|
||||
0.86872 0.86872
|
||||
0.79668 1.13007
|
||||
0.4599 1.05851
|
||||
0.27462 1.24928
|
||||
0.0 1.125
|
||||
1.375 0.0
|
||||
1.51779 0.35426
|
||||
1.32748 0.6142
|
||||
1.42864 1.03762
|
||||
1.19194 1.19194
|
||||
1.03762 1.42864
|
||||
0.6142 1.32748
|
||||
0.35426 1.51779
|
||||
0.0 1.375
|
||||
1.625 0.0
|
||||
1.78629 0.43396
|
||||
1.59649 0.76852
|
||||
1.72721 1.2785
|
||||
1.51516 1.51516
|
||||
1.2785 1.72721
|
||||
0.76852 1.59649
|
||||
0.43396 1.78629
|
||||
0.0 1.625
|
||||
1.875 0.0
|
||||
2.0 0.5
|
||||
1.8655 0.92284
|
||||
2.0 1.5
|
||||
1.83839 1.83839
|
||||
1.5 2.0
|
||||
0.92284 1.8655
|
||||
0.5 2.0
|
||||
0.0 1.875
|
||||
-0.17678 0.17678
|
||||
-0.125 0.0
|
||||
-0.18954 0.32357
|
||||
-0.32357 0.18954
|
||||
-0.46194 0.19134
|
||||
-0.375 0.0
|
||||
-0.19134 0.46194
|
||||
-0.50569 0.36729
|
||||
-0.59418 0.19384
|
||||
-0.72444 0.19411
|
||||
-0.625 0.0
|
||||
-0.19384 0.59418
|
||||
-0.36729 0.50569
|
||||
-0.53033 0.53033
|
||||
-0.19411 0.72444
|
||||
-0.78835 0.37964
|
||||
-0.85299 0.19501
|
||||
-0.98079 0.19509
|
||||
-0.875 0.0
|
||||
-0.54563 0.68405
|
||||
-0.68405 0.54563
|
||||
-0.83147 0.55557
|
||||
-0.19501 0.85299
|
||||
-0.37964 0.78835
|
||||
-0.55557 0.83147
|
||||
-0.19509 0.98079
|
||||
-1.05851 0.4599
|
||||
-1.24928 0.27462
|
||||
-1.125 0.0
|
||||
-0.86872 0.86872
|
||||
-1.13007 0.79668
|
||||
-0.4599 1.05851
|
||||
-0.79668 1.13007
|
||||
-0.27462 1.24928
|
||||
-1.32748 0.6142
|
||||
-1.51779 0.35426
|
||||
-1.375 0.0
|
||||
-1.19194 1.19194
|
||||
-1.42864 1.03762
|
||||
-0.6142 1.32748
|
||||
-1.03762 1.42864
|
||||
-0.35426 1.51779
|
||||
-1.59649 0.76852
|
||||
-1.78629 0.43396
|
||||
-1.625 0.0
|
||||
-1.51516 1.51516
|
||||
-1.72721 1.2785
|
||||
-0.76852 1.59649
|
||||
-1.2785 1.72721
|
||||
-0.43396 1.78629
|
||||
-1.8655 0.92284
|
||||
-2.0 0.5
|
||||
-1.875 0.0
|
||||
-1.83839 1.83839
|
||||
-2.0 1.5
|
||||
-0.92284 1.8655
|
||||
-1.5 2.0
|
||||
-0.5 2.0
|
||||
0.0 -0.125
|
||||
0.17678 -0.17678
|
||||
0.18954 -0.32357
|
||||
0.32357 -0.18954
|
||||
0.46194 -0.19134
|
||||
0.0 -0.375
|
||||
0.19134 -0.46194
|
||||
0.50569 -0.36729
|
||||
0.59418 -0.19384
|
||||
0.72444 -0.19411
|
||||
0.19384 -0.59418
|
||||
0.36729 -0.50569
|
||||
0.53033 -0.53033
|
||||
0.0 -0.625
|
||||
0.19411 -0.72444
|
||||
0.78835 -0.37964
|
||||
0.85299 -0.19501
|
||||
0.98079 -0.19509
|
||||
0.54563 -0.68405
|
||||
0.68405 -0.54563
|
||||
0.83147 -0.55557
|
||||
0.19501 -0.85299
|
||||
0.37964 -0.78835
|
||||
0.55557 -0.83147
|
||||
0.0 -0.875
|
||||
0.19509 -0.98079
|
||||
1.05851 -0.4599
|
||||
1.24928 -0.27462
|
||||
0.86872 -0.86872
|
||||
1.13007 -0.79668
|
||||
0.4599 -1.05851
|
||||
0.79668 -1.13007
|
||||
0.0 -1.125
|
||||
0.27462 -1.24928
|
||||
1.32748 -0.6142
|
||||
1.51779 -0.35426
|
||||
1.19194 -1.19194
|
||||
1.42864 -1.03762
|
||||
0.6142 -1.32748
|
||||
1.03762 -1.42864
|
||||
0.0 -1.375
|
||||
0.35426 -1.51779
|
||||
1.59649 -0.76852
|
||||
1.78629 -0.43396
|
||||
1.51516 -1.51516
|
||||
1.72721 -1.2785
|
||||
0.76852 -1.59649
|
||||
1.2785 -1.72721
|
||||
0.0 -1.625
|
||||
0.43396 -1.78629
|
||||
1.8655 -0.92284
|
||||
2.0 -0.5
|
||||
1.83839 -1.83839
|
||||
2.0 -1.5
|
||||
0.92284 -1.8655
|
||||
1.5 -2.0
|
||||
0.0 -1.875
|
||||
0.5 -2.0
|
||||
-0.17678 -0.17678
|
||||
-0.32357 -0.18954
|
||||
-0.18954 -0.32357
|
||||
-0.46194 -0.19134
|
||||
-0.19134 -0.46194
|
||||
-0.59418 -0.19384
|
||||
-0.50569 -0.36729
|
||||
-0.72444 -0.19411
|
||||
-0.36729 -0.50569
|
||||
-0.19384 -0.59418
|
||||
-0.53033 -0.53033
|
||||
-0.19411 -0.72444
|
||||
-0.85299 -0.19501
|
||||
-0.78835 -0.37964
|
||||
-0.98079 -0.19509
|
||||
-0.68405 -0.54563
|
||||
-0.54563 -0.68405
|
||||
-0.83147 -0.55557
|
||||
-0.37964 -0.78835
|
||||
-0.19501 -0.85299
|
||||
-0.55557 -0.83147
|
||||
-0.19509 -0.98079
|
||||
-1.24928 -0.27462
|
||||
-1.05851 -0.4599
|
||||
-1.13007 -0.79668
|
||||
-0.86872 -0.86872
|
||||
-0.79668 -1.13007
|
||||
-0.4599 -1.05851
|
||||
-0.27462 -1.24928
|
||||
-1.51779 -0.35426
|
||||
-1.32748 -0.6142
|
||||
-1.42864 -1.03762
|
||||
-1.19194 -1.19194
|
||||
-1.03762 -1.42864
|
||||
-0.6142 -1.32748
|
||||
-0.35426 -1.51779
|
||||
-1.78629 -0.43396
|
||||
-1.59649 -0.76852
|
||||
-1.72721 -1.2785
|
||||
-1.51516 -1.51516
|
||||
-1.2785 -1.72721
|
||||
-0.76852 -1.59649
|
||||
-0.43396 -1.78629
|
||||
-1.875 0.0
|
||||
-2.0 -0.5
|
||||
-1.8655 -0.92284
|
||||
-2.0 -1.5
|
||||
-1.83839 -1.83839
|
||||
-1.5 -2.0
|
||||
-0.92284 -1.8655
|
||||
-0.5 -2.0
|
||||
1.0917 0.22992
|
||||
0.96356 0.66428
|
||||
0.66428 0.96356
|
||||
0.22992 1.0917
|
||||
1.35121 0.30709
|
||||
1.25968 0.90306
|
||||
0.90306 1.25968
|
||||
0.30709 1.35121
|
||||
1.61073 0.38425
|
||||
1.55581 1.14184
|
||||
1.14184 1.55581
|
||||
0.38425 1.61073
|
||||
1.87024 0.46142
|
||||
1.85194 1.38061
|
||||
1.38061 1.85194
|
||||
0.46142 1.87024
|
||||
-1.0917 0.22992
|
||||
-0.96356 0.66428
|
||||
-0.66428 0.96356
|
||||
-0.22992 1.0917
|
||||
-1.35121 0.30709
|
||||
-1.25968 0.90306
|
||||
-0.90306 1.25968
|
||||
-0.30709 1.35121
|
||||
-1.61073 0.38425
|
||||
-1.55581 1.14184
|
||||
-1.14184 1.55581
|
||||
-0.38425 1.61073
|
||||
-1.87024 0.46142
|
||||
-1.85194 1.38061
|
||||
-1.38061 1.85194
|
||||
-0.46142 1.87024
|
||||
1.0917 -0.22992
|
||||
0.96356 -0.66428
|
||||
0.66428 -0.96356
|
||||
0.22992 -1.0917
|
||||
1.35121 -0.30709
|
||||
1.25968 -0.90306
|
||||
0.90306 -1.25968
|
||||
0.30709 -1.35121
|
||||
1.61073 -0.38425
|
||||
1.55581 -1.14184
|
||||
1.14184 -1.55581
|
||||
0.38425 -1.61073
|
||||
1.87024 -0.46142
|
||||
1.85194 -1.38061
|
||||
1.38061 -1.85194
|
||||
0.46142 -1.87024
|
||||
-1.0917 -0.22992
|
||||
-0.96356 -0.66428
|
||||
-0.66428 -0.96356
|
||||
-0.22992 -1.0917
|
||||
-1.35121 -0.30709
|
||||
-1.25968 -0.90306
|
||||
-0.90306 -1.25968
|
||||
-0.30709 -1.35121
|
||||
-1.61073 -0.38425
|
||||
-1.55581 -1.14184
|
||||
-1.14184 -1.55581
|
||||
-0.38425 -1.61073
|
||||
-1.87024 -0.46142
|
||||
-1.85194 -1.38061
|
||||
-1.38061 -1.85194
|
||||
-0.46142 -1.87024
|
||||
@@ -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 = v3.4.1
|
||||
PROJECT_NUMBER = v3.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
|
||||
@@ -140,7 +140,7 @@ INLINE_INHERITED_MEMB = NO
|
||||
# shortest path that makes the file name unique will be used
|
||||
# The default value is: YES.
|
||||
|
||||
FULL_PATH_NAMES = YES
|
||||
FULL_PATH_NAMES = NO
|
||||
|
||||
# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
|
||||
# Stripping is only done if one of the specified strings matches the left-hand
|
||||
@@ -152,7 +152,7 @@ FULL_PATH_NAMES = YES
|
||||
# will be relative from the directory where doxygen is started.
|
||||
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
|
||||
|
||||
STRIP_FROM_PATH = @MFEM_SOURCE_DIR@
|
||||
STRIP_FROM_PATH =
|
||||
|
||||
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
|
||||
# path mentioned in the documentation of a class, which tells the reader which
|
||||
@@ -767,12 +767,10 @@ INPUT = @MFEM_SOURCE_DIR@/doc/CodeDocumentation.dox \
|
||||
@MFEM_SOURCE_DIR@/fem \
|
||||
@MFEM_SOURCE_DIR@/examples \
|
||||
@MFEM_SOURCE_DIR@/examples/petsc \
|
||||
@MFEM_SOURCE_DIR@/examples/pumi \
|
||||
@MFEM_SOURCE_DIR@/examples/sundials \
|
||||
@MFEM_SOURCE_DIR@/miniapps/common \
|
||||
@MFEM_SOURCE_DIR@/miniapps/meshing \
|
||||
@MFEM_SOURCE_DIR@/miniapps/tools \
|
||||
@MFEM_SOURCE_DIR@/miniapps/nurbs \
|
||||
@MFEM_SOURCE_DIR@/miniapps/electromagnetics \
|
||||
@MFEM_SOURCE_DIR@/miniapps/performance
|
||||
|
||||
@@ -810,8 +808,7 @@ RECURSIVE = NO
|
||||
# Note that relative paths are relative to the directory from which doxygen is
|
||||
# run.
|
||||
|
||||
EXCLUDE = @MFEM_SOURCE_DIR@/config/_config.hpp \
|
||||
@MFEM_SOURCE_DIR@/config/get_hypre_version.cpp
|
||||
EXCLUDE =
|
||||
|
||||
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
|
||||
# directories that are symbolic links (a Unix file system feature) are excluded
|
||||
@@ -1443,7 +1440,7 @@ FORMULA_TRANSPARENT = YES
|
||||
# The default value is: NO.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
USE_MATHJAX = YES
|
||||
USE_MATHJAX = NO
|
||||
|
||||
# When MathJax is enabled you can set the default output format to be used for
|
||||
# the MathJax output. See the MathJax site (see:
|
||||
@@ -1466,14 +1463,14 @@ MATHJAX_FORMAT = HTML-CSS
|
||||
# The default value is: http://cdn.mathjax.org/mathjax/latest.
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
|
||||
MATHJAX_RELPATH = https://cdn.llnl.gov/mathjax/2.7.2
|
||||
MATHJAX_RELPATH = http://www.mathjax.org/mathjax
|
||||
|
||||
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
|
||||
# extension names that should be enabled during MathJax rendering. For example
|
||||
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
|
||||
# This tag requires that the tag USE_MATHJAX is set to YES.
|
||||
|
||||
MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
|
||||
MATHJAX_EXTENSIONS =
|
||||
|
||||
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
|
||||
# of code that will be used on startup of the MathJax code. See the MathJax site
|
||||
|
||||
@@ -36,8 +36,8 @@ namespace mfem {
|
||||
* - HypreSolver and other \link hypre.hpp hypre classes\endlink
|
||||
*
|
||||
* <H3>Example codes</H3>
|
||||
* - <a class="el" href="examples_2ex1_8cpp_source.html">Example 1</a>: nodal H1 FEM for the Laplace problem
|
||||
* - <a class="el" href="examples_2ex1p_8cpp_source.html">Example 1p</a>: parallel nodal H1 FEM for the Laplace problem
|
||||
* - <a class="el" href="ex1_8cpp_source.html">Example 1</a>: nodal H1 FEM for the Laplace problem
|
||||
* - <a class="el" href="ex1p_8cpp_source.html">Example 1p</a>: parallel nodal H1 FEM for the Laplace problem
|
||||
* - <a class="el" href="ex2_8cpp_source.html">Example 2</a>: vector FEM for linear elasticity
|
||||
* - <a class="el" href="ex2p_8cpp_source.html">Example 2p</a>: parallel vector FEM for linear elasticity
|
||||
* - <a class="el" href="ex3_8cpp_source.html">Example 3</a>: Nedelec H(curl) FEM for the definite Maxwell problem
|
||||
@@ -56,7 +56,7 @@ namespace mfem {
|
||||
* - <a class="el" href="ex9p_8cpp_source.html">Example 9p</a>: parallel Discontinuous Galerkin (DG) time-dependent advection
|
||||
* - <a class="el" href="ex10_8cpp_source.html">Example 10</a>: time-dependent implicit nonlinear elasticity
|
||||
* - <a class="el" href="ex10p_8cpp_source.html">Example 10p</a>: parallel time-dependent implicit nonlinear elasticity
|
||||
* - <a class="el" href="examples_2ex11p_8cpp_source.html">Example 11p</a>: parallel Laplace eigensolver
|
||||
* - <a class="el" href="ex11p_8cpp_source.html">Example 11p</a>: parallel Laplace eigensolver
|
||||
* - <a class="el" href="ex12p_8cpp_source.html">Example 12p</a>: parallel linear elasticity eigensolver
|
||||
* - <a class="el" href="ex13p_8cpp_source.html">Example 13p</a>: parallel Maxwell eigensolver
|
||||
* - <a class="el" href="ex14_8cpp_source.html">Example 14</a>: Discontinuous Galerkin (DG) for the Laplace problem
|
||||
@@ -67,20 +67,14 @@ namespace mfem {
|
||||
* - <a class="el" href="ex16p_8cpp_source.html">Example 16p</a>: parallel time-dependent nonlinear heat equation
|
||||
* - <a class="el" href="ex17_8cpp_source.html">Example 17</a>: Discontinuous Galerkin (DG) for linear elasticity
|
||||
* - <a class="el" href="ex17p_8cpp_source.html">Example 17p</a>: parallel Discontinuous Galerkin (DG) for linear elasticity
|
||||
* - <a class="el" href="ex18_8cpp_source.html">Example 18</a>: Discontinuous Galerkin (DG) for the Euler equations
|
||||
* - <a class="el" href="ex18p_8cpp_source.html">Example 18p</a>: parallel Discontinuous Galerkin (DG) for the Euler equations
|
||||
* - <a class="el" href="ex19_8cpp_source.html">Example 19</a>: incompressible nonlinear elasticity
|
||||
* - <a class="el" href="ex19p_8cpp_source.html">Example 19p</a>: parallel incompressible nonlinear elasticity
|
||||
*
|
||||
* <H4>SUNDIALS Examples</H4>
|
||||
* - Variants of Examples
|
||||
* <a class="el" href="sundials_2ex9_8cpp_source.html">9</a>,
|
||||
* <a class="el" href="sundials_2ex9p_8cpp_source.html">9p</a>,
|
||||
* <a class="el" href="sundials_2ex10_8cpp_source.html">10</a>,
|
||||
* <a class="el" href="sundials_2ex10p_8cpp_source.html">10p</a>,
|
||||
* <a class="el" href="sundials_2ex16_8cpp_source.html">16</a>,
|
||||
* and
|
||||
* <a class="el" href="sundials_2ex16p_8cpp_source.html">16p</a>
|
||||
* <a class="el" class="el" href="sundials_2ex10p_8cpp_source.html">10p</a>
|
||||
* demonstrating the use of MFEM's \link sundials.hpp SUNDIALS classes\endlink
|
||||
*
|
||||
* <H4>PETSc Examples</H4>
|
||||
@@ -96,28 +90,14 @@ namespace mfem {
|
||||
* <a class="el" href="petsc_2ex10p_8cpp_source.html">10p</a>
|
||||
* demonstrating the use of MFEM's \link petsc.hpp PETSc classes\endlink
|
||||
*
|
||||
* <H4>PUMI Examples</H4>
|
||||
* - Variants of Examples
|
||||
* <a class="el" href="examples_2pumi_2ex1_8cpp_source.html">1</a>,
|
||||
* <a class="el" href="examples_2pumi_2ex1p_8cpp_source.html">1p</a>,
|
||||
* <a class="el" href="pumi_2ex2_8cpp_source.html">2</a>,
|
||||
* and
|
||||
* <a class="el" href="pumi_2ex6p_8cpp_source.html">6p</a>
|
||||
* demonstrating the use of MFEM's \link pumi.hpp PUMI classes\endlink
|
||||
*
|
||||
* <H3>Miniapps</H3>
|
||||
* - <a class="el" href="volta_8cpp_source.html">Volta</a>: simple electrostatics simulation code
|
||||
* - <a class="el" href="tesla_8cpp_source.html">Tesla</a>: simple magnetostatics simulation code
|
||||
* - <a class="el" href="maxwell_8cpp_source.html">Maxwell</a>: simple transient full-wave electromagnetics simulation code
|
||||
* - <a class="el" href="joule_8cpp_source.html">Joule</a>: transient magnetics and Joule heating miniapp
|
||||
* - <a class="el" href="mobius-strip_8cpp_source.html">Mobius Strip</a>: generate various Mobius strip-like meshes
|
||||
* - <a class="el" href="klein-bottle_8cpp_source.html">Klein Bottle</a>: generate three types of Klein bottle surfaces
|
||||
* - <a class="el" href="shaper_8cpp_source.html">Shaper</a>: resolve material interfaces by mesh refinement
|
||||
* - <a class="el" href="mesh-explorer_8cpp_source.html">Mesh Explorer</a>: visualize and manipulate meshes
|
||||
* - <a class="el" href="mesh-optimizer_8cpp_source.html">Mesh Optimizer</a>: optimize high-order meshes, <a class="el" href="mesh-optimizer_8cpp_source.html">serial</a> and <a class="el" href="pmesh-optimizer_8cpp_source.html">parallel</a> versions
|
||||
* - <a class="el" href="display-basis_8cpp_source.html">Display Basis</a>: visualize finite element basis functions
|
||||
* - <a class="el" href="load-dc_8cpp_source.html">Load DC</a>: visualize fields saved via DataCollection classes
|
||||
* - <a class="el" href="convert-dc_8cpp_source.html">Convert DC</a>: convert between diffirent DataCollection formats
|
||||
* - <a class="el" href="miniapps_2performance_2ex1_8cpp_source.html">HPC Example 1</a>: high-performance nodal H1 FEM for the Laplace problem
|
||||
* - <a class="el" href="miniapps_2performance_2ex1p_8cpp_source.html">HPC Example 1p</a>: high-performance parallel nodal H1 FEM for the Laplace problem
|
||||
*
|
||||
|
||||
@@ -10,17 +10,17 @@
|
||||
# Software Foundation) version 2.1 dated February 1999.
|
||||
|
||||
MFEM_DIR ?= ..
|
||||
DOXYGEN_CONF = CodeDocumentation.conf
|
||||
DOXYGEN_CONG = CodeDocumentation.conf
|
||||
|
||||
# doxygen uses: graphviz, latex
|
||||
html: $(DOXYGEN_CONF)
|
||||
doxygen $(DOXYGEN_CONF)
|
||||
html: $(DOXYGEN_CONG)
|
||||
doxygen $(DOXYGEN_CONG)
|
||||
rm -f CodeDocumentation.html
|
||||
ln -s CodeDocumentation/html/index.html CodeDocumentation.html
|
||||
|
||||
clean:
|
||||
rm -rf $(DOXYGEN_CONF) CodeDocumentation CodeDocumentation.html *~
|
||||
rm -rf $(DOXYGEN_CONG) CodeDocumentation CodeDocumentation.html *~
|
||||
|
||||
$(DOXYGEN_CONF): $(MFEM_DIR)/doc/$(DOXYGEN_CONF).in
|
||||
$(DOXYGEN_CONG): $(MFEM_DIR)/doc/$(DOXYGEN_CONG).in
|
||||
sed -e 's%@MFEM_SOURCE_DIR@%$(MFEM_DIR)%g' $(<) \
|
||||
> $(DOXYGEN_CONF)
|
||||
> $(DOXYGEN_CONG)
|
||||
|
||||
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 95 KiB |
|
Before Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 118 KiB |
@@ -24,8 +24,6 @@ list(APPEND ALL_EXE_SRCS
|
||||
ex15.cpp
|
||||
ex16.cpp
|
||||
ex17.cpp
|
||||
ex18.cpp
|
||||
ex19.cpp
|
||||
)
|
||||
|
||||
if (MFEM_USE_MPI)
|
||||
@@ -47,13 +45,11 @@ if (MFEM_USE_MPI)
|
||||
ex15p.cpp
|
||||
ex16p.cpp
|
||||
ex17p.cpp
|
||||
ex18p.cpp
|
||||
ex19p.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
# Include the source directory where mfem.hpp and mfem-performance.hpp are.
|
||||
include_directories(BEFORE ${PROJECT_BINARY_DIR})
|
||||
include_directories(${PROJECT_BINARY_DIR})
|
||||
|
||||
# Add one executable per cpp file
|
||||
add_mfem_examples(ALL_EXE_SRCS)
|
||||
@@ -63,6 +59,8 @@ foreach(SRC_FILE ${ALL_EXE_SRCS})
|
||||
get_filename_component(SRC_FILENAME ${SRC_FILE} NAME)
|
||||
string(REPLACE ".cpp" "" TEST_NAME ${SRC_FILENAME})
|
||||
|
||||
string(FIND ${TEST_NAME} "p" is_parallel_test)
|
||||
|
||||
set(THIS_TEST_OPTIONS "-no-vis")
|
||||
if (${TEST_NAME} MATCHES "ex10p*")
|
||||
list(APPEND THIS_TEST_OPTIONS "-tf" "5")
|
||||
@@ -70,7 +68,7 @@ foreach(SRC_FILE ${ALL_EXE_SRCS})
|
||||
list(APPEND THIS_TEST_OPTIONS "-e" "1")
|
||||
endif()
|
||||
|
||||
if (NOT (${TEST_NAME} MATCHES ".*p$"))
|
||||
if (is_parallel_test EQUAL -1)
|
||||
add_test(NAME ${TEST_NAME}_ser
|
||||
COMMAND ${TEST_NAME} ${THIS_TEST_OPTIONS})
|
||||
else()
|
||||
@@ -82,17 +80,7 @@ foreach(SRC_FILE ${ALL_EXE_SRCS})
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Include the examples/sundials directory if SUNDIALS is enabled.
|
||||
if (MFEM_USE_SUNDIALS)
|
||||
add_subdirectory(sundials)
|
||||
endif()
|
||||
|
||||
# Include the examples/petsc directory if PETSc is enabled.
|
||||
if (MFEM_USE_PETSC)
|
||||
add_subdirectory(petsc)
|
||||
endif()
|
||||
|
||||
# Include the examples/pumi directory if PUMI is enabled
|
||||
if (MFEM_USE_PUMI)
|
||||
add_subdirectory(pumi)
|
||||
endif()
|
||||
# Include the examples/sundials directory.
|
||||
add_subdirectory(sundials)
|
||||
# Include the examples/petsc directory.
|
||||
add_subdirectory(petsc)
|
||||
|
||||
@@ -80,8 +80,8 @@ int main(int argc, char *argv[])
|
||||
// largest number that gives a final mesh with no more than 50,000
|
||||
// elements.
|
||||
{
|
||||
int ref_levels = 0;
|
||||
//(int)floor(log(50000./mesh->GetNE())/log(2.)/dim);
|
||||
int ref_levels =
|
||||
(int)floor(log(50000./mesh->GetNE())/log(2.)/dim);
|
||||
for (int l = 0; l < ref_levels; l++)
|
||||
{
|
||||
mesh->UniformRefinement();
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
// ex10 -m ../data/beam-tet.mesh -s 2 -r 1 -o 2 -dt 3
|
||||
// ex10 -m ../data/beam-quad.mesh -s 14 -r 2 -o 2 -dt 0.03 -vs 20
|
||||
// ex10 -m ../data/beam-hex.mesh -s 14 -r 1 -o 2 -dt 0.05 -vs 20
|
||||
// ex10 -m ../data/beam-quad-amr.mesh -s 3 -r 2 -o 2 -dt 3
|
||||
//
|
||||
// Description: This examples solves a time dependent nonlinear elasticity
|
||||
// problem of the form dv/dt = H(x) + S v, dx/dt = v, where H is a
|
||||
@@ -91,9 +90,9 @@ public:
|
||||
This is the only requirement for high-order SDIRK implicit integration.*/
|
||||
virtual void ImplicitSolve(const double dt, const Vector &x, Vector &k);
|
||||
|
||||
double ElasticEnergy(const Vector &x) const;
|
||||
double KineticEnergy(const Vector &v) const;
|
||||
void GetElasticEnergyDensity(const GridFunction &x, GridFunction &w) const;
|
||||
double ElasticEnergy(Vector &x) const;
|
||||
double KineticEnergy(Vector &v) const;
|
||||
void GetElasticEnergyDensity(GridFunction &x, GridFunction &w) const;
|
||||
|
||||
virtual ~HyperelasticOperator();
|
||||
};
|
||||
@@ -133,12 +132,12 @@ public:
|
||||
class ElasticEnergyCoefficient : public Coefficient
|
||||
{
|
||||
private:
|
||||
HyperelasticModel &model;
|
||||
const GridFunction &x;
|
||||
DenseMatrix J;
|
||||
HyperelasticModel &model;
|
||||
GridFunction &x;
|
||||
DenseMatrix J;
|
||||
|
||||
public:
|
||||
ElasticEnergyCoefficient(HyperelasticModel &m, const GridFunction &x_)
|
||||
ElasticEnergyCoefficient(HyperelasticModel &m, GridFunction &x_)
|
||||
: model(m), x(x_) { }
|
||||
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip);
|
||||
virtual ~ElasticEnergyCoefficient() { }
|
||||
@@ -222,14 +221,12 @@ int main(int argc, char *argv[])
|
||||
case 12: ode_solver = new RK2Solver(0.5); break; // midpoint method
|
||||
case 13: ode_solver = new RK3SSPSolver; break;
|
||||
case 14: ode_solver = new RK4Solver; break;
|
||||
case 15: ode_solver = new GeneralizedAlphaSolver(0.5); break;
|
||||
// Implicit A-stable methods (not L-stable)
|
||||
case 22: ode_solver = new ImplicitMidpointSolver; break;
|
||||
case 23: ode_solver = new SDIRK23Solver; break;
|
||||
case 24: ode_solver = new SDIRK34Solver; break;
|
||||
default:
|
||||
cout << "Unknown ODE solver type: " << ode_solver_type << '\n';
|
||||
delete mesh;
|
||||
return 3;
|
||||
}
|
||||
|
||||
@@ -250,7 +247,7 @@ int main(int argc, char *argv[])
|
||||
H1_FECollection fe_coll(order, dim);
|
||||
FiniteElementSpace fespace(mesh, &fe_coll, dim);
|
||||
|
||||
int fe_size = fespace.GetTrueVSize();
|
||||
int fe_size = fespace.GetVSize();
|
||||
cout << "Number of velocity/deformation unknowns: " << fe_size << endl;
|
||||
Array<int> fe_offset(3);
|
||||
fe_offset[0] = 0;
|
||||
@@ -259,8 +256,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
BlockVector vx(fe_offset);
|
||||
GridFunction v, x;
|
||||
v.MakeTRef(&fespace, vx.GetBlock(0), 0);
|
||||
x.MakeTRef(&fespace, vx.GetBlock(1), 0);
|
||||
v.MakeRef(&fespace, vx.GetBlock(0), 0);
|
||||
x.MakeRef(&fespace, vx.GetBlock(1), 0);
|
||||
|
||||
GridFunction x_ref(&fespace);
|
||||
mesh->GetNodes(x_ref);
|
||||
@@ -273,10 +270,8 @@ int main(int argc, char *argv[])
|
||||
// a beam-like mesh (see description above).
|
||||
VectorFunctionCoefficient velo(dim, InitialVelocity);
|
||||
v.ProjectCoefficient(velo);
|
||||
v.SetTrueVector();
|
||||
VectorFunctionCoefficient deform(dim, InitialDeformation);
|
||||
x.ProjectCoefficient(deform);
|
||||
x.SetTrueVector();
|
||||
|
||||
Array<int> ess_bdr(fespace.GetMesh()->bdr_attributes.Max());
|
||||
ess_bdr = 0;
|
||||
@@ -293,7 +288,6 @@ int main(int argc, char *argv[])
|
||||
int visport = 19916;
|
||||
vis_v.open(vishost, visport);
|
||||
vis_v.precision(8);
|
||||
v.SetFromTrueVector(); x.SetFromTrueVector();
|
||||
visualize(vis_v, mesh, &x, &v, "Velocity", true);
|
||||
vis_w.open(vishost, visport);
|
||||
if (vis_w)
|
||||
@@ -304,8 +298,8 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
double ee0 = oper.ElasticEnergy(x.GetTrueVector());
|
||||
double ke0 = oper.KineticEnergy(v.GetTrueVector());
|
||||
double ee0 = oper.ElasticEnergy(x);
|
||||
double ke0 = oper.KineticEnergy(v);
|
||||
cout << "initial elastic energy (EE) = " << ee0 << endl;
|
||||
cout << "initial kinetic energy (KE) = " << ke0 << endl;
|
||||
cout << "initial total energy (TE) = " << (ee0 + ke0) << endl;
|
||||
@@ -327,15 +321,14 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (last_step || (ti % vis_steps) == 0)
|
||||
{
|
||||
double ee = oper.ElasticEnergy(x.GetTrueVector());
|
||||
double ke = oper.KineticEnergy(v.GetTrueVector());
|
||||
double ee = oper.ElasticEnergy(x);
|
||||
double ke = oper.KineticEnergy(v);
|
||||
|
||||
cout << "step " << ti << ", t = " << t << ", EE = " << ee << ", KE = "
|
||||
<< ke << ", ΔTE = " << (ee+ke)-(ee0+ke0) << endl;
|
||||
|
||||
if (visualization)
|
||||
{
|
||||
v.SetFromTrueVector(); x.SetFromTrueVector();
|
||||
visualize(vis_v, mesh, &x, &v);
|
||||
if (vis_w)
|
||||
{
|
||||
@@ -348,7 +341,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
// 9. Save the displaced mesh, the velocity and elastic energy.
|
||||
{
|
||||
v.SetFromTrueVector(); x.SetFromTrueVector();
|
||||
GridFunction *nodes = &x;
|
||||
int owns_nodes = 0;
|
||||
mesh->SwapNodes(nodes, owns_nodes);
|
||||
@@ -449,7 +441,7 @@ ReducedSystemOperator::~ReducedSystemOperator()
|
||||
HyperelasticOperator::HyperelasticOperator(FiniteElementSpace &f,
|
||||
Array<int> &ess_bdr, double visc,
|
||||
double mu, double K)
|
||||
: TimeDependentOperator(2*f.GetTrueVSize(), 0.0), fespace(f),
|
||||
: TimeDependentOperator(2*f.GetVSize(), 0.0), fespace(f),
|
||||
M(&fespace), S(&fespace), H(&fespace),
|
||||
viscosity(visc), z(height/2)
|
||||
{
|
||||
@@ -460,10 +452,8 @@ HyperelasticOperator::HyperelasticOperator(FiniteElementSpace &f,
|
||||
ConstantCoefficient rho0(ref_density);
|
||||
M.AddDomainIntegrator(new VectorMassIntegrator(rho0));
|
||||
M.Assemble(skip_zero_entries);
|
||||
Array<int> ess_tdof_list;
|
||||
fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
|
||||
SparseMatrix tmp;
|
||||
M.FormSystemMatrix(ess_tdof_list, tmp);
|
||||
M.EliminateEssentialBC(ess_bdr);
|
||||
M.Finalize(skip_zero_entries);
|
||||
|
||||
M_solver.iterative_mode = false;
|
||||
M_solver.SetRelTol(rel_tol);
|
||||
@@ -475,12 +465,13 @@ HyperelasticOperator::HyperelasticOperator(FiniteElementSpace &f,
|
||||
|
||||
model = new NeoHookeanModel(mu, K);
|
||||
H.AddDomainIntegrator(new HyperelasticNLFIntegrator(model));
|
||||
H.SetEssentialTrueDofs(ess_tdof_list);
|
||||
H.SetEssentialBC(ess_bdr);
|
||||
|
||||
ConstantCoefficient visc_coeff(viscosity);
|
||||
S.AddDomainIntegrator(new VectorDiffusionIntegrator(visc_coeff));
|
||||
S.Assemble(skip_zero_entries);
|
||||
S.FormSystemMatrix(ess_tdof_list, tmp);
|
||||
S.EliminateEssentialBC(ess_bdr);
|
||||
S.Finalize(skip_zero_entries);
|
||||
|
||||
reduced_oper = new ReducedSystemOperator(&M, &S, &H);
|
||||
|
||||
@@ -549,18 +540,18 @@ void HyperelasticOperator::ImplicitSolve(const double dt,
|
||||
add(v, dt, dv_dt, dx_dt);
|
||||
}
|
||||
|
||||
double HyperelasticOperator::ElasticEnergy(const Vector &x) const
|
||||
double HyperelasticOperator::ElasticEnergy(Vector &x) const
|
||||
{
|
||||
return H.GetEnergy(x);
|
||||
}
|
||||
|
||||
double HyperelasticOperator::KineticEnergy(const Vector &v) const
|
||||
double HyperelasticOperator::KineticEnergy(Vector &v) const
|
||||
{
|
||||
return 0.5*M.InnerProduct(v, v);
|
||||
}
|
||||
|
||||
void HyperelasticOperator::GetElasticEnergyDensity(
|
||||
const GridFunction &x, GridFunction &w) const
|
||||
GridFunction &x, GridFunction &w) const
|
||||
{
|
||||
ElasticEnergyCoefficient w_coeff(*model, x);
|
||||
w.ProjectCoefficient(w_coeff);
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
// mpirun -np 4 ex10p -m ../data/beam-tet.mesh -s 2 -rs 1 -dt 3
|
||||
// mpirun -np 4 ex10p -m ../data/beam-quad.mesh -s 14 -rs 2 -dt 0.03 -vs 20
|
||||
// mpirun -np 4 ex10p -m ../data/beam-hex.mesh -s 14 -rs 1 -dt 0.05 -vs 20
|
||||
// mpirun -np 4 ex10p -m ../data/beam-quad-amr.mesh -s 3 -rs 2 -dt 3
|
||||
//
|
||||
// Description: This examples solves a time dependent nonlinear elasticity
|
||||
// problem of the form dv/dt = H(x) + S v, dx/dt = v, where H is a
|
||||
@@ -58,7 +57,6 @@ class HyperelasticOperator : public TimeDependentOperator
|
||||
{
|
||||
protected:
|
||||
ParFiniteElementSpace &fespace;
|
||||
Array<int> ess_tdof_list;
|
||||
|
||||
ParBilinearForm M, S;
|
||||
ParNonlinearForm H;
|
||||
@@ -93,10 +91,9 @@ public:
|
||||
This is the only requirement for high-order SDIRK implicit integration.*/
|
||||
virtual void ImplicitSolve(const double dt, const Vector &x, Vector &k);
|
||||
|
||||
double ElasticEnergy(const ParGridFunction &x) const;
|
||||
double KineticEnergy(const ParGridFunction &v) const;
|
||||
void GetElasticEnergyDensity(const ParGridFunction &x,
|
||||
ParGridFunction &w) const;
|
||||
double ElasticEnergy(ParGridFunction &x) const;
|
||||
double KineticEnergy(ParGridFunction &v) const;
|
||||
void GetElasticEnergyDensity(ParGridFunction &x, ParGridFunction &w) const;
|
||||
|
||||
virtual ~HyperelasticOperator();
|
||||
};
|
||||
@@ -114,11 +111,10 @@ private:
|
||||
double dt;
|
||||
const Vector *v, *x;
|
||||
mutable Vector w, z;
|
||||
const Array<int> &ess_tdof_list;
|
||||
|
||||
public:
|
||||
ReducedSystemOperator(ParBilinearForm *M_, ParBilinearForm *S_,
|
||||
ParNonlinearForm *H_, const Array<int> &ess_tdof_list);
|
||||
ParNonlinearForm *H_);
|
||||
|
||||
/// Set current dt, v, x values - needed to compute action and Jacobian.
|
||||
void SetParameters(double dt_, const Vector *v_, const Vector *x_);
|
||||
@@ -138,12 +134,12 @@ public:
|
||||
class ElasticEnergyCoefficient : public Coefficient
|
||||
{
|
||||
private:
|
||||
HyperelasticModel &model;
|
||||
const ParGridFunction &x;
|
||||
DenseMatrix J;
|
||||
HyperelasticModel &model;
|
||||
ParGridFunction &x;
|
||||
DenseMatrix J;
|
||||
|
||||
public:
|
||||
ElasticEnergyCoefficient(HyperelasticModel &m, const ParGridFunction &x_)
|
||||
ElasticEnergyCoefficient(HyperelasticModel &m, ParGridFunction &x_)
|
||||
: model(m), x(x_) { }
|
||||
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip);
|
||||
virtual ~ElasticEnergyCoefficient() { }
|
||||
@@ -244,7 +240,6 @@ int main(int argc, char *argv[])
|
||||
case 12: ode_solver = new RK2Solver(0.5); break; // midpoint method
|
||||
case 13: ode_solver = new RK3SSPSolver; break;
|
||||
case 14: ode_solver = new RK4Solver; break;
|
||||
case 15: ode_solver = new GeneralizedAlphaSolver(0.5); break;
|
||||
// Implicit A-stable methods (not L-stable)
|
||||
case 22: ode_solver = new ImplicitMidpointSolver; break;
|
||||
case 23: ode_solver = new SDIRK23Solver; break;
|
||||
@@ -254,7 +249,6 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
cout << "Unknown ODE solver type: " << ode_solver_type << '\n';
|
||||
}
|
||||
delete mesh;
|
||||
MPI_Finalize();
|
||||
return 3;
|
||||
}
|
||||
@@ -298,9 +292,7 @@ int main(int argc, char *argv[])
|
||||
true_offset[2] = 2*true_size;
|
||||
|
||||
BlockVector vx(true_offset);
|
||||
ParGridFunction v_gf, x_gf;
|
||||
v_gf.MakeTRef(&fespace, vx, true_offset[0]);
|
||||
x_gf.MakeTRef(&fespace, vx, true_offset[1]);
|
||||
ParGridFunction v_gf(&fespace), x_gf(&fespace);
|
||||
|
||||
ParGridFunction x_ref(&fespace);
|
||||
pmesh->GetNodes(x_ref);
|
||||
@@ -313,12 +305,11 @@ int main(int argc, char *argv[])
|
||||
// boundary conditions on a beam-like mesh (see description above).
|
||||
VectorFunctionCoefficient velo(dim, InitialVelocity);
|
||||
v_gf.ProjectCoefficient(velo);
|
||||
v_gf.SetTrueVector();
|
||||
VectorFunctionCoefficient deform(dim, InitialDeformation);
|
||||
x_gf.ProjectCoefficient(deform);
|
||||
x_gf.SetTrueVector();
|
||||
|
||||
v_gf.SetFromTrueVector(); x_gf.SetFromTrueVector();
|
||||
v_gf.GetTrueDofs(vx.GetBlock(0));
|
||||
x_gf.GetTrueDofs(vx.GetBlock(1));
|
||||
|
||||
Array<int> ess_bdr(fespace.GetMesh()->bdr_attributes.Max());
|
||||
ess_bdr = 0;
|
||||
@@ -374,7 +365,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (last_step || (ti % vis_steps) == 0)
|
||||
{
|
||||
v_gf.SetFromTrueVector(); x_gf.SetFromTrueVector();
|
||||
v_gf.Distribute(vx.GetBlock(0));
|
||||
x_gf.Distribute(vx.GetBlock(1));
|
||||
|
||||
double ee = oper.ElasticEnergy(x_gf);
|
||||
double ke = oper.KineticEnergy(v_gf);
|
||||
@@ -399,7 +391,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
// 11. Save the displaced mesh, the velocity and elastic energy.
|
||||
{
|
||||
v_gf.SetFromTrueVector(); x_gf.SetFromTrueVector();
|
||||
GridFunction *nodes = &x_gf;
|
||||
int owns_nodes = 0;
|
||||
pmesh->SwapNodes(nodes, owns_nodes);
|
||||
@@ -467,11 +458,9 @@ void visualize(ostream &out, ParMesh *mesh, ParGridFunction *deformed_nodes,
|
||||
|
||||
|
||||
ReducedSystemOperator::ReducedSystemOperator(
|
||||
ParBilinearForm *M_, ParBilinearForm *S_, ParNonlinearForm *H_,
|
||||
const Array<int> &ess_tdof_list_)
|
||||
ParBilinearForm *M_, ParBilinearForm *S_, ParNonlinearForm *H_)
|
||||
: Operator(M_->ParFESpace()->TrueVSize()), M(M_), S(S_), H(H_),
|
||||
Jacobian(NULL), dt(0.0), v(NULL), x(NULL), w(height), z(height),
|
||||
ess_tdof_list(ess_tdof_list_)
|
||||
Jacobian(NULL), dt(0.0), v(NULL), x(NULL), w(height), z(height)
|
||||
{ }
|
||||
|
||||
void ReducedSystemOperator::SetParameters(double dt_, const Vector *v_,
|
||||
@@ -488,7 +477,6 @@ void ReducedSystemOperator::Mult(const Vector &k, Vector &y) const
|
||||
H->Mult(z, y);
|
||||
M->TrueAddMult(k, y);
|
||||
S->TrueAddMult(w, y);
|
||||
y.SetSubVector(ess_tdof_list, 0.0);
|
||||
}
|
||||
|
||||
Operator &ReducedSystemOperator::GetGradient(const Vector &k) const
|
||||
@@ -500,8 +488,6 @@ Operator &ReducedSystemOperator::GetGradient(const Vector &k) const
|
||||
localJ->Add(dt*dt, H->GetLocalGradient(z));
|
||||
Jacobian = M->ParallelAssemble(localJ);
|
||||
delete localJ;
|
||||
HypreParMatrix *Je = Jacobian->EliminateRowsCols(ess_tdof_list);
|
||||
delete Je;
|
||||
return *Jacobian;
|
||||
}
|
||||
|
||||
@@ -526,11 +512,9 @@ HyperelasticOperator::HyperelasticOperator(ParFiniteElementSpace &f,
|
||||
ConstantCoefficient rho0(ref_density);
|
||||
M.AddDomainIntegrator(new VectorMassIntegrator(rho0));
|
||||
M.Assemble(skip_zero_entries);
|
||||
M.EliminateEssentialBC(ess_bdr);
|
||||
M.Finalize(skip_zero_entries);
|
||||
Mmat = M.ParallelAssemble();
|
||||
fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
|
||||
HypreParMatrix *Me = Mmat->EliminateRowsCols(ess_tdof_list);
|
||||
delete Me;
|
||||
|
||||
M_solver.iterative_mode = false;
|
||||
M_solver.SetRelTol(rel_tol);
|
||||
@@ -543,14 +527,15 @@ HyperelasticOperator::HyperelasticOperator(ParFiniteElementSpace &f,
|
||||
|
||||
model = new NeoHookeanModel(mu, K);
|
||||
H.AddDomainIntegrator(new HyperelasticNLFIntegrator(model));
|
||||
H.SetEssentialTrueDofs(ess_tdof_list);
|
||||
H.SetEssentialBC(ess_bdr);
|
||||
|
||||
ConstantCoefficient visc_coeff(viscosity);
|
||||
S.AddDomainIntegrator(new VectorDiffusionIntegrator(visc_coeff));
|
||||
S.Assemble(skip_zero_entries);
|
||||
S.EliminateEssentialBC(ess_bdr);
|
||||
S.Finalize(skip_zero_entries);
|
||||
|
||||
reduced_oper = new ReducedSystemOperator(&M, &S, &H, ess_tdof_list);
|
||||
reduced_oper = new ReducedSystemOperator(&M, &S, &H);
|
||||
|
||||
HypreSmoother *J_hypreSmoother = new HypreSmoother;
|
||||
J_hypreSmoother->SetType(HypreSmoother::l1Jacobi);
|
||||
@@ -587,7 +572,6 @@ void HyperelasticOperator::Mult(const Vector &vx, Vector &dvx_dt) const
|
||||
if (viscosity != 0.0)
|
||||
{
|
||||
S.TrueAddMult(v, z);
|
||||
z.SetSubVector(ess_tdof_list, 0.0);
|
||||
}
|
||||
z.Neg(); // z = -z
|
||||
M_solver.Mult(z, dv_dt);
|
||||
@@ -617,12 +601,12 @@ void HyperelasticOperator::ImplicitSolve(const double dt,
|
||||
add(v, dt, dv_dt, dx_dt);
|
||||
}
|
||||
|
||||
double HyperelasticOperator::ElasticEnergy(const ParGridFunction &x) const
|
||||
double HyperelasticOperator::ElasticEnergy(ParGridFunction &x) const
|
||||
{
|
||||
return H.GetEnergy(x);
|
||||
}
|
||||
|
||||
double HyperelasticOperator::KineticEnergy(const ParGridFunction &v) const
|
||||
double HyperelasticOperator::KineticEnergy(ParGridFunction &v) const
|
||||
{
|
||||
double loc_energy = 0.5*M.InnerProduct(v, v);
|
||||
double energy;
|
||||
@@ -632,7 +616,7 @@ double HyperelasticOperator::KineticEnergy(const ParGridFunction &v) const
|
||||
}
|
||||
|
||||
void HyperelasticOperator::GetElasticEnergyDensity(
|
||||
const ParGridFunction &x, ParGridFunction &w) const
|
||||
ParGridFunction &x, ParGridFunction &w) const
|
||||
{
|
||||
ElasticEnergyCoefficient w_coeff(*model, x);
|
||||
w.ProjectCoefficient(w_coeff);
|
||||
|
||||
@@ -32,9 +32,9 @@
|
||||
//
|
||||
// The example highlights the use of the LOBPCG eigenvalue solver
|
||||
// together with the BoomerAMG preconditioner in HYPRE, as well as
|
||||
// optionally the SuperLU or STRUMPACK parallel direct solvers.
|
||||
// Reusing a single GLVis visualization window for multiple
|
||||
// eigenfunctions is also illustrated.
|
||||
// optionally the SuperLU parallel direct solver. Reusing a single
|
||||
// GLVis visualization window for multiple eigenfunctions is also
|
||||
// illustrated.
|
||||
//
|
||||
// We recommend viewing Example 1 before viewing this example.
|
||||
|
||||
@@ -61,7 +61,6 @@ int main(int argc, char *argv[])
|
||||
int nev = 5;
|
||||
int seed = 75;
|
||||
bool slu_solver = false;
|
||||
bool sp_solver = false;
|
||||
bool visualization = 1;
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
@@ -81,36 +80,19 @@ int main(int argc, char *argv[])
|
||||
#ifdef MFEM_USE_SUPERLU
|
||||
args.AddOption(&slu_solver, "-slu", "--superlu", "-no-slu",
|
||||
"--no-superlu", "Use the SuperLU Solver.");
|
||||
#endif
|
||||
#ifdef MFEM_USE_STRUMPACK
|
||||
args.AddOption(&sp_solver, "-sp", "--strumpack", "-no-sp",
|
||||
"--no-strumpack", "Use the STRUMPACK Solver.");
|
||||
#endif
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
args.Parse();
|
||||
if (slu_solver && sp_solver)
|
||||
if (!args.Good())
|
||||
{
|
||||
if (myid == 0)
|
||||
cout << "WARNING: Both SuperLU and STRUMPACK have been selected,"
|
||||
<< " please choose either one." << endl
|
||||
<< " Defaulting to SuperLU." << endl;
|
||||
sp_solver = false;
|
||||
}
|
||||
// The command line options are also passed to the STRUMPACK
|
||||
// solver. So do not exit if some options are not recognized.
|
||||
if (!sp_solver)
|
||||
{
|
||||
if (!args.Good())
|
||||
{
|
||||
if (myid == 0)
|
||||
{
|
||||
args.PrintUsage(cout);
|
||||
}
|
||||
MPI_Finalize();
|
||||
return 1;
|
||||
args.PrintUsage(cout);
|
||||
}
|
||||
MPI_Finalize();
|
||||
return 1;
|
||||
}
|
||||
if (myid == 0)
|
||||
{
|
||||
@@ -203,20 +185,12 @@ int main(int argc, char *argv[])
|
||||
HypreParMatrix *A = a->ParallelAssemble();
|
||||
HypreParMatrix *M = m->ParallelAssemble();
|
||||
|
||||
#if defined(MFEM_USE_SUPERLU) || defined(MFEM_USE_STRUMPACK)
|
||||
Operator * Arow = NULL;
|
||||
#ifdef MFEM_USE_SUPERLU
|
||||
Operator * Arow = NULL;
|
||||
if (slu_solver)
|
||||
{
|
||||
Arow = new SuperLURowLocMatrix(*A);
|
||||
}
|
||||
#endif
|
||||
#ifdef MFEM_USE_STRUMPACK
|
||||
if (sp_solver)
|
||||
{
|
||||
Arow = new STRUMPACKRowLocMatrix(*A);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
delete a;
|
||||
@@ -226,42 +200,23 @@ int main(int argc, char *argv[])
|
||||
// preconditioner for A to be used within the solver. Set the matrices
|
||||
// which define the generalized eigenproblem A x = lambda M x.
|
||||
Solver * precond = NULL;
|
||||
if (!slu_solver && !sp_solver)
|
||||
if (!slu_solver)
|
||||
{
|
||||
HypreBoomerAMG * amg = new HypreBoomerAMG(*A);
|
||||
amg->SetPrintLevel(0);
|
||||
precond = amg;
|
||||
}
|
||||
#ifdef MFEM_USE_SUPERLU
|
||||
else
|
||||
{
|
||||
#ifdef MFEM_USE_SUPERLU
|
||||
if (slu_solver)
|
||||
{
|
||||
SuperLUSolver * superlu = new SuperLUSolver(MPI_COMM_WORLD);
|
||||
superlu->SetPrintStatistics(false);
|
||||
superlu->SetSymmetricPattern(true);
|
||||
superlu->SetColumnPermutation(superlu::PARMETIS);
|
||||
superlu->SetOperator(*Arow);
|
||||
precond = superlu;
|
||||
}
|
||||
#endif
|
||||
#ifdef MFEM_USE_STRUMPACK
|
||||
if (sp_solver)
|
||||
{
|
||||
STRUMPACKSolver * strumpack = new STRUMPACKSolver(argc, argv, MPI_COMM_WORLD);
|
||||
strumpack->SetPrintFactorStatistics(true);
|
||||
strumpack->SetPrintSolveStatistics(false);
|
||||
strumpack->SetKrylovSolver(strumpack::KrylovSolver::DIRECT);
|
||||
strumpack->SetReorderingStrategy(strumpack::ReorderingStrategy::METIS);
|
||||
strumpack->SetMC64Job(strumpack::MC64Job::NONE);
|
||||
// strumpack->SetSymmetricPattern(true);
|
||||
strumpack->SetOperator(*Arow);
|
||||
strumpack->SetFromCommandLine();
|
||||
precond = strumpack;
|
||||
}
|
||||
#endif
|
||||
SuperLUSolver * superlu = new SuperLUSolver(MPI_COMM_WORLD);
|
||||
superlu->SetPrintStatistics(false);
|
||||
superlu->SetSymmetricPattern(true);
|
||||
superlu->SetColumnPermutation(superlu::PARMETIS);
|
||||
superlu->SetOperator(*Arow);
|
||||
precond = superlu;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
HypreLOBPCG * lobpcg = new HypreLOBPCG(MPI_COMM_WORLD);
|
||||
lobpcg->SetNumModes(nev);
|
||||
@@ -352,7 +307,7 @@ int main(int argc, char *argv[])
|
||||
delete precond;
|
||||
delete M;
|
||||
delete A;
|
||||
#if defined(MFEM_USE_SUPERLU) || defined(MFEM_USE_STRUMPACK)
|
||||
#ifdef MFEM_USE_SUPERLU
|
||||
delete Arow;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -2,15 +2,14 @@
|
||||
//
|
||||
// Compile with: make ex12p
|
||||
//
|
||||
// Sample runs:
|
||||
// mpirun -np 4 ex12p -m ../data/beam-tri.mesh
|
||||
// mpirun -np 4 ex12p -m ../data/beam-quad.mesh
|
||||
// mpirun -np 4 ex12p -m ../data/beam-tet.mesh -n 10 -o 2 -elast
|
||||
// mpirun -np 4 ex12p -m ../data/beam-hex.mesh -s 3876
|
||||
// mpirun -np 4 ex12p -m ../data/beam-tri.mesh -o 2 -sys
|
||||
// mpirun -np 4 ex12p -m ../data/beam-quad.mesh -s 4526 -n 6 -o 3 -elast
|
||||
// mpirun -np 4 ex12p -m ../data/beam-quad-nurbs.mesh
|
||||
// mpirun -np 4 ex12p -m ../data/beam-hex-nurbs.mesh
|
||||
// Sample runs: mpirun -np 4 ex12p -m ../data/beam-tri.mesh
|
||||
// mpirun -np 4 ex12p -m ../data/beam-quad.mesh
|
||||
// mpirun -np 4 ex12p -m ../data/beam-tet.mesh -n 10 -o 2 -elast
|
||||
// mpirun -np 4 ex12p -m ../data/beam-hex.mesh -s 3876
|
||||
// mpirun -np 4 ex12p -m ../data/beam-tri.mesh -o 2 -sys
|
||||
// mpirun -np 4 ex12p -m ../data/beam-quad.mesh -n 6 -o 3 -elast
|
||||
// mpirun -np 4 ex12p -m ../data/beam-quad-nurbs.mesh
|
||||
// mpirun -np 4 ex12p -m ../data/beam-hex-nurbs.mesh
|
||||
//
|
||||
// Description: This example code solves the linear elasticity eigenvalue
|
||||
// problem for a multi-material cantilever beam.
|
||||
@@ -109,9 +108,9 @@ int main(int argc, char *argv[])
|
||||
|
||||
// 4. Select the order of the finite element discretization space. For NURBS
|
||||
// meshes, we increase the order by degree elevation.
|
||||
if (mesh->NURBSext)
|
||||
if (mesh->NURBSext && order > mesh->NURBSext->GetOrder())
|
||||
{
|
||||
mesh->DegreeElevate(order, order);
|
||||
mesh->DegreeElevate(order - mesh->NURBSext->GetOrder());
|
||||
}
|
||||
|
||||
// 5. Refine the serial mesh on all processors to increase the resolution. In
|
||||
|
||||
@@ -110,7 +110,6 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
pmesh->UniformRefinement();
|
||||
}
|
||||
pmesh->ReorientTetMesh();
|
||||
|
||||
// 6. Define a parallel finite element space on the parallel mesh. Here we
|
||||
// use the Nedelec finite elements of the specified order.
|
||||
|
||||
@@ -157,14 +157,12 @@ int main(int argc, char *argv[])
|
||||
case 12: ode_solver = new RK2Solver(0.5); break; // midpoint method
|
||||
case 13: ode_solver = new RK3SSPSolver; break;
|
||||
case 14: ode_solver = new RK4Solver; break;
|
||||
case 15: ode_solver = new GeneralizedAlphaSolver(0.5); break;
|
||||
// Implicit A-stable methods (not L-stable)
|
||||
case 22: ode_solver = new ImplicitMidpointSolver; break;
|
||||
case 23: ode_solver = new SDIRK23Solver; break;
|
||||
case 24: ode_solver = new SDIRK34Solver; break;
|
||||
default:
|
||||
cout << "Unknown ODE solver type: " << ode_solver_type << '\n';
|
||||
delete mesh;
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// MFEM Example 16 - Parallel Version
|
||||
// MFEM Example 16 - Parallel Version
|
||||
//
|
||||
// Compile with: make ex16p
|
||||
//
|
||||
@@ -173,14 +173,12 @@ int main(int argc, char *argv[])
|
||||
case 12: ode_solver = new RK2Solver(0.5); break; // midpoint method
|
||||
case 13: ode_solver = new RK3SSPSolver; break;
|
||||
case 14: ode_solver = new RK4Solver; break;
|
||||
case 15: ode_solver = new GeneralizedAlphaSolver(0.5); break;
|
||||
// Implicit A-stable methods (not L-stable)
|
||||
case 22: ode_solver = new ImplicitMidpointSolver; break;
|
||||
case 23: ode_solver = new SDIRK23Solver; break;
|
||||
case 24: ode_solver = new SDIRK34Solver; break;
|
||||
default:
|
||||
cout << "Unknown ODE solver type: " << ode_solver_type << '\n';
|
||||
delete mesh;
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,309 +0,0 @@
|
||||
// MFEM Example 18
|
||||
//
|
||||
// Compile with: make ex18
|
||||
//
|
||||
// Sample runs:
|
||||
//
|
||||
// ex18 -p 1 -r 2 -o 1 -s 3
|
||||
// ex18 -p 1 -r 1 -o 3 -s 4
|
||||
// ex18 -p 1 -r 0 -o 5 -s 6
|
||||
// ex18 -p 2 -r 1 -o 1 -s 3
|
||||
// ex18 -p 2 -r 0 -o 3 -s 3
|
||||
//
|
||||
// Description: This example code solves the compressible Euler system of
|
||||
// equations, a model nonlinear hyperbolic PDE, with a
|
||||
// discontinuous Galerkin (DG) formulation.
|
||||
//
|
||||
// Specifically, it solves for an exact solution of the equations
|
||||
// whereby a vortex is transported by a uniform flow. Since all
|
||||
// boundaries are periodic here, the method's accuracy can be
|
||||
// assessed by measuring the difference between the solution and
|
||||
// the initial condition at a later time when the vortex returns
|
||||
// to its initial location.
|
||||
//
|
||||
// Note that as the order of the spatial discretization increases,
|
||||
// the timestep must become smaller. This example currently uses a
|
||||
// simple estimate derived by Cockburn and Shu for the 1D RKDG
|
||||
// method. An additional factor can be tuned by passing the --cfl
|
||||
// (or -c shorter) flag.
|
||||
//
|
||||
// The example demonstrates user-defined bilinear and nonlinear
|
||||
// form integrators for systems of equations that are defined with
|
||||
// block vectors, and how these are used with an operator for
|
||||
// explicit time integrators. In this case the system also
|
||||
// involves an external approximate Riemann solver for the DG
|
||||
// interface flux. It also demonstrates how to use GLVis for
|
||||
// in-situ visualization of vector grid functions.
|
||||
//
|
||||
// We recommend viewing examples 9, 14 and 17 before viewing this
|
||||
// example.
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
// Classes FE_Evolution, RiemannSolver, DomainIntegrator and FaceIntegrator
|
||||
// shared between the serial and parallel version of the example.
|
||||
#include "ex18.hpp"
|
||||
|
||||
// Choice for the problem setup. See InitialCondition in ex18.hpp.
|
||||
int problem;
|
||||
|
||||
// Equation constant parameters.
|
||||
const int num_equation = 4;
|
||||
const double specific_heat_ratio = 1.4;
|
||||
const double gas_constant = 1.0;
|
||||
|
||||
// Maximum characteristic speed (updated by integrators)
|
||||
double max_char_speed;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// 1. Parse command-line options.
|
||||
problem = 1;
|
||||
const char *mesh_file = "../data/periodic-square.mesh";
|
||||
int ref_levels = 1;
|
||||
int order = 3;
|
||||
int ode_solver_type = 4;
|
||||
double t_final = 2.0;
|
||||
double dt = -0.01;
|
||||
double cfl = 0.3;
|
||||
bool visualization = true;
|
||||
int vis_steps = 50;
|
||||
|
||||
int precision = 8;
|
||||
cout.precision(precision);
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
args.AddOption(&mesh_file, "-m", "--mesh",
|
||||
"Mesh file to use.");
|
||||
args.AddOption(&problem, "-p", "--problem",
|
||||
"Problem setup to use. See options in velocity_function().");
|
||||
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(&ode_solver_type, "-s", "--ode-solver",
|
||||
"ODE solver: 1 - Forward Euler,\n\t"
|
||||
" 2 - RK2 SSP, 3 - RK3 SSP, 4 - RK4, 6 - RK6.");
|
||||
args.AddOption(&t_final, "-tf", "--t-final",
|
||||
"Final time; start time is 0.");
|
||||
args.AddOption(&dt, "-dt", "--time-step",
|
||||
"Time step. Positive number skips CFL timestep calculation.");
|
||||
args.AddOption(&cfl, "-c", "--cfl-number",
|
||||
"CFL number for timestep calculation.");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
args.AddOption(&vis_steps, "-vs", "--visualization-steps",
|
||||
"Visualize every n-th timestep.");
|
||||
|
||||
args.Parse();
|
||||
if (!args.Good())
|
||||
{
|
||||
args.PrintUsage(cout);
|
||||
return 1;
|
||||
}
|
||||
args.PrintOptions(cout);
|
||||
|
||||
// 2. Read the mesh from the given mesh file. This example requires a 2D
|
||||
// periodic mesh, such as ../data/periodic-square.mesh.
|
||||
Mesh mesh(mesh_file, 1, 1);
|
||||
const int dim = mesh.Dimension();
|
||||
|
||||
MFEM_ASSERT(dim == 2, "Need a two-dimensional mesh for the problem definition");
|
||||
|
||||
// 3. Define the ODE solver used for time integration. Several explicit
|
||||
// Runge-Kutta methods are available.
|
||||
ODESolver *ode_solver = NULL;
|
||||
switch (ode_solver_type)
|
||||
{
|
||||
case 1: ode_solver = new ForwardEulerSolver; break;
|
||||
case 2: ode_solver = new RK2Solver(1.0); break;
|
||||
case 3: ode_solver = new RK3SSPSolver; break;
|
||||
case 4: ode_solver = new RK4Solver; break;
|
||||
case 6: ode_solver = new RK6Solver; break;
|
||||
default:
|
||||
cout << "Unknown ODE solver type: " << ode_solver_type << '\n';
|
||||
return 3;
|
||||
}
|
||||
|
||||
// 4. Refine the mesh to increase the resolution. In this example we do
|
||||
// 'ref_levels' of uniform refinement, where 'ref_levels' is a
|
||||
// command-line parameter.
|
||||
for (int lev = 0; lev < ref_levels; lev++)
|
||||
{
|
||||
mesh.UniformRefinement();
|
||||
}
|
||||
|
||||
// 5. Define the discontinuous DG finite element space of the given
|
||||
// polynomial order on the refined mesh.
|
||||
DG_FECollection fec(order, dim);
|
||||
// Finite element space for a scalar (thermodynamic quantity)
|
||||
FiniteElementSpace fes(&mesh, &fec);
|
||||
// Finite element space for a mesh-dim vector quantity (momentum)
|
||||
FiniteElementSpace dfes(&mesh, &fec, dim, Ordering::byNODES);
|
||||
// Finite element space for all variables together (total thermodynamic state)
|
||||
FiniteElementSpace vfes(&mesh, &fec, num_equation, Ordering::byNODES);
|
||||
|
||||
// This example depends on this ordering of the space.
|
||||
MFEM_ASSERT(fes.GetOrdering() == Ordering::byNODES, "");
|
||||
|
||||
cout << "Number of unknowns: " << vfes.GetVSize() << endl;
|
||||
|
||||
// 6. Define the initial conditions, save the corresponding mesh and grid
|
||||
// functions to a file. This can be opened with GLVis with the -gc option.
|
||||
|
||||
// The solution u has components {density, x-momentum, y-momentum, energy}.
|
||||
// These are stored contiguously in the BlockVector u_block.
|
||||
Array<int> offsets(num_equation + 1);
|
||||
for (int k = 0; k <= num_equation; k++) { offsets[k] = k * vfes.GetNDofs(); }
|
||||
BlockVector u_block(offsets);
|
||||
|
||||
// Momentum grid function on dfes for visualization.
|
||||
GridFunction mom(&dfes, u_block.GetData() + offsets[1]);
|
||||
|
||||
// Initialize the state.
|
||||
VectorFunctionCoefficient u0(num_equation, InitialCondition);
|
||||
GridFunction sol(&vfes, u_block.GetData());
|
||||
sol.ProjectCoefficient(u0);
|
||||
|
||||
// Output the initial solution.
|
||||
{
|
||||
ofstream mesh_ofs("vortex.mesh");
|
||||
mesh_ofs.precision(precision);
|
||||
mesh_ofs << mesh;
|
||||
|
||||
for (int k = 0; k < num_equation; k++)
|
||||
{
|
||||
GridFunction uk(&fes, u_block.GetBlock(k));
|
||||
ostringstream sol_name;
|
||||
sol_name << "vortex-" << k << "-init.gf";
|
||||
ofstream sol_ofs(sol_name.str().c_str());
|
||||
sol_ofs.precision(precision);
|
||||
sol_ofs << uk;
|
||||
}
|
||||
}
|
||||
|
||||
// 7. Set up the nonlinear form corresponding to the DG discretization of the
|
||||
// flux divergence, and assemble the corresponding mass matrix.
|
||||
MixedBilinearForm Aflux(&dfes, &fes);
|
||||
Aflux.AddDomainIntegrator(new DomainIntegrator(dim));
|
||||
Aflux.Assemble();
|
||||
|
||||
NonlinearForm A(&vfes);
|
||||
RiemannSolver rsolver;
|
||||
A.AddInteriorFaceIntegrator(new FaceIntegrator(rsolver, dim));
|
||||
|
||||
// 8. Define the time-dependent evolution operator describing the ODE
|
||||
// right-hand side, and perform time-integration (looping over the time
|
||||
// iterations, ti, with a time-step dt).
|
||||
FE_Evolution euler(vfes, A, Aflux.SpMat());
|
||||
|
||||
// Visualize the density
|
||||
socketstream sout;
|
||||
if (visualization)
|
||||
{
|
||||
char vishost[] = "localhost";
|
||||
int visport = 19916;
|
||||
|
||||
sout.open(vishost, visport);
|
||||
if (!sout)
|
||||
{
|
||||
cout << "Unable to connect to GLVis server at "
|
||||
<< vishost << ':' << visport << endl;
|
||||
visualization = false;
|
||||
cout << "GLVis visualization disabled.\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
sout.precision(precision);
|
||||
sout << "solution\n" << mesh << mom;
|
||||
sout << "pause\n";
|
||||
sout << flush;
|
||||
cout << "GLVis visualization paused."
|
||||
<< " Press space (in the GLVis window) to resume it.\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the minimum element size.
|
||||
double hmin = 0.0;
|
||||
if (cfl > 0)
|
||||
{
|
||||
hmin = mesh.GetElementSize(0, 1);
|
||||
for (int i = 1; i < mesh.GetNE(); i++)
|
||||
{
|
||||
hmin = min(mesh.GetElementSize(i, 1), hmin);
|
||||
}
|
||||
}
|
||||
|
||||
// Start the timer.
|
||||
tic_toc.Clear();
|
||||
tic_toc.Start();
|
||||
|
||||
double t = 0.0;
|
||||
euler.SetTime(t);
|
||||
ode_solver->Init(euler);
|
||||
|
||||
if (cfl > 0)
|
||||
{
|
||||
// Find a safe dt, using a temporary vector. Calling Mult() computes the
|
||||
// maximum char speed at all quadrature points on all faces.
|
||||
Vector z(A.Width());
|
||||
max_char_speed = 0.;
|
||||
A.Mult(sol, z);
|
||||
dt = cfl * hmin / max_char_speed / (2*order+1);
|
||||
}
|
||||
|
||||
// Integrate in time.
|
||||
bool done = false;
|
||||
for (int ti = 0; !done; )
|
||||
{
|
||||
double dt_real = min(dt, t_final - t);
|
||||
|
||||
ode_solver->Step(sol, t, dt_real);
|
||||
if (cfl > 0)
|
||||
{
|
||||
dt = cfl * hmin / max_char_speed / (2*order+1);
|
||||
}
|
||||
ti++;
|
||||
|
||||
done = (t >= t_final - 1e-8*dt);
|
||||
if (done || ti % vis_steps == 0)
|
||||
{
|
||||
cout << "time step: " << ti << ", time: " << t << endl;
|
||||
if (visualization)
|
||||
{
|
||||
sout << "solution\n" << mesh << mom << flush;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tic_toc.Stop();
|
||||
cout << " done, " << tic_toc.RealTime() << "s." << endl;
|
||||
|
||||
// 9. Save the final solution. This output can be viewed later using GLVis:
|
||||
// "glvis -m vortex.mesh -g vortex-1-final.gf".
|
||||
for (int k = 0; k < num_equation; k++)
|
||||
{
|
||||
GridFunction uk(&fes, u_block.GetBlock(k));
|
||||
ostringstream sol_name;
|
||||
sol_name << "vortex-" << k << "-final.gf";
|
||||
ofstream sol_ofs(sol_name.str().c_str());
|
||||
sol_ofs.precision(precision);
|
||||
sol_ofs << uk;
|
||||
}
|
||||
|
||||
// 10. Compute the L2 solution error summed for all components.
|
||||
if (t_final == 2.0)
|
||||
{
|
||||
const double error = sol.ComputeLpError(2, u0);
|
||||
cout << "Solution error: " << error << endl;
|
||||
}
|
||||
|
||||
// Free the used memory.
|
||||
delete ode_solver;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,571 +0,0 @@
|
||||
// MFEM Example 18 - Serial/Parallel Shared Code
|
||||
|
||||
#include "mfem.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace mfem;
|
||||
|
||||
// Problem definition
|
||||
extern int problem;
|
||||
|
||||
// Maximum characteristic speed (updated by integrators)
|
||||
extern double max_char_speed;
|
||||
|
||||
extern const int num_equation;
|
||||
extern const double specific_heat_ratio;
|
||||
extern const double gas_constant;
|
||||
|
||||
// Time-dependent operator for the right-hand side of the ODE representing the
|
||||
// DG weak form.
|
||||
class FE_Evolution : public TimeDependentOperator
|
||||
{
|
||||
private:
|
||||
const int dim;
|
||||
|
||||
FiniteElementSpace &vfes;
|
||||
Operator &A;
|
||||
SparseMatrix &Aflux;
|
||||
DenseTensor Me_inv;
|
||||
|
||||
mutable Vector state;
|
||||
mutable DenseMatrix f;
|
||||
mutable DenseTensor flux;
|
||||
mutable Vector z;
|
||||
|
||||
void GetFlux(const DenseMatrix &state, DenseTensor &flux) const;
|
||||
|
||||
public:
|
||||
FE_Evolution(FiniteElementSpace &_vfes,
|
||||
Operator &_A, SparseMatrix &_Aflux);
|
||||
|
||||
virtual void Mult(const Vector &x, Vector &y) const;
|
||||
|
||||
virtual ~FE_Evolution() { }
|
||||
};
|
||||
|
||||
// Implements a simple Rusanov flux
|
||||
class RiemannSolver
|
||||
{
|
||||
private:
|
||||
Vector flux1;
|
||||
Vector flux2;
|
||||
|
||||
public:
|
||||
RiemannSolver();
|
||||
double Eval(const Vector &state1, const Vector &state2,
|
||||
const Vector &nor, Vector &flux);
|
||||
};
|
||||
|
||||
|
||||
// Constant (in time) mixed bilinear form multiplying the flux grid function.
|
||||
// The form is (vec(v), grad(w)) where the trial space = vector L2 space (mesh
|
||||
// dim) and test space = scalar L2 space.
|
||||
class DomainIntegrator : public BilinearFormIntegrator
|
||||
{
|
||||
private:
|
||||
Vector shape;
|
||||
DenseMatrix flux;
|
||||
DenseMatrix dshapedr;
|
||||
DenseMatrix dshapedx;
|
||||
|
||||
public:
|
||||
DomainIntegrator(const int dim);
|
||||
|
||||
virtual void AssembleElementMatrix2(const FiniteElement &trial_fe,
|
||||
const FiniteElement &test_fe,
|
||||
ElementTransformation &Tr,
|
||||
DenseMatrix &elmat);
|
||||
};
|
||||
|
||||
// Interior face term: <F.n(u),[w]>
|
||||
class FaceIntegrator : public NonlinearFormIntegrator
|
||||
{
|
||||
private:
|
||||
RiemannSolver rsolver;
|
||||
Vector shape1;
|
||||
Vector shape2;
|
||||
Vector funval1;
|
||||
Vector funval2;
|
||||
Vector nor;
|
||||
Vector fluxN;
|
||||
IntegrationPoint eip1;
|
||||
IntegrationPoint eip2;
|
||||
|
||||
public:
|
||||
FaceIntegrator(RiemannSolver &rsolver_, const int dim);
|
||||
|
||||
virtual void AssembleFaceVector(const FiniteElement &el1,
|
||||
const FiniteElement &el2,
|
||||
FaceElementTransformations &Tr,
|
||||
const Vector &elfun, Vector &elvect);
|
||||
};
|
||||
|
||||
// Implementation of class FE_Evolution
|
||||
FE_Evolution::FE_Evolution(FiniteElementSpace &_vfes,
|
||||
Operator &_A, SparseMatrix &_Aflux)
|
||||
: TimeDependentOperator(_A.Height()),
|
||||
dim(_vfes.GetFE(0)->GetDim()),
|
||||
vfes(_vfes),
|
||||
A(_A),
|
||||
Aflux(_Aflux),
|
||||
Me_inv(vfes.GetFE(0)->GetDof(), vfes.GetFE(0)->GetDof(), vfes.GetNE()),
|
||||
state(num_equation),
|
||||
f(num_equation, dim),
|
||||
flux(vfes.GetNDofs(), dim, num_equation),
|
||||
z(A.Height())
|
||||
{
|
||||
// Standard local assembly and inversion for energy mass matrices.
|
||||
const int dof = vfes.GetFE(0)->GetDof();
|
||||
DenseMatrix Me(dof);
|
||||
DenseMatrixInverse inv(&Me);
|
||||
MassIntegrator mi;
|
||||
for (int i = 0; i < vfes.GetNE(); i++)
|
||||
{
|
||||
mi.AssembleElementMatrix(*vfes.GetFE(i), *vfes.GetElementTransformation(i), Me);
|
||||
inv.Factor();
|
||||
inv.GetInverseMatrix(Me_inv(i));
|
||||
}
|
||||
}
|
||||
|
||||
void FE_Evolution::Mult(const Vector &x, Vector &y) const
|
||||
{
|
||||
// 0. Reset wavespeed computation before operator application.
|
||||
max_char_speed = 0.;
|
||||
|
||||
// 1. Create the vector z with the face terms -<F.n(u), [w]>.
|
||||
A.Mult(x, z);
|
||||
|
||||
// 2. Add the element terms.
|
||||
// i. computing the flux approximately as a grid function by interpolating
|
||||
// at the solution nodes.
|
||||
// ii. multiplying this grid function by a (constant) mixed bilinear form for
|
||||
// each of the num_equation, computing (F(u), grad(w)) for each equation.
|
||||
|
||||
DenseMatrix xmat(x.GetData(), vfes.GetNDofs(), num_equation);
|
||||
GetFlux(xmat, flux);
|
||||
|
||||
for (int k = 0; k < num_equation; k++)
|
||||
{
|
||||
Vector fk(flux(k).GetData(), dim * vfes.GetNDofs());
|
||||
Vector zk(z.GetData() + k * vfes.GetNDofs(), vfes.GetNDofs());
|
||||
Aflux.AddMult(fk, zk);
|
||||
}
|
||||
|
||||
// 3. Multiply element-wise by the inverse mass matrices.
|
||||
Vector zval;
|
||||
Array<int> vdofs;
|
||||
const int dof = vfes.GetFE(0)->GetDof();
|
||||
DenseMatrix zmat, ymat(dof, num_equation);
|
||||
|
||||
for (int i = 0; i < vfes.GetNE(); i++)
|
||||
{
|
||||
// Return the vdofs ordered byNODES
|
||||
vfes.GetElementVDofs(i, vdofs);
|
||||
z.GetSubVector(vdofs, zval);
|
||||
zmat.UseExternalData(zval.GetData(), dof, num_equation);
|
||||
mfem::Mult(Me_inv(i), zmat, ymat);
|
||||
y.SetSubVector(vdofs, ymat.GetData());
|
||||
}
|
||||
}
|
||||
|
||||
// Physicality check (at end)
|
||||
bool StateIsPhysical(const Vector &state, const int dim);
|
||||
|
||||
// Pressure (EOS) computation
|
||||
inline double ComputePressure(const Vector &state, int dim)
|
||||
{
|
||||
const double den = state(0);
|
||||
const Vector den_vel(state.GetData() + 1, dim);
|
||||
const double den_energy = state(1 + dim);
|
||||
|
||||
double den_vel2 = 0;
|
||||
for (int d = 0; d < dim; d++) { den_vel2 += den_vel(d) * den_vel(d); }
|
||||
den_vel2 /= den;
|
||||
|
||||
return (specific_heat_ratio - 1.0) * (den_energy - 0.5 * den_vel2);
|
||||
}
|
||||
|
||||
// Compute the vector flux F(u)
|
||||
void ComputeFlux(const Vector &state, int dim, DenseMatrix &flux)
|
||||
{
|
||||
const double den = state(0);
|
||||
const Vector den_vel(state.GetData() + 1, dim);
|
||||
const double den_energy = state(1 + dim);
|
||||
|
||||
MFEM_ASSERT(StateIsPhysical(state, dim), "");
|
||||
|
||||
const double pres = ComputePressure(state, dim);
|
||||
|
||||
for (int d = 0; d < dim; d++)
|
||||
{
|
||||
flux(0, d) = den_vel(d);
|
||||
for (int i = 0; i < dim; i++)
|
||||
{
|
||||
flux(1+i, d) = den_vel(i) * den_vel(d) / den;
|
||||
}
|
||||
flux(1+d, d) += pres;
|
||||
}
|
||||
|
||||
const double H = (den_energy + pres) / den;
|
||||
for (int d = 0; d < dim; d++)
|
||||
{
|
||||
flux(1+dim, d) = den_vel(d) * H;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the scalar F(u).n
|
||||
void ComputeFluxDotN(const Vector &state, const Vector &nor,
|
||||
Vector &fluxN)
|
||||
{
|
||||
// NOTE: nor in general is not a unit normal
|
||||
const int dim = nor.Size();
|
||||
const double den = state(0);
|
||||
const Vector den_vel(state.GetData() + 1, dim);
|
||||
const double den_energy = state(1 + dim);
|
||||
|
||||
MFEM_ASSERT(StateIsPhysical(state, dim), "");
|
||||
|
||||
const double pres = ComputePressure(state, dim);
|
||||
|
||||
double den_velN = 0;
|
||||
for (int d = 0; d < dim; d++) { den_velN += den_vel(d) * nor(d); }
|
||||
|
||||
fluxN(0) = den_velN;
|
||||
for (int d = 0; d < dim; d++)
|
||||
{
|
||||
fluxN(1+d) = den_velN * den_vel(d) / den + pres * nor(d);
|
||||
}
|
||||
|
||||
const double H = (den_energy + pres) / den;
|
||||
fluxN(1 + dim) = den_velN * H;
|
||||
}
|
||||
|
||||
// Compute the maximum characteristic speed.
|
||||
inline double ComputeMaxCharSpeed(const Vector &state, const int dim)
|
||||
{
|
||||
const double den = state(0);
|
||||
const Vector den_vel(state.GetData() + 1, dim);
|
||||
|
||||
double den_vel2 = 0;
|
||||
for (int d = 0; d < dim; d++) { den_vel2 += den_vel(d) * den_vel(d); }
|
||||
den_vel2 /= den;
|
||||
|
||||
const double pres = ComputePressure(state, dim);
|
||||
const double sound = sqrt(specific_heat_ratio * pres / den);
|
||||
const double vel = sqrt(den_vel2 / den);
|
||||
|
||||
return vel + sound;
|
||||
}
|
||||
|
||||
// Compute the flux at solution nodes.
|
||||
void FE_Evolution::GetFlux(const DenseMatrix &x, DenseTensor &flux) const
|
||||
{
|
||||
const int dof = flux.SizeI();
|
||||
const int dim = flux.SizeJ();
|
||||
|
||||
for (int i = 0; i < dof; i++)
|
||||
{
|
||||
for (int k = 0; k < num_equation; k++) { state(k) = x(i, k); }
|
||||
ComputeFlux(state, dim, f);
|
||||
|
||||
for (int d = 0; d < dim; d++)
|
||||
{
|
||||
for (int k = 0; k < num_equation; k++)
|
||||
{
|
||||
flux(i, d, k) = f(k, d);
|
||||
}
|
||||
}
|
||||
|
||||
// Update max char speed
|
||||
const double mcs = ComputeMaxCharSpeed(state, dim);
|
||||
if (mcs > max_char_speed) { max_char_speed = mcs; }
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation of class RiemannSolver
|
||||
RiemannSolver::RiemannSolver() :
|
||||
flux1(num_equation),
|
||||
flux2(num_equation) { }
|
||||
|
||||
double RiemannSolver::Eval(const Vector &state1, const Vector &state2,
|
||||
const Vector &nor, Vector &flux)
|
||||
{
|
||||
// NOTE: nor in general is not a unit normal
|
||||
const int dim = nor.Size();
|
||||
|
||||
MFEM_ASSERT(StateIsPhysical(state1, dim), "");
|
||||
MFEM_ASSERT(StateIsPhysical(state2, dim), "");
|
||||
|
||||
const double maxE1 = ComputeMaxCharSpeed(state1, dim);
|
||||
const double maxE2 = ComputeMaxCharSpeed(state2, dim);
|
||||
|
||||
const double maxE = max(maxE1, maxE2);
|
||||
|
||||
ComputeFluxDotN(state1, nor, flux1);
|
||||
ComputeFluxDotN(state2, nor, flux2);
|
||||
|
||||
double normag = 0;
|
||||
for (int i = 0; i < dim; i++)
|
||||
{
|
||||
normag += nor(i) * nor(i);
|
||||
}
|
||||
normag = sqrt(normag);
|
||||
|
||||
for (int i = 0; i < num_equation; i++)
|
||||
{
|
||||
flux(i) = 0.5 * (flux1(i) + flux2(i))
|
||||
- 0.5 * maxE * (state2(i) - state1(i)) * normag;
|
||||
}
|
||||
|
||||
return maxE;
|
||||
}
|
||||
|
||||
// Implementation of class DomainIntegrator
|
||||
DomainIntegrator::DomainIntegrator(const int dim) : flux(num_equation, dim) { }
|
||||
|
||||
void DomainIntegrator::AssembleElementMatrix2(const FiniteElement &trial_fe,
|
||||
const FiniteElement &test_fe,
|
||||
ElementTransformation &Tr,
|
||||
DenseMatrix &elmat)
|
||||
{
|
||||
// Assemble the form (vec(v), grad(w))
|
||||
|
||||
// Trial space = vector L2 space (mesh dim)
|
||||
// Test space = scalar L2 space
|
||||
|
||||
const int dof_trial = trial_fe.GetDof();
|
||||
const int dof_test = test_fe.GetDof();
|
||||
const int dim = trial_fe.GetDim();
|
||||
|
||||
shape.SetSize(dof_trial);
|
||||
dshapedr.SetSize(dof_test, dim);
|
||||
dshapedx.SetSize(dof_test, dim);
|
||||
|
||||
elmat.SetSize(dof_test, dof_trial * dim);
|
||||
elmat = 0.0;
|
||||
|
||||
const int maxorder = max(trial_fe.GetOrder(), test_fe.GetOrder());
|
||||
const int intorder = 2 * maxorder;
|
||||
const IntegrationRule *ir = &IntRules.Get(trial_fe.GetGeomType(), intorder);
|
||||
|
||||
for (int i = 0; i < ir->GetNPoints(); i++)
|
||||
{
|
||||
const IntegrationPoint &ip = ir->IntPoint(i);
|
||||
|
||||
// Calculate the shape functions
|
||||
trial_fe.CalcShape(ip, shape);
|
||||
shape *= ip.weight;
|
||||
|
||||
// Compute the physical gradients of the test functions
|
||||
Tr.SetIntPoint(&ip);
|
||||
test_fe.CalcDShape(ip, dshapedr);
|
||||
Mult(dshapedr, Tr.AdjugateJacobian(), dshapedx);
|
||||
|
||||
for (int d = 0; d < dim; d++)
|
||||
{
|
||||
for (int j = 0; j < dof_test; j++)
|
||||
{
|
||||
for (int k = 0; k < dof_trial; k++)
|
||||
{
|
||||
elmat(j, k + d * dof_trial) += shape(k) * dshapedx(j, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation of class FaceIntegrator
|
||||
FaceIntegrator::FaceIntegrator(RiemannSolver &rsolver_, const int dim) :
|
||||
rsolver(rsolver_),
|
||||
funval1(num_equation),
|
||||
funval2(num_equation),
|
||||
nor(dim),
|
||||
fluxN(num_equation) { }
|
||||
|
||||
void FaceIntegrator::AssembleFaceVector(const FiniteElement &el1,
|
||||
const FiniteElement &el2,
|
||||
FaceElementTransformations &Tr,
|
||||
const Vector &elfun, Vector &elvect)
|
||||
{
|
||||
// Compute the term <F.n(u),[w]> on the interior faces.
|
||||
const int dof1 = el1.GetDof();
|
||||
const int dof2 = el2.GetDof();
|
||||
|
||||
shape1.SetSize(dof1);
|
||||
shape2.SetSize(dof2);
|
||||
|
||||
elvect.SetSize((dof1 + dof2) * num_equation);
|
||||
elvect = 0.0;
|
||||
|
||||
DenseMatrix elfun1_mat(elfun.GetData(), dof1, num_equation);
|
||||
DenseMatrix elfun2_mat(elfun.GetData() + dof1 * num_equation, dof2,
|
||||
num_equation);
|
||||
|
||||
DenseMatrix elvect1_mat(elvect.GetData(), dof1, num_equation);
|
||||
DenseMatrix elvect2_mat(elvect.GetData() + dof1 * num_equation, dof2,
|
||||
num_equation);
|
||||
|
||||
// Integration order calculation from DGTraceIntegrator
|
||||
int intorder;
|
||||
if (Tr.Elem2No >= 0)
|
||||
intorder = (min(Tr.Elem1->OrderW(), Tr.Elem2->OrderW()) +
|
||||
2*max(el1.GetOrder(), el2.GetOrder()));
|
||||
else
|
||||
{
|
||||
intorder = Tr.Elem1->OrderW() + 2*el1.GetOrder();
|
||||
}
|
||||
if (el1.Space() == FunctionSpace::Pk)
|
||||
{
|
||||
intorder++;
|
||||
}
|
||||
const IntegrationRule *ir = &IntRules.Get(Tr.FaceGeom, intorder);
|
||||
|
||||
for (int i = 0; i < ir->GetNPoints(); i++)
|
||||
{
|
||||
const IntegrationPoint &ip = ir->IntPoint(i);
|
||||
|
||||
Tr.Loc1.Transform(ip, eip1);
|
||||
Tr.Loc2.Transform(ip, eip2);
|
||||
|
||||
// Calculate basis functions on both elements at the face
|
||||
el1.CalcShape(eip1, shape1);
|
||||
el2.CalcShape(eip2, shape2);
|
||||
|
||||
// Interpolate elfun at the point
|
||||
elfun1_mat.MultTranspose(shape1, funval1);
|
||||
elfun2_mat.MultTranspose(shape2, funval2);
|
||||
|
||||
Tr.Face->SetIntPoint(&ip);
|
||||
|
||||
// Get the normal vector and the flux on the face
|
||||
CalcOrtho(Tr.Face->Jacobian(), nor);
|
||||
const double mcs = rsolver.Eval(funval1, funval2, nor, fluxN);
|
||||
|
||||
// Update max char speed
|
||||
if (mcs > max_char_speed) { max_char_speed = mcs; }
|
||||
|
||||
fluxN *= ip.weight;
|
||||
for (int k = 0; k < num_equation; k++)
|
||||
{
|
||||
for (int s = 0; s < dof1; s++)
|
||||
{
|
||||
elvect1_mat(s, k) -= fluxN(k) * shape1(s);
|
||||
}
|
||||
for (int s = 0; s < dof2; s++)
|
||||
{
|
||||
elvect2_mat(s, k) += fluxN(k) * shape2(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the state is physical - enabled in debug mode
|
||||
bool StateIsPhysical(const Vector &state, const int dim)
|
||||
{
|
||||
const double den = state(0);
|
||||
const Vector den_vel(state.GetData() + 1, dim);
|
||||
const double den_energy = state(1 + dim);
|
||||
|
||||
if (den < 0)
|
||||
{
|
||||
cout << "Negative density: ";
|
||||
for (int i = 0; i < state.Size(); i++)
|
||||
{
|
||||
cout << state(i) << " ";
|
||||
}
|
||||
cout << endl;
|
||||
return false;
|
||||
}
|
||||
if (den_energy <= 0)
|
||||
{
|
||||
cout << "Negative energy: ";
|
||||
for (int i = 0; i < state.Size(); i++)
|
||||
{
|
||||
cout << state(i) << " ";
|
||||
}
|
||||
cout << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
double den_vel2 = 0;
|
||||
for (int i = 0; i < dim; i++) { den_vel2 += den_vel(i) * den_vel(i); }
|
||||
den_vel2 /= den;
|
||||
|
||||
const double pres = (specific_heat_ratio - 1.0) * (den_energy - 0.5 * den_vel2);
|
||||
|
||||
if (pres <= 0)
|
||||
{
|
||||
cout << "Negative pressure: " << pres << ", state: ";
|
||||
for (int i = 0; i < state.Size(); i++)
|
||||
{
|
||||
cout << state(i) << " ";
|
||||
}
|
||||
cout << endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Initial condition
|
||||
void InitialCondition(const Vector &x, Vector &y)
|
||||
{
|
||||
const int dim = x.Size();
|
||||
MFEM_ASSERT(dim == 2, "");
|
||||
|
||||
double radius = 0, Minf = 0, beta = 0;
|
||||
if (problem == 1)
|
||||
{
|
||||
// "Fast vortex"
|
||||
radius = 0.2;
|
||||
Minf = 0.5;
|
||||
beta = 1. / 5.;
|
||||
}
|
||||
else if (problem == 2)
|
||||
{
|
||||
// "Slow vortex"
|
||||
radius = 0.2;
|
||||
Minf = 0.05;
|
||||
beta = 1. / 50.;
|
||||
}
|
||||
else
|
||||
{
|
||||
mfem_error("Cannot recognize problem."
|
||||
"Options are: 1 - fast vortex, 2 - slow vortex");
|
||||
}
|
||||
|
||||
const double xc = 0.0, yc = 0.0;
|
||||
|
||||
// Nice units
|
||||
const double vel_inf = 1.;
|
||||
const double den_inf = 1.;
|
||||
|
||||
// Derive remainder of background state from this and Minf
|
||||
const double pres_inf = (den_inf / specific_heat_ratio) * (vel_inf / Minf) *
|
||||
(vel_inf / Minf);
|
||||
const double temp_inf = pres_inf / (den_inf * gas_constant);
|
||||
|
||||
double r2rad = 0.0;
|
||||
r2rad += (x(0) - xc) * (x(0) - xc);
|
||||
r2rad += (x(1) - yc) * (x(1) - yc);
|
||||
r2rad /= (radius * radius);
|
||||
|
||||
const double shrinv1 = 1.0 / (specific_heat_ratio - 1.);
|
||||
|
||||
const double velX = vel_inf * (1 - beta * (x(1) - yc) / radius * exp(
|
||||
-0.5 * r2rad));
|
||||
const double velY = vel_inf * beta * (x(0) - xc) / radius * exp(-0.5 * r2rad);
|
||||
const double vel2 = velX * velX + velY * velY;
|
||||
|
||||
const double specific_heat = gas_constant * specific_heat_ratio * shrinv1;
|
||||
const double temp = temp_inf - 0.5 * (vel_inf * beta) *
|
||||
(vel_inf * beta) / specific_heat * exp(-r2rad);
|
||||
|
||||
const double den = den_inf * pow(temp/temp_inf, shrinv1);
|
||||
const double pres = den * gas_constant * temp;
|
||||
const double energy = shrinv1 * pres / den + 0.5 * vel2;
|
||||
|
||||
y(0) = den;
|
||||
y(1) = den * velX;
|
||||
y(2) = den * velY;
|
||||
y(3) = den * energy;
|
||||
}
|
||||
@@ -1,364 +0,0 @@
|
||||
// MFEM Example 18 - Parallel Version
|
||||
//
|
||||
// Compile with: make ex18
|
||||
//
|
||||
// Sample runs:
|
||||
//
|
||||
// mpirun -np 4 ex18p -p 1 -rs 2 -rp 1 -o 1 -s 3
|
||||
// mpirun -np 4 ex18p -p 1 -rs 1 -rp 1 -o 3 -s 4
|
||||
// mpirun -np 4 ex18p -p 1 -rs 1 -rp 1 -o 5 -s 6
|
||||
// mpirun -np 4 ex18p -p 2 -rs 1 -rp 1 -o 1 -s 3
|
||||
// mpirun -np 4 ex18p -p 2 -rs 1 -rp 1 -o 3 -s 3
|
||||
//
|
||||
// Description: This example code solves the compressible Euler system of
|
||||
// equations, a model nonlinear hyperbolic PDE, with a
|
||||
// discontinuous Galerkin (DG) formulation.
|
||||
//
|
||||
// Specifically, it solves for an exact solution of the equations
|
||||
// whereby a vortex is transported by a uniform flow. Since all
|
||||
// boundaries are periodic here, the method's accuracy can be
|
||||
// assessed by measuring the difference between the solution and
|
||||
// the initial condition at a later time when the vortex returns
|
||||
// to its initial location.
|
||||
//
|
||||
// Note that as the order of the spatial discretization increases,
|
||||
// the timestep must become smaller. This example currently uses a
|
||||
// simple estimate derived by Cockburn and Shu for the 1D RKDG
|
||||
// method. An additional factor can be tuned by passing the --cfl
|
||||
// (or -c shorter) flag.
|
||||
//
|
||||
// The example demonstrates user-defined bilinear and nonlinear
|
||||
// form integrators for systems of equations that are defined with
|
||||
// block vectors, and how these are used with an operator for
|
||||
// explicit time integrators. In this case the system also
|
||||
// involves an external approximate Riemann solver for the DG
|
||||
// interface flux. It also demonstrates how to use GLVis for
|
||||
// in-situ visualization of vector grid functions.
|
||||
//
|
||||
// We recommend viewing examples 9, 14 and 17 before viewing this
|
||||
// example.
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
// Classes FE_Evolution, RiemannSolver, DomainIntegrator and FaceIntegrator
|
||||
// shared between the serial and parallel version of the example.
|
||||
#include "ex18.hpp"
|
||||
|
||||
// Choice for the problem setup. See InitialCondition in ex18.hpp.
|
||||
int problem;
|
||||
|
||||
// Equation constant parameters.
|
||||
const int num_equation = 4;
|
||||
const double specific_heat_ratio = 1.4;
|
||||
const double gas_constant = 1.0;
|
||||
|
||||
// Maximum characteristic speed (updated by integrators)
|
||||
double max_char_speed;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// 1. Initialize MPI.
|
||||
MPI_Session mpi(argc, argv);
|
||||
|
||||
// 2. Parse command-line options.
|
||||
problem = 1;
|
||||
const char *mesh_file = "../data/periodic-square.mesh";
|
||||
int ser_ref_levels = 0;
|
||||
int par_ref_levels = 1;
|
||||
int order = 3;
|
||||
int ode_solver_type = 4;
|
||||
double t_final = 2.0;
|
||||
double dt = -0.01;
|
||||
double cfl = 0.3;
|
||||
bool visualization = true;
|
||||
int vis_steps = 50;
|
||||
|
||||
int precision = 8;
|
||||
cout.precision(precision);
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
args.AddOption(&mesh_file, "-m", "--mesh",
|
||||
"Mesh file to use.");
|
||||
args.AddOption(&problem, "-p", "--problem",
|
||||
"Problem setup to use. See options in velocity_function().");
|
||||
args.AddOption(&ser_ref_levels, "-rs", "--refine-serial",
|
||||
"Number of times to refine the mesh uniformly before parallel"
|
||||
" partitioning, -1 for auto.");
|
||||
args.AddOption(&par_ref_levels, "-rp", "--refine-parallel",
|
||||
"Number of times to refine the mesh uniformly after parallel"
|
||||
" partitioning.");
|
||||
args.AddOption(&order, "-o", "--order",
|
||||
"Order (degree) of the finite elements.");
|
||||
args.AddOption(&ode_solver_type, "-s", "--ode-solver",
|
||||
"ODE solver: 1 - Forward Euler,\n\t"
|
||||
" 2 - RK2 SSP, 3 - RK3 SSP, 4 - RK4, 6 - RK6.");
|
||||
args.AddOption(&t_final, "-tf", "--t-final",
|
||||
"Final time; start time is 0.");
|
||||
args.AddOption(&dt, "-dt", "--time-step",
|
||||
"Time step. Positive number skips CFL timestep calculation.");
|
||||
args.AddOption(&cfl, "-c", "--cfl-number",
|
||||
"CFL number for timestep calculation.");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
args.AddOption(&vis_steps, "-vs", "--visualization-steps",
|
||||
"Visualize every n-th timestep.");
|
||||
|
||||
args.Parse();
|
||||
if (!args.Good())
|
||||
{
|
||||
if (mpi.Root()) { args.PrintUsage(cout); }
|
||||
return 1;
|
||||
}
|
||||
if (mpi.Root()) { args.PrintOptions(cout); }
|
||||
|
||||
// 3. Read the mesh from the given mesh file. This example requires a 2D
|
||||
// periodic mesh, such as ../data/periodic-square.mesh.
|
||||
Mesh mesh(mesh_file, 1, 1);
|
||||
const int dim = mesh.Dimension();
|
||||
|
||||
MFEM_ASSERT(dim == 2, "Need a two-dimensional mesh for the problem definition");
|
||||
|
||||
// 4. Define the ODE solver used for time integration. Several explicit
|
||||
// Runge-Kutta methods are available.
|
||||
ODESolver *ode_solver = NULL;
|
||||
switch (ode_solver_type)
|
||||
{
|
||||
case 1: ode_solver = new ForwardEulerSolver; break;
|
||||
case 2: ode_solver = new RK2Solver(1.0); break;
|
||||
case 3: ode_solver = new RK3SSPSolver; break;
|
||||
case 4: ode_solver = new RK4Solver; break;
|
||||
case 6: ode_solver = new RK6Solver; break;
|
||||
default:
|
||||
if (mpi.Root())
|
||||
{
|
||||
cout << "Unknown ODE solver type: " << ode_solver_type << '\n';
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
|
||||
// 5. Refine the mesh in serial to increase the resolution. In this example
|
||||
// we do 'ser_ref_levels' of uniform refinement, where 'ser_ref_levels' is
|
||||
// a command-line parameter.
|
||||
for (int lev = 0; lev < ser_ref_levels; lev++)
|
||||
{
|
||||
mesh.UniformRefinement();
|
||||
}
|
||||
|
||||
// 6. Define a parallel mesh by a partitioning of the serial mesh. Refine
|
||||
// this mesh further in parallel to increase the resolution. Once the
|
||||
// parallel mesh is defined, the serial mesh can be deleted.
|
||||
ParMesh pmesh(MPI_COMM_WORLD, mesh);
|
||||
mesh.Clear();
|
||||
for (int lev = 0; lev < par_ref_levels; lev++)
|
||||
{
|
||||
pmesh.UniformRefinement();
|
||||
}
|
||||
|
||||
// 7. Define the discontinuous DG finite element space of the given
|
||||
// polynomial order on the refined mesh.
|
||||
DG_FECollection fec(order, dim);
|
||||
// Finite element space for a scalar (thermodynamic quantity)
|
||||
ParFiniteElementSpace fes(&pmesh, &fec);
|
||||
// Finite element space for a mesh-dim vector quantity (momentum)
|
||||
ParFiniteElementSpace dfes(&pmesh, &fec, dim, Ordering::byNODES);
|
||||
// Finite element space for all variables together (total thermodynamic state)
|
||||
ParFiniteElementSpace vfes(&pmesh, &fec, num_equation, Ordering::byNODES);
|
||||
|
||||
// This example depends on this ordering of the space.
|
||||
MFEM_ASSERT(fes.GetOrdering() == Ordering::byNODES, "");
|
||||
|
||||
HYPRE_Int glob_size = vfes.GlobalTrueVSize();
|
||||
if (mpi.Root()) { cout << "Number of unknowns: " << glob_size << endl; }
|
||||
|
||||
// 8. Define the initial conditions, save the corresponding mesh and grid
|
||||
// functions to a file. This can be opened with GLVis with the -gc option.
|
||||
|
||||
// The solution u has components {density, x-momentum, y-momentum, energy}.
|
||||
// These are stored contiguously in the BlockVector u_block.
|
||||
Array<int> offsets(num_equation + 1);
|
||||
for (int k = 0; k <= num_equation; k++) { offsets[k] = k * vfes.GetNDofs(); }
|
||||
BlockVector u_block(offsets);
|
||||
|
||||
// Momentum grid function on dfes for visualization.
|
||||
ParGridFunction mom(&dfes, u_block.GetData() + offsets[1]);
|
||||
|
||||
// Initialize the state.
|
||||
VectorFunctionCoefficient u0(num_equation, InitialCondition);
|
||||
ParGridFunction sol(&vfes, u_block.GetData());
|
||||
sol.ProjectCoefficient(u0);
|
||||
|
||||
// Output the initial solution.
|
||||
{
|
||||
ostringstream mesh_name;
|
||||
mesh_name << "vortex-mesh." << setfill('0') << setw(6) << mpi.WorldRank();
|
||||
ofstream mesh_ofs(mesh_name.str().c_str());
|
||||
mesh_ofs.precision(precision);
|
||||
mesh_ofs << pmesh;
|
||||
|
||||
for (int k = 0; k < num_equation; k++)
|
||||
{
|
||||
ParGridFunction uk(&fes, u_block.GetBlock(k));
|
||||
ostringstream sol_name;
|
||||
sol_name << "vortex-" << k << "-init."
|
||||
<< setfill('0') << setw(6) << mpi.WorldRank();
|
||||
ofstream sol_ofs(sol_name.str().c_str());
|
||||
sol_ofs.precision(precision);
|
||||
sol_ofs << uk;
|
||||
}
|
||||
}
|
||||
|
||||
// 9. Set up the nonlinear form corresponding to the DG discretization of the
|
||||
// flux divergence, and assemble the corresponding mass matrix.
|
||||
MixedBilinearForm Aflux(&dfes, &fes);
|
||||
Aflux.AddDomainIntegrator(new DomainIntegrator(dim));
|
||||
Aflux.Assemble();
|
||||
|
||||
ParNonlinearForm A(&vfes);
|
||||
RiemannSolver rsolver;
|
||||
A.AddInteriorFaceIntegrator(new FaceIntegrator(rsolver, dim));
|
||||
|
||||
// 10. Define the time-dependent evolution operator describing the ODE
|
||||
// right-hand side, and perform time-integration (looping over the time
|
||||
// iterations, ti, with a time-step dt).
|
||||
FE_Evolution euler(vfes, A, Aflux.SpMat());
|
||||
|
||||
// Visualize the density
|
||||
socketstream sout;
|
||||
if (visualization)
|
||||
{
|
||||
char vishost[] = "localhost";
|
||||
int visport = 19916;
|
||||
|
||||
MPI_Barrier(pmesh.GetComm());
|
||||
sout.open(vishost, visport);
|
||||
if (!sout)
|
||||
{
|
||||
if (mpi.Root())
|
||||
{
|
||||
cout << "Unable to connect to GLVis server at "
|
||||
<< vishost << ':' << visport << endl;
|
||||
}
|
||||
visualization = false;
|
||||
if (mpi.Root()) { cout << "GLVis visualization disabled.\n"; }
|
||||
}
|
||||
else
|
||||
{
|
||||
sout << "parallel " << mpi.WorldSize() << " " << mpi.WorldRank() << "\n";
|
||||
sout.precision(precision);
|
||||
sout << "solution\n" << pmesh << mom;
|
||||
sout << "pause\n";
|
||||
sout << flush;
|
||||
if (mpi.Root())
|
||||
{
|
||||
cout << "GLVis visualization paused."
|
||||
<< " Press space (in the GLVis window) to resume it.\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Determine the minimum element size.
|
||||
double hmin;
|
||||
if (cfl > 0)
|
||||
{
|
||||
double my_hmin = pmesh.GetElementSize(0, 1);
|
||||
for (int i = 1; i < pmesh.GetNE(); i++)
|
||||
{
|
||||
my_hmin = min(pmesh.GetElementSize(i, 1), my_hmin);
|
||||
}
|
||||
// Reduce to find the global minimum element size
|
||||
MPI_Allreduce(&my_hmin, &hmin, 1, MPI_DOUBLE, MPI_MIN, pmesh.GetComm());
|
||||
}
|
||||
|
||||
// Start the timer.
|
||||
tic_toc.Clear();
|
||||
tic_toc.Start();
|
||||
|
||||
double t = 0.0;
|
||||
euler.SetTime(t);
|
||||
ode_solver->Init(euler);
|
||||
|
||||
if (cfl > 0)
|
||||
{
|
||||
// Find a safe dt, using a temporary vector. Calling Mult() computes the
|
||||
// maximum char speed at all quadrature points on all faces.
|
||||
max_char_speed = 0.;
|
||||
Vector z(sol.Size());
|
||||
A.Mult(sol, z);
|
||||
// Reduce to find the global maximum wave speed
|
||||
{
|
||||
double all_max_char_speed;
|
||||
MPI_Allreduce(&max_char_speed, &all_max_char_speed,
|
||||
1, MPI_DOUBLE, MPI_MAX, pmesh.GetComm());
|
||||
max_char_speed = all_max_char_speed;
|
||||
}
|
||||
dt = cfl * hmin / max_char_speed / (2*order+1);
|
||||
}
|
||||
|
||||
// Integrate in time.
|
||||
bool done = false;
|
||||
for (int ti = 0; !done; )
|
||||
{
|
||||
double dt_real = min(dt, t_final - t);
|
||||
|
||||
ode_solver->Step(sol, t, dt_real);
|
||||
if (cfl > 0)
|
||||
{
|
||||
// Reduce to find the global maximum wave speed
|
||||
{
|
||||
double all_max_char_speed;
|
||||
MPI_Allreduce(&max_char_speed, &all_max_char_speed,
|
||||
1, MPI_DOUBLE, MPI_MAX, pmesh.GetComm());
|
||||
max_char_speed = all_max_char_speed;
|
||||
}
|
||||
dt = cfl * hmin / max_char_speed / (2*order+1);
|
||||
}
|
||||
ti++;
|
||||
|
||||
done = (t >= t_final - 1e-8*dt);
|
||||
if (done || ti % vis_steps == 0)
|
||||
{
|
||||
if (mpi.Root())
|
||||
{
|
||||
cout << "time step: " << ti << ", time: " << t << endl;
|
||||
}
|
||||
if (visualization)
|
||||
{
|
||||
MPI_Barrier(pmesh.GetComm());
|
||||
sout << "parallel " << mpi.WorldSize() << " " << mpi.WorldRank() << "\n";
|
||||
sout << "solution\n" << pmesh << mom << flush;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tic_toc.Stop();
|
||||
if (mpi.Root()) { cout << " done, " << tic_toc.RealTime() << "s." << endl; }
|
||||
|
||||
// 11. Save the final solution. This output can be viewed later using GLVis:
|
||||
// "glvis -np 4 -m vortex-mesh -g vortex-1-final".
|
||||
for (int k = 0; k < num_equation; k++)
|
||||
{
|
||||
ParGridFunction uk(&fes, u_block.GetBlock(k));
|
||||
ostringstream sol_name;
|
||||
sol_name << "vortex-" << k << "-final."
|
||||
<< setfill('0') << setw(6) << mpi.WorldRank();
|
||||
ofstream sol_ofs(sol_name.str().c_str());
|
||||
sol_ofs.precision(precision);
|
||||
sol_ofs << uk;
|
||||
}
|
||||
|
||||
// 12. Compute the L2 solution error summed for all components.
|
||||
if (t_final == 2.0)
|
||||
{
|
||||
const double error = sol.ComputeLpError(2, u0);
|
||||
if (mpi.Root()) { cout << "Solution error: " << error << endl; }
|
||||
}
|
||||
|
||||
// Free the used memory.
|
||||
delete ode_solver;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,537 +0,0 @@
|
||||
// MFEM Example 19
|
||||
//
|
||||
// Compile with: make ex19
|
||||
//
|
||||
// Sample runs:
|
||||
// ex19 -m ../data/beam-quad.mesh
|
||||
// ex19 -m ../data/beam-tri.mesh
|
||||
// ex19 -m ../data/beam-hex.mesh
|
||||
// ex19 -m ../data/beam-tet.mesh
|
||||
//
|
||||
// Description: This examples solves a quasi-static incompressible nonlinear
|
||||
// elasticity problem of the form 0 = H(x), where H is an
|
||||
// incompressible hyperelastic model and x is a block state vector
|
||||
// containing displacement and pressure variables. The geometry of
|
||||
// the domain is assumed to be as follows:
|
||||
//
|
||||
// +---------------------+
|
||||
// boundary --->| |<--- boundary
|
||||
// attribute 1 | | attribute 2
|
||||
// (fixed) +---------------------+ (fixed, nonzero)
|
||||
//
|
||||
// The example demonstrates the use of block nonlinear operators
|
||||
// (the class RubberOperator defining H(x)) as well as a nonlinear
|
||||
// Newton solver for the quasi-static problem. Each Newton step
|
||||
// requires the inversion of a Jacobian matrix, which is done
|
||||
// through a (preconditioned) inner solver. The specialized block
|
||||
// preconditioner is implemented as a user-defined solver.
|
||||
//
|
||||
// We recommend viewing examples 2, 5, and 10 before viewing this
|
||||
// example.
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
using namespace std;
|
||||
using namespace mfem;
|
||||
|
||||
// Custom block preconditioner for the Jacobian of the incompressible nonlinear
|
||||
// elasticity operator. It has the form
|
||||
//
|
||||
// P^-1 = [ K^-1 0 ][ I -B^T ][ I 0 ]
|
||||
// [ 0 I ][ 0 I ][ 0 -\gamma S^-1 ]
|
||||
//
|
||||
// where the original Jacobian has the form
|
||||
//
|
||||
// J = [ K B^T ]
|
||||
// [ B 0 ]
|
||||
//
|
||||
// and K^-1 is an approximation of the inverse of the displacement part of the
|
||||
// Jacobian and S^-1 is an approximation of the inverse of the Schur
|
||||
// complement S = B K^-1 B^T. The Schur complement is approximated using
|
||||
// a mass matrix of the pressure variables.
|
||||
class JacobianPreconditioner : public Solver
|
||||
{
|
||||
protected:
|
||||
// Finite element spaces for setting up preconditioner blocks
|
||||
Array<FiniteElementSpace *> spaces;
|
||||
|
||||
// Offsets for extracting block vector segments
|
||||
Array<int> &block_offsets;
|
||||
|
||||
// Jacobian for block access
|
||||
BlockOperator *jacobian;
|
||||
|
||||
// Scaling factor for the pressure mass matrix in the block preconditioner
|
||||
double gamma;
|
||||
|
||||
// Objects for the block preconditioner application
|
||||
SparseMatrix *pressure_mass;
|
||||
Solver *mass_pcg;
|
||||
Solver *mass_prec;
|
||||
Solver *stiff_pcg;
|
||||
Solver *stiff_prec;
|
||||
|
||||
public:
|
||||
JacobianPreconditioner(Array<FiniteElementSpace *> &fes,
|
||||
SparseMatrix &mass, Array<int> &offsets);
|
||||
|
||||
virtual void Mult(const Vector &k, Vector &y) const;
|
||||
virtual void SetOperator(const Operator &op);
|
||||
|
||||
virtual ~JacobianPreconditioner();
|
||||
};
|
||||
|
||||
// After spatial discretization, the rubber model can be written as:
|
||||
// 0 = H(x)
|
||||
// where x is the block vector representing the deformation and pressure and
|
||||
// H(x) is the nonlinear incompressible neo-Hookean operator.
|
||||
class RubberOperator : public Operator
|
||||
{
|
||||
protected:
|
||||
// Finite element spaces
|
||||
Array<FiniteElementSpace *> spaces;
|
||||
|
||||
// Block nonlinear form
|
||||
BlockNonlinearForm *Hform;
|
||||
|
||||
// Pressure mass matrix for the preconditioner
|
||||
SparseMatrix *pressure_mass;
|
||||
|
||||
// Newton solver for the hyperelastic operator
|
||||
NewtonSolver newton_solver;
|
||||
|
||||
// Solver for the Jacobian solve in the Newton method
|
||||
Solver *j_solver;
|
||||
|
||||
// Preconditioner for the Jacobian
|
||||
Solver *j_prec;
|
||||
|
||||
// Shear modulus coefficient
|
||||
Coefficient μ
|
||||
|
||||
// Block offsets for variable access
|
||||
Array<int> &block_offsets;
|
||||
|
||||
public:
|
||||
RubberOperator(Array<FiniteElementSpace *> &fes, Array<Array<int> *>&ess_bdr,
|
||||
Array<int> &block_trueOffsets, double rel_tol, double abs_tol,
|
||||
int iter, Coefficient &mu);
|
||||
|
||||
// Required to use the native newton solver
|
||||
virtual Operator &GetGradient(const Vector &xp) const;
|
||||
virtual void Mult(const Vector &k, Vector &y) const;
|
||||
|
||||
// Driver for the newton solver
|
||||
void Solve(Vector &xp) const;
|
||||
|
||||
virtual ~RubberOperator();
|
||||
};
|
||||
|
||||
// Visualization driver
|
||||
void visualize(ostream &out, Mesh *mesh, GridFunction *deformed_nodes,
|
||||
GridFunction *field, const char *field_name = NULL,
|
||||
bool init_vis = false);
|
||||
|
||||
// Configuration definition functions
|
||||
void ReferenceConfiguration(const Vector &x, Vector &y);
|
||||
void InitialDeformation(const Vector &x, Vector &y);
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// 1. Parse command-line options
|
||||
const char *mesh_file = "../data/beam-hex.mesh";
|
||||
int ref_levels = 0;
|
||||
int order = 2;
|
||||
bool visualization = true;
|
||||
double newton_rel_tol = 1e-4;
|
||||
double newton_abs_tol = 1e-6;
|
||||
int newton_iter = 500;
|
||||
double mu = 1.0;
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
args.AddOption(&mesh_file, "-m", "--mesh",
|
||||
"Mesh file to use.");
|
||||
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(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
args.AddOption(&newton_rel_tol, "-rel", "--relative-tolerance",
|
||||
"Relative tolerance for the Newton solve.");
|
||||
args.AddOption(&newton_abs_tol, "-abs", "--absolute-tolerance",
|
||||
"Absolute tolerance for the Newton solve.");
|
||||
args.AddOption(&newton_iter, "-it", "--newton-iterations",
|
||||
"Maximum iterations for the Newton solve.");
|
||||
args.AddOption(&mu, "-mu", "--shear-modulus",
|
||||
"Shear modulus for the neo-Hookean material.");
|
||||
args.Parse();
|
||||
if (!args.Good())
|
||||
{
|
||||
args.PrintUsage(cout);
|
||||
return 1;
|
||||
}
|
||||
args.PrintOptions(cout);
|
||||
|
||||
// 2. Read the mesh from the given mesh file. We can handle triangular,
|
||||
// quadrilateral, tetrahedral and hexahedral meshes with the same code.
|
||||
Mesh *mesh = new Mesh(mesh_file, 1, 1);
|
||||
int dim = mesh->Dimension();
|
||||
|
||||
// 3. Refine the mesh to increase the resolution. In this example we do
|
||||
// 'ref_levels' of uniform refinement, where 'ref_levels' is a
|
||||
// command-line parameter.
|
||||
for (int lev = 0; lev < ref_levels; lev++)
|
||||
{
|
||||
mesh->UniformRefinement();
|
||||
}
|
||||
|
||||
// 4. Define the shear modulus for the incompressible Neo-Hookean material
|
||||
ConstantCoefficient c_mu(mu);
|
||||
|
||||
// 5. Define the finite element spaces for displacement and pressure
|
||||
// (Taylor-Hood elements). By default, the displacement (u/x) is a second
|
||||
// order vector field, while the pressure (p) is a linear scalar function.
|
||||
H1_FECollection quad_coll(order, dim);
|
||||
H1_FECollection lin_coll(order-1, dim);
|
||||
|
||||
FiniteElementSpace R_space(mesh, &quad_coll, dim, Ordering::byVDIM);
|
||||
FiniteElementSpace W_space(mesh, &lin_coll);
|
||||
|
||||
Array<FiniteElementSpace *> spaces(2);
|
||||
spaces[0] = &R_space;
|
||||
spaces[1] = &W_space;
|
||||
|
||||
int R_size = R_space.GetVSize();
|
||||
int W_size = W_space.GetVSize();
|
||||
|
||||
// 6. Define the Dirichlet conditions (set to boundary attribute 1 and 2)
|
||||
Array<Array<int> *> ess_bdr(2);
|
||||
|
||||
Array<int> ess_bdr_u(R_space.GetMesh()->bdr_attributes.Max());
|
||||
Array<int> ess_bdr_p(W_space.GetMesh()->bdr_attributes.Max());
|
||||
|
||||
ess_bdr_p = 0;
|
||||
ess_bdr_u = 0;
|
||||
ess_bdr_u[0] = 1;
|
||||
ess_bdr_u[1] = 1;
|
||||
|
||||
ess_bdr[0] = &ess_bdr_u;
|
||||
ess_bdr[1] = &ess_bdr_p;
|
||||
|
||||
// 7. Print the mesh statistics
|
||||
std::cout << "***********************************************************\n";
|
||||
std::cout << "dim(u) = " << R_size << "\n";
|
||||
std::cout << "dim(p) = " << W_size << "\n";
|
||||
std::cout << "dim(u+p) = " << R_size + W_size << "\n";
|
||||
std::cout << "***********************************************************\n";
|
||||
|
||||
// 8. Define the block structure of the solution vector (u then p)
|
||||
Array<int> block_offsets(3);
|
||||
block_offsets[0] = 0;
|
||||
block_offsets[1] = R_space.GetVSize();
|
||||
block_offsets[2] = W_space.GetVSize();
|
||||
block_offsets.PartialSum();
|
||||
|
||||
BlockVector xp(block_offsets);
|
||||
|
||||
// 9. Define grid functions for the current configuration, reference
|
||||
// configuration, final deformation, and pressure
|
||||
GridFunction x_gf(&R_space);
|
||||
GridFunction x_ref(&R_space);
|
||||
GridFunction x_def(&R_space);
|
||||
GridFunction p_gf(&W_space);
|
||||
|
||||
x_gf.MakeRef(&R_space, xp.GetBlock(0), 0);
|
||||
p_gf.MakeRef(&W_space, xp.GetBlock(1), 0);
|
||||
|
||||
VectorFunctionCoefficient deform(dim, InitialDeformation);
|
||||
VectorFunctionCoefficient refconfig(dim, ReferenceConfiguration);
|
||||
|
||||
x_gf.ProjectCoefficient(deform);
|
||||
x_ref.ProjectCoefficient(refconfig);
|
||||
p_gf = 0.0;
|
||||
|
||||
// 10. Initialize the incompressible neo-Hookean operator
|
||||
RubberOperator oper(spaces, ess_bdr, block_offsets,
|
||||
newton_rel_tol, newton_abs_tol, newton_iter, c_mu);
|
||||
|
||||
// 11. Solve the Newton system
|
||||
oper.Solve(xp);
|
||||
|
||||
// 12. Compute the final deformation
|
||||
subtract(x_gf, x_ref, x_def);
|
||||
|
||||
// 13. Visualize the results if requested
|
||||
socketstream vis_u, vis_p;
|
||||
if (visualization)
|
||||
{
|
||||
char vishost[] = "localhost";
|
||||
int visport = 19916;
|
||||
vis_u.open(vishost, visport);
|
||||
vis_u.precision(8);
|
||||
visualize(vis_u, mesh, &x_gf, &x_def, "Deformation", true);
|
||||
vis_p.open(vishost, visport);
|
||||
vis_p.precision(8);
|
||||
visualize(vis_p, mesh, &x_gf, &p_gf, "Pressure", true);
|
||||
}
|
||||
|
||||
// 14. Save the displaced mesh, the final deformation, and the pressure
|
||||
{
|
||||
GridFunction *nodes = &x_gf;
|
||||
int owns_nodes = 0;
|
||||
mesh->SwapNodes(nodes, owns_nodes);
|
||||
|
||||
ofstream mesh_ofs("deformed.mesh");
|
||||
mesh_ofs.precision(8);
|
||||
mesh->Print(mesh_ofs);
|
||||
|
||||
ofstream pressure_ofs("pressure.sol");
|
||||
pressure_ofs.precision(8);
|
||||
p_gf.Save(pressure_ofs);
|
||||
|
||||
ofstream deformation_ofs("deformation.sol");
|
||||
deformation_ofs.precision(8);
|
||||
x_def.Save(deformation_ofs);
|
||||
}
|
||||
|
||||
// 15. Free the used memory
|
||||
delete mesh;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
JacobianPreconditioner::JacobianPreconditioner(Array<FiniteElementSpace *> &fes,
|
||||
SparseMatrix &mass,
|
||||
Array<int> &offsets)
|
||||
: Solver(offsets[2]), block_offsets(offsets), pressure_mass(&mass)
|
||||
{
|
||||
fes.Copy(spaces);
|
||||
|
||||
gamma = 0.00001;
|
||||
|
||||
// The mass matrix and preconditioner do not change every Newton cycle, so we
|
||||
// only need to define them once
|
||||
GSSmoother *mass_prec_gs = new GSSmoother(*pressure_mass);
|
||||
|
||||
mass_prec = mass_prec_gs;
|
||||
|
||||
CGSolver *mass_pcg_iter = new CGSolver();
|
||||
mass_pcg_iter->SetRelTol(1e-12);
|
||||
mass_pcg_iter->SetAbsTol(1e-12);
|
||||
mass_pcg_iter->SetMaxIter(200);
|
||||
mass_pcg_iter->SetPrintLevel(0);
|
||||
mass_pcg_iter->SetPreconditioner(*mass_prec);
|
||||
mass_pcg_iter->SetOperator(*pressure_mass);
|
||||
mass_pcg_iter->iterative_mode = false;
|
||||
|
||||
mass_pcg = mass_pcg_iter;
|
||||
|
||||
// The stiffness matrix does change every Newton cycle, so we will define it
|
||||
// during SetOperator
|
||||
stiff_pcg = NULL;
|
||||
stiff_prec = NULL;
|
||||
}
|
||||
|
||||
void JacobianPreconditioner::Mult(const Vector &k, Vector &y) const
|
||||
{
|
||||
// Extract the blocks from the input and output vectors
|
||||
Vector disp_in(k.GetData() + block_offsets[0],
|
||||
block_offsets[1]-block_offsets[0]);
|
||||
Vector pres_in(k.GetData() + block_offsets[1],
|
||||
block_offsets[2]-block_offsets[1]);
|
||||
|
||||
Vector disp_out(y.GetData() + block_offsets[0],
|
||||
block_offsets[1]-block_offsets[0]);
|
||||
Vector pres_out(y.GetData() + block_offsets[1],
|
||||
block_offsets[2]-block_offsets[1]);
|
||||
|
||||
Vector temp(block_offsets[1]-block_offsets[0]);
|
||||
Vector temp2(block_offsets[1]-block_offsets[0]);
|
||||
|
||||
// Perform the block elimination for the preconditioner
|
||||
mass_pcg->Mult(pres_in, pres_out);
|
||||
pres_out *= -gamma;
|
||||
|
||||
jacobian->GetBlock(0,1).Mult(pres_out, temp);
|
||||
subtract(disp_in, temp, temp2);
|
||||
|
||||
stiff_pcg->Mult(temp2, disp_out);
|
||||
}
|
||||
|
||||
void JacobianPreconditioner::SetOperator(const Operator &op)
|
||||
{
|
||||
jacobian = (BlockOperator *) &op;
|
||||
|
||||
// Initialize the stiffness preconditioner and solver
|
||||
if (stiff_prec == NULL)
|
||||
{
|
||||
GSSmoother *stiff_prec_gs = new GSSmoother();
|
||||
|
||||
stiff_prec = stiff_prec_gs;
|
||||
|
||||
GMRESSolver *stiff_pcg_iter = new GMRESSolver();
|
||||
stiff_pcg_iter->SetRelTol(1e-8);
|
||||
stiff_pcg_iter->SetAbsTol(1e-8);
|
||||
stiff_pcg_iter->SetMaxIter(200);
|
||||
stiff_pcg_iter->SetPrintLevel(0);
|
||||
stiff_pcg_iter->SetPreconditioner(*stiff_prec);
|
||||
stiff_pcg_iter->iterative_mode = false;
|
||||
|
||||
stiff_pcg = stiff_pcg_iter;
|
||||
}
|
||||
|
||||
// At each Newton cycle, compute the new stiffness preconditioner by updating
|
||||
// the iterative solver which, in turn, updates its preconditioner
|
||||
stiff_pcg->SetOperator(jacobian->GetBlock(0,0));
|
||||
}
|
||||
|
||||
JacobianPreconditioner::~JacobianPreconditioner()
|
||||
{
|
||||
delete mass_pcg;
|
||||
delete mass_prec;
|
||||
delete stiff_prec;
|
||||
delete stiff_pcg;
|
||||
}
|
||||
|
||||
|
||||
RubberOperator::RubberOperator(Array<FiniteElementSpace *> &fes,
|
||||
Array<Array<int> *> &ess_bdr,
|
||||
Array<int> &offsets,
|
||||
double rel_tol,
|
||||
double abs_tol,
|
||||
int iter,
|
||||
Coefficient &c_mu)
|
||||
: Operator(fes[0]->GetVSize() + fes[1]->GetVSize()),
|
||||
newton_solver(), mu(c_mu), block_offsets(offsets)
|
||||
{
|
||||
Array<Vector *> rhs(2);
|
||||
rhs = NULL; // Set all entries in the array
|
||||
|
||||
fes.Copy(spaces);
|
||||
|
||||
// Define the block nonlinear form
|
||||
Hform = new BlockNonlinearForm(spaces);
|
||||
|
||||
// Add the incompressible neo-Hookean integrator
|
||||
Hform->AddDomainIntegrator(new IncompressibleNeoHookeanIntegrator(mu));
|
||||
|
||||
// Set the essential boundary conditions
|
||||
Hform->SetEssentialBC(ess_bdr, rhs);
|
||||
|
||||
// Compute the pressure mass stiffness matrix
|
||||
BilinearForm *a = new BilinearForm(spaces[1]);
|
||||
ConstantCoefficient one(1.0);
|
||||
a->AddDomainIntegrator(new MassIntegrator(one));
|
||||
a->Assemble();
|
||||
a->Finalize();
|
||||
pressure_mass = a->LoseMat();
|
||||
delete a;
|
||||
|
||||
// Initialize the Jacobian preconditioner
|
||||
JacobianPreconditioner *jac_prec =
|
||||
new JacobianPreconditioner(fes, *pressure_mass, block_offsets);
|
||||
j_prec = jac_prec;
|
||||
|
||||
// Set up the Jacobian solver
|
||||
GMRESSolver *j_gmres = new GMRESSolver();
|
||||
j_gmres->iterative_mode = false;
|
||||
j_gmres->SetRelTol(1e-12);
|
||||
j_gmres->SetAbsTol(1e-12);
|
||||
j_gmres->SetMaxIter(300);
|
||||
j_gmres->SetPrintLevel(0);
|
||||
j_gmres->SetPreconditioner(*j_prec);
|
||||
j_solver = j_gmres;
|
||||
|
||||
// Set the newton solve parameters
|
||||
newton_solver.iterative_mode = true;
|
||||
newton_solver.SetSolver(*j_solver);
|
||||
newton_solver.SetOperator(*this);
|
||||
newton_solver.SetPrintLevel(1);
|
||||
newton_solver.SetRelTol(rel_tol);
|
||||
newton_solver.SetAbsTol(abs_tol);
|
||||
newton_solver.SetMaxIter(iter);
|
||||
}
|
||||
|
||||
// Solve the Newton system
|
||||
void RubberOperator::Solve(Vector &xp) const
|
||||
{
|
||||
Vector zero;
|
||||
newton_solver.Mult(zero, xp);
|
||||
MFEM_VERIFY(newton_solver.GetConverged(),
|
||||
"Newton Solver did not converge.");
|
||||
}
|
||||
|
||||
// compute: y = H(x,p)
|
||||
void RubberOperator::Mult(const Vector &k, Vector &y) const
|
||||
{
|
||||
Hform->Mult(k, y);
|
||||
}
|
||||
|
||||
// Compute the Jacobian from the nonlinear form
|
||||
Operator &RubberOperator::GetGradient(const Vector &xp) const
|
||||
{
|
||||
return Hform->GetGradient(xp);
|
||||
}
|
||||
|
||||
RubberOperator::~RubberOperator()
|
||||
{
|
||||
delete Hform;
|
||||
delete pressure_mass;
|
||||
delete j_solver;
|
||||
delete j_prec;
|
||||
}
|
||||
|
||||
|
||||
// Inline visualization
|
||||
void visualize(ostream &out, Mesh *mesh, GridFunction *deformed_nodes,
|
||||
GridFunction *field, const char *field_name, bool init_vis)
|
||||
{
|
||||
if (!out)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GridFunction *nodes = deformed_nodes;
|
||||
int owns_nodes = 0;
|
||||
|
||||
mesh->SwapNodes(nodes, owns_nodes);
|
||||
|
||||
out << "solution\n" << *mesh << *field;
|
||||
|
||||
mesh->SwapNodes(nodes, owns_nodes);
|
||||
|
||||
if (init_vis)
|
||||
{
|
||||
out << "window_size 800 800\n";
|
||||
out << "window_title '" << field_name << "'\n";
|
||||
if (mesh->SpaceDimension() == 2)
|
||||
{
|
||||
out << "view 0 0\n"; // view from top
|
||||
out << "keys jlA\n"; // turn off perspective and light, +anti-aliasing
|
||||
}
|
||||
out << "keys cmA\n"; // show colorbar and mesh, +anti-aliasing
|
||||
out << "autoscale value\n"; // update value-range; keep mesh-extents fixed
|
||||
}
|
||||
out << flush;
|
||||
}
|
||||
|
||||
void ReferenceConfiguration(const Vector &x, Vector &y)
|
||||
{
|
||||
// Set the reference, stress free, configuration
|
||||
y = x;
|
||||
}
|
||||
|
||||
void InitialDeformation(const Vector &x, Vector &y)
|
||||
{
|
||||
// Set the initial configuration. Having this different from the reference
|
||||
// configuration can help convergence
|
||||
y = x;
|
||||
y[1] = x[1] + 0.25*x[0];
|
||||
}
|
||||
@@ -1,591 +0,0 @@
|
||||
// MFEM Example 19 - Parallel Version
|
||||
//
|
||||
// Compile with: make ex19p
|
||||
//
|
||||
// Sample runs:
|
||||
// mpirun -np 2 ex19p -m ../data/beam-quad.mesh
|
||||
// mpirun -np 2 ex19p -m ../data/beam-tri.mesh
|
||||
// mpirun -np 2 ex19p -m ../data/beam-hex.mesh
|
||||
// mpirun -np 2 ex19p -m ../data/beam-tet.mesh
|
||||
//
|
||||
// Description: This examples solves a quasi-static incompressible nonlinear
|
||||
// elasticity problem of the form 0 = H(x), where H is an
|
||||
// incompressible hyperelastic model and x is a block state vector
|
||||
// containing displacement and pressure variables. The geometry of
|
||||
// the domain is assumed to be as follows:
|
||||
//
|
||||
// +---------------------+
|
||||
// boundary --->| |<--- boundary
|
||||
// attribute 1 | | attribute 2
|
||||
// (fixed) +---------------------+ (fixed, nonzero)
|
||||
//
|
||||
// The example demonstrates the use of block nonlinear operators
|
||||
// (the class RubberOperator defining H(x)) as well as a nonlinear
|
||||
// Newton solver for the quasi-static problem. Each Newton step
|
||||
// requires the inversion of a Jacobian matrix, which is done
|
||||
// through a (preconditioned) inner solver. The specialized block
|
||||
// preconditioner is implemented as a user-defined solver.
|
||||
//
|
||||
// We recommend viewing examples 2, 5, and 10 before viewing this
|
||||
// example.
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
using namespace std;
|
||||
using namespace mfem;
|
||||
|
||||
// Custom block preconditioner for the Jacobian of the incompressible nonlinear
|
||||
// elasticity operator. It has the form
|
||||
//
|
||||
// P^-1 = [ K^-1 0 ][ I -B^T ][ I 0 ]
|
||||
// [ 0 I ][ 0 I ][ 0 -\gamma S^-1 ]
|
||||
//
|
||||
// where the original Jacobian has the form
|
||||
//
|
||||
// J = [ K B^T ]
|
||||
// [ B 0 ]
|
||||
//
|
||||
// and K^-1 is an approximation of the inverse of the displacement part of the
|
||||
// Jacobian and S^-1 is an approximation of the inverse of the Schur
|
||||
// complement S = B K^-1 B^T. The Schur complement is approximated using
|
||||
// a mass matrix of the pressure variables.
|
||||
class JacobianPreconditioner : public Solver
|
||||
{
|
||||
protected:
|
||||
// Finite element spaces for setting up preconditioner blocks
|
||||
Array<ParFiniteElementSpace *> spaces;
|
||||
|
||||
// Offsets for extracting block vector segments
|
||||
Array<int> &block_trueOffsets;
|
||||
|
||||
// Jacobian for block access
|
||||
BlockOperator *jacobian;
|
||||
|
||||
// Scaling factor for the pressure mass matrix in the block preconditioner
|
||||
double gamma;
|
||||
|
||||
// Objects for the block preconditioner application
|
||||
Operator *pressure_mass;
|
||||
Solver *mass_pcg;
|
||||
Solver *mass_prec;
|
||||
Solver *stiff_pcg;
|
||||
Solver *stiff_prec;
|
||||
|
||||
public:
|
||||
JacobianPreconditioner(Array<ParFiniteElementSpace *> &fes,
|
||||
Operator &mass, Array<int> &offsets);
|
||||
|
||||
virtual void Mult(const Vector &k, Vector &y) const;
|
||||
virtual void SetOperator(const Operator &op);
|
||||
|
||||
virtual ~JacobianPreconditioner();
|
||||
};
|
||||
|
||||
// After spatial discretization, the rubber model can be written as:
|
||||
// 0 = H(x)
|
||||
// where x is the block vector representing the deformation and pressure and
|
||||
// H(x) is the nonlinear incompressible neo-Hookean operator.
|
||||
class RubberOperator : public Operator
|
||||
{
|
||||
protected:
|
||||
// Finite element spaces
|
||||
Array<ParFiniteElementSpace *> spaces;
|
||||
|
||||
// Block nonlinear form
|
||||
ParBlockNonlinearForm *Hform;
|
||||
|
||||
// Pressure mass matrix for the preconditioner
|
||||
Operator *pressure_mass;
|
||||
|
||||
// Newton solver for the hyperelastic operator
|
||||
NewtonSolver newton_solver;
|
||||
|
||||
// Solver for the Jacobian solve in the Newton method
|
||||
Solver *j_solver;
|
||||
|
||||
// Preconditioner for the Jacobian
|
||||
Solver *j_prec;
|
||||
|
||||
// Shear modulus coefficient
|
||||
Coefficient μ
|
||||
|
||||
// Block offsets for variable access
|
||||
Array<int> &block_trueOffsets;
|
||||
|
||||
public:
|
||||
RubberOperator(Array<ParFiniteElementSpace *> &fes, Array<Array<int> *>&ess_bdr,
|
||||
Array<int> &block_trueOffsets, double rel_tol, double abs_tol,
|
||||
int iter, Coefficient &mu);
|
||||
|
||||
// Required to use the native newton solver
|
||||
virtual Operator &GetGradient(const Vector &xp) const;
|
||||
virtual void Mult(const Vector &k, Vector &y) const;
|
||||
|
||||
// Driver for the newton solver
|
||||
void Solve(Vector &xp) const;
|
||||
|
||||
virtual ~RubberOperator();
|
||||
};
|
||||
|
||||
// Visualization driver
|
||||
void visualize(ostream &out, ParMesh *mesh, ParGridFunction *deformed_nodes,
|
||||
ParGridFunction *field, const char *field_name = NULL,
|
||||
bool init_vis = false);
|
||||
|
||||
// Configuration definition functions
|
||||
void ReferenceConfiguration(const Vector &x, Vector &y);
|
||||
void InitialDeformation(const Vector &x, Vector &y);
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// 1. Initialize MPI
|
||||
int num_procs, myid;
|
||||
MPI_Init(&argc, &argv);
|
||||
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
|
||||
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
|
||||
|
||||
// 2. Parse command-line options
|
||||
const char *mesh_file = "../data/beam-hex.mesh";
|
||||
int ser_ref_levels = 0;
|
||||
int par_ref_levels = 0;
|
||||
int order = 2;
|
||||
bool visualization = true;
|
||||
double newton_rel_tol = 1e-4;
|
||||
double newton_abs_tol = 1e-6;
|
||||
int newton_iter = 500;
|
||||
double mu = 1.0;
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
args.AddOption(&mesh_file, "-m", "--mesh",
|
||||
"Mesh file to use.");
|
||||
args.AddOption(&ser_ref_levels, "-rs", "--refine-serial",
|
||||
"Number of times to refine the mesh uniformly in serial.");
|
||||
args.AddOption(&par_ref_levels, "-rp", "--refine-parallel",
|
||||
"Number of times to refine the mesh uniformly in parallel.");
|
||||
args.AddOption(&order, "-o", "--order",
|
||||
"Order (degree) of the finite elements.");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
args.AddOption(&newton_rel_tol, "-rel", "--relative-tolerance",
|
||||
"Relative tolerance for the Newton solve.");
|
||||
args.AddOption(&newton_abs_tol, "-abs", "--absolute-tolerance",
|
||||
"Absolute tolerance for the Newton solve.");
|
||||
args.AddOption(&newton_iter, "-it", "--newton-iterations",
|
||||
"Maximum iterations for the Newton solve.");
|
||||
args.AddOption(&mu, "-mu", "--shear-modulus",
|
||||
"Shear modulus for the neo-Hookean material.");
|
||||
args.Parse();
|
||||
if (!args.Good())
|
||||
{
|
||||
if (myid == 0)
|
||||
{
|
||||
args.PrintUsage(cout);
|
||||
}
|
||||
MPI_Finalize();
|
||||
return 1;
|
||||
}
|
||||
if (myid == 0)
|
||||
{
|
||||
args.PrintOptions(cout);
|
||||
}
|
||||
|
||||
// 3. Read the (serial) mesh from the given mesh file on all processors. We
|
||||
// can handle triangular, quadrilateral, tetrahedral and hexahedral meshes
|
||||
// with the same code.
|
||||
Mesh *mesh = new Mesh(mesh_file, 1, 1);
|
||||
int dim = mesh->Dimension();
|
||||
|
||||
// 4. Refine the mesh in serial to increase the resolution. In this example
|
||||
// we do 'ser_ref_levels' of uniform refinement, where 'ser_ref_levels' is
|
||||
// a command-line parameter.
|
||||
for (int lev = 0; lev < ser_ref_levels; lev++)
|
||||
{
|
||||
mesh->UniformRefinement();
|
||||
}
|
||||
|
||||
// 5. Define a parallel mesh by a partitioning of the serial mesh. Refine
|
||||
// this mesh further in parallel to increase the resolution. Once the
|
||||
// parallel mesh is defined, the serial mesh can be deleted.
|
||||
ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
|
||||
delete mesh;
|
||||
for (int lev = 0; lev < par_ref_levels; lev++)
|
||||
{
|
||||
pmesh->UniformRefinement();
|
||||
}
|
||||
|
||||
// 6. Define the shear modulus for the incompressible Neo-Hookean material
|
||||
ConstantCoefficient c_mu(mu);
|
||||
|
||||
// 7. Define the finite element spaces for displacement and pressure
|
||||
// (Taylor-Hood elements). By default, the displacement (u/x) is a second
|
||||
// order vector field, while the pressure (p) is a linear scalar function.
|
||||
H1_FECollection quad_coll(order, dim);
|
||||
H1_FECollection lin_coll(order-1, dim);
|
||||
|
||||
ParFiniteElementSpace R_space(pmesh, &quad_coll, dim, Ordering::byVDIM);
|
||||
ParFiniteElementSpace W_space(pmesh, &lin_coll);
|
||||
|
||||
Array<ParFiniteElementSpace *> spaces(2);
|
||||
spaces[0] = &R_space;
|
||||
spaces[1] = &W_space;
|
||||
|
||||
HYPRE_Int glob_R_size = R_space.GlobalTrueVSize();
|
||||
HYPRE_Int glob_W_size = W_space.GlobalTrueVSize();
|
||||
|
||||
// 8. Define the Dirichlet conditions (set to boundary attribute 1 and 2)
|
||||
Array<Array<int> *> ess_bdr(2);
|
||||
|
||||
Array<int> ess_bdr_u(R_space.GetMesh()->bdr_attributes.Max());
|
||||
Array<int> ess_bdr_p(W_space.GetMesh()->bdr_attributes.Max());
|
||||
|
||||
ess_bdr_p = 0;
|
||||
ess_bdr_u = 0;
|
||||
ess_bdr_u[0] = 1;
|
||||
ess_bdr_u[1] = 1;
|
||||
|
||||
ess_bdr[0] = &ess_bdr_u;
|
||||
ess_bdr[1] = &ess_bdr_p;
|
||||
|
||||
// 9. Print the mesh statistics
|
||||
if (myid == 0)
|
||||
{
|
||||
std::cout << "***********************************************************\n";
|
||||
std::cout << "dim(u) = " << glob_R_size << "\n";
|
||||
std::cout << "dim(p) = " << glob_W_size << "\n";
|
||||
std::cout << "dim(u+p) = " << glob_R_size + glob_W_size << "\n";
|
||||
std::cout << "***********************************************************\n";
|
||||
}
|
||||
|
||||
// 10. Define the block structure of the solution vector (u then p)
|
||||
Array<int> block_trueOffsets(3);
|
||||
block_trueOffsets[0] = 0;
|
||||
block_trueOffsets[1] = R_space.TrueVSize();
|
||||
block_trueOffsets[2] = W_space.TrueVSize();
|
||||
block_trueOffsets.PartialSum();
|
||||
|
||||
BlockVector xp(block_trueOffsets);
|
||||
|
||||
// 11. Define grid functions for the current configuration, reference
|
||||
// configuration, final deformation, and pressure
|
||||
ParGridFunction x_gf(&R_space);
|
||||
ParGridFunction x_ref(&R_space);
|
||||
ParGridFunction x_def(&R_space);
|
||||
ParGridFunction p_gf(&W_space);
|
||||
|
||||
VectorFunctionCoefficient deform(dim, InitialDeformation);
|
||||
VectorFunctionCoefficient refconfig(dim, ReferenceConfiguration);
|
||||
|
||||
x_gf.ProjectCoefficient(deform);
|
||||
x_ref.ProjectCoefficient(refconfig);
|
||||
p_gf = 0.0;
|
||||
|
||||
// 12. Set up the block solution vectors
|
||||
x_gf.GetTrueDofs(xp.GetBlock(0));
|
||||
p_gf.GetTrueDofs(xp.GetBlock(1));
|
||||
|
||||
// 13. Initialize the incompressible neo-Hookean operator
|
||||
RubberOperator oper(spaces, ess_bdr, block_trueOffsets,
|
||||
newton_rel_tol, newton_abs_tol, newton_iter, c_mu);
|
||||
|
||||
// 14. Solve the Newton system
|
||||
oper.Solve(xp);
|
||||
|
||||
// 15. Distribute the shared degrees of freedom
|
||||
x_gf.Distribute(xp.GetBlock(0));
|
||||
p_gf.Distribute(xp.GetBlock(1));
|
||||
|
||||
// 16. Compute the final deformation
|
||||
subtract(x_gf, x_ref, x_def);
|
||||
|
||||
// 17. Visualize the results if requested
|
||||
socketstream vis_u, vis_p;
|
||||
if (visualization)
|
||||
{
|
||||
char vishost[] = "localhost";
|
||||
int visport = 19916;
|
||||
vis_u.open(vishost, visport);
|
||||
vis_u.precision(8);
|
||||
visualize(vis_u, pmesh, &x_gf, &x_def, "Deformation", true);
|
||||
// Make sure all ranks have sent their 'u' solution before initiating
|
||||
// another set of GLVis connections (one from each rank):
|
||||
MPI_Barrier(pmesh->GetComm());
|
||||
vis_p.open(vishost, visport);
|
||||
vis_p.precision(8);
|
||||
visualize(vis_p, pmesh, &x_gf, &p_gf, "Pressure", true);
|
||||
}
|
||||
|
||||
// 18. Save the displaced mesh, the final deformation, and the pressure
|
||||
{
|
||||
GridFunction *nodes = &x_gf;
|
||||
int owns_nodes = 0;
|
||||
pmesh->SwapNodes(nodes, owns_nodes);
|
||||
|
||||
ostringstream mesh_name, pressure_name, deformation_name;
|
||||
mesh_name << "mesh." << setfill('0') << setw(6) << myid;
|
||||
pressure_name << "pressure." << setfill('0') << setw(6) << myid;
|
||||
deformation_name << "deformation." << setfill('0') << setw(6) << myid;
|
||||
|
||||
ofstream mesh_ofs(mesh_name.str().c_str());
|
||||
mesh_ofs.precision(8);
|
||||
pmesh->Print(mesh_ofs);
|
||||
|
||||
ofstream pressure_ofs(pressure_name.str().c_str());
|
||||
pressure_ofs.precision(8);
|
||||
p_gf.Save(pressure_ofs);
|
||||
|
||||
ofstream deformation_ofs(deformation_name.str().c_str());
|
||||
deformation_ofs.precision(8);
|
||||
x_def.Save(deformation_ofs);
|
||||
}
|
||||
|
||||
// 19. Free the used memory
|
||||
delete pmesh;
|
||||
|
||||
MPI_Finalize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
JacobianPreconditioner::JacobianPreconditioner(Array<ParFiniteElementSpace *>
|
||||
&fes,
|
||||
Operator &mass,
|
||||
Array<int> &offsets)
|
||||
: Solver(offsets[2]), block_trueOffsets(offsets), pressure_mass(&mass)
|
||||
{
|
||||
fes.Copy(spaces);
|
||||
|
||||
gamma = 0.00001;
|
||||
|
||||
// The mass matrix and preconditioner do not change every Newton cycle, so
|
||||
// we only need to define them once
|
||||
HypreBoomerAMG *mass_prec_amg = new HypreBoomerAMG();
|
||||
mass_prec_amg->SetPrintLevel(0);
|
||||
|
||||
mass_prec = mass_prec_amg;
|
||||
|
||||
CGSolver *mass_pcg_iter = new CGSolver(spaces[0]->GetComm());
|
||||
mass_pcg_iter->SetRelTol(1e-12);
|
||||
mass_pcg_iter->SetAbsTol(1e-12);
|
||||
mass_pcg_iter->SetMaxIter(200);
|
||||
mass_pcg_iter->SetPrintLevel(0);
|
||||
mass_pcg_iter->SetPreconditioner(*mass_prec);
|
||||
mass_pcg_iter->SetOperator(*pressure_mass);
|
||||
mass_pcg_iter->iterative_mode = false;
|
||||
|
||||
mass_pcg = mass_pcg_iter;
|
||||
|
||||
// The stiffness matrix does change every Newton cycle, so we will define it
|
||||
// during SetOperator
|
||||
stiff_pcg = NULL;
|
||||
stiff_prec = NULL;
|
||||
}
|
||||
|
||||
void JacobianPreconditioner::Mult(const Vector &k, Vector &y) const
|
||||
{
|
||||
// Extract the blocks from the input and output vectors
|
||||
Vector disp_in(k.GetData() + block_trueOffsets[0],
|
||||
block_trueOffsets[1]-block_trueOffsets[0]);
|
||||
Vector pres_in(k.GetData() + block_trueOffsets[1],
|
||||
block_trueOffsets[2]-block_trueOffsets[1]);
|
||||
|
||||
Vector disp_out(y.GetData() + block_trueOffsets[0],
|
||||
block_trueOffsets[1]-block_trueOffsets[0]);
|
||||
Vector pres_out(y.GetData() + block_trueOffsets[1],
|
||||
block_trueOffsets[2]-block_trueOffsets[1]);
|
||||
|
||||
Vector temp(block_trueOffsets[1]-block_trueOffsets[0]);
|
||||
Vector temp2(block_trueOffsets[1]-block_trueOffsets[0]);
|
||||
|
||||
// Perform the block elimination for the preconditioner
|
||||
mass_pcg->Mult(pres_in, pres_out);
|
||||
pres_out *= -gamma;
|
||||
|
||||
jacobian->GetBlock(0,1).Mult(pres_out, temp);
|
||||
subtract(disp_in, temp, temp2);
|
||||
|
||||
stiff_pcg->Mult(temp2, disp_out);
|
||||
}
|
||||
|
||||
void JacobianPreconditioner::SetOperator(const Operator &op)
|
||||
{
|
||||
jacobian = (BlockOperator *) &op;
|
||||
|
||||
// Initialize the stiffness preconditioner and solver
|
||||
if (stiff_prec == NULL)
|
||||
{
|
||||
HypreBoomerAMG *stiff_prec_amg = new HypreBoomerAMG();
|
||||
stiff_prec_amg->SetPrintLevel(0);
|
||||
stiff_prec_amg->SetElasticityOptions(spaces[0]);
|
||||
|
||||
stiff_prec = stiff_prec_amg;
|
||||
|
||||
GMRESSolver *stiff_pcg_iter = new GMRESSolver(spaces[0]->GetComm());
|
||||
stiff_pcg_iter->SetRelTol(1e-8);
|
||||
stiff_pcg_iter->SetAbsTol(1e-8);
|
||||
stiff_pcg_iter->SetMaxIter(200);
|
||||
stiff_pcg_iter->SetPrintLevel(0);
|
||||
stiff_pcg_iter->SetPreconditioner(*stiff_prec);
|
||||
stiff_pcg_iter->iterative_mode = false;
|
||||
|
||||
stiff_pcg = stiff_pcg_iter;
|
||||
}
|
||||
|
||||
// At each Newton cycle, compute the new stiffness AMG preconditioner by
|
||||
// updating the iterative solver which, in turn, updates its preconditioner
|
||||
stiff_pcg->SetOperator(jacobian->GetBlock(0,0));
|
||||
}
|
||||
|
||||
JacobianPreconditioner::~JacobianPreconditioner()
|
||||
{
|
||||
delete mass_pcg;
|
||||
delete mass_prec;
|
||||
delete stiff_prec;
|
||||
delete stiff_pcg;
|
||||
}
|
||||
|
||||
|
||||
RubberOperator::RubberOperator(Array<ParFiniteElementSpace *> &fes,
|
||||
Array<Array<int> *> &ess_bdr,
|
||||
Array<int> &trueOffsets,
|
||||
double rel_tol,
|
||||
double abs_tol,
|
||||
int iter,
|
||||
Coefficient &c_mu)
|
||||
: Operator(fes[0]->TrueVSize() + fes[1]->TrueVSize()),
|
||||
newton_solver(fes[0]->GetComm()), mu(c_mu), block_trueOffsets(trueOffsets)
|
||||
{
|
||||
Array<Vector *> rhs(2);
|
||||
rhs = NULL; // Set all entries in the array
|
||||
|
||||
fes.Copy(spaces);
|
||||
|
||||
// Define the block nonlinear form
|
||||
Hform = new ParBlockNonlinearForm(spaces);
|
||||
|
||||
// Add the incompressible neo-Hookean integrator
|
||||
Hform->AddDomainIntegrator(new IncompressibleNeoHookeanIntegrator(mu));
|
||||
|
||||
// Set the essential boundary conditions
|
||||
Hform->SetEssentialBC(ess_bdr, rhs);
|
||||
|
||||
// Compute the pressure mass stiffness matrix
|
||||
ParBilinearForm *a = new ParBilinearForm(spaces[1]);
|
||||
ConstantCoefficient one(1.0);
|
||||
OperatorHandle mass(Operator::Hypre_ParCSR);
|
||||
a->AddDomainIntegrator(new MassIntegrator(one));
|
||||
a->Assemble();
|
||||
a->Finalize();
|
||||
a->ParallelAssemble(mass);
|
||||
delete a;
|
||||
|
||||
mass.SetOperatorOwner(false);
|
||||
pressure_mass = mass.Ptr();
|
||||
|
||||
// Initialize the Jacobian preconditioner
|
||||
JacobianPreconditioner *jac_prec =
|
||||
new JacobianPreconditioner(fes, *pressure_mass, block_trueOffsets);
|
||||
j_prec = jac_prec;
|
||||
|
||||
// Set up the Jacobian solver
|
||||
GMRESSolver *j_gmres = new GMRESSolver(spaces[0]->GetComm());
|
||||
j_gmres->iterative_mode = false;
|
||||
j_gmres->SetRelTol(1e-12);
|
||||
j_gmres->SetAbsTol(1e-12);
|
||||
j_gmres->SetMaxIter(300);
|
||||
j_gmres->SetPrintLevel(0);
|
||||
j_gmres->SetPreconditioner(*j_prec);
|
||||
j_solver = j_gmres;
|
||||
|
||||
// Set the newton solve parameters
|
||||
newton_solver.iterative_mode = true;
|
||||
newton_solver.SetSolver(*j_solver);
|
||||
newton_solver.SetOperator(*this);
|
||||
newton_solver.SetPrintLevel(1);
|
||||
newton_solver.SetRelTol(rel_tol);
|
||||
newton_solver.SetAbsTol(abs_tol);
|
||||
newton_solver.SetMaxIter(iter);
|
||||
}
|
||||
|
||||
// Solve the Newton system
|
||||
void RubberOperator::Solve(Vector &xp) const
|
||||
{
|
||||
Vector zero;
|
||||
newton_solver.Mult(zero, xp);
|
||||
MFEM_VERIFY(newton_solver.GetConverged(),
|
||||
"Newton Solver did not converge.");
|
||||
}
|
||||
|
||||
// compute: y = H(x,p)
|
||||
void RubberOperator::Mult(const Vector &k, Vector &y) const
|
||||
{
|
||||
Hform->Mult(k, y);
|
||||
}
|
||||
|
||||
// Compute the Jacobian from the nonlinear form
|
||||
Operator &RubberOperator::GetGradient(const Vector &xp) const
|
||||
{
|
||||
return Hform->GetGradient(xp);
|
||||
}
|
||||
|
||||
RubberOperator::~RubberOperator()
|
||||
{
|
||||
delete Hform;
|
||||
delete pressure_mass;
|
||||
delete j_solver;
|
||||
delete j_prec;
|
||||
}
|
||||
|
||||
|
||||
// Inline visualization
|
||||
void visualize(ostream &out, ParMesh *mesh, ParGridFunction *deformed_nodes,
|
||||
ParGridFunction *field, const char *field_name, bool init_vis)
|
||||
{
|
||||
if (!out)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GridFunction *nodes = deformed_nodes;
|
||||
int owns_nodes = 0;
|
||||
|
||||
mesh->SwapNodes(nodes, owns_nodes);
|
||||
|
||||
out << "parallel " << mesh->GetNRanks() << " " << mesh->GetMyRank() << "\n";
|
||||
out << "solution\n" << *mesh << *field;
|
||||
|
||||
mesh->SwapNodes(nodes, owns_nodes);
|
||||
|
||||
if (init_vis)
|
||||
{
|
||||
out << "window_size 800 800\n";
|
||||
out << "window_title '" << field_name << "'\n";
|
||||
if (mesh->SpaceDimension() == 2)
|
||||
{
|
||||
out << "view 0 0\n"; // view from top
|
||||
out << "keys jlA\n"; // turn off perspective and light, +anti-aliasing
|
||||
}
|
||||
out << "keys cmA\n"; // show colorbar and mesh, +anti-aliasing
|
||||
out << "autoscale value\n"; // update value-range; keep mesh-extents fixed
|
||||
}
|
||||
out << flush;
|
||||
}
|
||||
|
||||
void ReferenceConfiguration(const Vector &x, Vector &y)
|
||||
{
|
||||
// Set the reference, stress free, configuration
|
||||
y = x;
|
||||
}
|
||||
|
||||
void InitialDeformation(const Vector &x, Vector &y)
|
||||
{
|
||||
// Set the initial configuration. Having this different from the reference
|
||||
// configuration can help convergence
|
||||
y = x;
|
||||
y[1] = x[1] + 0.25*x[0];
|
||||
}
|
||||
@@ -84,9 +84,9 @@ int main(int argc, char *argv[])
|
||||
|
||||
// 3. Select the order of the finite element discretization space. For NURBS
|
||||
// meshes, we increase the order by degree elevation.
|
||||
if (mesh->NURBSext)
|
||||
if (mesh->NURBSext && order > mesh->NURBSext->GetOrder())
|
||||
{
|
||||
mesh->DegreeElevate(order, order);
|
||||
mesh->DegreeElevate(order - mesh->NURBSext->GetOrder());
|
||||
}
|
||||
|
||||
// 4. Refine the mesh to increase the resolution. In this example we do
|
||||
|
||||
@@ -107,9 +107,9 @@ int main(int argc, char *argv[])
|
||||
|
||||
// 4. Select the order of the finite element discretization space. For NURBS
|
||||
// meshes, we increase the order by degree elevation.
|
||||
if (mesh->NURBSext)
|
||||
if (mesh->NURBSext && order > mesh->NURBSext->GetOrder())
|
||||
{
|
||||
mesh->DegreeElevate(order, order);
|
||||
mesh->DegreeElevate(order - mesh->NURBSext->GetOrder());
|
||||
}
|
||||
|
||||
// 5. Refine the serial mesh on all processors to increase the resolution. In
|
||||
|
||||
@@ -53,7 +53,6 @@ int main(int argc, char *argv[])
|
||||
// 2. Parse command-line options.
|
||||
const char *mesh_file = "../data/star.mesh";
|
||||
int order = 1;
|
||||
bool par_format = false;
|
||||
bool visualization = 1;
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
@@ -61,9 +60,6 @@ int main(int argc, char *argv[])
|
||||
"Mesh file to use.");
|
||||
args.AddOption(&order, "-o", "--order",
|
||||
"Finite element order (polynomial degree).");
|
||||
args.AddOption(&par_format, "-pf", "--parallel-format", "-sf",
|
||||
"--serial-format",
|
||||
"Format to use when saving the results for VisIt.");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
@@ -321,9 +317,6 @@ int main(int argc, char *argv[])
|
||||
VisItDataCollection visit_dc("Example5-Parallel", pmesh);
|
||||
visit_dc.RegisterField("velocity", u);
|
||||
visit_dc.RegisterField("pressure", p);
|
||||
visit_dc.SetFormat(!par_format ?
|
||||
DataCollection::SERIAL_FORMAT :
|
||||
DataCollection::PARALLEL_FORMAT);
|
||||
visit_dc.Save();
|
||||
|
||||
// 16. Send the solution by socket to a GLVis server.
|
||||
|
||||
@@ -146,7 +146,6 @@ int main(int argc, char *argv[])
|
||||
case 6: ode_solver = new RK6Solver; break;
|
||||
default:
|
||||
cout << "Unknown ODE solver type: " << ode_solver_type << '\n';
|
||||
delete mesh;
|
||||
return 3;
|
||||
}
|
||||
|
||||
|
||||
@@ -164,7 +164,6 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
cout << "Unknown ODE solver type: " << ode_solver_type << '\n';
|
||||
}
|
||||
delete mesh;
|
||||
MPI_Finalize();
|
||||
return 3;
|
||||
}
|
||||
@@ -271,8 +270,6 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
dc = new VisItDataCollection("Example9-Parallel", pmesh);
|
||||
dc->SetPrecision(precision);
|
||||
// To save the mesh using MFEM's parallel mesh format:
|
||||
// dc->SetFormat(DataCollection::PARALLEL_FORMAT);
|
||||
}
|
||||
dc->RegisterField("solution", u);
|
||||
dc->SetCycle(0);
|
||||
|
||||
@@ -14,37 +14,24 @@ MFEM_DIR ?= ..
|
||||
MFEM_BUILD_DIR ?= ..
|
||||
SRC = $(if $(MFEM_DIR:..=),$(MFEM_DIR)/examples/,)
|
||||
CONFIG_MK = $(MFEM_BUILD_DIR)/config/config.mk
|
||||
TEST_MK = $(MFEM_DIR)/config/test.mk
|
||||
# Use the MFEM install directory
|
||||
# MFEM_INSTALL_DIR = ../mfem
|
||||
# CONFIG_MK = $(MFEM_INSTALL_DIR)/share/mfem/config.mk
|
||||
# SRC = $(if $(MFEM_DIR),$(MFEM_DIR)/examples/,)
|
||||
# MFEM_DIR = ../mfem
|
||||
# CONFIG_MK = $(MFEM_DIR)/config.mk
|
||||
# TEST_MK = $(MFEM_DIR)/test.mk
|
||||
|
||||
MFEM_LIB_FILE = mfem_is_not_built
|
||||
-include $(CONFIG_MK)
|
||||
|
||||
SEQ_EXAMPLES = ex1 ex2 ex3 ex4 ex5 ex6 ex7 ex8 ex9 ex10 ex14 ex15 ex16 ex17\
|
||||
ex18 ex19
|
||||
SEQ_EXAMPLES = ex1 ex2 ex3 ex4 ex5 ex6 ex7 ex8 ex9 ex10 ex14 ex15 ex16 ex17
|
||||
PAR_EXAMPLES = ex1p ex2p ex3p ex4p ex5p ex6p ex7p ex8p ex9p ex10p ex11p ex12p\
|
||||
ex13p ex14p ex15p ex16p ex17p ex18p ex19p
|
||||
|
||||
ex13p ex14p ex15p ex16p ex17p
|
||||
ifeq ($(MFEM_USE_MPI),NO)
|
||||
EXAMPLES = $(SEQ_EXAMPLES)
|
||||
else
|
||||
EXAMPLES = $(PAR_EXAMPLES) $(SEQ_EXAMPLES)
|
||||
endif
|
||||
SUBDIRS =
|
||||
ifeq ($(MFEM_USE_SUNDIALS),YES)
|
||||
SUBDIRS += sundials
|
||||
endif
|
||||
ifeq ($(MFEM_USE_PETSC),YES)
|
||||
SUBDIRS += petsc
|
||||
endif
|
||||
ifeq ($(MFEM_USE_PUMI),YES)
|
||||
SUBDIRS += pumi
|
||||
endif
|
||||
SUBDIRS_ALL = $(addsuffix /all,$(SUBDIRS))
|
||||
SUBDIRS_TEST = $(addsuffix /test,$(SUBDIRS))
|
||||
SUBDIRS_CLEAN = $(addsuffix /clean,$(SUBDIRS))
|
||||
SUBDIRS_TPRINT = $(addsuffix /test-print,$(SUBDIRS))
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .o .cpp .mk
|
||||
@@ -57,27 +44,13 @@ SUBDIRS_TPRINT = $(addsuffix /test-print,$(SUBDIRS))
|
||||
%: $(SRC)%.cpp $(MFEM_LIB_FILE) $(CONFIG_MK)
|
||||
$(MFEM_CXX) $(MFEM_FLAGS) $< -o $@ $(MFEM_LIBS)
|
||||
|
||||
all: $(EXAMPLES) $(SUBDIRS_ALL)
|
||||
|
||||
.PHONY: $(SUBDIRS_ALL) $(SUBDIRS_TEST) $(SUBDIRS_CLEAN) $(SUBDIRS_TPRINT)
|
||||
$(SUBDIRS_ALL) $(SUBDIRS_TEST) $(SUBDIRS_CLEAN):
|
||||
$(MAKE) -C $(@D) $(@F)
|
||||
$(SUBDIRS_TPRINT):
|
||||
@$(MAKE) -C $(@D) $(@F)
|
||||
|
||||
# Additional dependencies
|
||||
ex18: $(SRC)ex18.hpp
|
||||
ifeq ($(MFEM_USE_MPI),YES)
|
||||
ex18p: $(SRC)ex18.hpp
|
||||
endif
|
||||
all: $(EXAMPLES)
|
||||
|
||||
MFEM_TESTS = EXAMPLES
|
||||
include $(MFEM_TEST_MK)
|
||||
test: $(SUBDIRS_TEST)
|
||||
test-print: $(SUBDIRS_TPRINT)
|
||||
include $(TEST_MK)
|
||||
|
||||
# Testing: Parallel vs. serial runs
|
||||
RUN_MPI = $(MFEM_MPIEXEC) $(MFEM_MPIEXEC_NP) $(MFEM_MPI_NP)
|
||||
RUN_MPI = $(MFEM_MPIEXEC) $(MFEM_MPIEXEC_NP) 4
|
||||
%-test-par: %
|
||||
@$(call mfem-test,$<, $(RUN_MPI), Parallel example)
|
||||
%-test-seq: %
|
||||
@@ -103,7 +76,7 @@ ex15p-test-par: ex15p
|
||||
$(MFEM_LIB_FILE):
|
||||
$(error The MFEM library is not built)
|
||||
|
||||
clean: clean-build clean-exec $(SUBDIRS_CLEAN)
|
||||
clean: clean-build clean-exec
|
||||
|
||||
clean-build:
|
||||
rm -f *.o *~ $(SEQ_EXAMPLES) $(PAR_EXAMPLES)
|
||||
@@ -116,5 +89,3 @@ clean-exec:
|
||||
@rm -f ex9.mesh ex9-mesh.* ex9-init.* ex9-final.*
|
||||
@rm -f deformed.* velocity.* elastic_energy.* mode_*
|
||||
@rm -f ex16.mesh ex16-mesh.* ex16-init.* ex16-final.*
|
||||
@rm -f vortex-mesh.* vortex.mesh vortex-?-init.* vortex-?-final.*
|
||||
@rm -f deformation.* pressure.*
|
||||
|
||||
@@ -35,7 +35,7 @@ if (MFEM_USE_MPI)
|
||||
endif()
|
||||
|
||||
# Include the source directory where mfem.hpp and mfem-performance.hpp are.
|
||||
include_directories(BEFORE ${PROJECT_BINARY_DIR})
|
||||
include_directories(${PROJECT_BINARY_DIR})
|
||||
|
||||
# Add targets to copy rc_* files from the source directory
|
||||
foreach(RC_FILE ${PETSC_RC_FILES})
|
||||
@@ -49,7 +49,7 @@ add_custom_target(copy_petsc_rc_files DEPENDS ${PETSC_RC_FILES}
|
||||
|
||||
# Add "test_petsc" target, see below.
|
||||
add_custom_target(test_petsc
|
||||
${CMAKE_CTEST_COMMAND} -R petsc USES_TERMINAL)
|
||||
${CMAKE_CTEST_COMMAND} -R petsc -C PETSC USES_TERMINAL)
|
||||
|
||||
# Add one executable per cpp file, adding "petsc_" as prefix. Sets
|
||||
# "copy_petsc_rc_files" as a prerequisite for the given examples. Also, sets
|
||||
@@ -58,47 +58,50 @@ set(PFX petsc_)
|
||||
add_mfem_examples(PETSC_EXAMPLES_SRCS ${PFX} copy_petsc_rc_files test_petsc)
|
||||
|
||||
# Testing.
|
||||
# The PETSc tests can be run separately using the target "test_petsc" which
|
||||
# builds the examples and runs:
|
||||
# ctest -R petsc
|
||||
# We do not want these tests to be run by default, so we add them to their own
|
||||
# configuration - PETSC. To run the tests defined here use the "test_petsc"
|
||||
# target which builds the examples and runs:
|
||||
# ctest -C PETSC -R 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(EX2_ARGS -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex2p)
|
||||
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)
|
||||
set(EX5_BDDC_LB_ARGS -m ../../data/star.mesh --usepetsc -o 0 --petscopts rc_ex5p_bddc --nonoverlapping --local-bdr)
|
||||
set(EX5_BDDC_GB_ARGS -m ../../data/star.mesh --usepetsc -o 0 --petscopts rc_ex5p_bddc --nonoverlapping)
|
||||
set(EX5_FSPL_ARGS -m ../../data/beam-tet.mesh --usepetsc -o 0 --petscopts rc_ex5p_fieldsplit)
|
||||
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_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(EX1P_ARGS -m ../../data/amr-quad.mesh --usepetsc --petscopts rc_ex1p)
|
||||
set(EX2P_ARGS -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex2p)
|
||||
set(EX3P_ARGS -m ../../data/klein-bottle.mesh
|
||||
-o 2 -f 0.1 --usepetsc --petscopts rc_ex3p_bddc --nonoverlapping)
|
||||
set(EX4P_ARGS -m ../../data/klein-bottle.mesh
|
||||
-o 2 --usepetsc --petscopts rc_ex4p_bddc --nonoverlapping)
|
||||
set(EX5_BDDC_ARGS -m ../../data/star.mesh
|
||||
--usepetsc --petscopts rc_ex5p_bddc --nonoverlapping)
|
||||
set(EX5_FSPL_ARGS -m ../../data/beam-tet.mesh
|
||||
--usepetsc --petscopts rc_ex5p_fieldsplit)
|
||||
set(EX5P_ARGS ${EX5_FSPL_ARGS})
|
||||
set(EX6P_ARGS -m ../../data/amr-quad.mesh --usepetsc)
|
||||
set(EX9P_ARGS -m ../../data/periodic-hexagon.mesh
|
||||
--usepetsc --petscopts rc_ex9p_expl)
|
||||
set(EX10P_ARGS -m ../../data/beam-quad.mesh
|
||||
-tf 30 -s 3 -rs 2 -dt 3 --usepetsc --petscopts rc_ex10p)
|
||||
|
||||
# Add the tests: one test per command-line-variable.
|
||||
foreach(TEST_OPTIONS_VAR
|
||||
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)
|
||||
string(REGEX REPLACE "^(.+)_ARGS" "\\1" TEST_NAME_UC ${TEST_OPTIONS_VAR})
|
||||
string(REGEX REPLACE "^([^_]+)" "\\1P" TEST_NAME_UC ${TEST_NAME_UC})
|
||||
string(TOLOWER ${TEST_NAME_UC} TEST_NAME_FULL)
|
||||
string(REGEX REPLACE "^([^_]+).*" "\\1" TEST_NAME ${TEST_NAME_FULL})
|
||||
set(TEST_NAME_FULL ${PFX}${TEST_NAME_FULL})
|
||||
# Add the tests: one test per source file.
|
||||
foreach(SRC_FILE ${PETSC_EXAMPLES_SRCS})
|
||||
get_filename_component(SRC_FILENAME ${SRC_FILE} NAME)
|
||||
string(REPLACE ".cpp" "" TEST_NAME ${SRC_FILENAME})
|
||||
string(TOUPPER ${TEST_NAME} UP_TEST_NAME)
|
||||
set(TEST_NAME ${PFX}${TEST_NAME})
|
||||
set(TEST_OPTIONS "-no-vis" ${${TEST_OPTIONS_VAR}})
|
||||
# message(STATUS "${TEST_NAME_FULL} --> ${TEST_NAME} ${TEST_OPTIONS}")
|
||||
|
||||
# All PETSC tests are parallel.
|
||||
if (MFEM_USE_MPI)
|
||||
add_test(NAME ${TEST_NAME_FULL}_np=4
|
||||
set(THIS_TEST_OPTIONS "-no-vis")
|
||||
list(APPEND THIS_TEST_OPTIONS ${${UP_TEST_NAME}_ARGS})
|
||||
# message(STATUS "Test ${TEST_NAME} options: ${THIS_TEST_OPTIONS}")
|
||||
|
||||
if (NOT (${TEST_NAME} MATCHES ".*p$"))
|
||||
add_test(NAME ${TEST_NAME}_ser
|
||||
COMMAND ${TEST_NAME} ${THIS_TEST_OPTIONS}
|
||||
CONFIGURATIONS PETSC)
|
||||
else()
|
||||
add_test(NAME ${TEST_NAME}_np=4
|
||||
COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} 4
|
||||
${MPIEXEC_PREFLAGS}
|
||||
$<TARGET_FILE:${TEST_NAME}> ${TEST_OPTIONS}
|
||||
${MPIEXEC_POSTFLAGS})
|
||||
$<TARGET_FILE:${TEST_NAME}> ${THIS_TEST_OPTIONS}
|
||||
${MPIEXEC_POSTFLAGS}
|
||||
CONFIGURATIONS PETSC)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
//
|
||||
// Sample runs:
|
||||
// mpirun -np 4 ex10p -m ../../data/beam-quad.mesh --petscopts rc_ex10p -s 3 -rs 2 -dt 3
|
||||
// mpirun -np 4 ex10p -m ../../data/beam-quad-amr.mesh --petscopts rc_ex10p -s 3 -rs 2 -dt 3
|
||||
//
|
||||
// Description: This examples solves a time dependent nonlinear elasticity
|
||||
// problem of the form dv/dt = H(x) + S v, dx/dt = v, where H is a
|
||||
@@ -61,7 +60,6 @@ class HyperelasticOperator : public TimeDependentOperator
|
||||
{
|
||||
protected:
|
||||
ParFiniteElementSpace &fespace;
|
||||
Array<int> ess_tdof_list;
|
||||
|
||||
ParBilinearForm M, S;
|
||||
ParNonlinearForm H;
|
||||
@@ -99,10 +97,9 @@ public:
|
||||
This is the only requirement for high-order SDIRK implicit integration.*/
|
||||
virtual void ImplicitSolve(const double dt, const Vector &x, Vector &k);
|
||||
|
||||
double ElasticEnergy(const ParGridFunction &x) const;
|
||||
double KineticEnergy(const ParGridFunction &v) const;
|
||||
void GetElasticEnergyDensity(const ParGridFunction &x,
|
||||
ParGridFunction &w) const;
|
||||
double ElasticEnergy(ParGridFunction &x) const;
|
||||
double KineticEnergy(ParGridFunction &v) const;
|
||||
void GetElasticEnergyDensity(ParGridFunction &x, ParGridFunction &w) const;
|
||||
|
||||
virtual ~HyperelasticOperator();
|
||||
};
|
||||
@@ -116,15 +113,14 @@ class ReducedSystemOperator : public Operator
|
||||
private:
|
||||
ParBilinearForm *M, *S;
|
||||
ParNonlinearForm *H;
|
||||
mutable HypreParMatrix *Jacobian;
|
||||
mutable Operator *Jacobian;
|
||||
double dt;
|
||||
const Vector *v, *x;
|
||||
mutable Vector w, z;
|
||||
const Array<int> &ess_tdof_list;
|
||||
|
||||
public:
|
||||
ReducedSystemOperator(ParBilinearForm *M_, ParBilinearForm *S_,
|
||||
ParNonlinearForm *H_, const Array<int> &ess_tdof_list);
|
||||
ParNonlinearForm *H_);
|
||||
|
||||
/// Set current dt, v, x values - needed to compute action and Jacobian.
|
||||
void SetParameters(double dt_, const Vector *v_, const Vector *x_);
|
||||
@@ -144,12 +140,12 @@ public:
|
||||
class ElasticEnergyCoefficient : public Coefficient
|
||||
{
|
||||
private:
|
||||
HyperelasticModel &model;
|
||||
const ParGridFunction &x;
|
||||
DenseMatrix J;
|
||||
HyperelasticModel &model;
|
||||
ParGridFunction &x;
|
||||
DenseMatrix J;
|
||||
|
||||
public:
|
||||
ElasticEnergyCoefficient(HyperelasticModel &m, const ParGridFunction &x_)
|
||||
ElasticEnergyCoefficient(HyperelasticModel &m, ParGridFunction &x_)
|
||||
: model(m), x(x_) { }
|
||||
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip);
|
||||
virtual ~ElasticEnergyCoefficient() { }
|
||||
@@ -315,9 +311,7 @@ int main(int argc, char *argv[])
|
||||
true_offset[2] = 2*true_size;
|
||||
|
||||
BlockVector vx(true_offset);
|
||||
ParGridFunction v_gf, x_gf;
|
||||
v_gf.MakeTRef(&fespace, vx, true_offset[0]);
|
||||
x_gf.MakeTRef(&fespace, vx, true_offset[1]);
|
||||
ParGridFunction v_gf(&fespace), x_gf(&fespace);
|
||||
|
||||
ParGridFunction x_ref(&fespace);
|
||||
pmesh->GetNodes(x_ref);
|
||||
@@ -330,12 +324,11 @@ int main(int argc, char *argv[])
|
||||
// boundary conditions on a beam-like mesh (see description above).
|
||||
VectorFunctionCoefficient velo(dim, InitialVelocity);
|
||||
v_gf.ProjectCoefficient(velo);
|
||||
v_gf.SetTrueVector();
|
||||
VectorFunctionCoefficient deform(dim, InitialDeformation);
|
||||
x_gf.ProjectCoefficient(deform);
|
||||
x_gf.SetTrueVector();
|
||||
|
||||
v_gf.SetFromTrueVector(); x_gf.SetFromTrueVector();
|
||||
v_gf.GetTrueDofs(vx.GetBlock(0));
|
||||
x_gf.GetTrueDofs(vx.GetBlock(1));
|
||||
|
||||
Array<int> ess_bdr(fespace.GetMesh()->bdr_attributes.Max());
|
||||
ess_bdr = 0;
|
||||
@@ -392,7 +385,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (last_step || (ti % vis_steps) == 0)
|
||||
{
|
||||
v_gf.SetFromTrueVector(); x_gf.SetFromTrueVector();
|
||||
v_gf.Distribute(vx.GetBlock(0));
|
||||
x_gf.Distribute(vx.GetBlock(1));
|
||||
|
||||
double ee = oper->ElasticEnergy(x_gf);
|
||||
double ke = oper->KineticEnergy(v_gf);
|
||||
@@ -417,7 +411,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
// 11. Save the displaced mesh, the velocity and elastic energy.
|
||||
{
|
||||
v_gf.SetFromTrueVector(); x_gf.SetFromTrueVector();
|
||||
GridFunction *nodes = &x_gf;
|
||||
int owns_nodes = 0;
|
||||
pmesh->SwapNodes(nodes, owns_nodes);
|
||||
@@ -489,11 +482,9 @@ void visualize(ostream &out, ParMesh *mesh, ParGridFunction *deformed_nodes,
|
||||
|
||||
|
||||
ReducedSystemOperator::ReducedSystemOperator(
|
||||
ParBilinearForm *M_, ParBilinearForm *S_, ParNonlinearForm *H_,
|
||||
const Array<int> &ess_tdof_list_)
|
||||
ParBilinearForm *M_, ParBilinearForm *S_, ParNonlinearForm *H_)
|
||||
: Operator(M_->ParFESpace()->TrueVSize()), M(M_), S(S_), H(H_),
|
||||
Jacobian(NULL), dt(0.0), v(NULL), x(NULL), w(height), z(height),
|
||||
ess_tdof_list(ess_tdof_list_)
|
||||
Jacobian(NULL), dt(0.0), v(NULL), x(NULL), w(height), z(height)
|
||||
{ }
|
||||
|
||||
void ReducedSystemOperator::SetParameters(double dt_, const Vector *v_,
|
||||
@@ -510,7 +501,6 @@ void ReducedSystemOperator::Mult(const Vector &k, Vector &y) const
|
||||
H->Mult(z, y);
|
||||
M->TrueAddMult(k, y);
|
||||
S->TrueAddMult(w, y);
|
||||
y.SetSubVector(ess_tdof_list, 0.0);
|
||||
}
|
||||
|
||||
Operator &ReducedSystemOperator::GetGradient(const Vector &k) const
|
||||
@@ -524,8 +514,6 @@ Operator &ReducedSystemOperator::GetGradient(const Vector &k) const
|
||||
// PETSc's AIJ on the fly
|
||||
Jacobian = M->ParallelAssemble(localJ);
|
||||
delete localJ;
|
||||
HypreParMatrix *Je = Jacobian->EliminateRowsCols(ess_tdof_list);
|
||||
delete Je;
|
||||
return *Jacobian;
|
||||
}
|
||||
|
||||
@@ -550,11 +538,9 @@ HyperelasticOperator::HyperelasticOperator(ParFiniteElementSpace &f,
|
||||
ConstantCoefficient rho0(ref_density);
|
||||
M.AddDomainIntegrator(new VectorMassIntegrator(rho0));
|
||||
M.Assemble(skip_zero_entries);
|
||||
M.EliminateEssentialBC(ess_bdr);
|
||||
M.Finalize(skip_zero_entries);
|
||||
Mmat = M.ParallelAssemble();
|
||||
fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
|
||||
HypreParMatrix *Me = Mmat->EliminateRowsCols(ess_tdof_list);
|
||||
delete Me;
|
||||
|
||||
M_solver.iterative_mode = false;
|
||||
M_solver.SetRelTol(rel_tol);
|
||||
@@ -567,14 +553,15 @@ HyperelasticOperator::HyperelasticOperator(ParFiniteElementSpace &f,
|
||||
|
||||
model = new NeoHookeanModel(mu, K);
|
||||
H.AddDomainIntegrator(new HyperelasticNLFIntegrator(model));
|
||||
H.SetEssentialTrueDofs(ess_tdof_list);
|
||||
H.SetEssentialBC(ess_bdr);
|
||||
|
||||
ConstantCoefficient visc_coeff(viscosity);
|
||||
S.AddDomainIntegrator(new VectorDiffusionIntegrator(visc_coeff));
|
||||
S.Assemble(skip_zero_entries);
|
||||
S.EliminateEssentialBC(ess_bdr);
|
||||
S.Finalize(skip_zero_entries);
|
||||
|
||||
reduced_oper = new ReducedSystemOperator(&M, &S, &H, ess_tdof_list);
|
||||
reduced_oper = new ReducedSystemOperator(&M, &S, &H);
|
||||
if (!use_petsc)
|
||||
{
|
||||
HypreSmoother *J_hypreSmoother = new HypreSmoother;
|
||||
@@ -626,7 +613,6 @@ void HyperelasticOperator::Mult(const Vector &vx, Vector &dvx_dt) const
|
||||
if (viscosity != 0.0)
|
||||
{
|
||||
S.TrueAddMult(v, z);
|
||||
z.SetSubVector(ess_tdof_list, 0.0);
|
||||
}
|
||||
z.Neg(); // z = -z
|
||||
M_solver.Mult(z, dv_dt);
|
||||
@@ -666,12 +652,12 @@ void HyperelasticOperator::ImplicitSolve(const double dt,
|
||||
add(v, dt, dv_dt, dx_dt);
|
||||
}
|
||||
|
||||
double HyperelasticOperator::ElasticEnergy(const ParGridFunction &x) const
|
||||
double HyperelasticOperator::ElasticEnergy(ParGridFunction &x) const
|
||||
{
|
||||
return H.GetEnergy(x);
|
||||
}
|
||||
|
||||
double HyperelasticOperator::KineticEnergy(const ParGridFunction &v) const
|
||||
double HyperelasticOperator::KineticEnergy(ParGridFunction &v) const
|
||||
{
|
||||
double loc_energy = 0.5*M.InnerProduct(v, v);
|
||||
double energy;
|
||||
@@ -681,7 +667,7 @@ double HyperelasticOperator::KineticEnergy(const ParGridFunction &v) const
|
||||
}
|
||||
|
||||
void HyperelasticOperator::GetElasticEnergyDensity(
|
||||
const ParGridFunction &x, ParGridFunction &w) const
|
||||
ParGridFunction &x, ParGridFunction &w) const
|
||||
{
|
||||
ElasticEnergyCoefficient w_coeff(*model, x);
|
||||
w.ProjectCoefficient(w_coeff);
|
||||
|
||||
@@ -121,9 +121,9 @@ int main(int argc, char *argv[])
|
||||
|
||||
// 4. Select the order of the finite element discretization space. For NURBS
|
||||
// meshes, we increase the order by degree elevation.
|
||||
if (mesh->NURBSext)
|
||||
if (mesh->NURBSext && order > mesh->NURBSext->GetOrder())
|
||||
{
|
||||
mesh->DegreeElevate(order, order);
|
||||
mesh->DegreeElevate(order - mesh->NURBSext->GetOrder());
|
||||
}
|
||||
|
||||
// 5. Refine the serial mesh on all processors to increase the resolution. In
|
||||
|
||||
@@ -60,11 +60,9 @@ int main(int argc, char *argv[])
|
||||
// 2. Parse command-line options.
|
||||
const char *mesh_file = "../../data/star.mesh";
|
||||
int order = 1;
|
||||
bool par_format = false;
|
||||
bool visualization = 1;
|
||||
bool use_petsc = true;
|
||||
bool use_nonoverlapping = false;
|
||||
bool local_bdr_spec = false;
|
||||
const char *petscrc_file = "";
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
@@ -72,9 +70,6 @@ int main(int argc, char *argv[])
|
||||
"Mesh file to use.");
|
||||
args.AddOption(&order, "-o", "--order",
|
||||
"Finite element order (polynomial degree).");
|
||||
args.AddOption(&par_format, "-pf", "--parallel-format", "-sf",
|
||||
"--serial-format",
|
||||
"Format to use when saving the results for VisIt.");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
@@ -87,9 +82,6 @@ int main(int argc, char *argv[])
|
||||
"-no-nonoverlapping", "--no-nonoverlapping",
|
||||
"Use or not the block diagonal PETSc's matrix format "
|
||||
"for non-overlapping domain decomposition.");
|
||||
args.AddOption(&local_bdr_spec, "-local-bdr", "--local-bdr", "-no-local-bdr",
|
||||
"--no-local-bdr",
|
||||
"Specify boundary dofs in local (Vdofs) ordering.");
|
||||
args.Parse();
|
||||
if (!args.Good())
|
||||
{
|
||||
@@ -218,7 +210,7 @@ int main(int argc, char *argv[])
|
||||
PetscParMatrix *pM = NULL, *pB = NULL, *pBT = NULL;
|
||||
HypreParMatrix *M = NULL, *B = NULL, *BT = NULL;
|
||||
Operator::Type tid =
|
||||
!use_petsc ? Operator::Hypre_ParCSR :
|
||||
!use_petsc ? Operator::HYPRE_PARCSR :
|
||||
(use_nonoverlapping ? Operator::PETSC_MATIS : Operator::PETSC_MATAIJ);
|
||||
OperatorHandle Mh(tid), Bh(tid);
|
||||
|
||||
@@ -310,38 +302,33 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
if (use_nonoverlapping)
|
||||
{
|
||||
PetscBDDCSolverParams opts;
|
||||
|
||||
// For saddle point problems, we need to provide BDDC the list of
|
||||
// boundary dofs either essential or natural.
|
||||
// Since R_space is the only space that may have boundary dofs and it
|
||||
// is ordered first then W_space, we don't need any local offset when
|
||||
// specifying the dofs.
|
||||
Array<int> bdr_tdof_list;
|
||||
bool local = false;
|
||||
if (pmesh->bdr_attributes.Size())
|
||||
{
|
||||
Array<int> bdr(pmesh->bdr_attributes.Max());
|
||||
bdr = 1;
|
||||
|
||||
if (!local_bdr_spec)
|
||||
{
|
||||
// Essential dofs in global ordering
|
||||
R_space->GetEssentialTrueDofs(bdr, bdr_tdof_list);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Alternatively, you can also provide the list of dofs in local
|
||||
// ordering
|
||||
R_space->GetEssentialVDofs(bdr, bdr_tdof_list);
|
||||
bdr_tdof_list.SetSize(R_space->GetVSize()+W_space->GetVSize(),0);
|
||||
}
|
||||
opts.SetNatBdrDofs(&bdr_tdof_list,local_bdr_spec);
|
||||
R_space->GetEssentialTrueDofs(bdr, bdr_tdof_list);
|
||||
local = false;
|
||||
// Alternatively, you can also provide the list of dofs in local
|
||||
// ordering:
|
||||
// R_space->GetEssentialVDofs(bdr, bdr_tdof_list);
|
||||
// bdr_tdof_list.SetSize(R_space->GetVSize()+W_space->GetVSize(),0);
|
||||
// local = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
MFEM_WARNING("Missing boundary dofs. This may cause solver failures.");
|
||||
MFEM_ABORT("Need to know the boundary dofs");
|
||||
}
|
||||
|
||||
PetscBDDCSolverParams opts;
|
||||
opts.SetNatBdrDofs(&bdr_tdof_list,local);
|
||||
// See also command line options rc_ex5p_bddc
|
||||
pdarcyPr = new PetscBDDCSolver(MPI_COMM_WORLD,*darcyOp,opts,"prec_");
|
||||
}
|
||||
@@ -491,9 +478,6 @@ int main(int argc, char *argv[])
|
||||
VisItDataCollection visit_dc("Example5-Parallel", pmesh);
|
||||
visit_dc.RegisterField("velocity", u);
|
||||
visit_dc.RegisterField("pressure", p);
|
||||
visit_dc.SetFormat(!par_format ?
|
||||
DataCollection::SERIAL_FORMAT :
|
||||
DataCollection::PARALLEL_FORMAT);
|
||||
visit_dc.Save();
|
||||
|
||||
// 16. Send the solution by socket to a GLVis server.
|
||||
|
||||
@@ -224,7 +224,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
a.Assemble();
|
||||
b.Assemble();
|
||||
a.SetOperatorType(Operator::Hypre_ParCSR);
|
||||
a.SetOperatorType(Operator::HYPRE_PARCSR);
|
||||
HypreParMatrix A;
|
||||
Vector B, X;
|
||||
MPI_Barrier(MPI_COMM_WORLD);
|
||||
|
||||
@@ -403,14 +403,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
double t = 0.0;
|
||||
adv->SetTime(t);
|
||||
if (use_petsc)
|
||||
{
|
||||
pode_solver->Init(*adv,PetscODESolver::ODE_SOLVER_LINEAR);
|
||||
}
|
||||
else
|
||||
{
|
||||
ode_solver->Init(*adv);
|
||||
}
|
||||
ode_solver->Init(*adv);
|
||||
|
||||
// Explicitly perform time-integration (looping over the time iterations, ti,
|
||||
// with a time-step dt), or use the Run method of the ODE solver class.
|
||||
@@ -431,6 +424,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
cout << "time step: " << ti << ", time: " << t << endl;
|
||||
}
|
||||
|
||||
// 11. Extract the parallel grid function corresponding to the finite
|
||||
// element approximation U (the local solution on each processor).
|
||||
*u = *U;
|
||||
|
||||
@@ -14,9 +14,12 @@ MFEM_DIR ?= ../..
|
||||
MFEM_BUILD_DIR ?= ../..
|
||||
SRC = $(if $(MFEM_DIR:../..=),$(MFEM_DIR)/examples/petsc/,)
|
||||
CONFIG_MK = $(MFEM_BUILD_DIR)/config/config.mk
|
||||
TEST_MK = $(MFEM_DIR)/config/test.mk
|
||||
# Use the MFEM install directory
|
||||
# MFEM_INSTALL_DIR = ../../mfem
|
||||
# CONFIG_MK = $(MFEM_INSTALL_DIR)/share/mfem/config.mk
|
||||
# SRC = $(if $(MFEM_DIR),$(MFEM_DIR)/examples/petsc/,)
|
||||
# MFEM_DIR = ../../mfem
|
||||
# CONFIG_MK = $(MFEM_DIR)/config.mk
|
||||
# TEST_MK = $(MFEM_DIR)/test.mk
|
||||
|
||||
MFEM_LIB_FILE = mfem_is_not_built
|
||||
-include $(CONFIG_MK)
|
||||
@@ -59,52 +62,40 @@ $(EXAMPLES):
|
||||
endif
|
||||
|
||||
MFEM_TESTS = EXAMPLES
|
||||
include $(MFEM_TEST_MK)
|
||||
include $(TEST_MK)
|
||||
|
||||
# Testing: Parallel runs
|
||||
RUN_MPI = $(MFEM_MPIEXEC) $(MFEM_MPIEXEC_NP) $(MFEM_MPI_NP)
|
||||
RUN_MPI = $(MFEM_MPIEXEC) $(MFEM_MPIEXEC_NP) 4
|
||||
TESTNAME = Parallel PETSc example
|
||||
%-test-par: %
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME))
|
||||
|
||||
|
||||
# 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
|
||||
EX2_ARGS := -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex2p
|
||||
EX3_ARGS := -m ../../data/klein-bottle.mesh -o 2 -f 0.1 --usepetsc --petscopts rc_ex3p_bddc --nonoverlapping
|
||||
EX4_ARGS := -m ../../data/klein-bottle.mesh -o 2 --usepetsc --petscopts rc_ex4p_bddc --nonoverlapping
|
||||
EX4_HYB_ARGS := -m ../../data/klein-bottle.mesh -o 2 --usepetsc --petscopts rc_ex4p_bddc --nonoverlapping --hybridization
|
||||
EX5_BDDC_LB_ARGS := -m ../../data/star.mesh --usepetsc -o 0 --petscopts rc_ex5p_bddc --nonoverlapping --local-bdr
|
||||
EX5_BDDC_GB_ARGS := -m ../../data/star.mesh --usepetsc -o 0 --petscopts rc_ex5p_bddc --nonoverlapping
|
||||
EX5_FSPL_ARGS := -m ../../data/beam-tet.mesh --usepetsc -o 0 --petscopts rc_ex5p_fieldsplit
|
||||
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_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
|
||||
EX1_ARGS := -m ../../data/amr-quad.mesh --usepetsc --petscopts rc_ex1p
|
||||
EX2_ARGS := -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex2p
|
||||
EX3_ARGS := -m ../../data/klein-bottle.mesh -o 2 -f 0.1 --usepetsc --petscopts rc_ex3p_bddc --nonoverlapping
|
||||
EX4_ARGS := -m ../../data/klein-bottle.mesh -o 2 --usepetsc --petscopts rc_ex4p_bddc --nonoverlapping
|
||||
EX5_BDDC_ARGS := -m ../../data/star.mesh --usepetsc -o 0 --petscopts rc_ex5p_bddc --nonoverlapping
|
||||
EX5_FSPL_ARGS := -m ../../data/beam-tet.mesh --usepetsc -o 0 --petscopts rc_ex5p_fieldsplit
|
||||
EX6_ARGS := -m ../../data/amr-quad.mesh --usepetsc
|
||||
EX9_ARGS := -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_expl
|
||||
EX10_ARGS := -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex10p -tf 30 -s 3 -rs 2 -dt 3
|
||||
ex1p-test-par: ex1p
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX1_ARGS_W))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX1_ARGS_P))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX1_ARGS))
|
||||
ex2p-test-par: ex2p
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX2_ARGS))
|
||||
ex3p-test-par: ex3p
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX3_ARGS))
|
||||
ex4p-test-par: ex4p
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX4_ARGS))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX4_HYB_ARGS))
|
||||
ex5p-test-par: ex5p
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX5_BDDC_LB_ARGS))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX5_BDDC_GB_ARGS))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX5_BDDC_ARGS))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX5_FSPL_ARGS))
|
||||
ex6p-test-par: ex6p
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX6_ARGS))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX6_NONOVL_ARGS))
|
||||
ex9p-test-par: ex9p
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX9_E_ARGS))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX9_ES_ARGS))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX9_IS_ARGS))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX9_ARGS))
|
||||
ex10p-test-par: ex10p
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX10_ARGS))
|
||||
|
||||
@@ -121,6 +112,6 @@ clean-build:
|
||||
rm -rf *.dSYM *.TVD.*breakpoints
|
||||
|
||||
clean-exec:
|
||||
@rm -rf mesh.* sol.* sol_p.* sol_u.* Example5*
|
||||
@rm -f ex9-mesh.* ex9-init.* ex9-final.* Example9*
|
||||
@rm -f deformed.* velocity.* elastic_energy.*
|
||||
@rm -rf sol_p.* sol_u.* Example5*
|
||||
@rm -f ex9.mesh ex9-mesh.* ex9-init.* ex9-final.* Example9*
|
||||
@rm -f mesh.* sol.* deformed.* velocity.* elastic_energy.*
|
||||
|
||||
@@ -6,7 +6,4 @@
|
||||
# it needs PETSc configured with MUMPS
|
||||
|
||||
-solver_pc_type cholesky
|
||||
# Petsc 3.9
|
||||
-solver_pc_factor_mat_solver_type mumps
|
||||
# Older versions of PETSc
|
||||
-solver_pc_factor_mat_solver_package mumps
|
||||
|
||||
@@ -16,10 +16,7 @@
|
||||
#-pc_bddc_adaptive_threshold 10
|
||||
|
||||
# Customization of the local solvers
|
||||
# With PETSc versions older than 3.9
|
||||
# use "mat_solver_package" instead of "mat_solver_type"
|
||||
#
|
||||
#-pc_bddc_neumann_pc_factor_mat_solver_type mumps
|
||||
#-pc_bddc_dirichlet_pc_factor_mat_solver_type mumps
|
||||
#-pc_bddc_neumann_pc_factor_mat_solver_package mumps
|
||||
#-pc_bddc_dirichlet_pc_factor_mat_solver_package mumps
|
||||
#-pc_bddc_coarse_pc_type cholesky
|
||||
#-pc_bddc_coarse_pc_factor_mat_solver_type mumps
|
||||
#-pc_bddc_coarse_pc_factor_mat_solver_package mumps
|
||||
|
||||
@@ -2,7 +2,4 @@
|
||||
# it needs PETSc configured with MUMPS
|
||||
|
||||
-solver_pc_type cholesky
|
||||
# Petsc 3.9
|
||||
-solver_pc_factor_mat_solver_type mumps
|
||||
# Older versions of PETSc
|
||||
-solver_pc_factor_mat_solver_package mumps
|
||||
|
||||
@@ -13,10 +13,7 @@
|
||||
#-pc_bddc_adaptive_threshold 10
|
||||
|
||||
# Customization of the local solvers
|
||||
# With PETSc versions older than 3.9
|
||||
# use "mat_solver_package" instead of "mat_solver_type"
|
||||
#
|
||||
#-pc_bddc_neumann_pc_factor_mat_solver_type mumps
|
||||
#-pc_bddc_dirichlet_pc_factor_mat_solver_type mumps
|
||||
#-pc_bddc_neumann_pc_factor_mat_solver_package mumps
|
||||
#-pc_bddc_dirichlet_pc_factor_mat_solver_package mumps
|
||||
#-pc_bddc_coarse_pc_type cholesky
|
||||
#-pc_bddc_coarse_pc_factor_mat_solver_type mumps
|
||||
#-pc_bddc_coarse_pc_factor_mat_solver_package mumps
|
||||
|
||||
@@ -25,29 +25,15 @@
|
||||
# verbose output
|
||||
#-prec_pc_bddc_check_level 1
|
||||
|
||||
# local solvers (default "petsc" solvers will fail)
|
||||
# needs PETSc compiled with support for MUMPS or SuiteSparse
|
||||
# use "umfpack" in place of "mumps" if you want to use
|
||||
# SuiteSparse solvers
|
||||
#
|
||||
# With PETSc versions older than 3.9
|
||||
# use "mat_solver_package" instead of "mat_solver_type"
|
||||
#
|
||||
# local solvers (needs PETSc compiled with support for SuiteSparse)
|
||||
# default solvers will fail
|
||||
-prec_pc_bddc_neumann_pc_type lu
|
||||
-prec_pc_bddc_neumann_pc_factor_mat_solver_type mumps
|
||||
-prec_pc_bddc_neumann_pc_factor_mat_solver_package mumps
|
||||
-prec_pc_bddc_neumann_pc_factor_mat_solver_package umfpack
|
||||
-prec_pc_bddc_dirichlet_pc_type lu
|
||||
-prec_pc_bddc_dirichlet_pc_factor_mat_solver_type mumps
|
||||
-prec_pc_bddc_dirichlet_pc_factor_mat_solver_package mumps
|
||||
|
||||
# MUMPS sometimes fails with a very annoying error
|
||||
-mat_mumps_icntl_14 500
|
||||
-prec_pc_bddc_dirichlet_mat_mumps_icntl_14 500
|
||||
-prec_pc_bddc_neumann_mat_mumps_icntl_14 500
|
||||
-prec_pc_bddc_dirichlet_pc_factor_mat_solver_package umfpack
|
||||
|
||||
# coarse solver (needs PETSc compiled with support for MUMPS)
|
||||
# default solver may fail
|
||||
-prec_pc_bddc_coarse_pc_factor_mat_solver_type mumps
|
||||
-prec_pc_bddc_coarse_pc_factor_mat_solver_package mumps
|
||||
-prec_pc_bddc_coarse_pc_type cholesky
|
||||
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
# Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at the
|
||||
# Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights reserved.
|
||||
# See file COPYRIGHT for details.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability see http://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Lesser General Public License (as published by the Free
|
||||
# Software Foundation) version 2.1 dated February 1999.
|
||||
|
||||
set(PUMI_EXAMPLES_SRCS)
|
||||
# All PUMI examples require MPI
|
||||
if (MFEM_USE_MPI)
|
||||
list(APPEND PUMI_EXAMPLES_SRCS
|
||||
ex1.cpp
|
||||
ex1p.cpp
|
||||
ex2.cpp
|
||||
ex6p.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
# Include the source directory where mfem.hpp and mfem-performance.hpp are.
|
||||
include_directories(BEFORE ${PROJECT_BINARY_DIR})
|
||||
|
||||
# Add "test_pumi" target, see below.
|
||||
add_custom_target(test_pumi
|
||||
${CMAKE_CTEST_COMMAND} -R pumi USES_TERMINAL)
|
||||
|
||||
# Add one executable per cpp file, adding "pumi_" as prefix. Sets
|
||||
# "test_pumi" as a target that depends on the given examples.
|
||||
set(PFX pumi_)
|
||||
add_mfem_examples(PUMI_EXAMPLES_SRCS ${PFX} "" test_pumi)
|
||||
|
||||
# Testing.
|
||||
# The PUMI tests can be run separately using the target "test_pumi"
|
||||
# which builds the examples and runs:
|
||||
# ctest -R pumi
|
||||
|
||||
# Command line options for the tests.
|
||||
# TODO...
|
||||
|
||||
# Set the number of processors for the parallel examples.
|
||||
set(EX1_TEST_NP 1)
|
||||
set(EX1P_TEST_NP 8)
|
||||
set(EX2_TEST_NP 1)
|
||||
set(EX6P_TEST_NP 8)
|
||||
|
||||
# Add the tests: one test per source file.
|
||||
foreach(SRC_FILE ${PUMI_EXAMPLES_SRCS})
|
||||
get_filename_component(SRC_FILENAME ${SRC_FILE} NAME)
|
||||
string(REPLACE ".cpp" "" TEST_NAME ${SRC_FILENAME})
|
||||
string(TOUPPER ${TEST_NAME} UP_TEST_NAME)
|
||||
set(TEST_NAME ${PFX}${TEST_NAME})
|
||||
|
||||
set(THIS_TEST_OPTIONS "-no-vis")
|
||||
list(APPEND THIS_TEST_OPTIONS ${${UP_TEST_NAME}_TEST_OPTS})
|
||||
# message(STATUS "Test ${TEST_NAME} options: ${THIS_TEST_OPTIONS}")
|
||||
|
||||
# All PUMI examples require MPI
|
||||
if (FALSE)
|
||||
add_test(NAME ${TEST_NAME}_ser
|
||||
COMMAND ${TEST_NAME} ${THIS_TEST_OPTIONS})
|
||||
else()
|
||||
set(TEST_NP ${${UP_TEST_NAME}_TEST_NP})
|
||||
add_test(NAME ${TEST_NAME}_np=${TEST_NP}
|
||||
COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${TEST_NP}
|
||||
${MPIEXEC_PREFLAGS}
|
||||
$<TARGET_FILE:${TEST_NAME}> ${THIS_TEST_OPTIONS}
|
||||
${MPIEXEC_POSTFLAGS})
|
||||
endif()
|
||||
endforeach()
|
||||
@@ -1,18 +0,0 @@
|
||||
Finite Element Discretization Library
|
||||
__
|
||||
_ __ ___ / _| ___ _ __ ___
|
||||
| '_ ` _ \ | |_ / _ \| '_ ` _ \
|
||||
| | | | | || _|| __/| | | | | |
|
||||
|_| |_| |_||_| \___||_| |_| |_|
|
||||
|
||||
http://mfem.org
|
||||
|
||||
This directory contains modifications of the example codes that illustrate the
|
||||
use of MFEM features based on the Parallel Unstructured Mesh Infrastructure,
|
||||
PUMI, from https://scorec.rpi.edu/pumi.
|
||||
|
||||
To build these examples, make sure that MFEM is configured with the option
|
||||
"MFEM_USE_PUMI = YES", see the top-level INSTALL file for details.
|
||||
|
||||
We recommend comparing the original example codes with the corresponding files
|
||||
in the current directory.
|
||||
@@ -1,262 +0,0 @@
|
||||
// MFEM Example 1
|
||||
// PUMI Modification
|
||||
//
|
||||
// Compile with: make ex1
|
||||
//
|
||||
// Sample runs:
|
||||
// ex1 -m ../../data/pumi/serial/Kova.smb -p ../../data/pumi/geom/Kova.dmg
|
||||
//
|
||||
// Note: Example models + meshes for the PUMI examples can be downloaded
|
||||
// from github.com/mfem/data/pumi. After downloading we recommend
|
||||
// creating a symbolic link to the above directory in ../../data.
|
||||
//
|
||||
// Description: This example code demonstrates the use of MFEM to define a
|
||||
// simple finite element discretization of the Laplace problem
|
||||
// -Delta u = 1 with homogeneous Dirichlet boundary conditions.
|
||||
// Specifically, we discretize using a FE space of the specified
|
||||
// order, or if order < 1 using an isoparametric/isogeometric
|
||||
// space (i.e. quadratic for quadratic curvilinear mesh, NURBS for
|
||||
// NURBS mesh, etc.)
|
||||
//
|
||||
// The example highlights the use of mesh refinement, finite
|
||||
// element grid functions, as well as linear and bilinear forms
|
||||
// corresponding to the left-hand side and right-hand side of the
|
||||
// discrete linear system. We also cover the explicit elimination
|
||||
// of essential boundary conditions, static condensation, and the
|
||||
// optional connection to the GLVis tool for visualization.
|
||||
//
|
||||
// This PUMI modification demonstrates how PUMI's API can be used
|
||||
// to load a PUMI mesh classified on a geometric model and then
|
||||
// convert it to the MFEM mesh format. The inputs are a Parasolid
|
||||
// model, "*.xmt_txt" and a SCOREC mesh "*.smb". The option "-o"
|
||||
// is used for the Finite Element order and "-go" is used for the
|
||||
// geometry order. Note that they can be used independently, i.e.
|
||||
// "-o 8 -go 3" solves for 8th order FE on a third order geometry.
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#ifdef MFEM_USE_SIMMETRIX
|
||||
#include <SimUtil.h>
|
||||
#include <gmi_sim.h>
|
||||
#endif
|
||||
#include <apfMDS.h>
|
||||
#include <gmi_null.h>
|
||||
#include <PCU.h>
|
||||
#include <apfConvert.h>
|
||||
#include <gmi_mesh.h>
|
||||
#include <crv.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace mfem;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// 1. Initialize MPI (required by PUMI).
|
||||
int num_procs, myid;
|
||||
MPI_Init(&argc, &argv);
|
||||
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
|
||||
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
|
||||
|
||||
// 2. Parse command-line options.
|
||||
const char *mesh_file = "../../data/pumi/serial/Kova.smb";
|
||||
#ifdef MFEM_USE_SIMMETRIX
|
||||
const char *model_file = "../../data/pumi/geom/Kova.x_t";
|
||||
#else
|
||||
const char *model_file = "../../data/pumi/geom/Kova.dmg";
|
||||
#endif
|
||||
int order = 1;
|
||||
bool static_cond = false;
|
||||
bool visualization = 1;
|
||||
int geom_order = 1;
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
args.AddOption(&mesh_file, "-m", "--mesh",
|
||||
"Mesh file to use.");
|
||||
args.AddOption(&order, "-o", "--order",
|
||||
"Finite element order (polynomial degree) or -1 for"
|
||||
" isoparametric space.");
|
||||
args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
|
||||
"--no-static-condensation", "Enable static condensation.");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
args.AddOption(&model_file, "-p", "--parasolid",
|
||||
"Parasolid model to use.");
|
||||
args.AddOption(&geom_order, "-go", "--geometry_order",
|
||||
"Geometric order of the model");
|
||||
args.Parse();
|
||||
if (!args.Good())
|
||||
{
|
||||
if (myid == 0)
|
||||
{
|
||||
args.PrintUsage(cout);
|
||||
}
|
||||
MPI_Finalize();
|
||||
return 1;
|
||||
}
|
||||
if (myid == 0)
|
||||
{
|
||||
args.PrintOptions(cout);
|
||||
}
|
||||
|
||||
// 3. Read the SCOREC Mesh.
|
||||
PCU_Comm_Init();
|
||||
#ifdef MFEM_USE_SIMMETRIX
|
||||
Sim_readLicenseFile(0);
|
||||
gmi_sim_start();
|
||||
gmi_register_sim();
|
||||
#endif
|
||||
gmi_register_mesh();
|
||||
|
||||
apf::Mesh2* pumi_mesh;
|
||||
pumi_mesh = apf::loadMdsMesh(model_file, mesh_file);
|
||||
|
||||
// 4. Increase the geometry order if necessary.
|
||||
if (geom_order > 1)
|
||||
{
|
||||
crv::BezierCurver bc(pumi_mesh, geom_order, 2);
|
||||
bc.run();
|
||||
}
|
||||
|
||||
pumi_mesh->verify();
|
||||
|
||||
// 5. Create the MFEM mesh object from the PUMI mesh. We can handle
|
||||
// triangular and tetrahedral meshes. Other inputs are the same as the
|
||||
// MFEM default constructor.
|
||||
Mesh *mesh = new PumiMesh(pumi_mesh, 1, 1);
|
||||
int dim = mesh->Dimension();
|
||||
|
||||
// 6. Refine the mesh to increase the resolution. In this example we do
|
||||
// 'ref_levels' of uniform refinement. We choose 'ref_levels' to be the
|
||||
// largest number that gives a final mesh with no more than 50,000
|
||||
// elements.
|
||||
{
|
||||
int ref_levels =
|
||||
(int)floor(log(50000./mesh->GetNE())/log(2.)/dim);
|
||||
for (int l = 0; l < ref_levels; l++)
|
||||
{
|
||||
mesh->UniformRefinement();
|
||||
}
|
||||
}
|
||||
|
||||
// 7. Define a finite element space on the mesh. Here we use continuous
|
||||
// Lagrange finite elements of the specified order. If order < 1, we
|
||||
// instead use an isoparametric/isogeometric space.
|
||||
FiniteElementCollection *fec;
|
||||
if (order > 0)
|
||||
{
|
||||
fec = new H1_FECollection(order, dim);
|
||||
}
|
||||
else if (mesh->GetNodes())
|
||||
{
|
||||
fec = mesh->GetNodes()->OwnFEC();
|
||||
cout << "Using isoparametric FEs: " << fec->Name() << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
fec = new H1_FECollection(order = 1, dim);
|
||||
}
|
||||
FiniteElementSpace *fespace = new FiniteElementSpace(mesh, fec);
|
||||
cout << "Number of finite element unknowns: "
|
||||
<< fespace->GetTrueVSize() << endl;
|
||||
|
||||
// 8. Determine the list of true (i.e. conforming) essential boundary dofs.
|
||||
// In this example, the boundary conditions are defined by marking all
|
||||
// the boundary attributes from the mesh as essential (Dirichlet) and
|
||||
// converting them to a list of true dofs.
|
||||
Array<int> ess_tdof_list;
|
||||
if (mesh->bdr_attributes.Size())
|
||||
{
|
||||
Array<int> ess_bdr(mesh->bdr_attributes.Max());
|
||||
ess_bdr = 1;
|
||||
fespace->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
|
||||
}
|
||||
|
||||
// 9. Set up the linear form b(.) which corresponds to the right-hand side of
|
||||
// the FEM linear system, which in this case is (1,phi_i) where phi_i are
|
||||
// the basis functions in the finite element fespace.
|
||||
LinearForm *b = new LinearForm(fespace);
|
||||
ConstantCoefficient one(1.0);
|
||||
b->AddDomainIntegrator(new DomainLFIntegrator(one));
|
||||
b->Assemble();
|
||||
|
||||
// 10. Define the solution vector x as a finite element grid function
|
||||
// corresponding to fespace. Initialize x with initial guess of zero,
|
||||
// which satisfies the boundary conditions.
|
||||
GridFunction x(fespace);
|
||||
x = 0.0;
|
||||
|
||||
// 11. Set up the bilinear form a(.,.) on the finite element space
|
||||
// corresponding to the Laplacian operator -Delta, by adding the
|
||||
// Diffusion domain integrator.
|
||||
BilinearForm *a = new BilinearForm(fespace);
|
||||
a->AddDomainIntegrator(new DiffusionIntegrator(one));
|
||||
|
||||
// 12. Assemble the bilinear form and the corresponding linear system,
|
||||
// applying any necessary transformations such as: eliminating boundary
|
||||
// conditions, applying conforming constraints for non-conforming AMR,
|
||||
// static condensation, etc.
|
||||
if (static_cond) { a->EnableStaticCondensation(); }
|
||||
a->Assemble();
|
||||
|
||||
SparseMatrix A;
|
||||
Vector B, X;
|
||||
a->FormLinearSystem(ess_tdof_list, x, *b, A, X, B);
|
||||
|
||||
cout << "Size of linear system: " << A.Height() << endl;
|
||||
|
||||
#ifndef MFEM_USE_SUITESPARSE
|
||||
// 13. Define a simple symmetric Gauss-Seidel preconditioner and use it to
|
||||
// solve the system A X = B with PCG.
|
||||
GSSmoother M(A);
|
||||
PCG(A, M, B, X, 1, 200, 1e-12, 0.0);
|
||||
#else
|
||||
// 13. If MFEM was compiled with SuiteSparse, use UMFPACK to solve the system.
|
||||
UMFPackSolver umf_solver;
|
||||
umf_solver.Control[UMFPACK_ORDERING] = UMFPACK_ORDERING_METIS;
|
||||
umf_solver.SetOperator(A);
|
||||
umf_solver.Mult(B, X);
|
||||
#endif
|
||||
|
||||
// 14. Recover the solution as a finite element grid function.
|
||||
a->RecoverFEMSolution(X, *b, x);
|
||||
|
||||
// 15. Save the refined mesh and the solution. This output can be viewed later
|
||||
// using GLVis: "glvis -m refined.mesh -g sol.gf".
|
||||
ofstream mesh_ofs("refined.mesh");
|
||||
mesh_ofs.precision(8);
|
||||
mesh->Print(mesh_ofs);
|
||||
ofstream sol_ofs("sol.gf");
|
||||
sol_ofs.precision(8);
|
||||
x.Save(sol_ofs);
|
||||
|
||||
// 16. Send the solution by socket to a GLVis server.
|
||||
if (visualization)
|
||||
{
|
||||
char vishost[] = "localhost";
|
||||
int visport = 19916;
|
||||
socketstream sol_sock(vishost, visport);
|
||||
sol_sock.precision(8);
|
||||
sol_sock << "solution\n" << *mesh << x << flush;
|
||||
}
|
||||
|
||||
// 17. Free the used memory.
|
||||
delete a;
|
||||
delete b;
|
||||
delete fespace;
|
||||
if (order > 0) { delete fec; }
|
||||
delete mesh;
|
||||
|
||||
pumi_mesh->destroyNative();
|
||||
apf::destroyMesh(pumi_mesh);
|
||||
PCU_Comm_Free();
|
||||
#ifdef MFEM_USE_SIMMETRIX
|
||||
gmi_sim_stop();
|
||||
Sim_unregisterAllKeys();
|
||||
#endif
|
||||
|
||||
MPI_Finalize();
|
||||
return 0;
|
||||
}
|
||||
@@ -1,292 +0,0 @@
|
||||
// MFEM Example 1 - Parallel Version
|
||||
// PUMI Modification
|
||||
//
|
||||
// Compile with: make ex1p
|
||||
//
|
||||
// Sample runs:
|
||||
// mpirun -np 8 ex1p -m ../../data/pumi/parallel/Kova/Kova100k_8.smb
|
||||
// -p ../../data/pumi/geom/Kova.dmg -o 1 -go 2
|
||||
//
|
||||
// Note: Example models + meshes for the PUMI examples can be downloaded
|
||||
// from github.com/mfem/data/pumi. After downloading we recommend
|
||||
// creating a symbolic link to the above directory in ../../data.
|
||||
//
|
||||
// Description: This example code demonstrates the use of MFEM to define a
|
||||
// simple finite element discretization of the Laplace problem
|
||||
// -Delta u = 1 with homogeneous Dirichlet boundary conditions.
|
||||
// Specifically, we discretize using a FE space of the specified
|
||||
// order, or if order < 1 using an isoparametric/isogeometric
|
||||
// space (i.e. quadratic for quadratic curvilinear mesh, NURBS for
|
||||
// NURBS mesh, etc.)
|
||||
//
|
||||
// The example highlights the use of mesh refinement, finite
|
||||
// element grid functions, as well as linear and bilinear forms
|
||||
// corresponding to the left-hand side and right-hand side of the
|
||||
// discrete linear system. We also cover the explicit elimination
|
||||
// of essential boundary conditions, static condensation, and the
|
||||
// optional connection to the GLVis tool for visualization.
|
||||
//
|
||||
// This PUMI modification demonstrates how PUMI's API can be used
|
||||
// to load a parallel PUMI mesh classified on a geometric model
|
||||
// and then generate the corresponding parallel MFEM mesh. The
|
||||
// example also performs a "uniform" refinement, similar to the
|
||||
// MFEM examples, for coarse meshes. However, the refinement is
|
||||
// performed using the PUMI API. The inputs are a Parasolid
|
||||
// model, "*.xmt_txt" and SCOREC parallel meshes "*.smb". The
|
||||
// option "-o" is used for the Finite Element order and "-go" for
|
||||
// the geometry order. Note that they can be used independently:
|
||||
// "-o 8 -go 3" solves for 8th order FE on third order geometry.
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#ifdef MFEM_USE_SIMMETRIX
|
||||
#include <SimUtil.h>
|
||||
#include <gmi_sim.h>
|
||||
#endif
|
||||
#include <apfMDS.h>
|
||||
#include <gmi_null.h>
|
||||
#include <PCU.h>
|
||||
#include <apfConvert.h>
|
||||
#include <gmi_mesh.h>
|
||||
#include <crv.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace mfem;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// 1. Initialize MPI.
|
||||
int num_procs, myid;
|
||||
MPI_Init(&argc, &argv);
|
||||
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
|
||||
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
|
||||
|
||||
// 2. Parse command-line options.
|
||||
const char *mesh_file = "../../data/pumi/parallel/Kova/Kova100k_8.smb";
|
||||
#ifdef MFEM_USE_SIMMETRIX
|
||||
const char *model_file = "../../data/pumi/geom/Kova.x_t";
|
||||
#else
|
||||
const char *model_file = "../../data/pumi/geom/Kova.dmg";
|
||||
#endif
|
||||
int order = 1;
|
||||
bool static_cond = false;
|
||||
bool visualization = 1;
|
||||
int geom_order = 1;
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
args.AddOption(&mesh_file, "-m", "--mesh",
|
||||
"Mesh file to use.");
|
||||
args.AddOption(&order, "-o", "--order",
|
||||
"Finite element order (polynomial degree) or -1 for"
|
||||
" isoparametric space.");
|
||||
args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
|
||||
"--no-static-condensation", "Enable static condensation.");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
args.AddOption(&model_file, "-p", "--parasolid",
|
||||
"Parasolid model to use.");
|
||||
args.AddOption(&geom_order, "-go", "--geometry_order",
|
||||
"Geometric order of the model");
|
||||
args.Parse();
|
||||
if (!args.Good())
|
||||
{
|
||||
if (myid == 0)
|
||||
{
|
||||
args.PrintUsage(cout);
|
||||
}
|
||||
MPI_Finalize();
|
||||
return 1;
|
||||
}
|
||||
if (myid == 0)
|
||||
{
|
||||
args.PrintOptions(cout);
|
||||
}
|
||||
|
||||
// 3. Read the SCOREC Mesh
|
||||
PCU_Comm_Init();
|
||||
#ifdef MFEM_USE_SIMMETRIX
|
||||
Sim_readLicenseFile(0);
|
||||
gmi_sim_start();
|
||||
gmi_register_sim();
|
||||
#endif
|
||||
gmi_register_mesh();
|
||||
|
||||
apf::Mesh2* pumi_mesh;
|
||||
pumi_mesh = apf::loadMdsMesh(model_file, mesh_file);
|
||||
|
||||
// 4. Increase the geometry order and refine the mesh if necessary. Parallel
|
||||
// uniform refinement is performed if the total number of elements is less
|
||||
// than 10,000.
|
||||
int dim = pumi_mesh->getDimension();
|
||||
int nEle = pumi_mesh->count(dim);
|
||||
int ref_levels = (int)floor(log(10000./nEle)/log(2.)/dim);
|
||||
|
||||
if (geom_order > 1)
|
||||
{
|
||||
crv::BezierCurver bc(pumi_mesh, geom_order, 2);
|
||||
bc.run();
|
||||
}
|
||||
|
||||
// Perform Uniform refinement
|
||||
if (ref_levels > 1)
|
||||
{
|
||||
ma::Input* uniInput = ma::configureUniformRefine(pumi_mesh, ref_levels);
|
||||
|
||||
if (geom_order > 1)
|
||||
{
|
||||
crv::adapt(uniInput);
|
||||
}
|
||||
else
|
||||
{
|
||||
ma::adapt(uniInput);
|
||||
}
|
||||
}
|
||||
|
||||
pumi_mesh->verify();
|
||||
|
||||
// 5. Create the parallel MFEM mesh object from the parallel PUMI mesh.
|
||||
// We can handle triangular and tetrahedral meshes. Note that the
|
||||
// mesh resolution is performed on the PUMI mesh.
|
||||
ParMesh *pmesh = new ParPumiMesh(MPI_COMM_WORLD, pumi_mesh);
|
||||
|
||||
// 6. Define a parallel finite element space on the parallel mesh. Here we
|
||||
// use continuous Lagrange finite elements of the specified order. If
|
||||
// order < 1, we instead use an isoparametric/isogeometric space.
|
||||
FiniteElementCollection *fec;
|
||||
if (order > 0)
|
||||
{
|
||||
fec = new H1_FECollection(order, dim);
|
||||
}
|
||||
else if (pmesh->GetNodes())
|
||||
{
|
||||
fec = pmesh->GetNodes()->OwnFEC();
|
||||
if (myid == 0)
|
||||
{
|
||||
cout << "Using isoparametric FEs: " << fec->Name() << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fec = new H1_FECollection(order = 1, dim);
|
||||
}
|
||||
ParFiniteElementSpace *fespace = new ParFiniteElementSpace(pmesh, fec);
|
||||
HYPRE_Int size = fespace->GlobalTrueVSize();
|
||||
if (myid == 0)
|
||||
{
|
||||
cout << "Number of finite element unknowns: " << size << endl;
|
||||
}
|
||||
|
||||
// 7. 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 from the mesh as essential
|
||||
// (Dirichlet) and converting them to a list of true dofs.
|
||||
Array<int> ess_tdof_list;
|
||||
if (pmesh->bdr_attributes.Size())
|
||||
{
|
||||
Array<int> ess_bdr(pmesh->bdr_attributes.Max());
|
||||
ess_bdr = 1;
|
||||
fespace->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
|
||||
}
|
||||
|
||||
// 8. Set up the parallel linear form b(.) which corresponds to the
|
||||
// right-hand side of the FEM linear system, which in this case is
|
||||
// (1,phi_i) where phi_i are the basis functions in fespace.
|
||||
ParLinearForm *b = new ParLinearForm(fespace);
|
||||
ConstantCoefficient one(1.0);
|
||||
b->AddDomainIntegrator(new DomainLFIntegrator(one));
|
||||
b->Assemble();
|
||||
|
||||
// 9. Define the solution vector x as a parallel finite element grid function
|
||||
// corresponding to fespace. Initialize x with initial guess of zero,
|
||||
// which satisfies the boundary conditions.
|
||||
ParGridFunction x(fespace);
|
||||
x = 0.0;
|
||||
|
||||
// 10. Set up the parallel bilinear form a(.,.) on the finite element space
|
||||
// corresponding to the Laplacian operator -Delta, by adding the Diffusion
|
||||
// domain integrator.
|
||||
ParBilinearForm *a = new ParBilinearForm(fespace);
|
||||
a->AddDomainIntegrator(new DiffusionIntegrator(one));
|
||||
|
||||
// 11. Assemble the parallel bilinear form and the corresponding linear
|
||||
// system, applying any necessary transformations such as: parallel
|
||||
// assembly, eliminating boundary conditions, applying conforming
|
||||
// constraints for non-conforming AMR, static condensation, etc.
|
||||
if (static_cond) { a->EnableStaticCondensation(); }
|
||||
a->Assemble();
|
||||
|
||||
HypreParMatrix A;
|
||||
Vector B, X;
|
||||
a->FormLinearSystem(ess_tdof_list, x, *b, A, X, B);
|
||||
|
||||
if (myid == 0)
|
||||
{
|
||||
cout << "Size of linear system: " << A.GetGlobalNumRows() << endl;
|
||||
}
|
||||
|
||||
// 12. Define and apply a parallel PCG solver for AX=B with the BoomerAMG
|
||||
// preconditioner from hypre.
|
||||
HypreSolver *amg = new HypreBoomerAMG(A);
|
||||
HyprePCG *pcg = new HyprePCG(A);
|
||||
pcg->SetTol(1e-12);
|
||||
pcg->SetMaxIter(200);
|
||||
pcg->SetPrintLevel(2);
|
||||
pcg->SetPreconditioner(*amg);
|
||||
pcg->Mult(B, X);
|
||||
|
||||
// 13. Recover the parallel grid function corresponding to X. This is the
|
||||
// local finite element solution on each processor.
|
||||
a->RecoverFEMSolution(X, *b, x);
|
||||
|
||||
// 14. Save the refined mesh and the solution in parallel. This output can
|
||||
// be viewed later using GLVis: "glvis -np <np> -m mesh -g sol".
|
||||
{
|
||||
ostringstream mesh_name, sol_name;
|
||||
mesh_name << "mesh." << setfill('0') << setw(6) << myid;
|
||||
sol_name << "sol." << setfill('0') << setw(6) << myid;
|
||||
|
||||
ofstream mesh_ofs(mesh_name.str().c_str());
|
||||
mesh_ofs.precision(8);
|
||||
pmesh->Print(mesh_ofs);
|
||||
|
||||
ofstream sol_ofs(sol_name.str().c_str());
|
||||
sol_ofs.precision(8);
|
||||
x.Save(sol_ofs);
|
||||
}
|
||||
|
||||
// 15. Send the solution by socket to a GLVis server.
|
||||
if (visualization)
|
||||
{
|
||||
char vishost[] = "localhost";
|
||||
int visport = 19916;
|
||||
socketstream sol_sock(vishost, visport);
|
||||
sol_sock << "parallel " << num_procs << " " << myid << "\n";
|
||||
sol_sock.precision(8);
|
||||
sol_sock << "solution\n" << *pmesh << x << flush;
|
||||
}
|
||||
|
||||
// 16. Free the used memory.
|
||||
delete pcg;
|
||||
delete amg;
|
||||
delete a;
|
||||
delete b;
|
||||
delete fespace;
|
||||
if (order > 0) { delete fec; }
|
||||
delete pmesh;
|
||||
|
||||
pumi_mesh->destroyNative();
|
||||
apf::destroyMesh(pumi_mesh);
|
||||
PCU_Comm_Free();
|
||||
|
||||
#ifdef MFEM_USE_SIMMETRIX
|
||||
gmi_sim_stop();
|
||||
Sim_unregisterAllKeys();
|
||||
#endif
|
||||
|
||||
MPI_Finalize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,413 +0,0 @@
|
||||
// MFEM Example 2
|
||||
// PUMI Modification
|
||||
//
|
||||
// Compile with: make ex2
|
||||
//
|
||||
// Sample runs:
|
||||
// ex2 -m ../../data/pumi/serial/pillbox.smb -p ../../data/pumi/geom/pillbox.dmg
|
||||
// -bf ../../data/pumi/serial/boundary.mesh
|
||||
//
|
||||
// Note: Example models + meshes for the PUMI examples can be downloaded
|
||||
// from github.com/mfem/data/pumi. After downloading we recommend
|
||||
// creating a symbolic link to the above directory in ../../data.
|
||||
//
|
||||
// Description: This example code solves a simple linear elasticity problem
|
||||
// describing a multi-material cantilever beam.
|
||||
//
|
||||
// Specifically, we approximate the weak form of -div(sigma(u))=0
|
||||
// where sigma(u)=lambda*div(u)*I+mu*(grad*u+u*grad) is the stress
|
||||
// tensor corresponding to displacement field u, and lambda and mu
|
||||
// are the material Lame constants. The boundary conditions are
|
||||
// u=0 on the fixed part of the boundary with attribute 1, and
|
||||
// sigma(u).n=f on the remainder with f being a constant pull down
|
||||
// vector on boundary elements with attribute 2, and zero
|
||||
// otherwise. The geometry of the domain is assumed to be as
|
||||
// follows:
|
||||
// boundary
|
||||
// attribute 2
|
||||
// (push down)
|
||||
// ||
|
||||
// \/
|
||||
// +----------+
|
||||
// | |
|
||||
// | |
|
||||
// +---------| material |----------+
|
||||
// boundary --->| material| 2 | material |<--- boundary
|
||||
// attribute 1 | 1 | | 3 | attribute 1
|
||||
// (fixed) +---------+----------+----------+ (fixed)
|
||||
//
|
||||
// The example demonstrates the use of high-order and NURBS vector
|
||||
// finite element spaces with the linear elasticity bilinear form,
|
||||
// meshes with curved elements, and the definition of piece-wise
|
||||
// constant and vector coefficient objects. Static condensation is
|
||||
// also illustrated.
|
||||
//
|
||||
// We recommend viewing Example 1 before viewing this example.
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "../../general/text.hpp"
|
||||
|
||||
#ifdef MFEM_USE_SIMMETRIX
|
||||
#include <SimUtil.h>
|
||||
#include <gmi_sim.h>
|
||||
#endif
|
||||
#include <apfMDS.h>
|
||||
#include <gmi_null.h>
|
||||
#include <PCU.h>
|
||||
#include <apfConvert.h>
|
||||
#include <gmi_mesh.h>
|
||||
#include <crv.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace mfem;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// 1. Initialize MPI (required by PUMI).
|
||||
int num_proc, myId;
|
||||
MPI_Init(&argc, &argv);
|
||||
MPI_Comm_size(MPI_COMM_WORLD, &num_proc);
|
||||
MPI_Comm_rank(MPI_COMM_WORLD, &myId);
|
||||
|
||||
// 2. Parse command-line options.
|
||||
const char *mesh_file = "../../data/pumi/serial/pillbox.smb";
|
||||
const char *boundary_file = "../../data/pumi/serial/boundary.mesh";
|
||||
#ifdef MFEM_USE_SIMMETRIX
|
||||
const char *model_file = "../../data/pumi/geom/pillbox.smd";
|
||||
#else
|
||||
const char *model_file = "../../data/pumi/geom/pillbox.dmg";
|
||||
#endif
|
||||
int order = 1;
|
||||
bool static_cond = false;
|
||||
bool visualization = 1;
|
||||
int geom_order = 1;
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
args.AddOption(&mesh_file, "-m", "--mesh",
|
||||
"Mesh file to use.");
|
||||
args.AddOption(&order, "-o", "--order",
|
||||
"Finite element order (polynomial degree).");
|
||||
args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
|
||||
"--no-static-condensation", "Enable static condensation.");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
args.AddOption(&model_file, "-p", "--parasolid",
|
||||
"Parasolid model to use.");
|
||||
args.AddOption(&geom_order, "-go", "--geometry_order",
|
||||
"Geometric order of the model");
|
||||
args.AddOption(&boundary_file, "-bf", "--txt",
|
||||
"txt file containing boundary tags");
|
||||
args.Parse();
|
||||
if (!args.Good())
|
||||
{
|
||||
args.PrintUsage(cout);
|
||||
return 1;
|
||||
}
|
||||
args.PrintOptions(cout);
|
||||
|
||||
// 3. Read the SCOREC Mesh.
|
||||
PCU_Comm_Init();
|
||||
#ifdef MFEM_USE_SIMMETRIX
|
||||
Sim_readLicenseFile(0);
|
||||
gmi_sim_start();
|
||||
gmi_register_sim();
|
||||
#endif
|
||||
gmi_register_mesh();
|
||||
|
||||
apf::Mesh2* pumi_mesh;
|
||||
pumi_mesh = apf::loadMdsMesh(model_file, mesh_file);
|
||||
|
||||
// 4. Increase the geometry order if necessary.
|
||||
if (geom_order > 1)
|
||||
{
|
||||
crv::BezierCurver bc(pumi_mesh, geom_order, 0);
|
||||
bc.run();
|
||||
}
|
||||
pumi_mesh->verify();
|
||||
|
||||
// Read boundary
|
||||
string bdr_tags;
|
||||
named_ifgzstream input_bdr(boundary_file);
|
||||
input_bdr >> ws;
|
||||
getline(input_bdr, bdr_tags);
|
||||
filter_dos(bdr_tags);
|
||||
cout << " the boundary tag is : " << bdr_tags << endl;
|
||||
Array<int> Dirichlet;
|
||||
int numOfent;
|
||||
if (bdr_tags == "Dirichlet")
|
||||
{
|
||||
input_bdr >> numOfent;
|
||||
cout << " num of Dirichlet bdr conditions : " << numOfent << endl;
|
||||
Dirichlet.SetSize(numOfent);
|
||||
for (int kk = 0; kk < numOfent; kk++)
|
||||
{
|
||||
input_bdr >> Dirichlet[kk];
|
||||
}
|
||||
}
|
||||
Dirichlet.Print();
|
||||
|
||||
Array<int> load_bdr;
|
||||
skip_comment_lines(input_bdr, '#');
|
||||
input_bdr >> bdr_tags;
|
||||
filter_dos(bdr_tags);
|
||||
cout << " the boundary tag is : " << bdr_tags << endl;
|
||||
if (bdr_tags == "Load")
|
||||
{
|
||||
input_bdr >> numOfent;
|
||||
load_bdr.SetSize(numOfent);
|
||||
cout << " num of load bdr conditions : " << numOfent << endl;
|
||||
for (int kk = 0; kk < numOfent; kk++)
|
||||
{
|
||||
input_bdr >> load_bdr[kk];
|
||||
}
|
||||
}
|
||||
load_bdr.Print();
|
||||
|
||||
// 5. Create the MFEM mesh object from the PUMI mesh. We can handle triangular
|
||||
// and tetrahedral meshes. Other inputs are the same as MFEM default
|
||||
// constructor.
|
||||
Mesh *mesh = new PumiMesh(pumi_mesh, 1, 1);
|
||||
int dim = mesh->Dimension();
|
||||
|
||||
// Boundary conditions hack.
|
||||
apf::MeshIterator* itr = pumi_mesh->begin(dim-1);
|
||||
apf::MeshEntity* ent ;
|
||||
int bdr_cnt = 0;
|
||||
while ((ent = pumi_mesh->iterate(itr)))
|
||||
{
|
||||
apf::ModelEntity *me = pumi_mesh->toModel(ent);
|
||||
if (pumi_mesh->getModelType(me) == (dim-1))
|
||||
{
|
||||
// Everywhere 3 as initial
|
||||
(mesh->GetBdrElement(bdr_cnt))->SetAttribute(3);
|
||||
int tag = pumi_mesh->getModelTag(me);
|
||||
if (Dirichlet.Find(tag) != -1)
|
||||
{
|
||||
// Dirichlet attr -> 1
|
||||
(mesh->GetBdrElement(bdr_cnt))->SetAttribute(1);
|
||||
}
|
||||
else if (load_bdr.Find(tag) != -1)
|
||||
{
|
||||
// Load attr -> 2
|
||||
(mesh->GetBdrElement(bdr_cnt))->SetAttribute(2);
|
||||
}
|
||||
bdr_cnt++;
|
||||
}
|
||||
}
|
||||
pumi_mesh->end(itr);
|
||||
|
||||
// Assign attributes for elements.
|
||||
double ppt[3];
|
||||
Vector cent(ppt, dim);
|
||||
for (int el = 0; el < mesh->GetNE(); el++)
|
||||
{
|
||||
(mesh->GetElementTransformation(el))->
|
||||
Transform(Geometries.GetCenter(mesh->GetElementBaseGeometry(el)),cent);
|
||||
if (cent(0) <= -0.05)
|
||||
{
|
||||
mesh->SetAttribute(el , 1);
|
||||
}
|
||||
else if (cent(0) >= 0.05)
|
||||
{
|
||||
mesh->SetAttribute(el , 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
mesh->SetAttribute(el , 3);
|
||||
}
|
||||
}
|
||||
mesh->SetAttributes();
|
||||
if (mesh->attributes.Max() < 2 || mesh->bdr_attributes.Max() < 2)
|
||||
{
|
||||
cerr << "\nInput mesh should have at least two materials and "
|
||||
<< "two boundary attributes! (See schematic in ex2.cpp)\n"
|
||||
<< endl;
|
||||
return 3;
|
||||
}
|
||||
|
||||
// 6. Refine the mesh to increase the resolution. In this example we do
|
||||
// 'ref_levels' of uniform refinement. We choose 'ref_levels' to be the
|
||||
// largest number that gives a final mesh with no more than 5,000
|
||||
// elements.
|
||||
{
|
||||
int ref_levels =
|
||||
(int)floor(log(5000./mesh->GetNE())/log(2.)/dim);
|
||||
for (int l = 0; l < ref_levels; l++)
|
||||
{
|
||||
mesh->UniformRefinement();
|
||||
}
|
||||
}
|
||||
|
||||
// 7. Define a finite element space on the mesh. Here we use vector finite
|
||||
// elements, i.e. dim copies of a scalar finite element space. The vector
|
||||
// dimension is specified by the last argument of the FiniteElementSpace
|
||||
// constructor. For NURBS meshes, we use the (degree elevated) NURBS space
|
||||
// associated with the mesh nodes.
|
||||
FiniteElementCollection *fec;
|
||||
FiniteElementSpace *fespace;
|
||||
if (mesh->NURBSext)
|
||||
{
|
||||
fec = NULL;
|
||||
fespace = mesh->GetNodes()->FESpace();
|
||||
}
|
||||
else
|
||||
{
|
||||
fec = new H1_FECollection(order, dim);
|
||||
fespace = new FiniteElementSpace(mesh, fec, dim);
|
||||
}
|
||||
cout << "Number of finite element unknowns: " << fespace->GetTrueVSize()
|
||||
<< endl << "Assembling: " << flush;
|
||||
|
||||
// 8. Determine the list of true (i.e. conforming) essential boundary dofs.
|
||||
// In this example, the boundary conditions are defined by marking only
|
||||
// boundary attribute 1 from the mesh as essential and converting it to a
|
||||
// list of true dofs.
|
||||
Array<int> ess_tdof_list, ess_bdr(mesh->bdr_attributes.Max());
|
||||
ess_bdr = 0;
|
||||
ess_bdr[0] = 1;
|
||||
fespace->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
|
||||
|
||||
// 9. Set up the linear form b(.) which corresponds to the right-hand side of
|
||||
// the FEM linear system. In this case, b_i equals the boundary integral
|
||||
// of f*phi_i where f represents a "pull down" force on the Neumann part
|
||||
// of the boundary and phi_i are the basis functions in the finite element
|
||||
// fespace. The force is defined by the VectorArrayCoefficient object f,
|
||||
// which is a vector of Coefficient objects. The fact that f is non-zero
|
||||
// on boundary attribute 2 is indicated by the use of piece-wise constants
|
||||
// coefficient for its last component.
|
||||
VectorArrayCoefficient f(dim);
|
||||
for (int i = 0; i < dim-1; i++)
|
||||
{
|
||||
f.Set(i, new ConstantCoefficient(0.0));
|
||||
}
|
||||
{
|
||||
Vector pull_force(mesh->bdr_attributes.Max());
|
||||
pull_force = 0.0;
|
||||
pull_force(1) = -3.0e-2;
|
||||
f.Set(dim-1, new PWConstCoefficient(pull_force));
|
||||
f.Set(dim-2, new PWConstCoefficient(pull_force));
|
||||
}
|
||||
|
||||
LinearForm *b = new LinearForm(fespace);
|
||||
b->AddBoundaryIntegrator(new VectorBoundaryLFIntegrator(f));
|
||||
cout << "r.h.s. ... " << flush;
|
||||
b->Assemble();
|
||||
|
||||
// 10. Define the solution vector x as a finite element grid function
|
||||
// corresponding to fespace. Initialize x with initial guess of zero,
|
||||
// which satisfies the boundary conditions.
|
||||
GridFunction x(fespace);
|
||||
x = 0.0;
|
||||
|
||||
// 11. Set up the bilinear form a(.,.) on the finite element space
|
||||
// corresponding to the linear elasticity integrator with piece-wise
|
||||
// constants coefficient lambda and mu.
|
||||
Vector lambda(mesh->attributes.Max());
|
||||
lambda = 1.0;
|
||||
lambda(0) = lambda(1)*10;
|
||||
lambda(1) = lambda(1)*100;
|
||||
PWConstCoefficient lambda_func(lambda);
|
||||
Vector mu(mesh->attributes.Max());
|
||||
mu = 1.0;
|
||||
mu(0) = mu(1)*10;
|
||||
mu(1) = mu(1)*100;
|
||||
PWConstCoefficient mu_func(mu);
|
||||
|
||||
BilinearForm *a = new BilinearForm(fespace);
|
||||
a->AddDomainIntegrator(new ElasticityIntegrator(lambda_func,mu_func));
|
||||
|
||||
// 12. Assemble the bilinear form and the corresponding linear system,
|
||||
// applying any necessary transformations such as: eliminating boundary
|
||||
// conditions, applying conforming constraints for non-conforming AMR,
|
||||
// static condensation, etc.
|
||||
cout << "matrix ... " << flush;
|
||||
if (static_cond) { a->EnableStaticCondensation(); }
|
||||
a->Assemble();
|
||||
|
||||
SparseMatrix A;
|
||||
Vector B, X;
|
||||
a->FormLinearSystem(ess_tdof_list, x, *b, A, X, B);
|
||||
cout << "done." << endl;
|
||||
|
||||
cout << "Size of linear system: " << A.Height() << endl;
|
||||
|
||||
#ifndef MFEM_USE_SUITESPARSE
|
||||
// 13. Define a simple symmetric Gauss-Seidel preconditioner and use it to
|
||||
// solve the system Ax=b with PCG.
|
||||
GSSmoother M(A);
|
||||
PCG(A, M, B, X, 1, 500, 1e-8, 0.0);
|
||||
#else
|
||||
// 13. If MFEM was compiled with SuiteSparse, use UMFPACK to solve the system.
|
||||
UMFPackSolver umf_solver;
|
||||
umf_solver.Control[UMFPACK_ORDERING] = UMFPACK_ORDERING_METIS;
|
||||
umf_solver.SetOperator(A);
|
||||
umf_solver.Mult(B, X);
|
||||
#endif
|
||||
|
||||
// 14. Recover the solution as a finite element grid function.
|
||||
a->RecoverFEMSolution(X, *b, x);
|
||||
|
||||
// 15. For non-NURBS meshes, make the mesh curved based on the finite element
|
||||
// space. This means that we define the mesh elements through a fespace
|
||||
// based transformation of the reference element. This allows us to save
|
||||
// the displaced mesh as a curved mesh when using high-order finite
|
||||
// element displacement field. We assume that the initial mesh (read from
|
||||
// the file) is not higher order curved mesh compared to the chosen FE
|
||||
// space.
|
||||
if (!mesh->NURBSext)
|
||||
{
|
||||
mesh->SetNodalFESpace(fespace);
|
||||
}
|
||||
|
||||
// 16. Save the displaced mesh and the inverted solution (which gives the
|
||||
// backward displacements to the original grid). This output can be
|
||||
// viewed later using GLVis: "glvis -m displaced.mesh -g sol.gf".
|
||||
{
|
||||
GridFunction *nodes = mesh->GetNodes();
|
||||
*nodes += x;
|
||||
x *= -1;
|
||||
ofstream mesh_ofs("displaced.mesh");
|
||||
mesh_ofs.precision(8);
|
||||
mesh->Print(mesh_ofs);
|
||||
ofstream sol_ofs("sol.gf");
|
||||
sol_ofs.precision(8);
|
||||
x.Save(sol_ofs);
|
||||
}
|
||||
|
||||
// 17. Send the above data by socket to a GLVis server. Use the "n" and "b"
|
||||
// keys in GLVis to visualize the displacements.
|
||||
if (visualization)
|
||||
{
|
||||
char vishost[] = "localhost";
|
||||
int visport = 19916;
|
||||
socketstream sol_sock(vishost, visport);
|
||||
sol_sock.precision(8);
|
||||
sol_sock << "solution\n" << *mesh << x << flush;
|
||||
}
|
||||
|
||||
// 18. Free the used memory.
|
||||
delete a;
|
||||
delete b;
|
||||
if (fec)
|
||||
{
|
||||
delete fespace;
|
||||
delete fec;
|
||||
}
|
||||
delete mesh;
|
||||
|
||||
pumi_mesh->destroyNative();
|
||||
apf::destroyMesh(pumi_mesh);
|
||||
PCU_Comm_Free();
|
||||
#ifdef MFEM_USE_SIMMETRIX
|
||||
gmi_sim_stop();
|
||||
Sim_unregisterAllKeys();
|
||||
#endif
|
||||
|
||||
MPI_Finalize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,387 +0,0 @@
|
||||
// MFEM Example 6 - Parallel Version
|
||||
// PUMI Modification
|
||||
//
|
||||
// Compile with: make ex1p
|
||||
//
|
||||
// Sample runs: mpirun -np 8 ex6p
|
||||
//
|
||||
// Description: This is a version of Example 1 with a simple adaptive mesh
|
||||
// refinement loop. The problem being solved is again the Laplace
|
||||
// equation -Delta u = 1 with homogeneous Dirichlet boundary
|
||||
// conditions. The problem is solved on a sequence of meshes which
|
||||
// are adapted in a conforming (tetrahedrons) manner according
|
||||
// to a simple SPR ZZ error estimator.
|
||||
//
|
||||
// This PUMI variation also performs a "uniform" refinement,
|
||||
// similar to MFEM examples, for coarse meshes. However, the
|
||||
// refinement is performed using the PUMI API. A new option "-ar"
|
||||
// is added to modify the "adapt_ratio" which is the fraction of
|
||||
// allowable error that scales the output size field of the error
|
||||
// estimator.
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#ifdef MFEM_USE_SIMMETRIX
|
||||
#include <SimUtil.h>
|
||||
#include <gmi_sim.h>
|
||||
#endif
|
||||
#include <apfMDS.h>
|
||||
#include <gmi_null.h>
|
||||
#include <PCU.h>
|
||||
#include <spr.h>
|
||||
#include <apfConvert.h>
|
||||
#include <gmi_mesh.h>
|
||||
#include <crv.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace mfem;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// 1. Initialize MPI.
|
||||
int num_procs, myid;
|
||||
MPI_Init(&argc, &argv);
|
||||
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
|
||||
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
|
||||
|
||||
// 2. Parse command-line options.
|
||||
const char *mesh_file = "../../data/pumi/parallel/Kova/Kova100k_8.smb";
|
||||
#ifdef MFEM_USE_SIMMETRIX
|
||||
const char *model_file = "../../data/pumi/geom/Kova.x_t";
|
||||
const char *smd_file = NULL;
|
||||
#else
|
||||
const char *model_file = "../../data/pumi/geom/Kova.dmg";
|
||||
#endif
|
||||
int order = 1;
|
||||
bool static_cond = false;
|
||||
bool visualization = 1;
|
||||
int geom_order = 1;
|
||||
double adapt_ratio = 0.05;
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
args.AddOption(&mesh_file, "-m", "--mesh",
|
||||
"Mesh file to use.");
|
||||
args.AddOption(&order, "-o", "--order",
|
||||
"Finite element order (polynomial degree) or -1 for"
|
||||
" isoparametric space.");
|
||||
args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
|
||||
"--no-static-condensation", "Enable static condensation.");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
args.AddOption(&model_file, "-p", "--model",
|
||||
"parasolid or .dmg model to use.");
|
||||
#ifdef MFEM_USE_SIMMETRIX
|
||||
args.AddOption(&smd_file, "-sm", "--smd_model",
|
||||
"smd model file to use.");
|
||||
#endif
|
||||
args.AddOption(&geom_order, "-go", "--geometry_order",
|
||||
"Geometric order of the model");
|
||||
args.AddOption(&adapt_ratio, "-ar", "--adapt_ratio",
|
||||
"adaptation factor used in MeshAdapt");
|
||||
args.Parse();
|
||||
if (!args.Good())
|
||||
{
|
||||
if (myid == 0)
|
||||
{
|
||||
args.PrintUsage(cout);
|
||||
}
|
||||
MPI_Finalize();
|
||||
return 1;
|
||||
}
|
||||
if (myid == 0)
|
||||
{
|
||||
args.PrintOptions(cout);
|
||||
}
|
||||
|
||||
// 3. Read the SCOREC Mesh.
|
||||
PCU_Comm_Init();
|
||||
#ifdef MFEM_USE_SIMMETRIX
|
||||
Sim_readLicenseFile(0);
|
||||
gmi_sim_start();
|
||||
gmi_register_sim();
|
||||
#endif
|
||||
gmi_register_mesh();
|
||||
|
||||
apf::Mesh2* pumi_mesh;
|
||||
#ifdef MFEM_USE_SIMMETRIX
|
||||
if (smd_file)
|
||||
{
|
||||
gmi_model *mixed_model = gmi_sim_load(model_file, smd_file);
|
||||
pumi_mesh = apf::loadMdsMesh(mixed_model, mesh_file);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
pumi_mesh = apf::loadMdsMesh(model_file, mesh_file);
|
||||
}
|
||||
|
||||
// 4. Increase the geometry order and refine the mesh if necessary. Parallel
|
||||
// uniform refinement is performed if the total number of elements is less
|
||||
// than 100,000.
|
||||
int dim = pumi_mesh->getDimension();
|
||||
int nEle = pumi_mesh->count(dim);
|
||||
int ref_levels = (int)floor(log(100000./nEle)/log(2.)/dim);
|
||||
|
||||
if (geom_order > 1)
|
||||
{
|
||||
crv::BezierCurver bc(pumi_mesh, geom_order, 2);
|
||||
bc.run();
|
||||
}
|
||||
|
||||
// Perform Uniform refinement
|
||||
if (myid == 1)
|
||||
{
|
||||
std::cout << " ref level : " << ref_levels << std::endl;
|
||||
}
|
||||
|
||||
if (ref_levels > 1)
|
||||
{
|
||||
ma::Input* uniInput = ma::configureUniformRefine(pumi_mesh, ref_levels);
|
||||
|
||||
if ( geom_order > 1)
|
||||
{
|
||||
crv::adapt(uniInput);
|
||||
}
|
||||
else
|
||||
{
|
||||
ma::adapt(uniInput);
|
||||
}
|
||||
}
|
||||
|
||||
pumi_mesh->verify();
|
||||
|
||||
// 5. Create the parallel MFEM mesh object from the parallel PUMI mesh. We
|
||||
// can handle triangular and tetrahedral meshes. Note that the mesh
|
||||
// resolution is performed on the PUMI mesh.
|
||||
ParMesh *pmesh = new ParPumiMesh(MPI_COMM_WORLD, pumi_mesh);
|
||||
|
||||
// 6. Define a parallel finite element space on the parallel mesh. Here we
|
||||
// use continuous Lagrange finite elements of the specified order. If
|
||||
// order < 1, we instead use an isoparametric/isogeometric space.
|
||||
FiniteElementCollection *fec;
|
||||
if (order > 0)
|
||||
{
|
||||
fec = new H1_FECollection(order, dim);
|
||||
}
|
||||
else if (pmesh->GetNodes())
|
||||
{
|
||||
fec = pmesh->GetNodes()->OwnFEC();
|
||||
if (myid == 1)
|
||||
{
|
||||
cout << "Using isoparametric FEs: " << fec->Name() << endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fec = new H1_FECollection(order = 1, dim);
|
||||
}
|
||||
ParFiniteElementSpace *fespace = new ParFiniteElementSpace(pmesh, fec);
|
||||
HYPRE_Int size = fespace->GlobalTrueVSize();
|
||||
if (myid == 1)
|
||||
{
|
||||
cout << "Number of finite element unknowns: " << size << endl;
|
||||
}
|
||||
|
||||
// 7. Set up the parallel linear form b(.) which corresponds to the
|
||||
// right-hand side of the FEM linear system, which in this case is
|
||||
// (1,phi_i) where phi_i are the basis functions in fespace.
|
||||
ParLinearForm *b = new ParLinearForm(fespace);
|
||||
ConstantCoefficient one(1.0);
|
||||
b->AddDomainIntegrator(new DomainLFIntegrator(one));
|
||||
|
||||
// 8. Define the solution vector x as a parallel finite element grid function
|
||||
// corresponding to fespace. Initialize x with initial guess of zero,
|
||||
// which satisfies the boundary conditions.
|
||||
ParGridFunction x(fespace);
|
||||
x = 0.0;
|
||||
|
||||
// 9. Connect to GLVis.
|
||||
char vishost[] = "localhost";
|
||||
int visport = 19916;
|
||||
|
||||
socketstream sout;
|
||||
if (visualization)
|
||||
{
|
||||
sout.open(vishost, visport);
|
||||
if (!sout)
|
||||
{
|
||||
if (myid == 0)
|
||||
{
|
||||
cout << "Unable to connect to GLVis server at "
|
||||
<< vishost << ':' << visport << endl;
|
||||
cout << "GLVis visualization disabled.\n";
|
||||
}
|
||||
visualization = false;
|
||||
}
|
||||
|
||||
sout.precision(8);
|
||||
}
|
||||
|
||||
// 10. Set up the parallel bilinear form a(.,.) on the finite element space
|
||||
// corresponding to the Laplacian operator -Delta, by adding the
|
||||
// Diffusion domain integrator.
|
||||
ParBilinearForm *a = new ParBilinearForm(fespace);
|
||||
a->AddDomainIntegrator(new DiffusionIntegrator(one));
|
||||
|
||||
// 11. Assemble the parallel bilinear form and the corresponding linear
|
||||
// system, applying any necessary transformations such as: parallel
|
||||
// assembly, eliminating boundary conditions, applying conforming
|
||||
// constraints for non-conforming AMR, static condensation, etc.
|
||||
if (static_cond) { a->EnableStaticCondensation(); }
|
||||
|
||||
// 12. The main AMR loop. In each iteration we solve the problem on the
|
||||
// current mesh, visualize the solution, and adapt the mesh.
|
||||
apf::Field* Tmag_field = 0;
|
||||
apf::Field* temp_field = 0;
|
||||
apf::Field* ipfield = 0;
|
||||
apf::Field* sizefield = 0;
|
||||
int max_iter = 3;
|
||||
|
||||
for (int Itr = 0; Itr < max_iter; Itr++)
|
||||
{
|
||||
HYPRE_Int global_dofs = fespace->GlobalTrueVSize();
|
||||
if (myid == 1)
|
||||
{
|
||||
cout << "\nAMR iteration " << Itr << endl;
|
||||
cout << "Number of unknowns: " << global_dofs << endl;
|
||||
}
|
||||
|
||||
// Assemble.
|
||||
a->Assemble();
|
||||
b->Assemble();
|
||||
|
||||
// Essential boundary condition.
|
||||
Array<int> ess_tdof_list;
|
||||
if (pmesh->bdr_attributes.Size())
|
||||
{
|
||||
Array<int> ess_bdr(pmesh->bdr_attributes.Max());
|
||||
ess_bdr = 1;
|
||||
fespace->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
|
||||
}
|
||||
|
||||
// Form linear system.
|
||||
HypreParMatrix A;
|
||||
Vector B, X;
|
||||
const int copy_interior = 1;
|
||||
a->FormLinearSystem(ess_tdof_list, x, *b, A, X, B, copy_interior);
|
||||
|
||||
// 13. Define and apply a parallel PCG solver for AX=B with the BoomerAMG
|
||||
// preconditioner from hypre.
|
||||
HypreBoomerAMG amg;
|
||||
amg.SetPrintLevel(0);
|
||||
CGSolver pcg(A.GetComm());
|
||||
pcg.SetPreconditioner(amg);
|
||||
pcg.SetOperator(A);
|
||||
pcg.SetRelTol(1e-6);
|
||||
pcg.SetMaxIter(200);
|
||||
pcg.SetPrintLevel(3); // print the first and the last iterations only
|
||||
pcg.Mult(B, X);
|
||||
|
||||
// 14. Recover the parallel grid function corresponding to X. This is the
|
||||
// local finite element solution on each processor.
|
||||
a->RecoverFEMSolution(X, *b, x);
|
||||
|
||||
// 15. Save in parallel the displaced mesh and the inverted solution (which
|
||||
// gives the backward displacements to the original grid). This output
|
||||
// can be viewed later using GLVis: "glvis -np <np> -m mesh -g sol".
|
||||
{
|
||||
ostringstream mesh_name, sol_name;
|
||||
mesh_name << "mesh." << setfill('0') << setw(6) << myid;
|
||||
sol_name << "sol." << setfill('0') << setw(6) << myid;
|
||||
|
||||
ofstream mesh_ofs(mesh_name.str().c_str());
|
||||
mesh_ofs.precision(8);
|
||||
pmesh->Print(mesh_ofs);
|
||||
|
||||
ofstream sol_ofs(sol_name.str().c_str());
|
||||
sol_ofs.precision(8);
|
||||
x.Save(sol_ofs);
|
||||
}
|
||||
|
||||
// 16. Send the above data by socket to a GLVis server. Use the "n" and "b"
|
||||
// keys in GLVis to visualize the displacements.
|
||||
if (visualization)
|
||||
{
|
||||
sout << "parallel " << num_procs << " " << myid << "\n";
|
||||
sout << "solution\n" << *pmesh << x << flush;
|
||||
}
|
||||
|
||||
// 17. Field transfer. Scalar solution field and magnitude field for error
|
||||
// estimation are created the PUMI mesh.
|
||||
if (order > geom_order)
|
||||
{
|
||||
Tmag_field = apf::createField(pumi_mesh, "field_mag",
|
||||
apf::SCALAR, apf::getLagrange(order));
|
||||
temp_field = apf::createField(pumi_mesh, "T_field",
|
||||
apf::SCALAR, apf::getLagrange(order));
|
||||
}
|
||||
else
|
||||
{
|
||||
Tmag_field = apf::createFieldOn(pumi_mesh, "field_mag",apf::SCALAR);
|
||||
temp_field = apf::createFieldOn(pumi_mesh, "T_field", apf::SCALAR);
|
||||
}
|
||||
|
||||
ParPumiMesh* pPPmesh = dynamic_cast<ParPumiMesh*>(pmesh);
|
||||
pPPmesh->FieldMFEMtoPUMI(pumi_mesh, &x, temp_field, Tmag_field);
|
||||
|
||||
ipfield= spr::getGradIPField(Tmag_field, "MFEM_gradip", 2);
|
||||
sizefield = spr::getSPRSizeField(ipfield, adapt_ratio);
|
||||
|
||||
apf::destroyField(Tmag_field);
|
||||
apf::destroyField(ipfield);
|
||||
apf::destroyNumbering(pumi_mesh->findNumbering("LocalVertexNumbering"));
|
||||
|
||||
// 18. Perform MesAdapt.
|
||||
ma::Input* erinput = ma::configure(pumi_mesh, sizefield);
|
||||
erinput->shouldFixShape = true;
|
||||
erinput->maximumIterations = 2;
|
||||
if ( geom_order > 1)
|
||||
{
|
||||
crv::adapt(erinput);
|
||||
}
|
||||
else
|
||||
{
|
||||
ma::adapt(erinput);
|
||||
}
|
||||
|
||||
ParMesh* Adapmesh = new ParPumiMesh(MPI_COMM_WORLD, pumi_mesh);
|
||||
pPPmesh->UpdateMesh(Adapmesh);
|
||||
delete Adapmesh;
|
||||
|
||||
// 19. Update the FiniteElementSpace, GridFunction, and bilinear form.
|
||||
fespace->Update();
|
||||
x.Update();
|
||||
x = 0.0;
|
||||
|
||||
pPPmesh->FieldPUMItoMFEM(pumi_mesh, temp_field, &x);
|
||||
a->Update();
|
||||
b->Update();
|
||||
|
||||
// Destroy fields.
|
||||
apf::destroyField(temp_field);
|
||||
apf::destroyField(sizefield);
|
||||
}
|
||||
|
||||
// 20. Free the used memory.
|
||||
delete a;
|
||||
delete b;
|
||||
delete fespace;
|
||||
if (order > 0) { delete fec; }
|
||||
delete pmesh;
|
||||
|
||||
pumi_mesh->destroyNative();
|
||||
apf::destroyMesh(pumi_mesh);
|
||||
PCU_Comm_Free();
|
||||
|
||||
#ifdef MFEM_USE_SIMMETRIX
|
||||
gmi_sim_stop();
|
||||
Sim_unregisterAllKeys();
|
||||
#endif
|
||||
|
||||
MPI_Finalize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
# Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at the
|
||||
# Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights reserved.
|
||||
# See file COPYRIGHT for details.
|
||||
#
|
||||
# This file is part of the MFEM library. For more information and source code
|
||||
# availability see http://mfem.org.
|
||||
#
|
||||
# MFEM is free software; you can redistribute it and/or modify it under the
|
||||
# terms of the GNU Lesser General Public License (as published by the Free
|
||||
# Software Foundation) version 2.1 dated February 1999.
|
||||
|
||||
# Use the MFEM build directory
|
||||
MFEM_DIR ?= ../..
|
||||
MFEM_BUILD_DIR ?= ../..
|
||||
SRC = $(if $(MFEM_DIR:../..=),$(MFEM_DIR)/examples/pumi/,)
|
||||
CONFIG_MK = $(MFEM_BUILD_DIR)/config/config.mk
|
||||
# Use the MFEM install directory
|
||||
# MFEM_INSTALL_DIR = ../../mfem
|
||||
# CONFIG_MK = $(MFEM_INSTALL_DIR)/share/mfem/config.mk
|
||||
|
||||
MFEM_LIB_FILE = mfem_is_not_built
|
||||
-include $(CONFIG_MK)
|
||||
|
||||
# All PUMI examples require MPI
|
||||
SEQ_EXAMPLES =
|
||||
PAR_EXAMPLES = ex1 ex1p ex2 ex6p
|
||||
ifeq ($(MFEM_USE_MPI),NO)
|
||||
EXAMPLES = $(SEQ_EXAMPLES)
|
||||
else
|
||||
EXAMPLES = $(PAR_EXAMPLES) $(SEQ_EXAMPLES)
|
||||
endif
|
||||
|
||||
.SUFFIXES:
|
||||
.SUFFIXES: .o .cpp .mk
|
||||
.PHONY: all clean clean-build clean-exec
|
||||
|
||||
# Remove built-in rule
|
||||
%: %.cpp
|
||||
|
||||
# Replace the default implicit rule for *.cpp files
|
||||
%: $(SRC)%.cpp $(MFEM_LIB_FILE) $(CONFIG_MK)
|
||||
$(MFEM_CXX) $(MFEM_FLAGS) $< -o $@ $(MFEM_LIBS)
|
||||
|
||||
all: $(EXAMPLES)
|
||||
|
||||
ifeq ($(MFEM_USE_PUMI),NO)
|
||||
$(EXAMPLES):
|
||||
$(error MFEM is not configured with PUMI)
|
||||
endif
|
||||
|
||||
MFEM_TESTS = EXAMPLES
|
||||
include $(MFEM_TEST_MK)
|
||||
|
||||
ifneq (,$(filter test%,$(MAKECMDGOALS)))
|
||||
ifeq (,$(wildcard ../../data/pumi))
|
||||
$(info PUMI data directory not found. The PUMI tests will be SKIPPED.)
|
||||
mfem-test = printf " $(3) [$(2) $(1) ... ]: "; $(PRINT_SKIP)
|
||||
endif
|
||||
endif
|
||||
|
||||
# Testing: Parallel vs. serial runs
|
||||
RUN_MPI_NP = $(MFEM_MPIEXEC) $(MFEM_MPIEXEC_NP)
|
||||
RUN_MPI = $(RUN_MPI_NP) $(MFEM_MPI_NP)
|
||||
SERIAL_NAME := Serial PUMI example
|
||||
PARALLEL_NAME := Parallel PUMI example
|
||||
%-test-par: %
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(PARALLEL_NAME))
|
||||
%-test-seq: %
|
||||
@$(call mfem-test,$<,, $(SERIAL_NAME))
|
||||
|
||||
# Testing: Example-specific execution options:
|
||||
ex1-test-par: ex1
|
||||
@$(call mfem-test,$<, $(RUN_MPI_NP) 1, $(PARALLEL_NAME))
|
||||
ex1p-test-par: ex1p
|
||||
@$(call mfem-test,$<, $(RUN_MPI_NP) 8, $(PARALLEL_NAME))
|
||||
ex2-test-par: ex2
|
||||
@$(call mfem-test,$<, $(RUN_MPI_NP) 1, $(PARALLEL_NAME))
|
||||
ex6p-test-par: ex6p
|
||||
@$(call mfem-test,$<, $(RUN_MPI_NP) 8, $(PARALLEL_NAME))
|
||||
|
||||
# Testing: "test" target and mfem-test* variables are defined in config/test.mk
|
||||
|
||||
# Generate an error message if the MFEM library is not built and exit
|
||||
$(MFEM_LIB_FILE):
|
||||
$(error The MFEM library is not built)
|
||||
|
||||
clean: clean-build clean-exec
|
||||
|
||||
clean-build:
|
||||
rm -f *.o *~ $(SEQ_EXAMPLES) $(PAR_EXAMPLES)
|
||||
rm -rf *.dSYM *.TVD.*breakpoints
|
||||
|
||||
clean-exec:
|
||||
@rm -f refined.mesh sol.gf mesh.* sol.* displaced.mesh
|
||||
@@ -13,23 +13,21 @@ set(SUNDIALS_EXAMPLES_SRCS)
|
||||
list(APPEND SUNDIALS_EXAMPLES_SRCS
|
||||
ex9.cpp
|
||||
ex10.cpp
|
||||
ex16.cpp
|
||||
)
|
||||
|
||||
if (MFEM_USE_MPI)
|
||||
list(APPEND SUNDIALS_EXAMPLES_SRCS
|
||||
ex9p.cpp
|
||||
ex10p.cpp
|
||||
ex16p.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
# Include the source directory where mfem.hpp and mfem-performance.hpp are.
|
||||
include_directories(BEFORE ${PROJECT_BINARY_DIR})
|
||||
include_directories(${PROJECT_BINARY_DIR})
|
||||
|
||||
# Add "test_sundials" target, see below.
|
||||
add_custom_target(test_sundials
|
||||
${CMAKE_CTEST_COMMAND} -R sundials USES_TERMINAL)
|
||||
${CMAKE_CTEST_COMMAND} -R sundials -C SUNDIALS USES_TERMINAL)
|
||||
|
||||
# Add one executable per cpp file, adding "sundials_" as prefix. Sets
|
||||
# "test_sundials" as a target that depends on the given examples.
|
||||
@@ -37,9 +35,10 @@ set(PFX sundials_)
|
||||
add_mfem_examples(SUNDIALS_EXAMPLES_SRCS ${PFX} "" test_sundials)
|
||||
|
||||
# Testing.
|
||||
# The SUNDIALS tests can be run separately using the target "test_sundials"
|
||||
# which builds the examples and runs:
|
||||
# ctest -R sundials
|
||||
# We do not want these tests to be run by default, so we add them to their own
|
||||
# configuration - SUNDIALS. To run the tests defined here use the
|
||||
# "test_sundials" target which builds the examples and runs:
|
||||
# ctest -C SUNDIALS -R sundials
|
||||
|
||||
# Command line options for the tests.
|
||||
# Example 9: test explicit CVODE time stepping
|
||||
@@ -50,7 +49,6 @@ set(EX9P_TEST_OPTS ${EX9_COMMON_OPTS} -rp 1 -dt 0.0009 -vs 50)
|
||||
set(EX10_COMMON_OPTS -m ../../data/beam-quad.mesh -o 2 -s 5 -dt 0.15 -vs 10)
|
||||
set(EX10_TEST_OPTS ${EX10_COMMON_OPTS} -r 2)
|
||||
set(EX10P_TEST_OPTS ${EX10_COMMON_OPTS} -rp 1)
|
||||
# Example 16: use the default options
|
||||
|
||||
# Add the tests: one test per source file.
|
||||
foreach(SRC_FILE ${SUNDIALS_EXAMPLES_SRCS})
|
||||
@@ -65,12 +63,14 @@ foreach(SRC_FILE ${SUNDIALS_EXAMPLES_SRCS})
|
||||
|
||||
if (NOT (${TEST_NAME} MATCHES ".*p$"))
|
||||
add_test(NAME ${TEST_NAME}_ser
|
||||
COMMAND ${TEST_NAME} ${THIS_TEST_OPTIONS})
|
||||
COMMAND ${TEST_NAME} ${THIS_TEST_OPTIONS}
|
||||
CONFIGURATIONS SUNDIALS)
|
||||
else()
|
||||
add_test(NAME ${TEST_NAME}_np=4
|
||||
COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} 4
|
||||
${MPIEXEC_PREFLAGS}
|
||||
$<TARGET_FILE:${TEST_NAME}> ${THIS_TEST_OPTIONS}
|
||||
${MPIEXEC_POSTFLAGS})
|
||||
${MPIEXEC_POSTFLAGS}
|
||||
CONFIGURATIONS SUNDIALS)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
// ex10 -m ../../data/beam-quad.mesh -r 2 -o 2 -s 15 -dt 5e-3 -vs 60
|
||||
// ex10 -m ../../data/beam-tri.mesh -r 2 -o 2 -s 16 -dt 0.01 -vs 30
|
||||
// ex10 -m ../../data/beam-hex.mesh -r 1 -o 2 -s 15 -dt 0.01 -vs 30
|
||||
// ex10 -m ../../data/beam-quad-amr.mesh -r 2 -o 2 -s 5 -dt 0.15 -vs 10
|
||||
//
|
||||
// Description: This examples solves a time dependent nonlinear elasticity
|
||||
// problem of the form dv/dt = H(x) + S v, dx/dt = v, where H is a
|
||||
@@ -116,9 +115,9 @@ public:
|
||||
method of SundialsJacSolver. */
|
||||
void InitSundialsJacSolver(SundialsJacSolver &sjsolv);
|
||||
|
||||
double ElasticEnergy(const Vector &x) const;
|
||||
double KineticEnergy(const Vector &v) const;
|
||||
void GetElasticEnergyDensity(const GridFunction &x, GridFunction &w) const;
|
||||
double ElasticEnergy(Vector &x) const;
|
||||
double KineticEnergy(Vector &v) const;
|
||||
void GetElasticEnergyDensity(GridFunction &x, GridFunction &w) const;
|
||||
|
||||
virtual ~HyperelasticOperator();
|
||||
};
|
||||
@@ -205,12 +204,12 @@ public:
|
||||
class ElasticEnergyCoefficient : public Coefficient
|
||||
{
|
||||
private:
|
||||
HyperelasticModel &model;
|
||||
const GridFunction &x;
|
||||
DenseMatrix J;
|
||||
HyperelasticModel &model;
|
||||
GridFunction &x;
|
||||
DenseMatrix J;
|
||||
|
||||
public:
|
||||
ElasticEnergyCoefficient(HyperelasticModel &m, const GridFunction &x_)
|
||||
ElasticEnergyCoefficient(HyperelasticModel &m, GridFunction &x_)
|
||||
: model(m), x(x_) { }
|
||||
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip);
|
||||
virtual ~ElasticEnergyCoefficient() { }
|
||||
@@ -349,7 +348,6 @@ int main(int argc, char *argv[])
|
||||
case 24: ode_solver = new SDIRK34Solver; break;
|
||||
default:
|
||||
cout << "Unknown ODE solver type: " << ode_solver_type << '\n';
|
||||
delete mesh;
|
||||
return 3;
|
||||
}
|
||||
|
||||
@@ -379,7 +377,7 @@ int main(int argc, char *argv[])
|
||||
H1_FECollection fe_coll(order, dim);
|
||||
FiniteElementSpace fespace(mesh, &fe_coll, dim);
|
||||
|
||||
int fe_size = fespace.GetTrueVSize();
|
||||
int fe_size = fespace.GetVSize();
|
||||
cout << "Number of velocity/deformation unknowns: " << fe_size << endl;
|
||||
Array<int> fe_offset(3);
|
||||
fe_offset[0] = 0;
|
||||
@@ -388,8 +386,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
BlockVector vx(fe_offset);
|
||||
GridFunction v, x;
|
||||
v.MakeTRef(&fespace, vx.GetBlock(0), 0);
|
||||
x.MakeTRef(&fespace, vx.GetBlock(1), 0);
|
||||
v.MakeRef(&fespace, vx.GetBlock(0), 0);
|
||||
x.MakeRef(&fespace, vx.GetBlock(1), 0);
|
||||
|
||||
GridFunction x_ref(&fespace);
|
||||
mesh->GetNodes(x_ref);
|
||||
@@ -402,10 +400,8 @@ int main(int argc, char *argv[])
|
||||
// a beam-like mesh (see description above).
|
||||
VectorFunctionCoefficient velo(dim, InitialVelocity);
|
||||
v.ProjectCoefficient(velo);
|
||||
v.SetTrueVector();
|
||||
VectorFunctionCoefficient deform(dim, InitialDeformation);
|
||||
x.ProjectCoefficient(deform);
|
||||
x.SetTrueVector();
|
||||
|
||||
Array<int> ess_bdr(fespace.GetMesh()->bdr_attributes.Max());
|
||||
ess_bdr = 0;
|
||||
@@ -422,7 +418,6 @@ int main(int argc, char *argv[])
|
||||
int visport = 19916;
|
||||
vis_v.open(vishost, visport);
|
||||
vis_v.precision(8);
|
||||
v.SetFromTrueVector(); x.SetFromTrueVector();
|
||||
visualize(vis_v, mesh, &x, &v, "Velocity", true);
|
||||
vis_w.open(vishost, visport);
|
||||
if (vis_w)
|
||||
@@ -433,8 +428,8 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
double ee0 = oper.ElasticEnergy(x.GetTrueVector());
|
||||
double ke0 = oper.KineticEnergy(v.GetTrueVector());
|
||||
double ee0 = oper.ElasticEnergy(x);
|
||||
double ke0 = oper.KineticEnergy(v);
|
||||
cout << "initial elastic energy (EE) = " << ee0 << endl;
|
||||
cout << "initial kinetic energy (KE) = " << ke0 << endl;
|
||||
cout << "initial total energy (TE) = " << (ee0 + ke0) << endl;
|
||||
@@ -456,8 +451,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (last_step || (ti % vis_steps) == 0)
|
||||
{
|
||||
double ee = oper.ElasticEnergy(x.GetTrueVector());
|
||||
double ke = oper.KineticEnergy(v.GetTrueVector());
|
||||
double ee = oper.ElasticEnergy(x);
|
||||
double ke = oper.KineticEnergy(v);
|
||||
|
||||
cout << "step " << ti << ", t = " << t << ", EE = " << ee << ", KE = "
|
||||
<< ke << ", ΔTE = " << (ee+ke)-(ee0+ke0) << endl;
|
||||
@@ -467,7 +462,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (visualization)
|
||||
{
|
||||
v.SetFromTrueVector(); x.SetFromTrueVector();
|
||||
visualize(vis_v, mesh, &x, &v);
|
||||
if (vis_w)
|
||||
{
|
||||
@@ -480,7 +474,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
// 9. Save the displaced mesh, the velocity and elastic energy.
|
||||
{
|
||||
v.SetFromTrueVector(); x.SetFromTrueVector();
|
||||
GridFunction *nodes = &x;
|
||||
int owns_nodes = 0;
|
||||
mesh->SwapNodes(nodes, owns_nodes);
|
||||
@@ -651,7 +644,7 @@ HyperelasticOperator::HyperelasticOperator(FiniteElementSpace &f,
|
||||
Array<int> &ess_bdr, double visc,
|
||||
double mu, double K,
|
||||
NonlinearSolverType nls_type)
|
||||
: TimeDependentOperator(2*f.GetTrueVSize(), 0.0), fespace(f),
|
||||
: TimeDependentOperator(2*f.GetVSize(), 0.0), fespace(f),
|
||||
M(&fespace), S(&fespace), H(&fespace),
|
||||
viscosity(visc), z(height/2)
|
||||
{
|
||||
@@ -662,10 +655,8 @@ HyperelasticOperator::HyperelasticOperator(FiniteElementSpace &f,
|
||||
ConstantCoefficient rho0(ref_density);
|
||||
M.AddDomainIntegrator(new VectorMassIntegrator(rho0));
|
||||
M.Assemble(skip_zero_entries);
|
||||
Array<int> ess_tdof_list;
|
||||
fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
|
||||
SparseMatrix tmp;
|
||||
M.FormSystemMatrix(ess_tdof_list, tmp);
|
||||
M.EliminateEssentialBC(ess_bdr);
|
||||
M.Finalize(skip_zero_entries);
|
||||
|
||||
M_solver.iterative_mode = false;
|
||||
M_solver.SetRelTol(rel_tol);
|
||||
@@ -677,12 +668,13 @@ HyperelasticOperator::HyperelasticOperator(FiniteElementSpace &f,
|
||||
|
||||
model = new NeoHookeanModel(mu, K);
|
||||
H.AddDomainIntegrator(new HyperelasticNLFIntegrator(model));
|
||||
H.SetEssentialTrueDofs(ess_tdof_list);
|
||||
H.SetEssentialBC(ess_bdr);
|
||||
|
||||
ConstantCoefficient visc_coeff(viscosity);
|
||||
S.AddDomainIntegrator(new VectorDiffusionIntegrator(visc_coeff));
|
||||
S.Assemble(skip_zero_entries);
|
||||
S.FormSystemMatrix(ess_tdof_list, tmp);
|
||||
S.EliminateEssentialBC(ess_bdr);
|
||||
S.Finalize(skip_zero_entries);
|
||||
|
||||
reduced_oper = new ReducedSystemOperator(&M, &S, &H);
|
||||
|
||||
@@ -773,18 +765,18 @@ void HyperelasticOperator::InitSundialsJacSolver(SundialsJacSolver &sjsolv)
|
||||
sjsolv.SetOperators(M, S, H, *J_solver);
|
||||
}
|
||||
|
||||
double HyperelasticOperator::ElasticEnergy(const Vector &x) const
|
||||
double HyperelasticOperator::ElasticEnergy(Vector &x) const
|
||||
{
|
||||
return H.GetEnergy(x);
|
||||
}
|
||||
|
||||
double HyperelasticOperator::KineticEnergy(const Vector &v) const
|
||||
double HyperelasticOperator::KineticEnergy(Vector &v) const
|
||||
{
|
||||
return 0.5*M.InnerProduct(v, v);
|
||||
}
|
||||
|
||||
void HyperelasticOperator::GetElasticEnergyDensity(
|
||||
const GridFunction &x, GridFunction &w) const
|
||||
GridFunction &x, GridFunction &w) const
|
||||
{
|
||||
ElasticEnergyCoefficient w_coeff(*model, x);
|
||||
w.ProjectCoefficient(w_coeff);
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
// mpirun -np 4 ex10p -m ../../data/beam-quad.mesh -rp 1 -o 2 -s 15 -dt 3e-3 -vs 120
|
||||
// mpirun -np 4 ex10p -m ../../data/beam-tri.mesh -rp 1 -o 2 -s 16 -dt 5e-3 -vs 60
|
||||
// mpirun -np 4 ex10p -m ../../data/beam-hex.mesh -rp 0 -o 2 -s 15 -dt 5e-3 -vs 60
|
||||
// mpirun -np 4 ex10p -m ../../data/beam-quad-amr.mesh -rp 1 -o 2 -s 5 -dt 0.15 -vs 10
|
||||
//
|
||||
// Description: This examples solves a time dependent nonlinear elasticity
|
||||
// problem of the form dv/dt = H(x) + S v, dx/dt = v, where H is a
|
||||
@@ -69,7 +68,6 @@ class HyperelasticOperator : public TimeDependentOperator
|
||||
{
|
||||
protected:
|
||||
ParFiniteElementSpace &fespace;
|
||||
Array<int> ess_tdof_list;
|
||||
|
||||
ParBilinearForm M, S;
|
||||
ParNonlinearForm H;
|
||||
@@ -118,10 +116,9 @@ public:
|
||||
method of SundialsJacSolver. */
|
||||
void InitSundialsJacSolver(SundialsJacSolver &sjsolv);
|
||||
|
||||
double ElasticEnergy(const ParGridFunction &x) const;
|
||||
double KineticEnergy(const ParGridFunction &v) const;
|
||||
void GetElasticEnergyDensity(const ParGridFunction &x,
|
||||
ParGridFunction &w) const;
|
||||
double ElasticEnergy(ParGridFunction &x) const;
|
||||
double KineticEnergy(ParGridFunction &v) const;
|
||||
void GetElasticEnergyDensity(ParGridFunction &x, ParGridFunction &w) const;
|
||||
|
||||
virtual ~HyperelasticOperator();
|
||||
};
|
||||
@@ -139,11 +136,10 @@ private:
|
||||
double dt;
|
||||
const Vector *v, *x;
|
||||
mutable Vector w, z;
|
||||
const Array<int> &ess_tdof_list;
|
||||
|
||||
public:
|
||||
ReducedSystemOperator(ParBilinearForm *M_, ParBilinearForm *S_,
|
||||
ParNonlinearForm *H_, const Array<int> &ess_tdof_list);
|
||||
ParNonlinearForm *H_);
|
||||
|
||||
/// Set current dt, v, x values - needed to compute action and Jacobian.
|
||||
void SetParameters(double dt_, const Vector *v_, const Vector *x_);
|
||||
@@ -177,7 +173,6 @@ private:
|
||||
const SparseMatrix *local_grad_H;
|
||||
HypreParMatrix *Jacobian;
|
||||
Solver *J_solver;
|
||||
const Array<int> *ess_tdof_list;
|
||||
|
||||
public:
|
||||
SundialsJacSolver()
|
||||
@@ -185,11 +180,9 @@ public:
|
||||
|
||||
/// Connect the solver to the objects created inside HyperelasticOperator.
|
||||
void SetOperators(ParBilinearForm &M_, ParBilinearForm &S_,
|
||||
ParNonlinearForm &H_, Solver &solver,
|
||||
const Array<int> &ess_tdof_list_)
|
||||
ParNonlinearForm &H_, Solver &solver)
|
||||
{
|
||||
M = &M_; S = &S_; H = &H_; J_solver = &solver;
|
||||
ess_tdof_list = &ess_tdof_list_;
|
||||
}
|
||||
|
||||
/** Linear solve applicable to the SUNDIALS format.
|
||||
@@ -214,12 +207,12 @@ public:
|
||||
class ElasticEnergyCoefficient : public Coefficient
|
||||
{
|
||||
private:
|
||||
HyperelasticModel &model;
|
||||
const ParGridFunction &x;
|
||||
DenseMatrix J;
|
||||
HyperelasticModel &model;
|
||||
ParGridFunction &x;
|
||||
DenseMatrix J;
|
||||
|
||||
public:
|
||||
ElasticEnergyCoefficient(HyperelasticModel &m, const ParGridFunction &x_)
|
||||
ElasticEnergyCoefficient(HyperelasticModel &m, ParGridFunction &x_)
|
||||
: model(m), x(x_) { }
|
||||
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip);
|
||||
virtual ~ElasticEnergyCoefficient() { }
|
||||
@@ -377,7 +370,6 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
cout << "Unknown ODE solver type: " << ode_solver_type << '\n';
|
||||
}
|
||||
delete mesh;
|
||||
MPI_Finalize();
|
||||
return 3;
|
||||
}
|
||||
@@ -391,8 +383,6 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
cout << "Unknown type of nonlinear solver: " << nls << endl;
|
||||
}
|
||||
delete ode_solver;
|
||||
delete mesh;
|
||||
MPI_Finalize();
|
||||
return 4;
|
||||
}
|
||||
@@ -436,9 +426,7 @@ int main(int argc, char *argv[])
|
||||
true_offset[2] = 2*true_size;
|
||||
|
||||
BlockVector vx(true_offset);
|
||||
ParGridFunction v_gf, x_gf;
|
||||
v_gf.MakeTRef(&fespace, vx, true_offset[0]);
|
||||
x_gf.MakeTRef(&fespace, vx, true_offset[1]);
|
||||
ParGridFunction v_gf(&fespace), x_gf(&fespace);
|
||||
|
||||
ParGridFunction x_ref(&fespace);
|
||||
pmesh->GetNodes(x_ref);
|
||||
@@ -451,12 +439,11 @@ int main(int argc, char *argv[])
|
||||
// boundary conditions on a beam-like mesh (see description above).
|
||||
VectorFunctionCoefficient velo(dim, InitialVelocity);
|
||||
v_gf.ProjectCoefficient(velo);
|
||||
v_gf.SetTrueVector();
|
||||
VectorFunctionCoefficient deform(dim, InitialDeformation);
|
||||
x_gf.ProjectCoefficient(deform);
|
||||
x_gf.SetTrueVector();
|
||||
|
||||
v_gf.SetFromTrueVector(); x_gf.SetFromTrueVector();
|
||||
v_gf.GetTrueDofs(vx.GetBlock(0));
|
||||
x_gf.GetTrueDofs(vx.GetBlock(1));
|
||||
|
||||
Array<int> ess_bdr(fespace.GetMesh()->bdr_attributes.Max());
|
||||
ess_bdr = 0;
|
||||
@@ -512,7 +499,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
if (last_step || (ti % vis_steps) == 0)
|
||||
{
|
||||
v_gf.SetFromTrueVector(); x_gf.SetFromTrueVector();
|
||||
v_gf.Distribute(vx.GetBlock(0));
|
||||
x_gf.Distribute(vx.GetBlock(1));
|
||||
|
||||
double ee = oper.ElasticEnergy(x_gf);
|
||||
double ke = oper.KineticEnergy(v_gf);
|
||||
@@ -540,7 +528,6 @@ int main(int argc, char *argv[])
|
||||
|
||||
// 11. Save the displaced mesh, the velocity and elastic energy.
|
||||
{
|
||||
v_gf.SetFromTrueVector(); x_gf.SetFromTrueVector();
|
||||
GridFunction *nodes = &x_gf;
|
||||
int owns_nodes = 0;
|
||||
pmesh->SwapNodes(nodes, owns_nodes);
|
||||
@@ -609,11 +596,9 @@ void visualize(ostream &out, ParMesh *mesh, ParGridFunction *deformed_nodes,
|
||||
|
||||
|
||||
ReducedSystemOperator::ReducedSystemOperator(
|
||||
ParBilinearForm *M_, ParBilinearForm *S_, ParNonlinearForm *H_,
|
||||
const Array<int> &ess_tdof_list_)
|
||||
ParBilinearForm *M_, ParBilinearForm *S_, ParNonlinearForm *H_)
|
||||
: Operator(M_->ParFESpace()->TrueVSize()), M(M_), S(S_), H(H_),
|
||||
Jacobian(NULL), dt(0.0), v(NULL), x(NULL), w(height), z(height),
|
||||
ess_tdof_list(ess_tdof_list_)
|
||||
Jacobian(NULL), dt(0.0), v(NULL), x(NULL), w(height), z(height)
|
||||
{ }
|
||||
|
||||
void ReducedSystemOperator::SetParameters(double dt_, const Vector *v_,
|
||||
@@ -630,7 +615,6 @@ void ReducedSystemOperator::Mult(const Vector &k, Vector &y) const
|
||||
H->Mult(z, y);
|
||||
M->TrueAddMult(k, y);
|
||||
S->TrueAddMult(w, y);
|
||||
y.SetSubVector(ess_tdof_list, 0.0);
|
||||
}
|
||||
|
||||
Operator &ReducedSystemOperator::GetGradient(const Vector &k) const
|
||||
@@ -642,8 +626,6 @@ Operator &ReducedSystemOperator::GetGradient(const Vector &k) const
|
||||
localJ->Add(dt*dt, H->GetLocalGradient(z));
|
||||
Jacobian = M->ParallelAssemble(localJ);
|
||||
delete localJ;
|
||||
HypreParMatrix *Je = Jacobian->EliminateRowsCols(ess_tdof_list);
|
||||
delete Je;
|
||||
return *Jacobian;
|
||||
}
|
||||
|
||||
@@ -685,8 +667,6 @@ int SundialsJacSolver::SetupSystem(void *sundials_mem, int conv_fail,
|
||||
localJ->Add(dt*dt, *local_grad_H);
|
||||
Jacobian = M->ParallelAssemble(localJ);
|
||||
delete localJ;
|
||||
HypreParMatrix *Je = Jacobian->EliminateRowsCols(*ess_tdof_list);
|
||||
delete Je;
|
||||
|
||||
J_solver->SetOperator(*Jacobian);
|
||||
|
||||
@@ -706,8 +686,6 @@ int SundialsJacSolver::SolveSystem(void *sundials_mem, Vector &b,
|
||||
Vector rhs(sc);
|
||||
double dt = GetTimeStep(sundials_mem);
|
||||
|
||||
// We can assume that b_v and b_x have zeros at essential tdofs.
|
||||
|
||||
// rhs = M b_v - dt*grad(H) b_x
|
||||
ParGridFunction lb_x(fes), lrhs(fes);
|
||||
lb_x.Distribute(b_x);
|
||||
@@ -715,7 +693,6 @@ int SundialsJacSolver::SolveSystem(void *sundials_mem, Vector &b,
|
||||
lrhs.ParallelAssemble(rhs);
|
||||
rhs *= -dt;
|
||||
M->TrueAddMult(b_v, rhs);
|
||||
rhs.SetSubVector(*ess_tdof_list, 0.0);
|
||||
|
||||
J_solver->iterative_mode = false;
|
||||
J_solver->Mult(rhs, b_v);
|
||||
@@ -747,11 +724,9 @@ HyperelasticOperator::HyperelasticOperator(ParFiniteElementSpace &f,
|
||||
ConstantCoefficient rho0(ref_density);
|
||||
M.AddDomainIntegrator(new VectorMassIntegrator(rho0));
|
||||
M.Assemble(skip_zero_entries);
|
||||
M.EliminateEssentialBC(ess_bdr);
|
||||
M.Finalize(skip_zero_entries);
|
||||
Mmat = M.ParallelAssemble();
|
||||
fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
|
||||
HypreParMatrix *Me = Mmat->EliminateRowsCols(ess_tdof_list);
|
||||
delete Me;
|
||||
|
||||
M_solver.iterative_mode = false;
|
||||
M_solver.SetRelTol(rel_tol);
|
||||
@@ -764,14 +739,15 @@ HyperelasticOperator::HyperelasticOperator(ParFiniteElementSpace &f,
|
||||
|
||||
model = new NeoHookeanModel(mu, K);
|
||||
H.AddDomainIntegrator(new HyperelasticNLFIntegrator(model));
|
||||
H.SetEssentialTrueDofs(ess_tdof_list);
|
||||
H.SetEssentialBC(ess_bdr);
|
||||
|
||||
ConstantCoefficient visc_coeff(viscosity);
|
||||
S.AddDomainIntegrator(new VectorDiffusionIntegrator(visc_coeff));
|
||||
S.Assemble(skip_zero_entries);
|
||||
S.EliminateEssentialBC(ess_bdr);
|
||||
S.Finalize(skip_zero_entries);
|
||||
|
||||
reduced_oper = new ReducedSystemOperator(&M, &S, &H, ess_tdof_list);
|
||||
reduced_oper = new ReducedSystemOperator(&M, &S, &H);
|
||||
|
||||
HypreSmoother *J_hypreSmoother = new HypreSmoother;
|
||||
J_hypreSmoother->SetType(HypreSmoother::l1Jacobi);
|
||||
@@ -820,7 +796,6 @@ void HyperelasticOperator::Mult(const Vector &vx, Vector &dvx_dt) const
|
||||
if (viscosity != 0.0)
|
||||
{
|
||||
S.TrueAddMult(v, z);
|
||||
z.SetSubVector(ess_tdof_list, 0.0);
|
||||
}
|
||||
z.Neg(); // z = -z
|
||||
M_solver.Mult(z, dv_dt);
|
||||
@@ -860,15 +835,15 @@ void HyperelasticOperator::ImplicitSolve(const double dt,
|
||||
|
||||
void HyperelasticOperator::InitSundialsJacSolver(SundialsJacSolver &sjsolv)
|
||||
{
|
||||
sjsolv.SetOperators(M, S, H, *J_solver, ess_tdof_list);
|
||||
sjsolv.SetOperators(M, S, H, *J_solver);
|
||||
}
|
||||
|
||||
double HyperelasticOperator::ElasticEnergy(const ParGridFunction &x) const
|
||||
double HyperelasticOperator::ElasticEnergy(ParGridFunction &x) const
|
||||
{
|
||||
return H.GetEnergy(x);
|
||||
}
|
||||
|
||||
double HyperelasticOperator::KineticEnergy(const ParGridFunction &v) const
|
||||
double HyperelasticOperator::KineticEnergy(ParGridFunction &v) const
|
||||
{
|
||||
double loc_energy = 0.5*M.InnerProduct(v, v);
|
||||
double energy;
|
||||
@@ -878,7 +853,7 @@ double HyperelasticOperator::KineticEnergy(const ParGridFunction &v) const
|
||||
}
|
||||
|
||||
void HyperelasticOperator::GetElasticEnergyDensity(
|
||||
const ParGridFunction &x, ParGridFunction &w) const
|
||||
ParGridFunction &x, ParGridFunction &w) const
|
||||
{
|
||||
ElasticEnergyCoefficient w_coeff(*model, x);
|
||||
w.ProjectCoefficient(w_coeff);
|
||||
|
||||
@@ -1,524 +0,0 @@
|
||||
// MFEM Example 16
|
||||
// SUNDIALS Modification
|
||||
//
|
||||
// Compile with: make ex16
|
||||
//
|
||||
// Sample runs: ex16
|
||||
// ex16 -m ../../data/inline-tri.mesh
|
||||
// ex16 -m ../../data/disc-nurbs.mesh -tf 2
|
||||
// ex16 -s 12 -a 0.0 -k 1.0
|
||||
// ex16 -s 1 -a 1.0 -k 0.0 -dt 1e-4 -tf 5e-2 -vs 25
|
||||
// ex16 -s 2 -a 0.5 -k 0.5 -o 4 -dt 1e-4 -tf 2e-2 -vs 25
|
||||
// ex16 -s 3 -dt 1.0e-4 -tf 4.0e-2 -vs 40
|
||||
// ex16 -m ../../data/fichera-q2.mesh
|
||||
// ex16 -m ../../data/escher.mesh
|
||||
// ex16 -m ../../data/beam-tet.mesh -tf 10 -dt 0.1
|
||||
// ex16 -m ../../data/amr-quad.mesh -o 4 -r 0
|
||||
// ex16 -m ../../data/amr-hex.mesh -o 2 -r 0
|
||||
//
|
||||
// Description: This example solves a time dependent nonlinear heat equation
|
||||
// problem of the form du/dt = C(u), with a non-linear diffusion
|
||||
// operator C(u) = \nabla \cdot (\kappa + \alpha u) \nabla u.
|
||||
//
|
||||
// The example demonstrates the use of nonlinear operators (the
|
||||
// class ConductionOperator defining C(u)), as well as their
|
||||
// implicit time integration. Note that implementing the method
|
||||
// ConductionOperator::ImplicitSolve is the only requirement for
|
||||
// high-order implicit (SDIRK) time integration. By default, this
|
||||
// example uses the SUNDIALS ODE solvers from CVODE and ARKODE.
|
||||
//
|
||||
// We recommend viewing examples 2, 9 and 10 before viewing this
|
||||
// example.
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
using namespace mfem;
|
||||
|
||||
/** After spatial discretization, the conduction model can be written as:
|
||||
*
|
||||
* du/dt = M^{-1}(-Ku)
|
||||
*
|
||||
* where u is the vector representing the temperature, M is the mass matrix,
|
||||
* and K is the diffusion operator with diffusivity depending on u:
|
||||
* (\kappa + \alpha u).
|
||||
*
|
||||
* Class ConductionOperator represents the right-hand side of the above ODE.
|
||||
*/
|
||||
class ConductionOperator : public TimeDependentOperator
|
||||
{
|
||||
protected:
|
||||
FiniteElementSpace &fespace;
|
||||
Array<int> ess_tdof_list; // this list remains empty for pure Neumann b.c.
|
||||
|
||||
BilinearForm *M;
|
||||
BilinearForm *K;
|
||||
|
||||
SparseMatrix Mmat, Kmat;
|
||||
SparseMatrix *T; // T = M + dt K
|
||||
double current_dt;
|
||||
|
||||
CGSolver M_solver; // Krylov solver for inverting the mass matrix M
|
||||
DSmoother M_prec; // Preconditioner for the mass matrix M
|
||||
|
||||
CGSolver T_solver; // Implicit solver for T = M + dt K
|
||||
DSmoother T_prec; // Preconditioner for the implicit solver
|
||||
|
||||
double alpha, kappa;
|
||||
|
||||
mutable Vector z; // auxiliary vector
|
||||
|
||||
public:
|
||||
ConductionOperator(FiniteElementSpace &f, double alpha, double kappa,
|
||||
const Vector &u);
|
||||
|
||||
virtual void Mult(const Vector &u, Vector &du_dt) const;
|
||||
/** Solve the Backward-Euler equation: k = f(u + dt*k, t), for the unknown k.
|
||||
This is the only requirement for high-order SDIRK implicit integration.*/
|
||||
virtual void ImplicitSolve(const double dt, const Vector &u, Vector &k);
|
||||
|
||||
/** Solve the system (M + dt K) y = M b. The result y replaces the input b.
|
||||
This method is used by the implicit SUNDIALS solvers. */
|
||||
void SundialsSolve(const double dt, Vector &b);
|
||||
|
||||
/// Update the diffusion BilinearForm K using the given true-dof vector `u`.
|
||||
void SetParameters(const Vector &u);
|
||||
|
||||
virtual ~ConductionOperator();
|
||||
};
|
||||
|
||||
/// Custom Jacobian system solver for the SUNDIALS time integrators.
|
||||
/** For the ODE system represented by ConductionOperator
|
||||
|
||||
M du/dt = -K(u),
|
||||
|
||||
this class facilitates the solution of linear systems of the form
|
||||
|
||||
(M + γK) y = M b,
|
||||
|
||||
for given b, u (not used), and γ = GetTimeStep(). */
|
||||
class SundialsJacSolver : public SundialsODELinearSolver
|
||||
{
|
||||
private:
|
||||
ConductionOperator *oper;
|
||||
|
||||
public:
|
||||
SundialsJacSolver() : oper(NULL) { }
|
||||
|
||||
int InitSystem(void *sundials_mem);
|
||||
int SetupSystem(void *sundials_mem, int conv_fail,
|
||||
const Vector &y_pred, const Vector &f_pred, int &jac_cur,
|
||||
Vector &v_temp1, Vector &v_temp2, Vector &v_temp3);
|
||||
int SolveSystem(void *sundials_mem, Vector &b, const Vector &weight,
|
||||
const Vector &y_cur, const Vector &f_cur);
|
||||
int FreeSystem(void *sundials_mem);
|
||||
};
|
||||
|
||||
double InitialTemperature(const Vector &x);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// 1. Parse command-line options.
|
||||
const char *mesh_file = "../../data/star.mesh";
|
||||
int ref_levels = 2;
|
||||
int order = 2;
|
||||
int ode_solver_type = 11; // 11 = CVODE implicit
|
||||
double t_final = 0.5;
|
||||
double dt = 1.0e-2;
|
||||
double alpha = 1.0e-2;
|
||||
double kappa = 0.5;
|
||||
bool visualization = true;
|
||||
bool visit = false;
|
||||
int vis_steps = 5;
|
||||
|
||||
// Relative and absolute tolerances for CVODE and ARKODE.
|
||||
const double reltol = 1e-4, abstol = 1e-4;
|
||||
|
||||
int precision = 8;
|
||||
cout.precision(precision);
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
args.AddOption(&mesh_file, "-m", "--mesh",
|
||||
"Mesh file to use.");
|
||||
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(&ode_solver_type, "-s", "--ode-solver",
|
||||
"ODE solver:\n"
|
||||
"\t 1/11 - CVODE (explicit/implicit),\n"
|
||||
"\t 2/12 - ARKODE (default explicit/implicit),\n"
|
||||
"\t 3 - ARKODE (Fehlberg-6-4-5)\n"
|
||||
"\t 4 - Forward Euler, 5 - RK2, 6 - RK3 SSP, 7 - RK4,\n"
|
||||
"\t 8 - Backward Euler, 9 - SDIRK23, 10 - SDIRK33.");
|
||||
args.AddOption(&t_final, "-tf", "--t-final",
|
||||
"Final time; start time is 0.");
|
||||
args.AddOption(&dt, "-dt", "--time-step",
|
||||
"Time step.");
|
||||
args.AddOption(&alpha, "-a", "--alpha",
|
||||
"Alpha coefficient.");
|
||||
args.AddOption(&kappa, "-k", "--kappa",
|
||||
"Kappa coefficient offset.");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
args.AddOption(&visit, "-visit", "--visit-datafiles", "-no-visit",
|
||||
"--no-visit-datafiles",
|
||||
"Save data files for VisIt (visit.llnl.gov) visualization.");
|
||||
args.AddOption(&vis_steps, "-vs", "--visualization-steps",
|
||||
"Visualize every n-th timestep.");
|
||||
args.Parse();
|
||||
if (!args.Good())
|
||||
{
|
||||
args.PrintUsage(cout);
|
||||
return 1;
|
||||
}
|
||||
args.PrintOptions(cout);
|
||||
|
||||
// 2. Read the mesh from the given mesh file. We can handle triangular,
|
||||
// quadrilateral, tetrahedral and hexahedral meshes with the same code.
|
||||
Mesh *mesh = new Mesh(mesh_file, 1, 1);
|
||||
int dim = mesh->Dimension();
|
||||
|
||||
// 3. Define the ODE solver used for time integration. Several
|
||||
// SUNDIALS solvers are available, as well as included both
|
||||
// explicit and implicit MFEM ODE solvers.
|
||||
ODESolver *ode_solver = NULL;
|
||||
CVODESolver *cvode = NULL;
|
||||
ARKODESolver *arkode = NULL;
|
||||
SundialsJacSolver sun_solver; // Used by the implicit SUNDIALS ode solvers.
|
||||
switch (ode_solver_type)
|
||||
{
|
||||
// SUNDIALS solvers
|
||||
case 1:
|
||||
cvode = new CVODESolver(CV_ADAMS, CV_FUNCTIONAL);
|
||||
cvode->SetSStolerances(reltol, abstol);
|
||||
cvode->SetMaxStep(dt);
|
||||
ode_solver = cvode; break;
|
||||
case 11:
|
||||
cvode = new CVODESolver(CV_BDF, CV_NEWTON);
|
||||
cvode->SetLinearSolver(sun_solver);
|
||||
cvode->SetSStolerances(reltol, abstol);
|
||||
cvode->SetMaxStep(dt);
|
||||
ode_solver = cvode; break;
|
||||
case 2:
|
||||
case 3:
|
||||
arkode = new ARKODESolver(ARKODESolver::EXPLICIT);
|
||||
arkode->SetSStolerances(reltol, abstol);
|
||||
arkode->SetMaxStep(dt);
|
||||
if (ode_solver_type == 3) { arkode->SetERKTableNum(FEHLBERG_13_7_8); }
|
||||
ode_solver = arkode; break;
|
||||
case 12:
|
||||
arkode = new ARKODESolver(ARKODESolver::IMPLICIT);
|
||||
arkode->SetLinearSolver(sun_solver);
|
||||
arkode->SetSStolerances(reltol, abstol);
|
||||
arkode->SetMaxStep(dt);
|
||||
ode_solver = arkode; break;
|
||||
// Other MFEM explicit methods
|
||||
case 4: ode_solver = new ForwardEulerSolver; break;
|
||||
case 5: ode_solver = new RK2Solver(0.5); break; // midpoint method
|
||||
case 6: ode_solver = new RK3SSPSolver; break;
|
||||
case 7: ode_solver = new RK4Solver; break;
|
||||
// MFEM implicit L-stable methods
|
||||
case 8: ode_solver = new BackwardEulerSolver; break;
|
||||
case 9: ode_solver = new SDIRK23Solver(2); break;
|
||||
case 10: ode_solver = new SDIRK33Solver; break;
|
||||
default:
|
||||
cout << "Unknown ODE solver type: " << ode_solver_type << '\n';
|
||||
delete mesh;
|
||||
return 3;
|
||||
}
|
||||
|
||||
// Since we want to update the diffusion coefficient after every time step,
|
||||
// we need to use the "one-step" mode of the SUNDIALS solvers.
|
||||
if (cvode) { cvode->SetStepMode(CV_ONE_STEP); }
|
||||
if (arkode) { arkode->SetStepMode(ARK_ONE_STEP); }
|
||||
|
||||
// 4. Refine the mesh to increase the resolution. In this example we do
|
||||
// 'ref_levels' of uniform refinement, where 'ref_levels' is a
|
||||
// command-line parameter.
|
||||
for (int lev = 0; lev < ref_levels; lev++)
|
||||
{
|
||||
mesh->UniformRefinement();
|
||||
}
|
||||
|
||||
// 5. Define the vector finite element space representing the current and the
|
||||
// initial temperature, u_ref.
|
||||
H1_FECollection fe_coll(order, dim);
|
||||
FiniteElementSpace fespace(mesh, &fe_coll);
|
||||
|
||||
int fe_size = fespace.GetTrueVSize();
|
||||
cout << "Number of temperature unknowns: " << fe_size << endl;
|
||||
|
||||
GridFunction u_gf(&fespace);
|
||||
|
||||
// 6. Set the initial conditions for u. All boundaries are considered
|
||||
// natural.
|
||||
FunctionCoefficient u_0(InitialTemperature);
|
||||
u_gf.ProjectCoefficient(u_0);
|
||||
Vector u;
|
||||
u_gf.GetTrueDofs(u);
|
||||
|
||||
// 7. Initialize the conduction operator and the visualization.
|
||||
ConductionOperator oper(fespace, alpha, kappa, u);
|
||||
|
||||
u_gf.SetFromTrueDofs(u);
|
||||
{
|
||||
ofstream omesh("ex16.mesh");
|
||||
omesh.precision(precision);
|
||||
mesh->Print(omesh);
|
||||
ofstream osol("ex16-init.gf");
|
||||
osol.precision(precision);
|
||||
u_gf.Save(osol);
|
||||
}
|
||||
|
||||
VisItDataCollection visit_dc("Example16", mesh);
|
||||
visit_dc.RegisterField("temperature", &u_gf);
|
||||
if (visit)
|
||||
{
|
||||
visit_dc.SetCycle(0);
|
||||
visit_dc.SetTime(0.0);
|
||||
visit_dc.Save();
|
||||
}
|
||||
|
||||
socketstream sout;
|
||||
if (visualization)
|
||||
{
|
||||
char vishost[] = "localhost";
|
||||
int visport = 19916;
|
||||
sout.open(vishost, visport);
|
||||
if (!sout)
|
||||
{
|
||||
cout << "Unable to connect to GLVis server at "
|
||||
<< vishost << ':' << visport << endl;
|
||||
visualization = false;
|
||||
cout << "GLVis visualization disabled.\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
sout.precision(precision);
|
||||
sout << "solution\n" << *mesh << u_gf;
|
||||
sout << "pause\n";
|
||||
sout << flush;
|
||||
cout << "GLVis visualization paused."
|
||||
<< " Press space (in the GLVis window) to resume it.\n";
|
||||
}
|
||||
}
|
||||
|
||||
// 8. Perform time-integration (looping over the time iterations, ti, with a
|
||||
// time-step dt).
|
||||
cout << "Integrating the ODE ..." << endl;
|
||||
tic_toc.Clear();
|
||||
tic_toc.Start();
|
||||
ode_solver->Init(oper);
|
||||
double t = 0.0;
|
||||
|
||||
bool last_step = false;
|
||||
for (int ti = 1; !last_step; ti++)
|
||||
{
|
||||
double dt_real = min(dt, t_final - t);
|
||||
|
||||
// Note that since we are using the "one-step" mode of the SUNDIALS
|
||||
// solvers, they will, generally, step over the final time and will not
|
||||
// explicitly perform the interpolation to t_final as they do in the
|
||||
// "normal" step mode.
|
||||
|
||||
ode_solver->Step(u, t, dt_real);
|
||||
|
||||
last_step = (t >= t_final - 1e-8*dt);
|
||||
|
||||
if (last_step || (ti % vis_steps) == 0)
|
||||
{
|
||||
cout << "step " << ti << ", t = " << t << endl;
|
||||
if (cvode) { cvode->PrintInfo(); }
|
||||
if (arkode) { arkode->PrintInfo(); }
|
||||
|
||||
u_gf.SetFromTrueDofs(u);
|
||||
if (visualization)
|
||||
{
|
||||
sout << "solution\n" << *mesh << u_gf << flush;
|
||||
}
|
||||
|
||||
if (visit)
|
||||
{
|
||||
visit_dc.SetCycle(ti);
|
||||
visit_dc.SetTime(t);
|
||||
visit_dc.Save();
|
||||
}
|
||||
}
|
||||
oper.SetParameters(u);
|
||||
}
|
||||
tic_toc.Stop();
|
||||
cout << "Done, " << tic_toc.RealTime() << "s." << endl;
|
||||
|
||||
// 9. Save the final solution. This output can be viewed later using GLVis:
|
||||
// "glvis -m ex16.mesh -g ex16-final.gf".
|
||||
{
|
||||
ofstream osol("ex16-final.gf");
|
||||
osol.precision(precision);
|
||||
u_gf.Save(osol);
|
||||
}
|
||||
|
||||
// 10. Free the used memory.
|
||||
delete ode_solver;
|
||||
delete mesh;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ConductionOperator::ConductionOperator(FiniteElementSpace &f, double al,
|
||||
double kap, const Vector &u)
|
||||
: TimeDependentOperator(f.GetTrueVSize(), 0.0), fespace(f), M(NULL), K(NULL),
|
||||
T(NULL), current_dt(0.0), z(height)
|
||||
{
|
||||
const double rel_tol = 1e-8;
|
||||
|
||||
M = new BilinearForm(&fespace);
|
||||
M->AddDomainIntegrator(new MassIntegrator());
|
||||
M->Assemble();
|
||||
M->FormSystemMatrix(ess_tdof_list, Mmat);
|
||||
|
||||
M_solver.iterative_mode = false;
|
||||
M_solver.SetRelTol(rel_tol);
|
||||
M_solver.SetAbsTol(0.0);
|
||||
M_solver.SetMaxIter(50);
|
||||
M_solver.SetPrintLevel(0);
|
||||
M_solver.SetPreconditioner(M_prec);
|
||||
M_solver.SetOperator(Mmat);
|
||||
|
||||
alpha = al;
|
||||
kappa = kap;
|
||||
|
||||
T_solver.iterative_mode = false;
|
||||
T_solver.SetRelTol(rel_tol);
|
||||
T_solver.SetAbsTol(0.0);
|
||||
T_solver.SetMaxIter(100);
|
||||
T_solver.SetPrintLevel(0);
|
||||
T_solver.SetPreconditioner(T_prec);
|
||||
|
||||
SetParameters(u);
|
||||
}
|
||||
|
||||
void ConductionOperator::Mult(const Vector &u, Vector &du_dt) const
|
||||
{
|
||||
// Compute:
|
||||
// du_dt = M^{-1}*-K(u)
|
||||
// for du_dt
|
||||
Kmat.Mult(u, z);
|
||||
z.Neg(); // z = -z
|
||||
M_solver.Mult(z, du_dt);
|
||||
}
|
||||
|
||||
void ConductionOperator::ImplicitSolve(const double dt,
|
||||
const Vector &u, Vector &du_dt)
|
||||
{
|
||||
// Solve the equation:
|
||||
// du_dt = M^{-1}*[-K(u + dt*du_dt)]
|
||||
// for du_dt
|
||||
if (!T)
|
||||
{
|
||||
T = Add(1.0, Mmat, dt, Kmat);
|
||||
current_dt = dt;
|
||||
T_solver.SetOperator(*T);
|
||||
}
|
||||
MFEM_VERIFY(dt == current_dt, ""); // SDIRK methods use the same dt
|
||||
Kmat.Mult(u, z);
|
||||
z.Neg();
|
||||
T_solver.Mult(z, du_dt);
|
||||
}
|
||||
|
||||
void ConductionOperator::SundialsSolve(const double dt, Vector &b)
|
||||
{
|
||||
// Solve the system (M + dt K) y = M b. The result y replaces the input b.
|
||||
if (!T || dt != current_dt)
|
||||
{
|
||||
delete T;
|
||||
T = Add(1.0, Mmat, dt, Kmat);
|
||||
current_dt = dt;
|
||||
T_solver.SetOperator(*T);
|
||||
}
|
||||
Mmat.Mult(b, z);
|
||||
T_solver.Mult(z, b);
|
||||
}
|
||||
|
||||
void ConductionOperator::SetParameters(const Vector &u)
|
||||
{
|
||||
GridFunction u_alpha_gf(&fespace);
|
||||
u_alpha_gf.SetFromTrueDofs(u);
|
||||
for (int i = 0; i < u_alpha_gf.Size(); i++)
|
||||
{
|
||||
u_alpha_gf(i) = kappa + alpha*u_alpha_gf(i);
|
||||
}
|
||||
|
||||
delete K;
|
||||
K = new BilinearForm(&fespace);
|
||||
|
||||
GridFunctionCoefficient u_coeff(&u_alpha_gf);
|
||||
|
||||
K->AddDomainIntegrator(new DiffusionIntegrator(u_coeff));
|
||||
K->Assemble();
|
||||
K->FormSystemMatrix(ess_tdof_list, Kmat);
|
||||
delete T;
|
||||
T = NULL; // re-compute T on the next ImplicitSolve or SundialsSolve
|
||||
}
|
||||
|
||||
ConductionOperator::~ConductionOperator()
|
||||
{
|
||||
delete T;
|
||||
delete M;
|
||||
delete K;
|
||||
}
|
||||
|
||||
|
||||
int SundialsJacSolver::InitSystem(void *sundials_mem)
|
||||
{
|
||||
TimeDependentOperator *td_oper = GetTimeDependentOperator(sundials_mem);
|
||||
|
||||
// During development, we use dynamic_cast<> to ensure the setup is correct:
|
||||
oper = dynamic_cast<ConductionOperator*>(td_oper);
|
||||
MFEM_VERIFY(oper, "operator is not ConductionOperator");
|
||||
|
||||
// When the implementation is finalized, we can switch to static_cast<>:
|
||||
// oper = static_cast<ConductionOperator*>(td_oper);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SundialsJacSolver::SetupSystem(void *sundials_mem, int conv_fail,
|
||||
const Vector &y_pred, const Vector &f_pred,
|
||||
int &jac_cur, Vector &v_temp1,
|
||||
Vector &v_temp2, Vector &v_temp3)
|
||||
{
|
||||
jac_cur = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SundialsJacSolver::SolveSystem(void *sundials_mem, Vector &b,
|
||||
const Vector &weight, const Vector &y_cur,
|
||||
const Vector &f_cur)
|
||||
{
|
||||
oper->SundialsSolve(GetTimeStep(sundials_mem), b);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int SundialsJacSolver::FreeSystem(void *sundials_mem)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
double InitialTemperature(const Vector &x)
|
||||
{
|
||||
if (x.Norml2() < 0.5)
|
||||
{
|
||||
return 2.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1.0;
|
||||
}
|
||||
}
|
||||