Compare commits

..
305 changed files with 9145 additions and 116216 deletions
-49
View File
@@ -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
-167
View File
@@ -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*
+67 -230
View File
@@ -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
+7 -294
View File
@@ -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), 431448.
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 NavierStokes 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.
+46 -149
View File
@@ -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})
-538
View File
@@ -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.
+17 -128
View File
@@ -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.
+6 -11
View File
@@ -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
-182
View File
@@ -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()
+2 -13
View File
@@ -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}")
+5 -44
View File
@@ -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)
+1 -14
View File
@@ -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)
-16
View File
@@ -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()
-36
View File
@@ -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;
}
"
)
-29
View File
@@ -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
)
+44 -197
View File
@@ -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)
-6
View File
@@ -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
+5 -44
View File
@@ -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
-16
View File
@@ -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@
+11 -44
View File
@@ -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.")
+33 -115
View File
@@ -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
-48
View File
@@ -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
}
+5 -32
View File
@@ -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)
-525
View File
@@ -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
+7 -55
View File
@@ -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
-122
View File
@@ -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
-218
View File
@@ -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
-924
View File
@@ -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')
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -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
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -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
-45
View File
@@ -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
-45
View File
@@ -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
File diff suppressed because it is too large Load Diff
@@ -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
-147
View File
@@ -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
+7 -10
View File
@@ -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
+4 -24
View File
@@ -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
*
+6 -6
View File
@@ -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)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 KiB

+8 -20
View File
@@ -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)
+76 -303
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -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();
+23 -32
View File
@@ -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);
+22 -38
View File
@@ -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);
+18 -63
View File
@@ -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
+10 -11
View File
@@ -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
-1
View File
@@ -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.
-2
View File
@@ -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 -3
View File
@@ -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;
}
-309
View File
@@ -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;
}
-571
View File
@@ -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;
}
-364
View File
@@ -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;
}
-537
View File
@@ -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 &mu;
// 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];
}
-591
View File
@@ -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 &mu;
// 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];
}
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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
-7
View File
@@ -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.
-1
View File
@@ -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;
}
-3
View File
@@ -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);
+11 -40
View File
@@ -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.*
+40 -37
View File
@@ -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()
+23 -37
View File
@@ -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);
+2 -2
View File
@@ -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
+12 -28
View File
@@ -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.
+1 -1
View File
@@ -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);
+2 -8
View File
@@ -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;
+22 -31
View File
@@ -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.*
-3
View File
@@ -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
+3 -6
View File
@@ -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
-3
View File
@@ -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
+3 -6
View File
@@ -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
+4 -18
View File
@@ -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
-72
View File
@@ -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()
-18
View File
@@ -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.
-262
View File
@@ -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;
}
-292
View File
@@ -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;
}
-413
View File
@@ -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;
}
-387
View File
@@ -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;
}
-94
View File
@@ -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
+10 -10
View File
@@ -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()
+23 -31
View File
@@ -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);
+24 -49
View File
@@ -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);
-524
View File
@@ -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;
}
}

Some files were not shown because too many files have changed in this diff Show More