Compare commits
264
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d61e4807a | ||
|
|
29bf750349 | ||
|
|
97368ef77f | ||
|
|
2fbe31f57a | ||
|
|
d27ca5e40c | ||
|
|
fd9aa3afeb | ||
|
|
c9dd7fc319 | ||
|
|
893b127aed | ||
|
|
550f8b1844 | ||
|
|
761a9269c2 | ||
|
|
62b33689a5 | ||
|
|
bfdf9efe31 | ||
|
|
523cc56fe3 | ||
|
|
cad5015b15 | ||
|
|
eea8eb2185 | ||
|
|
8847515e10 | ||
|
|
77e891594c | ||
|
|
9e463e651f | ||
|
|
550013e3ca | ||
|
|
ca3153c960 | ||
|
|
22a2ff788b | ||
|
|
cd66c1dd39 | ||
|
|
eaa31ad517 | ||
|
|
59600de4e2 | ||
|
|
4ff1f83372 | ||
|
|
ed24bda6ba | ||
|
|
df73fff427 | ||
|
|
40e07a61c3 | ||
|
|
abd5c313d9 | ||
|
|
d949c58e7d | ||
|
|
11131bf004 | ||
|
|
76b79f5b0f | ||
|
|
955b1a8e78 | ||
|
|
e684c8d7bf | ||
|
|
0290cdf39f | ||
|
|
e785777248 | ||
|
|
577399cb45 | ||
|
|
58f8873b73 | ||
|
|
5feae230e2 | ||
|
|
be1d6582fc | ||
|
|
ee38e0bc9f | ||
|
|
39fd944dba | ||
|
|
1ace21502c | ||
|
|
7482db6bc0 | ||
|
|
3552fc6223 | ||
|
|
f950613551 | ||
|
|
1dcbb71b8a | ||
|
|
282f35f6e0 | ||
|
|
acafb9f51a | ||
|
|
91e027f3da | ||
|
|
14ffb48a7f | ||
|
|
adf023e004 | ||
|
|
1a3e725327 | ||
|
|
05381c7054 | ||
|
|
c0b2b60849 | ||
|
|
ff25ff7fc7 | ||
|
|
dbabb7b0f6 | ||
|
|
e67555245b | ||
|
|
e5629820e1 | ||
|
|
ebe26c548c | ||
|
|
d8c6edeb4a | ||
|
|
8ebd1614a3 | ||
|
|
dd905c22a1 | ||
|
|
be0751c4d2 | ||
|
|
3dc412dcc0 | ||
|
|
8a82a839bb | ||
|
|
22af5c49f3 | ||
|
|
0e0a2b1611 | ||
|
|
5ebce1f5e0 | ||
|
|
a88beec11e | ||
|
|
f46f27daac | ||
|
|
0824833e35 | ||
|
|
f03324b804 | ||
|
|
4884209327 | ||
|
|
fd809e44b5 | ||
|
|
5d466d9583 | ||
|
|
4eb307758e | ||
|
|
996842cb94 | ||
|
|
4d3b1fab9a | ||
|
|
e50bf78531 | ||
|
|
8a87fbffde | ||
|
|
fa3ded8e1a | ||
|
|
d73d29508b | ||
|
|
b8fb486ba5 | ||
|
|
eb651cd3fc | ||
|
|
3d62128f3a | ||
|
|
b79d47eb93 | ||
|
|
30f623bdad | ||
|
|
a7e2df44c6 | ||
|
|
4a4ed4c0c3 | ||
|
|
7b2e60490d | ||
|
|
0715efbaf9 | ||
|
|
0cdd280bb4 | ||
|
|
ce12d07d38 | ||
|
|
37757faaae | ||
|
|
ca14e8054a | ||
|
|
a0dec4d0fb | ||
|
|
787efc1f52 | ||
|
|
4a3c6794a0 | ||
|
|
c77e3318e9 | ||
|
|
59afdb57fc | ||
|
|
b1112870d1 | ||
|
|
954c5b7f04 | ||
|
|
7f515c1031 | ||
|
|
e48992b6e3 | ||
|
|
055efbad50 | ||
|
|
81e8551911 | ||
|
|
55fc5f2536 | ||
|
|
2886d5b08f | ||
|
|
b6b5e5f53e | ||
|
|
3e4784271a | ||
|
|
fb1d5b98dd | ||
|
|
55b058e498 | ||
|
|
601f1cfbfa | ||
|
|
1acffab78f | ||
|
|
6f2aebc7bb | ||
|
|
66fbfd2a41 | ||
|
|
da6de9371a | ||
|
|
a7efad3e4a | ||
|
|
0afab1d564 | ||
|
|
401a66040c | ||
|
|
93525246b0 | ||
|
|
d0661f2302 | ||
|
|
acacabd432 | ||
|
|
91615ed76b | ||
|
|
bd790b1996 | ||
|
|
d501e8c9f3 | ||
|
|
a818788468 | ||
|
|
15e3c5f821 | ||
|
|
50f8519818 | ||
|
|
79f2e1bd05 | ||
|
|
3d052b07a6 | ||
|
|
75f47a3deb | ||
|
|
f91d406ce3 | ||
|
|
d9e12f8c7e | ||
|
|
f212f83a13 | ||
|
|
56ebcb4016 | ||
|
|
7e89151592 | ||
|
|
878338b1a5 | ||
|
|
bba14e664e | ||
|
|
67da6e2d30 | ||
|
|
99e3fccd32 | ||
|
|
b0987500a4 | ||
|
|
d363dd71d4 | ||
|
|
b90140c46f | ||
|
|
386e342e68 | ||
|
|
78a1b093fe | ||
|
|
8d1a5dfa31 | ||
|
|
31ac08e6f2 | ||
|
|
1e76ed107a | ||
|
|
e09f9d8128 | ||
|
|
ec4fcba705 | ||
|
|
e4eb8aa6df | ||
|
|
1f4ead94a3 | ||
|
|
179fc91a55 | ||
|
|
4037e17135 | ||
|
|
67e8010987 | ||
|
|
48dd20d2e8 | ||
|
|
33427e3bcd | ||
|
|
e090a781a2 | ||
|
|
b62a60837a | ||
|
|
c94be388e1 | ||
|
|
37ddcfe14d | ||
|
|
37686b0321 | ||
|
|
293687453e | ||
|
|
d9d6807ad7 | ||
|
|
1a82b944dc | ||
|
|
656de6b184 | ||
|
|
0eaf88244b | ||
|
|
67401330d9 | ||
|
|
1287280696 | ||
|
|
78d65bd549 | ||
|
|
62bfbf8251 | ||
|
|
b004cf56fe | ||
|
|
717abb99a7 | ||
|
|
fa568f5d6e | ||
|
|
9921143298 | ||
|
|
324d66b0c7 | ||
|
|
ee335b1d08 | ||
|
|
b73e7a2eca | ||
|
|
f57edec989 | ||
|
|
99b0797c5b | ||
|
|
c74ef16efc | ||
|
|
1eeb2f4465 | ||
|
|
4b774a2667 | ||
|
|
7c6a445b6b | ||
|
|
036ab7f2fd | ||
|
|
5df5d039f0 | ||
|
|
dce6ebf20d | ||
|
|
15b684fe21 | ||
|
|
1bd99fd5dc | ||
|
|
165dea0c66 | ||
|
|
473240f1c2 | ||
|
|
bb0cae0619 | ||
|
|
6d1a1a19fe | ||
|
|
6601d3757b | ||
|
|
5252b05a79 | ||
|
|
de5c1c376b | ||
|
|
12c109f9e9 | ||
|
|
1007624ddb | ||
|
|
d65e45277b | ||
|
|
4824b02b48 | ||
|
|
ddecdf017f | ||
|
|
25e5327b6a | ||
|
|
c4fe5bcde1 | ||
|
|
dbf8797f2c | ||
|
|
7763533785 | ||
|
|
d5874e20e5 | ||
|
|
56dd3dd069 | ||
|
|
4e3f26c602 | ||
|
|
caeae60c12 | ||
|
|
92a8d83a14 | ||
|
|
134f97c0d8 | ||
|
|
5caeea07a0 | ||
|
|
e5c7383441 | ||
|
|
41e6d31236 | ||
|
|
a22eeeab5a | ||
|
|
e60e51db39 | ||
|
|
e17ee11dc1 | ||
|
|
4f00b2d6bb | ||
|
|
eba6d4805b | ||
|
|
482378c7ec | ||
|
|
d2cf23afde | ||
|
|
2b541c5e12 | ||
|
|
9e294fc98c | ||
|
|
aaa7fc536c | ||
|
|
1d3cbc5871 | ||
|
|
60ed92ab5a | ||
|
|
5560d92fab | ||
|
|
36650e8833 | ||
|
|
5dd5511fdd | ||
|
|
7ff222b79d | ||
|
|
72e42566a9 | ||
|
|
66e1b3641c | ||
|
|
c790490f91 | ||
|
|
4f34a3b696 | ||
|
|
9dfe4dc6f4 | ||
|
|
7474b3deb9 | ||
|
|
325479260c | ||
|
|
6ca81275dc | ||
|
|
00baeb86c3 | ||
|
|
54d850bbe1 | ||
|
|
c375afe382 | ||
|
|
3102f164d6 | ||
|
|
04acee1f28 | ||
|
|
71d87aa1f2 | ||
|
|
bcfe52d498 | ||
|
|
a8d474f3f6 | ||
|
|
6143572d6a | ||
|
|
f0a41dd3d6 | ||
|
|
7b3e124613 | ||
|
|
02b65854c2 | ||
|
|
ffea082dc9 | ||
|
|
9d79904c50 | ||
|
|
eb2017b5b5 | ||
|
|
c09d22b6c0 | ||
|
|
4b6ab370ca | ||
|
|
adb40b62f7 | ||
|
|
cfcbbfd6cf | ||
|
|
f36a7f40f2 | ||
|
|
0138d7fbd9 | ||
|
|
2ae20dde47 | ||
|
|
a360b53521 | ||
|
|
fb9a4d61d2 |
@@ -112,6 +112,15 @@ 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
|
||||
|
||||
@@ -8,11 +8,30 @@
|
||||
http://mfem.org
|
||||
|
||||
|
||||
Version 3.3.3 (development)
|
||||
Version 3.4.1 (development)
|
||||
===========================
|
||||
- Added support for reading linear and quadratic 2D quadrilateral and triangular
|
||||
Cubit meshes.
|
||||
|
||||
- The tetrahedral mesh refinement algorithm in serial and in parallel now
|
||||
follows precisely the paper:
|
||||
D. Arnold, A. Mukherjee, and L. Pouly, "Locally Adapted Tetrahedral Meshes
|
||||
Using Bisection", SIAM J. Sci. Comput., 22(2), 431–448.
|
||||
This guarantees that the shape regularity of the elements will be preserved
|
||||
under refinement.
|
||||
|
||||
|
||||
Version 3.4, released on May 29, 2018
|
||||
=====================================
|
||||
|
||||
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.
|
||||
|
||||
More efficient non-conforming adaptive mesh refinement
|
||||
------------------------------------------------------
|
||||
- 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
|
||||
@@ -54,8 +73,10 @@ Discretization improvements
|
||||
- In the classes NonlinearForm and ParNonlinearForm, added support for
|
||||
non-conforming AMR meshes; see also the "API changes" section.
|
||||
|
||||
- Added symplectic integrators of orders 1-4 for systems of first order ODEs
|
||||
derived from a Hamiltonian, see class SIASolver in linalg/ode.hpp.
|
||||
- New specialized time integrators: symplectic integrators of orders 1-4 for
|
||||
systems of first order ODEs derived from a Hamiltonian and generalized-alpha
|
||||
ODE solver for the filtered Navier–Stokes equations with stabilization. See
|
||||
classes SIASolver and GeneralizedAlphaSolver in linalg/ode.hpp.
|
||||
|
||||
- Inherit finite element classes from the new base class TensorBasisElement,
|
||||
whenever the basis can be represented by a tensor product of 1D bases.
|
||||
@@ -79,6 +100,11 @@ New and updated examples and miniapps
|
||||
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
|
||||
|
||||
+20
-4
@@ -45,7 +45,7 @@ project(mfem NONE)
|
||||
# Current version of MFEM, see also `makefile`.
|
||||
# mfem_VERSION = (string)
|
||||
# MFEM_VERSION = (int) [automatically derived from mfem_VERSION]
|
||||
set(${PROJECT_NAME}_VERSION 3.3.3)
|
||||
set(${PROJECT_NAME}_VERSION 3.4.1)
|
||||
|
||||
# Prohibit in-source build
|
||||
if (${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR})
|
||||
@@ -139,7 +139,7 @@ if (MFEM_USE_MPI)
|
||||
set(PETSC_INCLUDE_DIRS ${PETSC_INCLUDES})
|
||||
endif()
|
||||
else()
|
||||
set(PKGS_NEED_MPI SUPERLU PETSC STRUMPACK)
|
||||
set(PKGS_NEED_MPI SUPERLU PETSC STRUMPACK PUMI)
|
||||
foreach(PKG IN LISTS PKGS_NEED_MPI)
|
||||
if (MFEM_USE_${PKG})
|
||||
message(STATUS "Disabling package ${PKG} - requires MPI")
|
||||
@@ -246,6 +246,22 @@ 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)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# MFEM_TIMER_TYPE
|
||||
if (NOT DEFINED MFEM_TIMER_TYPE)
|
||||
if (APPLE)
|
||||
@@ -270,8 +286,8 @@ endif()
|
||||
# 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 POSIXCLOCKS
|
||||
MFEMBacktrace ZLIB)
|
||||
MESQUITE SuperLUDist STRUMPACK AXOM CONDUIT GECKO GNUTLS NETCDF MPFR PUMI
|
||||
POSIXCLOCKS MFEMBacktrace ZLIB)
|
||||
# Add all *_FOUND libraries in the variable TPL_LIBRARIES.
|
||||
set(TPL_LIBRARIES "")
|
||||
set(TPL_INCLUDE_DIRS "")
|
||||
|
||||
+103
-2
@@ -1,3 +1,15 @@
|
||||
<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
|
||||
@@ -16,6 +28,7 @@ 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)
|
||||
@@ -53,6 +66,94 @@ Origin](#developers-certificate-of-origin-11) at the end of this file.*
|
||||
- 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
|
||||
@@ -122,7 +223,7 @@ will allow us to reach you directly with project announcements.
|
||||
# Work on "feature-dev", add local commits
|
||||
# ...
|
||||
|
||||
# One time only) push the branch to github and setup your local
|
||||
# (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
|
||||
|
||||
@@ -332,7 +433,7 @@ MFEM uses a `master`/`next`-branch workflow as described below:
|
||||
- [ ] `CHANGELOG`
|
||||
- [ ] `makefile`
|
||||
- [ ] `CMakeLists.txt`
|
||||
- [ ] `doc/CodeDocumentation.conf`
|
||||
- [ ] `doc/CodeDocumentation.conf.in`
|
||||
- [ ] (LLNL only) Make sure all `README.html` files in the source repo are up to date.
|
||||
- [ ] Tag the repository:
|
||||
|
||||
|
||||
@@ -25,10 +25,16 @@ 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 Homebrew/Science, https://github.com/Homebrew/homebrew-science, and the
|
||||
Spack, https://github.com/LLNL/spack, package managers.
|
||||
In addition to the native build systems, MFEM packages are also available in the
|
||||
following 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
|
||||
=========================
|
||||
@@ -349,6 +355,13 @@ MFEM_USE_GZSTREAM = YES/NO
|
||||
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.
|
||||
Can be used to identify the MFEM build from other makefiles.
|
||||
@@ -458,6 +471,10 @@ The specific libraries and their options are:
|
||||
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.
|
||||
@@ -590,6 +607,7 @@ MFEM_USE_GNUTLS
|
||||
MFEM_USE_NETCDF
|
||||
MFEM_USE_MPFR
|
||||
MFEM_USE_GZSTREAM
|
||||
MFEM_USE_PUMI
|
||||
|
||||
The following options are CMake specific:
|
||||
|
||||
@@ -635,6 +653,7 @@ The CMake build system adds auto-detection for the following packages/libraries:
|
||||
- MPFR
|
||||
- LIBUNWIND
|
||||
- POSIXCLOCKS
|
||||
- PUMI
|
||||
|
||||
The following built-in CMake packages are also used:
|
||||
|
||||
|
||||
@@ -12,11 +12,15 @@ 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". Copyright
|
||||
information and licensing restrictions can be found in the file COPYRIGHT.
|
||||
* For building instructions, see the file INSTALL, or type "make help".
|
||||
|
||||
The best starting point for new users interested in MFEM's features is the
|
||||
interactive documentation in examples/README.html.
|
||||
* 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.
|
||||
|
||||
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
|
||||
@@ -56,7 +60,8 @@ 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. See LICENSE file for full
|
||||
details.
|
||||
This project is released under the LGPL v2.1 license with static linking
|
||||
exception. See files COPYRIGHT and LICENSE file for full details.
|
||||
|
||||
LLNL Release Number: LLNL-CODE-443211
|
||||
DOI: 10.11578/dc.20171025.1248
|
||||
|
||||
@@ -39,6 +39,7 @@ 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@")
|
||||
|
||||
@@ -98,6 +98,9 @@
|
||||
// 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.
|
||||
// If not defined, an option is selected automatically.
|
||||
@@ -113,4 +116,8 @@
|
||||
// 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
|
||||
|
||||
@@ -36,4 +36,7 @@
|
||||
#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
|
||||
|
||||
@@ -58,9 +58,6 @@
|
||||
// Use LAPACK routines for various dense linear algebra operations.
|
||||
// #define MFEM_USE_LAPACK
|
||||
|
||||
// Use Eigen for math routines
|
||||
// #define MFEM_USE_EIGEN
|
||||
|
||||
// Use thread-safe implementation. This comes at the cost of extra memory
|
||||
// allocation and de-allocation.
|
||||
// #define MFEM_THREAD_SAFE
|
||||
@@ -112,6 +109,9 @@
|
||||
// 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?)
|
||||
@@ -121,4 +121,8 @@
|
||||
// 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
|
||||
|
||||
+1
-1
@@ -21,7 +21,6 @@ MFEM_USE_EXCEPTIONS = @MFEM_USE_EXCEPTIONS@
|
||||
MFEM_USE_GZSTREAM = @MFEM_USE_GZSTREAM@
|
||||
MFEM_USE_LIBUNWIND = @MFEM_USE_LIBUNWIND@
|
||||
MFEM_USE_LAPACK = @MFEM_USE_LAPACK@
|
||||
MFEM_USE_EIGEN = @MFEM_USE_EIGEN@
|
||||
MFEM_THREAD_SAFE = @MFEM_THREAD_SAFE@
|
||||
MFEM_USE_OPENMP = @MFEM_USE_OPENMP@
|
||||
MFEM_USE_MEMALLOC = @MFEM_USE_MEMALLOC@
|
||||
@@ -38,6 +37,7 @@ 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@
|
||||
|
||||
@@ -40,6 +40,7 @@ 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)
|
||||
|
||||
# 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
|
||||
@@ -145,6 +146,9 @@ set(AXOM_DIR "${MFEM_DIR}/../axom" CACHE PATH "Path to the Axom library.")
|
||||
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(BLAS_INCLUDE_DIRS "" CACHE STRING "Path to BLAS headers.")
|
||||
set(BLAS_LIBRARIES "" CACHE STRING "The BLAS library.")
|
||||
set(LAPACK_INCLUDE_DIRS "" CACHE STRING "Path to LAPACK headers.")
|
||||
|
||||
+9
-7
@@ -21,7 +21,7 @@ NOTMAC := $(subst Darwin,,$(shell uname -s))
|
||||
CXX = g++
|
||||
MPICXX = mpicxx
|
||||
|
||||
OPTIM_FLAGS = -O3 -pg
|
||||
OPTIM_FLAGS = -O3
|
||||
DEBUG_FLAGS = -g -Wall
|
||||
|
||||
# Destination location of make install
|
||||
@@ -90,7 +90,6 @@ MFEM_USE_EXCEPTIONS = NO
|
||||
MFEM_USE_GZSTREAM = NO
|
||||
MFEM_USE_LIBUNWIND = NO
|
||||
MFEM_USE_LAPACK = NO
|
||||
MFEM_USE_EIGEN = NO
|
||||
MFEM_THREAD_SAFE = NO
|
||||
MFEM_USE_OPENMP = NO
|
||||
MFEM_USE_MEMALLOC = YES
|
||||
@@ -107,6 +106,7 @@ 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 =
|
||||
@@ -146,11 +146,6 @@ endif
|
||||
LAPACK_OPT =
|
||||
LAPACK_LIB = $(if $(NOTMAC),-llapack -lblas,-framework Accelerate)
|
||||
|
||||
# Eigen configuration
|
||||
EIGEN_DIR = @MFEM_DIR@/../eigen
|
||||
EIGEN_OPT = -I$(EIGEN_DIR) -std=c++11 -Wno-enum-compare
|
||||
EIGEN_LIB =
|
||||
|
||||
# OpenMP configuration
|
||||
OPENMP_OPT = -fopenmp
|
||||
OPENMP_LIB =
|
||||
@@ -277,6 +272,13 @@ SIDRE_LIB = \
|
||||
-Wl,-rpath,$(HDF5_DIR)/lib -L$(HDF5_DIR)/lib \
|
||||
-lsidre -lslic -laxom_utils -lconduit -lconduit_relay -lhdf5 $(ZLIB_LIB) -ldl
|
||||
|
||||
# PUMI
|
||||
# Note that PUMI_DIR is needed -- it is used to check for gmi_sim.h
|
||||
PUMI_DIR = @MFEM_DIR@/../pumi-2.1.0
|
||||
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
|
||||
|
||||
# If YES, enable some informational messages
|
||||
VERBOSE = NO
|
||||
|
||||
|
||||
+11
-2
@@ -38,6 +38,9 @@ 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 ...)
|
||||
@@ -52,10 +55,16 @@ get-hypre-version: $(GHV).out
|
||||
$(info HYPRE version: $(MFEM_HYPRE_VERSION)),\
|
||||
$(error Unable to determine HYPRE version))
|
||||
|
||||
header: $(if $(MPI),get-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)
|
||||
$(call mfem-info, Writing $(CONFIG_HPP) ...)
|
||||
@set -- && \
|
||||
for def in $${MFEM_DEFINES} $(if $(MPI),MFEM_HYPRE_VERSION,); do \
|
||||
for def in $${MFEM_DEFINES} $(if $(MPI),MFEM_HYPRE_VERSION) $(SMX); do \
|
||||
eval var=\$$$$def && \
|
||||
if [ "NO" != "$${var}" ]; then \
|
||||
set -- "$$@" -e "s|// \(#define $${def} \)|\1|" && \
|
||||
|
||||
@@ -14,11 +14,13 @@
|
||||
# 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
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
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
|
||||
@@ -0,0 +1,74 @@
|
||||
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
|
||||
@@ -0,0 +1,924 @@
|
||||
#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
@@ -0,0 +1,264 @@
|
||||
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
@@ -0,0 +1,72 @@
|
||||
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
|
||||
@@ -0,0 +1,362 @@
|
||||
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
|
||||
@@ -0,0 +1,66 @@
|
||||
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
|
||||
@@ -0,0 +1,45 @@
|
||||
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
|
||||
@@ -0,0 +1,45 @@
|
||||
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
@@ -0,0 +1,57 @@
|
||||
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
|
||||
@@ -0,0 +1,147 @@
|
||||
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
|
||||
@@ -0,0 +1,73 @@
|
||||
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
|
||||
@@ -0,0 +1,567 @@
|
||||
MFEM mesh v1.0
|
||||
|
||||
dimension
|
||||
2
|
||||
|
||||
elements
|
||||
128
|
||||
1 2 0 1 2
|
||||
1 2 1 4 2
|
||||
1 2 1 3 4
|
||||
1 2 2 4 5
|
||||
1 2 3 7 4
|
||||
1 2 3 6 7
|
||||
1 2 4 8 5
|
||||
1 2 4 7 8
|
||||
1 2 5 8 9
|
||||
1 2 6 11 7
|
||||
1 2 6 10 11
|
||||
1 2 7 12 8
|
||||
1 2 7 11 12
|
||||
1 2 8 13 9
|
||||
1 2 8 12 13
|
||||
1 2 9 13 14
|
||||
2 3 10 15 16 11
|
||||
2 3 11 16 17 12
|
||||
2 3 12 17 18 13
|
||||
2 3 13 18 19 14
|
||||
2 3 15 20 21 16
|
||||
2 3 16 21 22 17
|
||||
2 3 17 22 23 18
|
||||
2 3 18 23 24 19
|
||||
2 3 20 25 26 21
|
||||
2 3 21 26 27 22
|
||||
2 3 22 27 28 23
|
||||
2 3 23 28 29 24
|
||||
2 3 25 30 31 26
|
||||
2 3 26 31 32 27
|
||||
2 3 27 32 33 28
|
||||
2 3 28 33 34 29
|
||||
1 2 0 2 35
|
||||
1 2 35 2 37
|
||||
1 2 35 37 36
|
||||
1 2 2 5 37
|
||||
1 2 36 37 39
|
||||
1 2 36 39 38
|
||||
1 2 37 5 40
|
||||
1 2 37 40 39
|
||||
1 2 5 9 40
|
||||
1 2 38 39 42
|
||||
1 2 38 42 41
|
||||
1 2 39 40 43
|
||||
1 2 39 43 42
|
||||
1 2 40 9 44
|
||||
1 2 40 44 43
|
||||
1 2 9 14 44
|
||||
2 3 41 42 46 45
|
||||
2 3 42 43 47 46
|
||||
2 3 43 44 48 47
|
||||
2 3 44 14 19 48
|
||||
2 3 45 46 50 49
|
||||
2 3 46 47 51 50
|
||||
2 3 47 48 52 51
|
||||
2 3 48 19 24 52
|
||||
2 3 49 50 54 53
|
||||
2 3 50 51 55 54
|
||||
2 3 51 52 56 55
|
||||
2 3 52 24 29 56
|
||||
2 3 53 54 58 57
|
||||
2 3 54 55 59 58
|
||||
2 3 55 56 60 59
|
||||
2 3 56 29 34 60
|
||||
1 2 0 61 1
|
||||
1 2 1 61 62
|
||||
1 2 1 62 3
|
||||
1 2 61 63 62
|
||||
1 2 3 62 64
|
||||
1 2 3 64 6
|
||||
1 2 62 63 65
|
||||
1 2 62 65 64
|
||||
1 2 63 66 65
|
||||
1 2 6 64 67
|
||||
1 2 6 67 10
|
||||
1 2 64 65 68
|
||||
1 2 64 68 67
|
||||
1 2 65 66 69
|
||||
1 2 65 69 68
|
||||
1 2 66 70 69
|
||||
2 3 10 67 71 15
|
||||
2 3 67 68 72 71
|
||||
2 3 68 69 73 72
|
||||
2 3 69 70 74 73
|
||||
2 3 15 71 75 20
|
||||
2 3 71 72 76 75
|
||||
2 3 72 73 77 76
|
||||
2 3 73 74 78 77
|
||||
2 3 20 75 79 25
|
||||
2 3 75 76 80 79
|
||||
2 3 76 77 81 80
|
||||
2 3 77 78 82 81
|
||||
2 3 25 79 83 30
|
||||
2 3 79 80 84 83
|
||||
2 3 80 81 85 84
|
||||
2 3 81 82 86 85
|
||||
1 2 0 35 61
|
||||
1 2 35 87 61
|
||||
1 2 35 36 87
|
||||
1 2 61 87 63
|
||||
1 2 36 88 87
|
||||
1 2 36 38 88
|
||||
1 2 87 89 63
|
||||
1 2 87 88 89
|
||||
1 2 63 89 66
|
||||
1 2 38 90 88
|
||||
1 2 38 41 90
|
||||
1 2 88 91 89
|
||||
1 2 88 90 91
|
||||
1 2 89 92 66
|
||||
1 2 89 91 92
|
||||
1 2 66 92 70
|
||||
2 3 41 45 93 90
|
||||
2 3 90 93 94 91
|
||||
2 3 91 94 95 92
|
||||
2 3 92 95 74 70
|
||||
2 3 45 49 96 93
|
||||
2 3 93 96 97 94
|
||||
2 3 94 97 98 95
|
||||
2 3 95 98 78 74
|
||||
2 3 49 53 99 96
|
||||
2 3 96 99 100 97
|
||||
2 3 97 100 101 98
|
||||
2 3 98 101 82 78
|
||||
2 3 53 102 103 99
|
||||
2 3 99 103 104 100
|
||||
2 3 100 104 105 101
|
||||
2 3 101 105 86 82
|
||||
|
||||
boundary
|
||||
16
|
||||
1 1 30 31
|
||||
1 1 31 32
|
||||
1 1 32 33
|
||||
1 1 33 34
|
||||
1 1 34 60
|
||||
1 1 60 59
|
||||
1 1 59 58
|
||||
1 1 58 57
|
||||
1 1 102 103
|
||||
1 1 103 104
|
||||
1 1 104 105
|
||||
1 1 105 86
|
||||
1 1 86 85
|
||||
1 1 85 84
|
||||
1 1 84 83
|
||||
1 1 83 30
|
||||
|
||||
vertices
|
||||
106
|
||||
|
||||
nodes
|
||||
FiniteElementSpace
|
||||
FiniteElementCollection: H1_2D_P2
|
||||
VDim: 2
|
||||
Ordering: 1
|
||||
|
||||
0.0 0.0
|
||||
0.25 0.0
|
||||
0.0 0.25
|
||||
0.5 0.0
|
||||
0.35355 0.35355
|
||||
0.0 0.5
|
||||
0.75 0.0
|
||||
0.64952 0.375
|
||||
0.375 0.64952
|
||||
0.0 0.75
|
||||
1.0 0.0
|
||||
0.92388 0.38268
|
||||
0.70711 0.70711
|
||||
0.38268 0.92388
|
||||
0.0 1.0
|
||||
1.25 0.0
|
||||
1.19291 0.53701
|
||||
1.03033 1.03033
|
||||
0.53701 1.19291
|
||||
0.0 1.25
|
||||
1.5 0.0
|
||||
1.46194 0.69134
|
||||
1.35355 1.35355
|
||||
0.69134 1.46194
|
||||
0.0 1.5
|
||||
1.75 0.0
|
||||
1.73097 0.84567
|
||||
1.67678 1.67678
|
||||
0.84567 1.73097
|
||||
0.0 1.75
|
||||
2.0 0.0
|
||||
2.0 1.0
|
||||
2.0 2.0
|
||||
1.0 2.0
|
||||
0.0 2.0
|
||||
-0.25 0.0
|
||||
-0.5 0.0
|
||||
-0.35355 0.35355
|
||||
-0.75 0.0
|
||||
-0.64952 0.375
|
||||
-0.375 0.64952
|
||||
-1.0 0.0
|
||||
-0.92388 0.38268
|
||||
-0.70711 0.70711
|
||||
-0.38268 0.92388
|
||||
-1.25 0.0
|
||||
-1.19291 0.53701
|
||||
-1.03033 1.03033
|
||||
-0.53701 1.19291
|
||||
-1.5 0.0
|
||||
-1.46194 0.69134
|
||||
-1.35355 1.35355
|
||||
-0.69134 1.46194
|
||||
-1.75 0.0
|
||||
-1.73097 0.84567
|
||||
-1.67678 1.67678
|
||||
-0.84567 1.73097
|
||||
-2.0 0.0
|
||||
-2.0 1.0
|
||||
-2.0 2.0
|
||||
-1.0 2.0
|
||||
0.0 -0.25
|
||||
0.35355 -0.35355
|
||||
0.0 -0.5
|
||||
0.64952 -0.375
|
||||
0.375 -0.64952
|
||||
0.0 -0.75
|
||||
0.92388 -0.38268
|
||||
0.70711 -0.70711
|
||||
0.38268 -0.92388
|
||||
0.0 -1.0
|
||||
1.19291 -0.53701
|
||||
1.03033 -1.03033
|
||||
0.53701 -1.19291
|
||||
0.0 -1.25
|
||||
1.46194 -0.69134
|
||||
1.35355 -1.35355
|
||||
0.69134 -1.46194
|
||||
0.0 -1.5
|
||||
1.73097 -0.84567
|
||||
1.67678 -1.67678
|
||||
0.84567 -1.73097
|
||||
0.0 -1.75
|
||||
2.0 -1.0
|
||||
2.0 -2.0
|
||||
1.0 -2.0
|
||||
0.0 -2.0
|
||||
-0.35355 -0.35355
|
||||
-0.64952 -0.375
|
||||
-0.375 -0.64952
|
||||
-0.92388 -0.38268
|
||||
-0.70711 -0.70711
|
||||
-0.38268 -0.92388
|
||||
-1.19291 -0.53701
|
||||
-1.03033 -1.03033
|
||||
-0.53701 -1.19291
|
||||
-1.46194 -0.69134
|
||||
-1.35355 -1.35355
|
||||
-0.69134 -1.46194
|
||||
-1.73097 -0.84567
|
||||
-1.67678 -1.67678
|
||||
-0.84567 -1.73097
|
||||
-2.0 -0.0
|
||||
-2.0 -1.0
|
||||
-2.0 -2.0
|
||||
-1.0 -2.0
|
||||
0.125 0.0
|
||||
0.17678 0.17678
|
||||
0.0 0.125
|
||||
0.32357 0.18954
|
||||
0.18954 0.32357
|
||||
0.375 0.0
|
||||
0.46194 0.19134
|
||||
0.19134 0.46194
|
||||
0.0 0.375
|
||||
0.59418 0.19384
|
||||
0.50569 0.36729
|
||||
0.625 0.0
|
||||
0.72444 0.19411
|
||||
0.36729 0.50569
|
||||
0.19384 0.59418
|
||||
0.53033 0.53033
|
||||
0.19411 0.72444
|
||||
0.0 0.625
|
||||
0.85299 0.19501
|
||||
0.78835 0.37964
|
||||
0.875 0.0
|
||||
0.98079 0.19509
|
||||
0.68405 0.54563
|
||||
0.54563 0.68405
|
||||
0.83147 0.55557
|
||||
0.37964 0.78835
|
||||
0.19501 0.85299
|
||||
0.55557 0.83147
|
||||
0.19509 0.98079
|
||||
0.0 0.875
|
||||
1.125 0.0
|
||||
1.24928 0.27462
|
||||
1.05851 0.4599
|
||||
1.13007 0.79668
|
||||
0.86872 0.86872
|
||||
0.79668 1.13007
|
||||
0.4599 1.05851
|
||||
0.27462 1.24928
|
||||
0.0 1.125
|
||||
1.375 0.0
|
||||
1.51779 0.35426
|
||||
1.32748 0.6142
|
||||
1.42864 1.03762
|
||||
1.19194 1.19194
|
||||
1.03762 1.42864
|
||||
0.6142 1.32748
|
||||
0.35426 1.51779
|
||||
0.0 1.375
|
||||
1.625 0.0
|
||||
1.78629 0.43396
|
||||
1.59649 0.76852
|
||||
1.72721 1.2785
|
||||
1.51516 1.51516
|
||||
1.2785 1.72721
|
||||
0.76852 1.59649
|
||||
0.43396 1.78629
|
||||
0.0 1.625
|
||||
1.875 0.0
|
||||
2.0 0.5
|
||||
1.8655 0.92284
|
||||
2.0 1.5
|
||||
1.83839 1.83839
|
||||
1.5 2.0
|
||||
0.92284 1.8655
|
||||
0.5 2.0
|
||||
0.0 1.875
|
||||
-0.17678 0.17678
|
||||
-0.125 0.0
|
||||
-0.18954 0.32357
|
||||
-0.32357 0.18954
|
||||
-0.46194 0.19134
|
||||
-0.375 0.0
|
||||
-0.19134 0.46194
|
||||
-0.50569 0.36729
|
||||
-0.59418 0.19384
|
||||
-0.72444 0.19411
|
||||
-0.625 0.0
|
||||
-0.19384 0.59418
|
||||
-0.36729 0.50569
|
||||
-0.53033 0.53033
|
||||
-0.19411 0.72444
|
||||
-0.78835 0.37964
|
||||
-0.85299 0.19501
|
||||
-0.98079 0.19509
|
||||
-0.875 0.0
|
||||
-0.54563 0.68405
|
||||
-0.68405 0.54563
|
||||
-0.83147 0.55557
|
||||
-0.19501 0.85299
|
||||
-0.37964 0.78835
|
||||
-0.55557 0.83147
|
||||
-0.19509 0.98079
|
||||
-1.05851 0.4599
|
||||
-1.24928 0.27462
|
||||
-1.125 0.0
|
||||
-0.86872 0.86872
|
||||
-1.13007 0.79668
|
||||
-0.4599 1.05851
|
||||
-0.79668 1.13007
|
||||
-0.27462 1.24928
|
||||
-1.32748 0.6142
|
||||
-1.51779 0.35426
|
||||
-1.375 0.0
|
||||
-1.19194 1.19194
|
||||
-1.42864 1.03762
|
||||
-0.6142 1.32748
|
||||
-1.03762 1.42864
|
||||
-0.35426 1.51779
|
||||
-1.59649 0.76852
|
||||
-1.78629 0.43396
|
||||
-1.625 0.0
|
||||
-1.51516 1.51516
|
||||
-1.72721 1.2785
|
||||
-0.76852 1.59649
|
||||
-1.2785 1.72721
|
||||
-0.43396 1.78629
|
||||
-1.8655 0.92284
|
||||
-2.0 0.5
|
||||
-1.875 0.0
|
||||
-1.83839 1.83839
|
||||
-2.0 1.5
|
||||
-0.92284 1.8655
|
||||
-1.5 2.0
|
||||
-0.5 2.0
|
||||
0.0 -0.125
|
||||
0.17678 -0.17678
|
||||
0.18954 -0.32357
|
||||
0.32357 -0.18954
|
||||
0.46194 -0.19134
|
||||
0.0 -0.375
|
||||
0.19134 -0.46194
|
||||
0.50569 -0.36729
|
||||
0.59418 -0.19384
|
||||
0.72444 -0.19411
|
||||
0.19384 -0.59418
|
||||
0.36729 -0.50569
|
||||
0.53033 -0.53033
|
||||
0.0 -0.625
|
||||
0.19411 -0.72444
|
||||
0.78835 -0.37964
|
||||
0.85299 -0.19501
|
||||
0.98079 -0.19509
|
||||
0.54563 -0.68405
|
||||
0.68405 -0.54563
|
||||
0.83147 -0.55557
|
||||
0.19501 -0.85299
|
||||
0.37964 -0.78835
|
||||
0.55557 -0.83147
|
||||
0.0 -0.875
|
||||
0.19509 -0.98079
|
||||
1.05851 -0.4599
|
||||
1.24928 -0.27462
|
||||
0.86872 -0.86872
|
||||
1.13007 -0.79668
|
||||
0.4599 -1.05851
|
||||
0.79668 -1.13007
|
||||
0.0 -1.125
|
||||
0.27462 -1.24928
|
||||
1.32748 -0.6142
|
||||
1.51779 -0.35426
|
||||
1.19194 -1.19194
|
||||
1.42864 -1.03762
|
||||
0.6142 -1.32748
|
||||
1.03762 -1.42864
|
||||
0.0 -1.375
|
||||
0.35426 -1.51779
|
||||
1.59649 -0.76852
|
||||
1.78629 -0.43396
|
||||
1.51516 -1.51516
|
||||
1.72721 -1.2785
|
||||
0.76852 -1.59649
|
||||
1.2785 -1.72721
|
||||
0.0 -1.625
|
||||
0.43396 -1.78629
|
||||
1.8655 -0.92284
|
||||
2.0 -0.5
|
||||
1.83839 -1.83839
|
||||
2.0 -1.5
|
||||
0.92284 -1.8655
|
||||
1.5 -2.0
|
||||
0.0 -1.875
|
||||
0.5 -2.0
|
||||
-0.17678 -0.17678
|
||||
-0.32357 -0.18954
|
||||
-0.18954 -0.32357
|
||||
-0.46194 -0.19134
|
||||
-0.19134 -0.46194
|
||||
-0.59418 -0.19384
|
||||
-0.50569 -0.36729
|
||||
-0.72444 -0.19411
|
||||
-0.36729 -0.50569
|
||||
-0.19384 -0.59418
|
||||
-0.53033 -0.53033
|
||||
-0.19411 -0.72444
|
||||
-0.85299 -0.19501
|
||||
-0.78835 -0.37964
|
||||
-0.98079 -0.19509
|
||||
-0.68405 -0.54563
|
||||
-0.54563 -0.68405
|
||||
-0.83147 -0.55557
|
||||
-0.37964 -0.78835
|
||||
-0.19501 -0.85299
|
||||
-0.55557 -0.83147
|
||||
-0.19509 -0.98079
|
||||
-1.24928 -0.27462
|
||||
-1.05851 -0.4599
|
||||
-1.13007 -0.79668
|
||||
-0.86872 -0.86872
|
||||
-0.79668 -1.13007
|
||||
-0.4599 -1.05851
|
||||
-0.27462 -1.24928
|
||||
-1.51779 -0.35426
|
||||
-1.32748 -0.6142
|
||||
-1.42864 -1.03762
|
||||
-1.19194 -1.19194
|
||||
-1.03762 -1.42864
|
||||
-0.6142 -1.32748
|
||||
-0.35426 -1.51779
|
||||
-1.78629 -0.43396
|
||||
-1.59649 -0.76852
|
||||
-1.72721 -1.2785
|
||||
-1.51516 -1.51516
|
||||
-1.2785 -1.72721
|
||||
-0.76852 -1.59649
|
||||
-0.43396 -1.78629
|
||||
-1.875 0.0
|
||||
-2.0 -0.5
|
||||
-1.8655 -0.92284
|
||||
-2.0 -1.5
|
||||
-1.83839 -1.83839
|
||||
-1.5 -2.0
|
||||
-0.92284 -1.8655
|
||||
-0.5 -2.0
|
||||
1.0917 0.22992
|
||||
0.96356 0.66428
|
||||
0.66428 0.96356
|
||||
0.22992 1.0917
|
||||
1.35121 0.30709
|
||||
1.25968 0.90306
|
||||
0.90306 1.25968
|
||||
0.30709 1.35121
|
||||
1.61073 0.38425
|
||||
1.55581 1.14184
|
||||
1.14184 1.55581
|
||||
0.38425 1.61073
|
||||
1.87024 0.46142
|
||||
1.85194 1.38061
|
||||
1.38061 1.85194
|
||||
0.46142 1.87024
|
||||
-1.0917 0.22992
|
||||
-0.96356 0.66428
|
||||
-0.66428 0.96356
|
||||
-0.22992 1.0917
|
||||
-1.35121 0.30709
|
||||
-1.25968 0.90306
|
||||
-0.90306 1.25968
|
||||
-0.30709 1.35121
|
||||
-1.61073 0.38425
|
||||
-1.55581 1.14184
|
||||
-1.14184 1.55581
|
||||
-0.38425 1.61073
|
||||
-1.87024 0.46142
|
||||
-1.85194 1.38061
|
||||
-1.38061 1.85194
|
||||
-0.46142 1.87024
|
||||
1.0917 -0.22992
|
||||
0.96356 -0.66428
|
||||
0.66428 -0.96356
|
||||
0.22992 -1.0917
|
||||
1.35121 -0.30709
|
||||
1.25968 -0.90306
|
||||
0.90306 -1.25968
|
||||
0.30709 -1.35121
|
||||
1.61073 -0.38425
|
||||
1.55581 -1.14184
|
||||
1.14184 -1.55581
|
||||
0.38425 -1.61073
|
||||
1.87024 -0.46142
|
||||
1.85194 -1.38061
|
||||
1.38061 -1.85194
|
||||
0.46142 -1.87024
|
||||
-1.0917 -0.22992
|
||||
-0.96356 -0.66428
|
||||
-0.66428 -0.96356
|
||||
-0.22992 -1.0917
|
||||
-1.35121 -0.30709
|
||||
-1.25968 -0.90306
|
||||
-0.90306 -1.25968
|
||||
-0.30709 -1.35121
|
||||
-1.61073 -0.38425
|
||||
-1.55581 -1.14184
|
||||
-1.14184 -1.55581
|
||||
-0.38425 -1.61073
|
||||
-1.87024 -0.46142
|
||||
-1.85194 -1.38061
|
||||
-1.38061 -1.85194
|
||||
-0.46142 -1.87024
|
||||
@@ -38,7 +38,7 @@ PROJECT_NAME = "MFEM"
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = v3.3.3
|
||||
PROJECT_NUMBER = v3.4.1
|
||||
|
||||
# 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
|
||||
@@ -767,6 +767,7 @@ 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 \
|
||||
|
||||
@@ -36,8 +36,8 @@ namespace mfem {
|
||||
* - HypreSolver and other \link hypre.hpp hypre classes\endlink
|
||||
*
|
||||
* <H3>Example codes</H3>
|
||||
* - <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="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="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="ex11p_8cpp_source.html">Example 11p</a>: parallel Laplace eigensolver
|
||||
* - <a class="el" href="examples_2ex11p_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
|
||||
@@ -96,6 +96,15 @@ 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
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 44 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 51 KiB |
@@ -25,6 +25,7 @@ list(APPEND ALL_EXE_SRCS
|
||||
ex16.cpp
|
||||
ex17.cpp
|
||||
ex18.cpp
|
||||
ex19.cpp
|
||||
)
|
||||
|
||||
if (MFEM_USE_MPI)
|
||||
@@ -47,6 +48,7 @@ if (MFEM_USE_MPI)
|
||||
ex16p.cpp
|
||||
ex17p.cpp
|
||||
ex18p.cpp
|
||||
ex19p.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -61,8 +63,6 @@ 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 +70,7 @@ foreach(SRC_FILE ${ALL_EXE_SRCS})
|
||||
list(APPEND THIS_TEST_OPTIONS "-e" "1")
|
||||
endif()
|
||||
|
||||
if (is_parallel_test EQUAL -1)
|
||||
if (NOT (${TEST_NAME} MATCHES ".*p$"))
|
||||
add_test(NAME ${TEST_NAME}_ser
|
||||
COMMAND ${TEST_NAME} ${THIS_TEST_OPTIONS})
|
||||
else()
|
||||
@@ -91,3 +91,8 @@ endif()
|
||||
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()
|
||||
|
||||
+160
-77
File diff suppressed because one or more lines are too long
+16
-46
@@ -48,9 +48,7 @@ int main(int argc, char *argv[])
|
||||
const char *mesh_file = "../data/star.mesh";
|
||||
int order = 1;
|
||||
bool static_cond = false;
|
||||
bool visualization = true;
|
||||
bool use_partial_assembly = false;
|
||||
bool use_smoother = true;
|
||||
bool visualization = 1;
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
args.AddOption(&mesh_file, "-m", "--mesh",
|
||||
@@ -58,12 +56,8 @@ int main(int argc, char *argv[])
|
||||
args.AddOption(&order, "-o", "--order",
|
||||
"Finite element order (polynomial degree) or -1 for"
|
||||
" isoparametric space.");
|
||||
args.AddOption(&use_partial_assembly, "-pa", "--partial-assembly",
|
||||
"-no-pa", "--no-partial-assembly", "Enable partial assembly.");
|
||||
args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
|
||||
"--no-static-condensation", "Enable static condensation.");
|
||||
args.AddOption(&use_smoother, "-pc", "--peconditioner", "-no-pc",
|
||||
"--no-preconditioner", "Use a Gauss-Seidel preconditioner.");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
@@ -86,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 =
|
||||
(int)floor(log(50000./mesh->GetNE())/log(2.)/dim);
|
||||
int ref_levels = 0;
|
||||
//(int)floor(log(50000./mesh->GetNE())/log(2.)/dim);
|
||||
for (int l = 0; l < ref_levels; l++)
|
||||
{
|
||||
mesh->UniformRefinement();
|
||||
@@ -144,56 +138,33 @@ int main(int argc, char *argv[])
|
||||
// 8. Set up the bilinear form a(.,.) on the finite element space
|
||||
// corresponding to the Laplacian operator -Delta, by adding the Diffusion
|
||||
// domain integrator.
|
||||
Vector B, X;
|
||||
BilinearForm *a = new BilinearForm(fespace);
|
||||
a->AddDomainIntegrator(new DiffusionIntegrator(one));
|
||||
|
||||
BilinearFormOperator A_pa(new PAIntegratorMap);
|
||||
SparseMatrix A_sp;
|
||||
if (!use_partial_assembly)
|
||||
{
|
||||
a->AssembleForm(A_sp);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Can add a custom FESpaceIntegrator in this way:
|
||||
// a->AddIntegrator(new PADiffusionIntegrator(new DiffusionIntegrator(one)));
|
||||
a->AssembleForm(A_pa);
|
||||
}
|
||||
|
||||
Operator *A;
|
||||
a->FormLinearSystem(ess_tdof_list, x, *b, A, X, B);
|
||||
|
||||
// 9. 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();
|
||||
|
||||
cout << "Size of linear system: " << A->Height() << endl;
|
||||
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
|
||||
// 10. Define a simple symmetric Gauss-Seidel preconditioner and use it to
|
||||
// solve the system A X = B with PCG.
|
||||
|
||||
if (use_smoother && !use_partial_assembly)
|
||||
{
|
||||
GSSmoother M(A_sp);
|
||||
PCG(*A, M, B, X, 1, 200, 1e-12, 0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
CG(*A, B, X, 1, 200, 1e-12, 0.0);
|
||||
}
|
||||
|
||||
GSSmoother M(A);
|
||||
PCG(A, M, B, X, 1, 200, 1e-12, 0.0);
|
||||
#else
|
||||
// 10. If MFEM was compiled with SuiteSparse, use UMFPACK to solve the system.
|
||||
if (!use_partial_assembly)
|
||||
{
|
||||
UMFPackSolver umf_solver;
|
||||
umf_solver.Control[UMFPACK_ORDERING] = UMFPACK_ORDERING_METIS;
|
||||
umf_solver.SetOperator(A_sp);
|
||||
umf_solver.Mult(B, X);
|
||||
}
|
||||
UMFPackSolver umf_solver;
|
||||
umf_solver.Control[UMFPACK_ORDERING] = UMFPACK_ORDERING_METIS;
|
||||
umf_solver.SetOperator(A);
|
||||
umf_solver.Mult(B, X);
|
||||
#endif
|
||||
|
||||
// 11. Recover the solution as a finite element grid function.
|
||||
@@ -219,7 +190,6 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// 14. Free the used memory.
|
||||
delete A;
|
||||
delete a;
|
||||
delete b;
|
||||
delete fespace;
|
||||
|
||||
@@ -222,6 +222,7 @@ 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;
|
||||
|
||||
@@ -244,6 +244,7 @@ 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;
|
||||
|
||||
@@ -110,6 +110,7 @@ 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.
|
||||
|
||||
+19
-95
@@ -35,10 +35,6 @@
|
||||
using namespace std;
|
||||
using namespace mfem;
|
||||
|
||||
bool partial_assembly_mass;
|
||||
bool partial_assembly_diff;
|
||||
bool preconditioner;
|
||||
|
||||
/** After spatial discretization, the conduction model can be written as:
|
||||
*
|
||||
* du/dt = M^{-1}(-Ku)
|
||||
@@ -58,8 +54,6 @@ protected:
|
||||
BilinearForm *M;
|
||||
BilinearForm *K;
|
||||
|
||||
Operator *Koper, *Moper, *Toper;
|
||||
BilinearFormOperator Mpaop, Kpaop;
|
||||
SparseMatrix Mmat, Kmat;
|
||||
SparseMatrix *T; // T = M + dt K
|
||||
double current_dt;
|
||||
@@ -89,39 +83,11 @@ public:
|
||||
virtual ~ConductionOperator();
|
||||
};
|
||||
|
||||
class TimeDerivativeOperator : public Operator
|
||||
{
|
||||
Operator *Moper;
|
||||
Operator *Koper;
|
||||
mutable Vector Kdu;
|
||||
const double dt;
|
||||
|
||||
public:
|
||||
TimeDerivativeOperator(Operator *_Moper, const double _dt, Operator *_Koper)
|
||||
: Operator(_Moper->Height(), _Moper->Width()),
|
||||
Moper(_Moper),
|
||||
Koper(_Koper),
|
||||
Kdu(Height()),
|
||||
dt(_dt) { }
|
||||
|
||||
virtual void Mult(const Vector &x, Vector &y) const
|
||||
{
|
||||
Moper->Mult(x, y);
|
||||
Koper->Mult(x, Kdu);
|
||||
|
||||
Kdu *= dt;
|
||||
y += Kdu;
|
||||
}
|
||||
};
|
||||
|
||||
double InitialTemperature(const Vector &x);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// 1. Parse command-line options.
|
||||
partial_assembly_mass = false;
|
||||
partial_assembly_diff = false;
|
||||
preconditioner = true;
|
||||
const char *mesh_file = "../data/star.mesh";
|
||||
int ref_levels = 2;
|
||||
int order = 2;
|
||||
@@ -155,12 +121,6 @@ int main(int argc, char *argv[])
|
||||
"Alpha coefficient.");
|
||||
args.AddOption(&kappa, "-k", "--kappa",
|
||||
"Kappa coefficient offset.");
|
||||
args.AddOption(&partial_assembly_mass, "-pam", "--partial-assembly-mass",
|
||||
"-no-pam", "--no-partial-assembly-mass", "Enable partial assembly for the mass.");
|
||||
args.AddOption(&partial_assembly_diff, "-pad", "--partial-assembly-diff",
|
||||
"-no-pad", "--no-partial-assembly-diff", "Enable partial assembly for the diffusion.");
|
||||
args.AddOption(&preconditioner, "-pc", "--peconditioner", "-no-pc",
|
||||
"--no-preconditioner", "Use a Gauss-Seidel preconditioner.");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
@@ -197,6 +157,7 @@ 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;
|
||||
@@ -331,35 +292,22 @@ int main(int argc, char *argv[])
|
||||
ConductionOperator::ConductionOperator(FiniteElementSpace &f, double al,
|
||||
double kap, const Vector &u)
|
||||
: TimeDependentOperator(f.GetTrueVSize(), 0.0), fespace(f), M(NULL), K(NULL),
|
||||
Toper(NULL), Mpaop(new PAIntegratorMap), Kpaop(new PAIntegratorMap),
|
||||
T(NULL), current_dt(0.0), z(height)
|
||||
{
|
||||
const double rel_tol = 1e-8;
|
||||
|
||||
M = new BilinearForm(&fespace);
|
||||
M->AddDomainIntegrator(new MassIntegrator);
|
||||
if (!partial_assembly_mass)
|
||||
{
|
||||
M->AssembleForm(Mmat);
|
||||
M->FormSystemOperator(ess_tdof_list, Moper);
|
||||
M_solver.SetOperator(static_cast<SparseMatrix&>(*Moper));
|
||||
}
|
||||
else
|
||||
{
|
||||
M->AssembleForm(Mpaop);
|
||||
M->FormSystemOperator(ess_tdof_list, Moper);
|
||||
M_solver.SetOperator(*Moper);
|
||||
}
|
||||
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(30);
|
||||
M_solver.SetPrintLevel(0);
|
||||
if (preconditioner && !partial_assembly_mass)
|
||||
{
|
||||
M_solver.SetPreconditioner(M_prec);
|
||||
}
|
||||
M_solver.SetPreconditioner(M_prec);
|
||||
M_solver.SetOperator(Mmat);
|
||||
|
||||
alpha = al;
|
||||
kappa = kap;
|
||||
@@ -369,12 +317,7 @@ ConductionOperator::ConductionOperator(FiniteElementSpace &f, double al,
|
||||
T_solver.SetAbsTol(0.0);
|
||||
T_solver.SetMaxIter(100);
|
||||
T_solver.SetPrintLevel(0);
|
||||
if (preconditioner &&
|
||||
!partial_assembly_diff &&
|
||||
!partial_assembly_mass)
|
||||
{
|
||||
T_solver.SetPreconditioner(T_prec);
|
||||
}
|
||||
T_solver.SetPreconditioner(T_prec);
|
||||
|
||||
SetParameters(u);
|
||||
}
|
||||
@@ -384,7 +327,7 @@ void ConductionOperator::Mult(const Vector &u, Vector &du_dt) const
|
||||
// Compute:
|
||||
// du_dt = M^{-1}*-K(u)
|
||||
// for du_dt
|
||||
Koper->Mult(u, z);
|
||||
Kmat.Mult(u, z);
|
||||
z.Neg(); // z = -z
|
||||
M_solver.Mult(z, du_dt);
|
||||
}
|
||||
@@ -395,22 +338,14 @@ void ConductionOperator::ImplicitSolve(const double dt,
|
||||
// Solve the equation:
|
||||
// du_dt = M^{-1}*[-K(u + dt*du_dt)]
|
||||
// for du_dt
|
||||
if (!T && !Toper)
|
||||
if (!T)
|
||||
{
|
||||
T = Add(1.0, Mmat, dt, Kmat);
|
||||
current_dt = dt;
|
||||
if (!partial_assembly_diff && !partial_assembly_mass)
|
||||
{
|
||||
T = Add(1.0, Mmat, dt, Kmat);
|
||||
T_solver.SetOperator(*T);
|
||||
}
|
||||
else
|
||||
{
|
||||
Toper = new TimeDerivativeOperator(Moper, dt, Koper);
|
||||
T_solver.SetOperator(*Toper);
|
||||
}
|
||||
T_solver.SetOperator(*T);
|
||||
}
|
||||
MFEM_VERIFY(dt == current_dt, ""); // SDIRK methods use the same dt
|
||||
Koper->Mult(u, z);
|
||||
Kmat.Mult(u, z);
|
||||
z.Neg();
|
||||
T_solver.Mult(z, du_dt);
|
||||
}
|
||||
@@ -424,32 +359,21 @@ void ConductionOperator::SetParameters(const Vector &u)
|
||||
u_alpha_gf(i) = kappa + alpha*u_alpha_gf(i);
|
||||
}
|
||||
|
||||
GridFunctionCoefficient u_coeff(&u_alpha_gf);
|
||||
|
||||
delete K;
|
||||
K = new BilinearForm(&fespace);
|
||||
K->AddDomainIntegrator(new DiffusionIntegrator(u_coeff));
|
||||
if (!partial_assembly_diff)
|
||||
{
|
||||
K->AssembleForm(Kmat);
|
||||
K->FormSystemOperator(ess_tdof_list, Koper);
|
||||
}
|
||||
else
|
||||
{
|
||||
K->AssembleForm(Kpaop);
|
||||
K->FormSystemOperator(ess_tdof_list, Koper);
|
||||
}
|
||||
|
||||
// re-compute on the next ImplicitSolve
|
||||
GridFunctionCoefficient u_coeff(&u_alpha_gf);
|
||||
|
||||
K->AddDomainIntegrator(new DiffusionIntegrator(u_coeff));
|
||||
K->Assemble();
|
||||
K->FormSystemMatrix(ess_tdof_list, Kmat);
|
||||
delete T;
|
||||
delete Toper;
|
||||
Toper = NULL;
|
||||
T = NULL;
|
||||
T = NULL; // re-compute T on the next ImplicitSolve
|
||||
}
|
||||
|
||||
ConductionOperator::~ConductionOperator()
|
||||
{
|
||||
delete Toper;
|
||||
delete T;
|
||||
delete M;
|
||||
delete K;
|
||||
}
|
||||
|
||||
@@ -173,6 +173,7 @@ 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;
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ using namespace mfem;
|
||||
//
|
||||
// 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 approximiated using
|
||||
// complement S = B K^-1 B^T. The Schur complement is approximated using
|
||||
// a mass matrix of the pressure variables.
|
||||
class JacobianPreconditioner : public Solver
|
||||
{
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ using namespace mfem;
|
||||
//
|
||||
// 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 approximiated using
|
||||
// complement S = B K^-1 B^T. The Schur complement is approximated using
|
||||
// a mass matrix of the pressure variables.
|
||||
class JacobianPreconditioner : public Solver
|
||||
{
|
||||
|
||||
+12
-48
@@ -54,9 +54,7 @@ int main(int argc, char *argv[])
|
||||
const char *mesh_file = "../data/star.mesh";
|
||||
int order = 1;
|
||||
bool static_cond = false;
|
||||
bool visualization = true;
|
||||
bool use_partial_assembly = false;
|
||||
bool use_amg = true;
|
||||
bool visualization = 1;
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
args.AddOption(&mesh_file, "-m", "--mesh",
|
||||
@@ -64,12 +62,8 @@ int main(int argc, char *argv[])
|
||||
args.AddOption(&order, "-o", "--order",
|
||||
"Finite element order (polynomial degree) or -1 for"
|
||||
" isoparametric space.");
|
||||
args.AddOption(&use_partial_assembly, "-pa", "--partial-assembly",
|
||||
"-no-pa", "--no-partial-assembly", "Enable partial assembly.");
|
||||
args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
|
||||
"--no-static-condensation", "Enable static condensation.");
|
||||
args.AddOption(&use_amg, "-pc", "--peconditioner", "-no-pc",
|
||||
"--no-preconditioner", "Use an algebraic multigrid preconditioner.");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
@@ -179,59 +173,30 @@ int main(int argc, char *argv[])
|
||||
ParBilinearForm *a = new ParBilinearForm(fespace);
|
||||
a->AddDomainIntegrator(new DiffusionIntegrator(one));
|
||||
|
||||
// Use the global map instead
|
||||
BilinearFormOperator A_pa(new PAIntegratorMap);
|
||||
HypreParMatrix A_hpm;
|
||||
Vector B, X;
|
||||
|
||||
if (static_cond) { a->EnableStaticCondensation(); }
|
||||
// 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 (!use_partial_assembly)
|
||||
{
|
||||
a->AssembleForm(A_hpm);
|
||||
}
|
||||
else
|
||||
{
|
||||
a->AssembleForm(A_pa);
|
||||
}
|
||||
if (static_cond) { a->EnableStaticCondensation(); }
|
||||
a->Assemble();
|
||||
|
||||
Operator *A;
|
||||
HypreParMatrix A;
|
||||
Vector B, X;
|
||||
a->FormLinearSystem(ess_tdof_list, x, *b, A, X, B);
|
||||
|
||||
if (myid == 0)
|
||||
{
|
||||
cout << "Size of linear system: " << A->Height() << endl;
|
||||
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.
|
||||
Solver *pcg = NULL;
|
||||
HypreSolver *amg = NULL;
|
||||
if (!use_partial_assembly)
|
||||
{
|
||||
HyprePCG *hypre_pcg = new HyprePCG(A_hpm);
|
||||
pcg = hypre_pcg;
|
||||
hypre_pcg->SetTol(1e-12);
|
||||
hypre_pcg->SetMaxIter(200);
|
||||
hypre_pcg->SetPrintLevel(2);
|
||||
if (use_amg)
|
||||
{
|
||||
amg = new HypreBoomerAMG(A_hpm);
|
||||
hypre_pcg->SetPreconditioner(*amg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CGSolver *mfem_pcg = new CGSolver(MPI_COMM_WORLD);
|
||||
pcg = mfem_pcg;
|
||||
mfem_pcg->SetRelTol(1e-12);
|
||||
mfem_pcg->SetMaxIter(200);
|
||||
mfem_pcg->SetPrintLevel(1);
|
||||
mfem_pcg->SetOperator(*A);
|
||||
}
|
||||
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
|
||||
@@ -266,7 +231,6 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// 16. Free the used memory.
|
||||
delete A;
|
||||
delete pcg;
|
||||
delete amg;
|
||||
delete a;
|
||||
|
||||
+7
-56
@@ -78,7 +78,6 @@ public:
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
// 1. Parse command-line options.
|
||||
problem = 0;
|
||||
const char *mesh_file = "../data/periodic-hexagon.mesh";
|
||||
@@ -179,20 +178,8 @@ int main(int argc, char *argv[])
|
||||
FunctionCoefficient inflow(inflow_function);
|
||||
FunctionCoefficient u0(u0_function);
|
||||
|
||||
tic_toc.Clear();
|
||||
tic_toc.Start();
|
||||
|
||||
BilinearForm m(&fes);
|
||||
m.AddDomainIntegrator(new MassIntegrator);
|
||||
m.Assemble();
|
||||
m.Finalize();
|
||||
|
||||
tic_toc.Stop();
|
||||
double mass_init_time = tic_toc.RealTime();
|
||||
cout << " Mass initialization time: " << mass_init_time << "s." << endl;
|
||||
tic_toc.Clear();
|
||||
tic_toc.Start();
|
||||
|
||||
BilinearForm k(&fes);
|
||||
k.AddDomainIntegrator(new ConvectionIntegrator(velocity, -1.0));
|
||||
k.AddInteriorFaceIntegrator(
|
||||
@@ -200,20 +187,15 @@ int main(int argc, char *argv[])
|
||||
k.AddBdrFaceIntegrator(
|
||||
new TransposeIntegrator(new DGTraceIntegrator(velocity, 1.0, -0.5)));
|
||||
|
||||
|
||||
int skip_zeros = 0;
|
||||
k.Assemble(skip_zeros);
|
||||
k.Finalize(skip_zeros);
|
||||
|
||||
tic_toc.Stop();
|
||||
double adv_init_time = tic_toc.RealTime();
|
||||
cout << " Advection initialization time: " << adv_init_time << "s." << endl;
|
||||
tic_toc.Clear();
|
||||
tic_toc.Start();
|
||||
|
||||
LinearForm b(&fes);
|
||||
b.AddBdrFaceIntegrator(
|
||||
new BoundaryFlowIntegrator(inflow, velocity, -1.0, -0.5));
|
||||
|
||||
m.Assemble();
|
||||
m.Finalize();
|
||||
int skip_zeros = 0;
|
||||
k.Assemble(skip_zeros);
|
||||
k.Finalize(skip_zeros);
|
||||
b.Assemble();
|
||||
|
||||
// 7. Define the initial conditions, save the corresponding grid function to
|
||||
@@ -231,10 +213,6 @@ int main(int argc, char *argv[])
|
||||
u.Save(osol);
|
||||
}
|
||||
|
||||
tic_toc.Stop();
|
||||
double total_init_time = mass_init_time + adv_init_time + tic_toc.RealTime();
|
||||
cout << " Initialization time: " << total_init_time << "s." << endl;
|
||||
|
||||
// Create data collection for solution output: either VisItDataCollection for
|
||||
// ascii data files, or SidreDataCollection for binary data files.
|
||||
DataCollection *dc = NULL;
|
||||
@@ -292,9 +270,6 @@ int main(int argc, char *argv[])
|
||||
adv.SetTime(t);
|
||||
ode_solver->Init(adv);
|
||||
|
||||
tic_toc.Clear();
|
||||
tic_toc.Start();
|
||||
|
||||
bool done = false;
|
||||
for (int ti = 0; !done; )
|
||||
{
|
||||
@@ -322,9 +297,6 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
tic_toc.Stop();
|
||||
cout << " Computation time: " << tic_toc.RealTime() << "s." << endl;
|
||||
|
||||
// 9. Save the final solution. This output can be viewed later using GLVis:
|
||||
// "glvis -m ex9.mesh -g ex9-final.gf".
|
||||
{
|
||||
@@ -345,7 +317,7 @@ int main(int argc, char *argv[])
|
||||
FE_Evolution::FE_Evolution(SparseMatrix &_M, SparseMatrix &_K, const Vector &_b)
|
||||
: TimeDependentOperator(_M.Size()), M(_M), K(_K), b(_b), z(_M.Size())
|
||||
{
|
||||
//M_solver.SetPreconditioner(M_prec);
|
||||
M_solver.SetPreconditioner(M_prec);
|
||||
M_solver.SetOperator(M);
|
||||
|
||||
M_solver.iterative_mode = false;
|
||||
@@ -357,31 +329,10 @@ FE_Evolution::FE_Evolution(SparseMatrix &_M, SparseMatrix &_K, const Vector &_b)
|
||||
|
||||
void FE_Evolution::Mult(const Vector &x, Vector &y) const
|
||||
{
|
||||
/*y = 0.;
|
||||
Vector xx(x);
|
||||
int size = xx.Size();
|
||||
int n = size;
|
||||
int order = 1;
|
||||
int dofs = (order+1)*(order+1);
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
cout << "cacahuete " << i << endl;
|
||||
xx = 0.;
|
||||
xx(i) = 1000.;
|
||||
// y = M^{-1} (K x + b)
|
||||
K.Mult(xx, z);
|
||||
for (int j = 0; j < z.Size(); ++j)
|
||||
{
|
||||
z(j) = abs(z(j)) < 1e-12 ? 0 : z(j);
|
||||
}
|
||||
z.Print(std::cout,dofs);
|
||||
y += z;
|
||||
}*/
|
||||
// y = M^{-1} (K x + b)
|
||||
K.Mult(x, z);
|
||||
z += b;
|
||||
M_solver.Mult(z, y);
|
||||
// K.Mult(x, y);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,584 +0,0 @@
|
||||
// MFEM Example 9
|
||||
//
|
||||
// Compile with: make ex9
|
||||
//
|
||||
// Sample runs:
|
||||
// ex9 -m ../data/periodic-segment.mesh -p 0 -r 2 -dt 0.005
|
||||
// ex9 -m ../data/periodic-square.mesh -p 0 -r 2 -dt 0.01 -tf 10
|
||||
// ex9 -m ../data/periodic-hexagon.mesh -p 0 -r 2 -dt 0.01 -tf 10
|
||||
// ex9 -m ../data/periodic-square.mesh -p 1 -r 2 -dt 0.005 -tf 9
|
||||
// ex9 -m ../data/periodic-hexagon.mesh -p 1 -r 2 -dt 0.005 -tf 9
|
||||
// ex9 -m ../data/amr-quad.mesh -p 1 -r 2 -dt 0.002 -tf 9
|
||||
// ex9 -m ../data/star-q3.mesh -p 1 -r 2 -dt 0.005 -tf 9
|
||||
// ex9 -m ../data/disc-nurbs.mesh -p 1 -r 3 -dt 0.005 -tf 9
|
||||
// ex9 -m ../data/disc-nurbs.mesh -p 2 -r 3 -dt 0.005 -tf 9
|
||||
// ex9 -m ../data/periodic-square.mesh -p 3 -r 4 -dt 0.0025 -tf 9 -vs 20
|
||||
// ex9 -m ../data/periodic-cube.mesh -p 0 -r 2 -o 2 -dt 0.02 -tf 8
|
||||
//
|
||||
// Description: This example code solves the time-dependent advection equation
|
||||
// du/dt + v.grad(u) = 0, where v is a given fluid velocity, and
|
||||
// u0(x)=u(0,x) is a given initial condition.
|
||||
//
|
||||
// The example demonstrates the use of Discontinuous Galerkin (DG)
|
||||
// bilinear forms in MFEM (face integrators), the use of explicit
|
||||
// ODE time integrators, the definition of periodic boundary
|
||||
// conditions through periodic meshes, as well as the use of GLVis
|
||||
// for persistent visualization of a time-evolving solution. The
|
||||
// saving of time-dependent data files for external visualization
|
||||
// with VisIt (visit.llnl.gov) is also illustrated.
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
#include "../fem/dgpabilininteg.hpp"
|
||||
#include "../fem/dgfacefunctions.hpp"
|
||||
#include "../fem/partialassemblykernel.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace mfem;
|
||||
|
||||
// Choice for the problem setup. The fluid velocity, initial condition and
|
||||
// inflow boundary condition are chosen based on this parameter.
|
||||
int problem;
|
||||
|
||||
// Velocity coefficient
|
||||
void velocity_function(const Vector &x, Vector &v);
|
||||
|
||||
// Initial condition
|
||||
double u0_function(const Vector &x);
|
||||
|
||||
// Inflow boundary condition
|
||||
double inflow_function(const Vector &x);
|
||||
|
||||
// Mesh bounding box
|
||||
Vector bb_min, bb_max;
|
||||
|
||||
|
||||
/** A time-dependent operator for the right-hand side of the ODE. The DG weak
|
||||
form of du/dt = -v.grad(u) is M du/dt = K u + b, where M and K are the mass
|
||||
and advection matrices, and b describes the flow on the boundary. This can
|
||||
be written as a general ODE, du/dt = M^{-1} (K u + b), and this class is
|
||||
used to evaluate the right-hand side. */
|
||||
class FE_Evolution : public TimeDependentOperator
|
||||
{
|
||||
private:
|
||||
// BilinearForm &M;
|
||||
Operator &M;
|
||||
Operator &K;
|
||||
const Vector &b;
|
||||
|
||||
CGSolver M_solver;
|
||||
DSmoother M_prec;
|
||||
|
||||
mutable Vector z;
|
||||
|
||||
public:
|
||||
// FE_Evolution(BilinearForm &_M, BilinearForm &_K, const Vector &_b);
|
||||
FE_Evolution(Operator &_M, Operator &_K, const Vector &_b);
|
||||
|
||||
virtual void Mult(const Vector &x, Vector &y) const;
|
||||
|
||||
virtual ~FE_Evolution() { }
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
// 1. Parse command-line options.
|
||||
problem = 0;
|
||||
const char *mesh_file = "../data/periodic-hexagon.mesh";
|
||||
int ref_levels = 2;
|
||||
int order = 3;
|
||||
int ode_solver_type = 4;
|
||||
double t_final = 10.0;
|
||||
double dt = 0.01;
|
||||
bool visualization = true;
|
||||
bool visit = false;
|
||||
bool binary = false;
|
||||
int vis_steps = 5;
|
||||
|
||||
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.");
|
||||
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(&binary, "-binary", "--binary-datafiles", "-ascii",
|
||||
"--ascii-datafiles",
|
||||
"Use binary (Sidre) or ascii format for VisIt data files.");
|
||||
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 geometrically
|
||||
// periodic meshes in this code.
|
||||
Mesh *mesh = new Mesh(mesh_file, 1, 1);
|
||||
int dim = mesh->Dimension();
|
||||
|
||||
// 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. If the mesh is of NURBS type, we convert it to
|
||||
// a (piecewise-polynomial) high-order mesh.
|
||||
for (int lev = 0; lev < ref_levels; lev++)
|
||||
{
|
||||
mesh->UniformRefinement();
|
||||
}
|
||||
if (mesh->NURBSext)
|
||||
{
|
||||
mesh->SetCurvature(max(order, 1));
|
||||
}
|
||||
if (!mesh->GetNodes())
|
||||
{
|
||||
mesh->SetCurvature(1);
|
||||
}
|
||||
mesh->GetBoundingBox(bb_min, bb_max, max(order, 1));
|
||||
|
||||
// 5. Define the discontinuous DG finite element space of the given
|
||||
// polynomial order on the refined mesh.
|
||||
|
||||
DG_FECollection fec(order, dim);
|
||||
//H1_FECollection fec(order, dim);
|
||||
FiniteElementSpace fes(mesh, &fec);
|
||||
|
||||
cout << "Number of unknowns: " << fes.GetVSize() << endl;
|
||||
|
||||
// 6. Set up and assemble the bilinear and linear forms corresponding to the
|
||||
// DG discretization. The DGTraceIntegrator involves integrals over mesh
|
||||
// interior faces.
|
||||
VectorFunctionCoefficient velocity(dim, velocity_function);
|
||||
FunctionCoefficient inflow(inflow_function);
|
||||
FunctionCoefficient u0(u0_function);
|
||||
|
||||
//Creating a partial assembly Kernel
|
||||
//Maybe not the right place to initialize tensor size.
|
||||
int ir_order = 2*order+1;
|
||||
|
||||
tic_toc.Clear();
|
||||
tic_toc.Start();
|
||||
|
||||
//Initialization of the Mass operator
|
||||
// BilinearFormOperator m(&fes);
|
||||
// m.AddDomainIntegrator(new PAMassIntegrator(&fes,ir_order));
|
||||
// m.AddDomainIntegrator(new EigenPAMassIntegrator<2>(&fes,ir_order));
|
||||
// m.AddDomainIntegrator(new EigenPAMassIntegrator<2,EigenDomainPAK>(&fes,ir_order));
|
||||
//BilinearForm m(&fes);
|
||||
//m.AddIntegrator(new PADomainInt<MassEquation>(&fes,ir_order,MassEquation::ArgsEmpty{}));
|
||||
// m.AddDomainIntegrator(new MassIntegrator());
|
||||
// m.AddIntegrator(new PADomainInt<MassEquation,CGSolverDG>(&fes,ir_order,MassEquation::ArgsEmpty{}));
|
||||
// m.AddIntegrator(new PADomainInt<MassEquation>(&fes,ir_order));
|
||||
PADomainInt<MassEquation> mass(&fes,ir_order,MassEquation::ArgsEmpty{});
|
||||
// DiagSolverDG m(fes,ir_order,mass);
|
||||
// PACGSolver<PADomainInt<MassEquation>> m(&fes,mass);
|
||||
DiagSolverDG prec(fes,ir_order,mass);
|
||||
// PAPrecCGSolver<PADomainInt<MassEquation>,DiagSolverDG> m(&fes,mass,prec);
|
||||
// CGSolverDG<PADomainInt<MassEquation>> m(fes,ir_order,mass);
|
||||
PrecCGSolverDG<PADomainInt<MassEquation>,DiagSolverDG> m(fes,ir_order,mass,prec);
|
||||
Operator* mo = &m;
|
||||
|
||||
Array<int> ess_tdof_list;
|
||||
// SparseMatrix msp;
|
||||
// BilinearFormOperator mbf;
|
||||
// Operator *mo;
|
||||
// m.AssembleForm(msp);
|
||||
// m.AssembleForm(mbf);
|
||||
// m.FormSystemOperator(ess_tdof_list, mo);
|
||||
|
||||
tic_toc.Stop();
|
||||
double mass_init_time = tic_toc.RealTime();
|
||||
cout << " Mass initialization time: " << mass_init_time << "s." << endl;
|
||||
tic_toc.Clear();
|
||||
tic_toc.Start();
|
||||
|
||||
//Initialization of the Stiffness operator
|
||||
BilinearForm k(&fes);
|
||||
//k.AddDomainIntegrator(new EigenPAConvectionIntegrator<2>(&fes,ir_order,velocity, -1.0));
|
||||
// k.AddDomainIntegrator(new PAConvectionIntegrator<DummyDomainPAK>(&fes,ir_order,velocity, -1.0));
|
||||
typename DGConvectionEquation::Args argsEq(velocity,-1.0,-0.5);
|
||||
k.AddIntegrator(new PADomainInt<DGConvectionEquation>(&fes,ir_order,argsEq));
|
||||
// k.AddIntegrator(new PADomainInt<DGConvectionEquation>(&fes,ir_order,velocity,-1.0));
|
||||
// k.AddDomainIntegrator(
|
||||
// new PADGConvectionFaceIntegrator<DummyFacePAK>(&fes,ir_order,velocity, 1.0, -0.5));
|
||||
// k.AddDomainIntegrator(
|
||||
// new PADGConvectionFaceIntegrator2<FacePAK>(&fes,ir_order,velocity, 1.0, -0.5));
|
||||
k.AddIntegrator(new PAFaceInt<DGConvectionEquation>(&fes,ir_order,argsEq));
|
||||
// k.AddIntegrator(new PAFaceInt<DGConvectionEquation>(&fes,ir_order,velocity, 1.0, -0.5));
|
||||
|
||||
BilinearFormOperator kbf;
|
||||
Operator *ko;
|
||||
k.AssembleForm(kbf);
|
||||
k.FormSystemOperator(ess_tdof_list, ko);
|
||||
|
||||
tic_toc.Stop();
|
||||
double adv_init_time = tic_toc.RealTime();
|
||||
cout << " Advection initialization time: " << adv_init_time << "s." << endl;
|
||||
tic_toc.Clear();
|
||||
tic_toc.Start();
|
||||
|
||||
//No need to do PA
|
||||
LinearForm b(&fes);
|
||||
b.AddBdrFaceIntegrator(
|
||||
new BoundaryFlowIntegrator(inflow, velocity, -1.0, -0.5));
|
||||
|
||||
b.Assemble();
|
||||
|
||||
tic_toc.Stop();
|
||||
double total_init_time = mass_init_time + adv_init_time + tic_toc.RealTime();
|
||||
cout << " Initialization time: " << total_init_time << "s." << endl;
|
||||
|
||||
// 7. Define the initial conditions, save the corresponding grid function to
|
||||
// a file and (optionally) save data in the VisIt format and initialize
|
||||
// GLVis visualization.
|
||||
GridFunction u(&fes);
|
||||
u.ProjectCoefficient(u0);
|
||||
|
||||
{
|
||||
ofstream omesh("ex9.mesh");
|
||||
omesh.precision(precision);
|
||||
mesh->Print(omesh);
|
||||
ofstream osol("ex9-init.gf");
|
||||
osol.precision(precision);
|
||||
u.Save(osol);
|
||||
}
|
||||
|
||||
// Create data collection for solution output: either VisItDataCollection for
|
||||
// ascii data files, or SidreDataCollection for binary data files.
|
||||
DataCollection *dc = NULL;
|
||||
if (visit)
|
||||
{
|
||||
if (binary)
|
||||
{
|
||||
#ifdef MFEM_USE_SIDRE
|
||||
dc = new SidreDataCollection("Example9", mesh);
|
||||
#else
|
||||
MFEM_ABORT("Must build with MFEM_USE_SIDRE=YES for binary output.");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
dc = new VisItDataCollection("Example9", mesh);
|
||||
dc->SetPrecision(precision);
|
||||
}
|
||||
dc->RegisterField("solution", &u);
|
||||
dc->SetCycle(0);
|
||||
dc->SetTime(0.0);
|
||||
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;
|
||||
sout << "pause\n";
|
||||
sout << flush;
|
||||
cout << "GLVis visualization paused."
|
||||
<< " Press space (in the GLVis window) to resume it.\n";
|
||||
}
|
||||
}
|
||||
|
||||
// 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 adv(*mo, *ko, b);
|
||||
// FE_Evolution adv(m, k, b);
|
||||
|
||||
double t = 0.0;
|
||||
adv.SetTime(t);
|
||||
ode_solver->Init(adv);
|
||||
|
||||
tic_toc.Clear();
|
||||
tic_toc.Start();
|
||||
|
||||
bool done = false;
|
||||
for (int ti = 0; !done; )
|
||||
{
|
||||
double dt_real = min(dt, t_final - t);
|
||||
ode_solver->Step(u, t, dt_real);
|
||||
ti++;
|
||||
|
||||
//done = true;
|
||||
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 << u << flush;
|
||||
// sout << "screenshot\n" << "ex9-" << ti << ".png" << flush;
|
||||
}
|
||||
|
||||
if (visit)
|
||||
{
|
||||
dc->SetCycle(ti);
|
||||
dc->SetTime(t);
|
||||
dc->Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tic_toc.Stop();
|
||||
cout << " Computation time: " << tic_toc.RealTime() << "s." << endl;
|
||||
|
||||
// 9. Save the final solution. This output can be viewed later using GLVis:
|
||||
// "glvis -m ex9.mesh -g ex9-final.gf".
|
||||
{
|
||||
ofstream osol("ex9-final.gf");
|
||||
osol.precision(precision);
|
||||
u.Save(osol);
|
||||
}
|
||||
|
||||
// 10. Free the used memory.
|
||||
delete ode_solver;
|
||||
delete dc;
|
||||
//delete mo;
|
||||
//delete ko;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Implementation of class FE_Evolution
|
||||
// FE_Evolution::FE_Evolution(BilinearForm &_M, BilinearForm &_K, const Vector &_b)
|
||||
// : TimeDependentOperator(_M.Size(), 0.0), M(_M), K(_K), b(_b), z(_M.Size())
|
||||
// {
|
||||
// //TODO have to take into account the block diagonal structure of M
|
||||
// //M_solver.SetPreconditioner(M_prec);
|
||||
// M_solver.SetOperator(M);
|
||||
|
||||
// M_solver.iterative_mode = true;
|
||||
// M_solver.SetRelTol(1e-9);
|
||||
// M_solver.SetAbsTol(0.0);
|
||||
// M_solver.SetMaxIter(100);
|
||||
// M_solver.SetPrintLevel(0);
|
||||
// }
|
||||
FE_Evolution::FE_Evolution(Operator &_M, Operator &_K, const Vector &_b)
|
||||
: TimeDependentOperator(_M.Height(), 0.0), M(_M), K(_K), b(_b), z(_M.Height())
|
||||
{
|
||||
//TODO have to take into account the block diagonal structure of M
|
||||
// M_solver.SetPreconditioner(M_prec);
|
||||
M_solver.SetOperator(M);
|
||||
|
||||
M_solver.iterative_mode = true;
|
||||
M_solver.SetRelTol(1e-9);
|
||||
M_solver.SetAbsTol(0.0);
|
||||
M_solver.SetMaxIter(100);
|
||||
M_solver.SetPrintLevel(0);
|
||||
}
|
||||
|
||||
void FE_Evolution::Mult(const Vector &x, Vector &y) const
|
||||
{
|
||||
// y = 0.;
|
||||
// Vector xx(x);
|
||||
// int size = xx.Size();
|
||||
// int n = size;
|
||||
// int order = 1;
|
||||
// int dofs = (order+1)*(order+1);
|
||||
// for (int i = 0; i < n; ++i)
|
||||
// {
|
||||
// cout << "cacahuete " << i << endl;
|
||||
// xx = 0.;
|
||||
// xx(i) = 1000.;
|
||||
// // y = M^{-1} (K x + b)
|
||||
// K.Mult(xx, z);
|
||||
// for (int j = 0; j < z.Size(); ++j)
|
||||
// {
|
||||
// z(j) = abs(z(j)) < 1e-12 ? 0 : z(j);
|
||||
// }
|
||||
// z.Print(std::cout,dofs);
|
||||
// y += z;
|
||||
// }
|
||||
K.Mult(x, z);
|
||||
z += b;
|
||||
// M_solver.Mult(z, y);
|
||||
M.Mult(z,y);
|
||||
// K.Mult(x, y);
|
||||
}
|
||||
|
||||
|
||||
// Velocity coefficient
|
||||
void velocity_function(const Vector &x, Vector &v)
|
||||
{
|
||||
int dim = x.Size();
|
||||
|
||||
// map to the reference [-1,1] domain
|
||||
Vector X(dim);
|
||||
for (int i = 0; i < dim; i++)
|
||||
{
|
||||
double center = (bb_min[i] + bb_max[i]) * 0.5;
|
||||
X(i) = 2 * (x(i) - center) / (bb_max[i] - bb_min[i]);
|
||||
}
|
||||
|
||||
switch (problem)
|
||||
{
|
||||
case 4:
|
||||
case 0:
|
||||
{
|
||||
// Translations in 1D, 2D, and 3D
|
||||
switch (dim)
|
||||
{
|
||||
case 1: v(0) = 1.0; break;
|
||||
case 2: v(0) = sqrt(2./3.); v(1) = sqrt(1./3.); break;
|
||||
// case 2: v(0) = 1+abs(X(0)); v(1) = 1+abs(X(0)); break;
|
||||
case 3: v(0) = sqrt(3./6.); v(1) = sqrt(2./6.); v(2) = sqrt(1./6.);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
case 2:
|
||||
{
|
||||
// Clockwise rotation in 2D around the origin
|
||||
const double w = M_PI/2;
|
||||
switch (dim)
|
||||
{
|
||||
case 1: v(0) = 1.0; break;
|
||||
case 2: v(0) = w*X(1); v(1) = -w*X(0); break;
|
||||
case 3: v(0) = w*X(1); v(1) = -w*X(0); v(2) = 0.0; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
// Clockwise twisting rotation in 2D around the origin
|
||||
const double w = M_PI/2;
|
||||
double d = max((X(0)+1.)*(1.-X(0)),0.) * max((X(1)+1.)*(1.-X(1)),0.);
|
||||
d = d*d;
|
||||
switch (dim)
|
||||
{
|
||||
case 1: v(0) = 1.0; break;
|
||||
case 2: v(0) = d*w*X(1); v(1) = -d*w*X(0); break;
|
||||
case 3: v(0) = d*w*X(1); v(1) = -d*w*X(0); v(2) = 0.0; break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Initial condition
|
||||
double u0_function(const Vector &x)
|
||||
{
|
||||
int dim = x.Size();
|
||||
|
||||
// map to the reference [-1,1] domain
|
||||
Vector X(dim);
|
||||
for (int i = 0; i < dim; i++)
|
||||
{
|
||||
double center = (bb_min[i] + bb_max[i]) * 0.5;
|
||||
X(i) = 2 * (x(i) - center) / (bb_max[i] - bb_min[i]);
|
||||
}
|
||||
|
||||
switch (problem)
|
||||
{
|
||||
case 0:
|
||||
|
||||
case 1:
|
||||
{
|
||||
switch (dim)
|
||||
{
|
||||
case 1:
|
||||
return exp(-40.*pow(X(0)-0.5,2));
|
||||
case 2:
|
||||
case 3:
|
||||
{
|
||||
double rx = 0.45, ry = 0.25, cx = 0., cy = -0.2, w = 10.;
|
||||
// double rx = 0.05, ry = 0.05, cx = -0., cy = -0.5, w = 10.;
|
||||
if (dim == 3)
|
||||
{
|
||||
const double s = (1. + 0.25*cos(2*M_PI*X(2)));
|
||||
rx *= s;
|
||||
ry *= s;
|
||||
}
|
||||
return ( erfc(w*(X(0)-cx-rx))*erfc(-w*(X(0)-cx+rx)) *
|
||||
erfc(w*(X(1)-cy-ry))*erfc(-w*(X(1)-cy+ry)) )/16;
|
||||
}
|
||||
}
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
double x_ = X(0), y_ = X(1), rho, phi;
|
||||
rho = hypot(x_, y_);
|
||||
phi = atan2(y_, x_);
|
||||
return pow(sin(M_PI*rho),2)*sin(3*phi);
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
const double f = M_PI;
|
||||
return sin(f*X(0))*sin(f*X(1));
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
return exp( -40*( X(0)*X(0) + X(1)*X(1) + X(2)*X(2) ) );
|
||||
}
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// Inflow boundary condition (zero for the problems considered in this example)
|
||||
double inflow_function(const Vector &x)
|
||||
{
|
||||
switch (problem)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3: return 0.0;
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
+5
-2
@@ -21,8 +21,8 @@ CONFIG_MK = $(MFEM_BUILD_DIR)/config/config.mk
|
||||
MFEM_LIB_FILE = mfem_is_not_built
|
||||
-include $(CONFIG_MK)
|
||||
|
||||
SEQ_EXAMPLES = ex1 ex2 ex3 ex4 ex5 ex6 ex7 ex8 ex9 ex9PA ex10 ex14 ex15 ex16\
|
||||
ex17 ex18 ex19
|
||||
SEQ_EXAMPLES = ex1 ex2 ex3 ex4 ex5 ex6 ex7 ex8 ex9 ex10 ex14 ex15 ex16 ex17\
|
||||
ex18 ex19
|
||||
PAR_EXAMPLES = ex1p ex2p ex3p ex4p ex5p ex6p ex7p ex8p ex9p ex10p ex11p ex12p\
|
||||
ex13p ex14p ex15p ex16p ex17p ex18p ex19p
|
||||
|
||||
@@ -38,6 +38,9 @@ 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))
|
||||
|
||||
@@ -63,31 +63,29 @@ add_mfem_examples(PETSC_EXAMPLES_SRCS ${PFX} copy_petsc_rc_files test_petsc)
|
||||
# ctest -R petsc
|
||||
|
||||
# Command line options for the tests.
|
||||
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(EX5P_BDDC_ARGS -m ../../data/star.mesh
|
||||
--usepetsc --petscopts rc_ex5p_bddc --nonoverlapping)
|
||||
set(EX5P_FSPL_ARGS -m ../../data/beam-tet.mesh
|
||||
--usepetsc --petscopts rc_ex5p_fieldsplit)
|
||||
set(EX6P_ARGS -m ../../data/amr-quad.mesh --usepetsc)
|
||||
set(EX9P_E_ARGS -m ../../data/periodic-hexagon.mesh
|
||||
--usepetsc --petscopts rc_ex9p_expl -dt 0.1)
|
||||
set(EX9P_ES_ARGS -m ../../data/periodic-hexagon.mesh
|
||||
--usepetsc --petscopts rc_ex9p_expl --no-step)
|
||||
set(EX9P_IS_ARGS -m ../../data/periodic-hexagon.mesh
|
||||
--usepetsc --petscopts rc_ex9p_impl --implicit -tf 0.5)
|
||||
set(EX10P_ARGS -m ../../data/beam-quad.mesh
|
||||
-tf 30 -s 3 -rs 2 -dt 3 --usepetsc --petscopts rc_ex10p)
|
||||
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)
|
||||
|
||||
# Add the tests: one test per command-line-variable.
|
||||
foreach(TEST_OPTIONS_VAR
|
||||
EX1P_ARGS EX2P_ARGS EX3P_ARGS EX4P_ARGS EX5P_BDDC_ARGS EX5P_FSPL_ARGS
|
||||
EX6P_ARGS EX9P_E_ARGS EX9P_ES_ARGS EX9P_IS_ARGS EX10P_ARGS)
|
||||
EX1_ARGS_W EX1_ARGS_P EX2_ARGS EX3_ARGS EX4_ARGS EX4_HYB_ARGS
|
||||
EX5_BDDC_LB_ARGS EX5_BDDC_GB_ARGS EX5_FSPL_ARGS EX6_ARGS EX6_NONOVL_ARGS
|
||||
EX9_E_ARGS EX9_ES_ARGS EX9_IS_ARGS EX10_ARGS)
|
||||
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})
|
||||
|
||||
+20
-11
@@ -64,6 +64,7 @@ int main(int argc, char *argv[])
|
||||
bool visualization = 1;
|
||||
bool use_petsc = true;
|
||||
bool use_nonoverlapping = false;
|
||||
bool local_bdr_spec = false;
|
||||
const char *petscrc_file = "";
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
@@ -86,6 +87,9 @@ 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())
|
||||
{
|
||||
@@ -306,33 +310,38 @@ 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;
|
||||
|
||||
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;
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
MFEM_ABORT("Need to know the boundary dofs");
|
||||
MFEM_WARNING("Missing boundary dofs. This may cause solver failures.");
|
||||
}
|
||||
|
||||
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_");
|
||||
}
|
||||
|
||||
+19
-13
@@ -69,18 +69,21 @@ TESTNAME = Parallel PETSc example
|
||||
|
||||
|
||||
# Testing PETSc execution options.
|
||||
EX1_ARGS_W := -m ../../data/amr-quad.mesh --usepetsc
|
||||
EX1_ARGS_P := -m ../../data/amr-quad.mesh --usepetsc --petscopts rc_ex1p
|
||||
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_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_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
|
||||
ex1p-test-par: ex1p
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX1_ARGS_W))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX1_ARGS_P))
|
||||
@@ -90,11 +93,14 @@ 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_ARGS))
|
||||
@$(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_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))
|
||||
|
||||
@@ -6,4 +6,7 @@
|
||||
# it needs PETSc configured with MUMPS
|
||||
|
||||
-solver_pc_type cholesky
|
||||
# Petsc 3.9
|
||||
-solver_pc_factor_mat_solver_type mumps
|
||||
# Older versions of PETSc
|
||||
-solver_pc_factor_mat_solver_package mumps
|
||||
|
||||
@@ -16,7 +16,10 @@
|
||||
#-pc_bddc_adaptive_threshold 10
|
||||
|
||||
# Customization of the local solvers
|
||||
#-pc_bddc_neumann_pc_factor_mat_solver_package mumps
|
||||
#-pc_bddc_dirichlet_pc_factor_mat_solver_package mumps
|
||||
# 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_coarse_pc_type cholesky
|
||||
#-pc_bddc_coarse_pc_factor_mat_solver_package mumps
|
||||
#-pc_bddc_coarse_pc_factor_mat_solver_type mumps
|
||||
|
||||
@@ -2,4 +2,7 @@
|
||||
# it needs PETSc configured with MUMPS
|
||||
|
||||
-solver_pc_type cholesky
|
||||
# Petsc 3.9
|
||||
-solver_pc_factor_mat_solver_type mumps
|
||||
# Older versions of PETSc
|
||||
-solver_pc_factor_mat_solver_package mumps
|
||||
|
||||
@@ -13,7 +13,10 @@
|
||||
#-pc_bddc_adaptive_threshold 10
|
||||
|
||||
# Customization of the local solvers
|
||||
#-pc_bddc_neumann_pc_factor_mat_solver_package mumps
|
||||
#-pc_bddc_dirichlet_pc_factor_mat_solver_package mumps
|
||||
# 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_coarse_pc_type cholesky
|
||||
#-pc_bddc_coarse_pc_factor_mat_solver_package mumps
|
||||
#-pc_bddc_coarse_pc_factor_mat_solver_type mumps
|
||||
|
||||
@@ -25,15 +25,29 @@
|
||||
# verbose output
|
||||
#-prec_pc_bddc_check_level 1
|
||||
|
||||
# local solvers (needs PETSc compiled with support for SuiteSparse)
|
||||
# default solvers will fail
|
||||
# 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"
|
||||
#
|
||||
-prec_pc_bddc_neumann_pc_type lu
|
||||
-prec_pc_bddc_neumann_pc_factor_mat_solver_package umfpack
|
||||
-prec_pc_bddc_neumann_pc_factor_mat_solver_type mumps
|
||||
-prec_pc_bddc_neumann_pc_factor_mat_solver_package mumps
|
||||
-prec_pc_bddc_dirichlet_pc_type lu
|
||||
-prec_pc_bddc_dirichlet_pc_factor_mat_solver_package umfpack
|
||||
-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
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
# 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()
|
||||
@@ -0,0 +1,18 @@
|
||||
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.
|
||||
@@ -0,0 +1,262 @@
|
||||
// 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;
|
||||
}
|
||||
@@ -0,0 +1,292 @@
|
||||
// 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;
|
||||
}
|
||||
@@ -0,0 +1,413 @@
|
||||
// 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;
|
||||
}
|
||||
@@ -0,0 +1,387 @@
|
||||
// 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;
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
# 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
|
||||
+8
-99
@@ -68,8 +68,6 @@ BilinearForm::BilinearForm (FiniteElementSpace * f)
|
||||
fes = f;
|
||||
sequence = f->GetSequence();
|
||||
mat = mat_e = NULL;
|
||||
oper = NULL;
|
||||
oper_type = MFEM_SPARSEMAT;
|
||||
extern_bfs = 0;
|
||||
element_matrices = NULL;
|
||||
static_cond = NULL;
|
||||
@@ -87,8 +85,6 @@ BilinearForm::BilinearForm (FiniteElementSpace * f, BilinearForm * bf, int ps)
|
||||
fes = f;
|
||||
sequence = f->GetSequence();
|
||||
mat_e = NULL;
|
||||
oper = NULL;
|
||||
oper_type = MFEM_SPARSEMAT;
|
||||
extern_bfs = 1;
|
||||
element_matrices = NULL;
|
||||
static_cond = NULL;
|
||||
@@ -239,11 +235,6 @@ void BilinearForm::AddBdrFaceIntegrator(BilinearFormIntegrator *bfi,
|
||||
bfbfi_marker.Append(&bdr_marker);
|
||||
}
|
||||
|
||||
void BilinearForm::AddIntegrator(LinearFESpaceIntegrator *bfi)
|
||||
{
|
||||
fesi.Append(bfi);
|
||||
}
|
||||
|
||||
void BilinearForm::ComputeElementMatrix(int i, DenseMatrix &elmat)
|
||||
{
|
||||
if (element_matrices)
|
||||
@@ -329,8 +320,6 @@ void BilinearForm::Assemble (int skip_zeros)
|
||||
AllocMat();
|
||||
}
|
||||
|
||||
oper_type = MFEM_SPARSEMAT;
|
||||
|
||||
#ifdef MFEM_USE_OPENMP
|
||||
int free_element_matrices = 0;
|
||||
if (!element_matrices)
|
||||
@@ -516,21 +505,6 @@ void BilinearForm::Assemble (int skip_zeros)
|
||||
#endif
|
||||
}
|
||||
|
||||
void BilinearForm::AssembleForm(SparseMatrix &A, int skip_zeros)
|
||||
{
|
||||
Assemble(skip_zeros);
|
||||
oper = &A;
|
||||
oper_type = MFEM_SPARSEMAT;
|
||||
}
|
||||
|
||||
void BilinearForm::AssembleForm(BilinearFormOperator &A)
|
||||
{
|
||||
A.Assemble(this);
|
||||
oper = &A;
|
||||
oper_type = MFEM_FORMOPER;
|
||||
}
|
||||
|
||||
|
||||
void BilinearForm::ConformingAssemble()
|
||||
{
|
||||
// Do not remove zero entries to preserve the symmetric structure of the
|
||||
@@ -574,7 +548,6 @@ void BilinearForm::FormLinearSystem(const Array<int> &ess_tdof_list,
|
||||
const SparseMatrix *P = fes->GetConformingProlongation();
|
||||
|
||||
FormSystemMatrix(ess_tdof_list, A);
|
||||
oper = &A;
|
||||
|
||||
// Transform the system and perform the elimination in B, based on the
|
||||
// essential BC values from x. Restrict the BC part of x in X, and set the
|
||||
@@ -633,29 +606,6 @@ void BilinearForm::FormLinearSystem(const Array<int> &ess_tdof_list,
|
||||
}
|
||||
}
|
||||
|
||||
void BilinearForm::FormLinearSystem(const Array<int> &ess_tdof_list, Vector &x, Vector &b,
|
||||
Operator * &A, Vector &X, Vector &B,
|
||||
int copy_interior)
|
||||
{
|
||||
if (oper_type == MFEM_SPARSEMAT)
|
||||
{
|
||||
SparseMatrix &Amat = static_cast<SparseMatrix&>(*oper);
|
||||
FormLinearSystem(ess_tdof_list, x, b, Amat,
|
||||
X, B, copy_interior);
|
||||
SparseMatrix *M = new SparseMatrix;
|
||||
M->MakeRef(Amat);
|
||||
A = M;
|
||||
}
|
||||
else if (oper_type == MFEM_FORMOPER)
|
||||
{
|
||||
oper->FormLinearSystem(ess_tdof_list, x, b, A, X, B, copy_interior);
|
||||
}
|
||||
else
|
||||
{
|
||||
mfem_error("Not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
void BilinearForm::FormSystemMatrix(const Array<int> &ess_tdof_list,
|
||||
SparseMatrix &A)
|
||||
{
|
||||
@@ -693,24 +643,6 @@ void BilinearForm::FormSystemMatrix(const Array<int> &ess_tdof_list,
|
||||
}
|
||||
}
|
||||
|
||||
void BilinearForm::FormSystemOperator(const Array<int> &ess_tdof_list,
|
||||
Operator * &A)
|
||||
{
|
||||
if (oper_type == MFEM_SPARSEMAT)
|
||||
{
|
||||
FormSystemMatrix(ess_tdof_list, static_cast<SparseMatrix&>(*oper));
|
||||
A = oper;
|
||||
}
|
||||
else if (oper_type == MFEM_FORMOPER)
|
||||
{
|
||||
A = oper;
|
||||
}
|
||||
else
|
||||
{
|
||||
mfem_error("Not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
void BilinearForm::RecoverFEMSolution(const Vector &X,
|
||||
const Vector &b, Vector &x)
|
||||
{
|
||||
@@ -802,7 +734,7 @@ void BilinearForm::ComputeElementMatrices()
|
||||
}
|
||||
|
||||
void BilinearForm::EliminateEssentialBC(const Array<int> &bdr_attr_is_ess,
|
||||
Vector &sol, Vector &rhs, DiagonalPolicy dpolicy)
|
||||
const Vector &sol, Vector &rhs, DiagonalPolicy dpolicy)
|
||||
{
|
||||
Array<int> ess_dofs, conf_ess_dofs;
|
||||
fes->GetEssentialVDofs(bdr_attr_is_ess, ess_dofs);
|
||||
@@ -853,7 +785,7 @@ void BilinearForm::EliminateEssentialBCDiag (const Array<int> &bdr_attr_is_ess,
|
||||
}
|
||||
|
||||
void BilinearForm::EliminateVDofs(const Array<int> &vdofs,
|
||||
Vector &sol, Vector &rhs,
|
||||
const Vector &sol, Vector &rhs,
|
||||
DiagonalPolicy dpolicy)
|
||||
{
|
||||
for (int i = 0; i < vdofs.Size(); i++)
|
||||
@@ -893,7 +825,8 @@ void BilinearForm::EliminateVDofs(const Array<int> &vdofs,
|
||||
}
|
||||
|
||||
void BilinearForm::EliminateEssentialBCFromDofs(
|
||||
const Array<int> &ess_dofs, Vector &sol, Vector &rhs, DiagonalPolicy dpolicy)
|
||||
const Array<int> &ess_dofs, const Vector &sol, Vector &rhs,
|
||||
DiagonalPolicy dpolicy)
|
||||
{
|
||||
MFEM_ASSERT(ess_dofs.Size() == height, "incorrect dof Array size");
|
||||
MFEM_ASSERT(sol.Size() == height, "incorrect sol Vector size");
|
||||
@@ -997,10 +930,10 @@ BilinearForm::~BilinearForm()
|
||||
for (k=0; k < bbfi.Size(); k++) { delete bbfi[k]; }
|
||||
for (k=0; k < fbfi.Size(); k++) { delete fbfi[k]; }
|
||||
for (k=0; k < bfbfi.Size(); k++) { delete bfbfi[k]; }
|
||||
for (k=0; k < fesi.Size(); k++) { delete fesi[k]; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MixedBilinearForm::MixedBilinearForm (FiniteElementSpace *tr_fes,
|
||||
FiniteElementSpace *te_fes)
|
||||
: Matrix(te_fes->GetVSize(), tr_fes->GetVSize())
|
||||
@@ -1022,7 +955,7 @@ const double & MixedBilinearForm::Elem (int i, int j) const
|
||||
|
||||
void MixedBilinearForm::Mult (const Vector & x, Vector & y) const
|
||||
{
|
||||
oper -> Mult (x, y);
|
||||
mat -> Mult (x, y);
|
||||
}
|
||||
|
||||
void MixedBilinearForm::AddMult (const Vector & x, Vector & y,
|
||||
@@ -1074,12 +1007,6 @@ void MixedBilinearForm::AddTraceFaceIntegrator (BilinearFormIntegrator * bfi)
|
||||
skt.Append (bfi);
|
||||
}
|
||||
|
||||
void MixedBilinearForm::AddIntegrator(LinearFESpaceIntegrator *integ)
|
||||
{
|
||||
fesi.Append(integ);
|
||||
}
|
||||
|
||||
|
||||
void MixedBilinearForm::Assemble (int skip_zeros)
|
||||
{
|
||||
int i, k;
|
||||
@@ -1163,21 +1090,6 @@ void MixedBilinearForm::Assemble (int skip_zeros)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
oper = mat;
|
||||
}
|
||||
|
||||
void MixedBilinearForm::AssembleForm(SparseMatrix &A, int skip_zeros)
|
||||
{
|
||||
Assemble(skip_zeros);
|
||||
oper = mat;
|
||||
A.MakeRef(*mat);
|
||||
}
|
||||
|
||||
void MixedBilinearForm::AssembleForm(BilinearFormOperator &A, int skip_zeros)
|
||||
{
|
||||
A.Assemble(this);
|
||||
oper = &A;
|
||||
}
|
||||
|
||||
void MixedBilinearForm::ConformingAssemble()
|
||||
@@ -1202,14 +1114,12 @@ void MixedBilinearForm::ConformingAssemble()
|
||||
mat = RAP;
|
||||
}
|
||||
|
||||
oper = mat;
|
||||
|
||||
height = mat->Height();
|
||||
width = mat->Width();
|
||||
}
|
||||
|
||||
void MixedBilinearForm::EliminateTrialDofs (
|
||||
Array<int> &bdr_attr_is_ess, Vector &sol, Vector &rhs )
|
||||
Array<int> &bdr_attr_is_ess, const Vector &sol, Vector &rhs )
|
||||
{
|
||||
int i, j, k;
|
||||
Array<int> tr_vdofs, cols_marker (trial_fes -> GetVSize());
|
||||
@@ -1232,7 +1142,7 @@ void MixedBilinearForm::EliminateTrialDofs (
|
||||
}
|
||||
|
||||
void MixedBilinearForm::EliminateEssentialBCFromTrialDofs (
|
||||
Array<int> &marked_vdofs, Vector &sol, Vector &rhs)
|
||||
Array<int> &marked_vdofs, const Vector &sol, Vector &rhs)
|
||||
{
|
||||
mat -> EliminateCols (marked_vdofs, &sol, &rhs);
|
||||
}
|
||||
@@ -1273,7 +1183,6 @@ MixedBilinearForm::~MixedBilinearForm()
|
||||
for (i = 0; i < dom.Size(); i++) { delete dom[i]; }
|
||||
for (i = 0; i < bdr.Size(); i++) { delete bdr[i]; }
|
||||
for (i = 0; i < skt.Size(); i++) { delete skt[i]; }
|
||||
for (i = 0; i < fesi.Size(); i++) { delete fesi[i]; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
+7
-52
@@ -24,27 +24,17 @@
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
// Forward declare BilinearFormOperator
|
||||
class BilinearFormOperator;
|
||||
|
||||
/** Class for bilinear form - "Matrix" with associated FE space and
|
||||
BLFIntegrators. */
|
||||
class BilinearForm : public Matrix
|
||||
{
|
||||
protected:
|
||||
// TODO remove mat
|
||||
/// Sparse matrix to be associated with the form.
|
||||
SparseMatrix *mat;
|
||||
|
||||
/// Matrix used to eliminate b.c.
|
||||
SparseMatrix *mat_e;
|
||||
|
||||
/// Generic operator associated with the form.
|
||||
Operator *oper;
|
||||
|
||||
/// Operator type.
|
||||
enum Type oper_type;
|
||||
|
||||
/// FE space on which the form lives.
|
||||
FiniteElementSpace *fes;
|
||||
|
||||
@@ -68,9 +58,6 @@ protected:
|
||||
Array<BilinearFormIntegrator*> bfbfi;
|
||||
Array<Array<int>*> bfbfi_marker;
|
||||
|
||||
/// Set of fespace integrators (does not matter what type)
|
||||
Array<LinearFESpaceIntegrator*> fesi;
|
||||
|
||||
DenseMatrix elemmat;
|
||||
Array<int> vdofs;
|
||||
|
||||
@@ -96,9 +83,7 @@ protected:
|
||||
BilinearForm() : Matrix (0)
|
||||
{
|
||||
fes = NULL; sequence = -1;
|
||||
mat = mat_e = NULL;
|
||||
oper = NULL; oper_type = MFEM_SPARSEMAT;
|
||||
extern_bfs = 0; element_matrices = NULL;
|
||||
mat = mat_e = NULL; extern_bfs = 0; element_matrices = NULL;
|
||||
static_cond = NULL; hybridization = NULL;
|
||||
precompute_sparsity = 0;
|
||||
diag_policy = DIAG_KEEP;
|
||||
@@ -166,8 +151,6 @@ public:
|
||||
|
||||
Array<BilinearFormIntegrator*> *GetBFBFI() { return &bfbfi; }
|
||||
|
||||
Array<LinearFESpaceIntegrator*> *GetFESI() { return &fesi; }
|
||||
|
||||
const double &operator()(int i, int j) { return (*mat)(i,j); }
|
||||
|
||||
/// Returns reference to a_{ij}.
|
||||
@@ -249,9 +232,6 @@ public:
|
||||
/// Adds new boundary Face Integrator.
|
||||
void AddBdrFaceIntegrator(BilinearFormIntegrator *bfi);
|
||||
|
||||
/// Adds a LinearFESpaceIntegrator.
|
||||
void AddIntegrator(LinearFESpaceIntegrator *integ);
|
||||
|
||||
/** @brief Adds new boundary Face Integrator, restricted to specific boundary
|
||||
attributes. */
|
||||
void AddBdrFaceIntegrator(BilinearFormIntegrator *bfi,
|
||||
@@ -266,9 +246,6 @@ public:
|
||||
/// Assembles the form i.e. sums over all domain/bdr integrators.
|
||||
void Assemble(int skip_zeros = 1);
|
||||
|
||||
void AssembleForm(BilinearFormOperator &A);
|
||||
void AssembleForm(SparseMatrix &A, int skip_zeros = 1);
|
||||
|
||||
/// Get the finite element space prolongation matrix
|
||||
virtual const Operator *GetProlongation() const
|
||||
{ return fes->GetConformingProlongation(); }
|
||||
@@ -301,17 +278,10 @@ public:
|
||||
|
||||
NOTE: If there are no transformations, @a X simply reuses the data of
|
||||
@a x. */
|
||||
void FormLinearSystem(const Array<int> &ess_tdof_list, Vector &x, Vector &b,
|
||||
Operator * &A, Vector &X, Vector &B,
|
||||
int copy_interior = 0);
|
||||
|
||||
void FormLinearSystem(const Array<int> &ess_tdof_list, Vector &x, Vector &b,
|
||||
SparseMatrix &A, Vector &X, Vector &B,
|
||||
int copy_interior = 0);
|
||||
|
||||
/// Form the linear system matrix A, see FormLinearSystem for details.
|
||||
void FormSystemOperator(const Array<int> &ess_tdof_list, Operator * &Aoper);
|
||||
|
||||
/// Form the linear system matrix A, see FormLinearSystem() for details.
|
||||
void FormSystemMatrix(const Array<int> &ess_tdof_list, SparseMatrix &A);
|
||||
|
||||
@@ -341,7 +311,7 @@ public:
|
||||
essential DOFs is set to 1.0. This behavior is controlled by the argument
|
||||
@a dpolicy. */
|
||||
void EliminateEssentialBC(const Array<int> &bdr_attr_is_ess,
|
||||
Vector &sol, Vector &rhs,
|
||||
const Vector &sol, Vector &rhs,
|
||||
DiagonalPolicy dpolicy = DIAG_ONE);
|
||||
|
||||
/// Eliminate essential boundary DOFs from the system matrix.
|
||||
@@ -352,7 +322,7 @@ public:
|
||||
double value);
|
||||
|
||||
/// Eliminate the given @a vdofs. NOTE: here, @a vdofs is a list of DOFs.
|
||||
void EliminateVDofs(const Array<int> &vdofs, Vector &sol, Vector &rhs,
|
||||
void EliminateVDofs(const Array<int> &vdofs, const Vector &sol, Vector &rhs,
|
||||
DiagonalPolicy dpolicy = DIAG_ONE);
|
||||
|
||||
/// Eliminate the given @a vdofs, storing the eliminated part internally.
|
||||
@@ -363,10 +333,10 @@ public:
|
||||
DiagonalPolicy dpolicy = DIAG_ONE);
|
||||
|
||||
/** @brief Similar to
|
||||
EliminateVDofs(const Array<int> &, Vector &, Vector &, DiagonalPolicy)
|
||||
EliminateVDofs(const Array<int> &, const Vector &, Vector &, DiagonalPolicy)
|
||||
but here @a ess_dofs is a marker (boolean) array on all vector-dofs
|
||||
(@a ess_dofs[i] < 0 is true). */
|
||||
void EliminateEssentialBCFromDofs(const Array<int> &ess_dofs, Vector &sol,
|
||||
void EliminateEssentialBCFromDofs(const Array<int> &ess_dofs, const Vector &sol,
|
||||
Vector &rhs, DiagonalPolicy dpolicy = DIAG_ONE);
|
||||
|
||||
/** @brief Similar to EliminateVDofs(const Array<int> &, DiagonalPolicy) but
|
||||
@@ -405,7 +375,6 @@ public:
|
||||
virtual ~BilinearForm();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Class for assembling of bilinear forms `a(u,v)` defined on different
|
||||
trial and test spaces. The assembled matrix `A` is such that
|
||||
@@ -425,14 +394,12 @@ class MixedBilinearForm : public Matrix
|
||||
{
|
||||
protected:
|
||||
SparseMatrix *mat;
|
||||
Operator *oper;
|
||||
|
||||
FiniteElementSpace *trial_fes, *test_fes;
|
||||
|
||||
Array<BilinearFormIntegrator*> dom;
|
||||
Array<BilinearFormIntegrator*> bdr;
|
||||
Array<BilinearFormIntegrator*> skt; // trace face integrators
|
||||
Array<LinearFESpaceIntegrator*> fesi;
|
||||
|
||||
public:
|
||||
MixedBilinearForm (FiniteElementSpace *tr_fes,
|
||||
@@ -475,24 +442,16 @@ public:
|
||||
two adjacent volume FEs from the test space. */
|
||||
void AddTraceFaceIntegrator (BilinearFormIntegrator * bfi);
|
||||
|
||||
/// Add an FESpaceIntegrator
|
||||
void AddIntegrator (LinearFESpaceIntegrator *integ);
|
||||
|
||||
Array<BilinearFormIntegrator*> *GetDBFI() { return &dom; }
|
||||
|
||||
Array<BilinearFormIntegrator*> *GetBBFI() { return &bdr; }
|
||||
|
||||
Array<BilinearFormIntegrator*> *GetTFBFI() { return &skt; }
|
||||
|
||||
Array<LinearFESpaceIntegrator*> *GetFESI() { return &fesi; }
|
||||
|
||||
void operator= (const double a) { *mat = a; }
|
||||
|
||||
void Assemble (int skip_zeros = 1);
|
||||
|
||||
void AssembleForm(BilinearFormOperator &A, int skip_zeros = 1);
|
||||
void AssembleForm(SparseMatrix &A, int skip_zeros = 1);
|
||||
|
||||
/** For partially conforming trial and/or test FE spaces, complete the
|
||||
assembly process by performing A := P2^t A P1 where A is the internal
|
||||
sparse matrix; P1 and P2 are the conforming prolongation matrices of the
|
||||
@@ -501,19 +460,15 @@ public:
|
||||
void ConformingAssemble();
|
||||
|
||||
void EliminateTrialDofs(Array<int> &bdr_attr_is_ess,
|
||||
Vector &sol, Vector &rhs);
|
||||
const Vector &sol, Vector &rhs);
|
||||
|
||||
void EliminateEssentialBCFromTrialDofs(Array<int> &marked_vdofs,
|
||||
Vector &sol, Vector &rhs);
|
||||
const Vector &sol, Vector &rhs);
|
||||
|
||||
virtual void EliminateTestDofs(Array<int> &bdr_attr_is_ess);
|
||||
|
||||
void Update();
|
||||
|
||||
FiniteElementSpace *TrialFESpace() const { return trial_fes; }
|
||||
|
||||
FiniteElementSpace *TestFESpace() const { return test_fes; }
|
||||
|
||||
virtual ~MixedBilinearForm();
|
||||
};
|
||||
|
||||
|
||||
@@ -1,316 +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.
|
||||
|
||||
// Implementation of BilinearFormOperator
|
||||
|
||||
#include "fem.hpp"
|
||||
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
static void BuildDofMaps(FiniteElementSpace *fespace, Array<int> *&off,
|
||||
Array<int> *&ind)
|
||||
{
|
||||
// Get the total size without vdim
|
||||
int size = 0;
|
||||
const int vdim = fespace->GetVDim();
|
||||
for (int e = 0; e < fespace->GetNE(); e++)
|
||||
{
|
||||
const FiniteElement *fe = fespace->GetFE(e);
|
||||
size += fe->GetDof();
|
||||
}
|
||||
const int local_size = size * vdim;
|
||||
const int global_size = fespace->GetVSize();
|
||||
|
||||
// Now we can allocate and fill the global map
|
||||
off = new Array<int>(global_size + 1);
|
||||
ind = new Array<int>(local_size);
|
||||
|
||||
Array<int> &offsets = *off;
|
||||
Array<int> &indices = *ind;
|
||||
|
||||
Array<int> global_map(local_size);
|
||||
Array<int> elem_vdof;
|
||||
|
||||
int offset = 0;
|
||||
for (int e = 0; e < fespace->GetNE(); e++)
|
||||
{
|
||||
const FiniteElement *fe = fespace->GetFE(e);
|
||||
const int dofs = fe->GetDof();
|
||||
const int vdofs = dofs * vdim;
|
||||
const TensorBasisElement *tfe = dynamic_cast<const TensorBasisElement *>(fe);
|
||||
const Array<int> &dof_map = tfe->GetDofMap();
|
||||
|
||||
fespace->GetElementVDofs(e, elem_vdof);
|
||||
|
||||
if (dof_map.Size()==0)
|
||||
{
|
||||
for (int vd = 0; vd < vdim; vd++)
|
||||
for (int i = 0; i < vdofs; i++)
|
||||
{
|
||||
global_map[offset + dofs*vd + i] = elem_vdof[dofs*vd + i];
|
||||
}
|
||||
}else{
|
||||
for (int vd = 0; vd < vdim; vd++)
|
||||
for (int i = 0; i < vdofs; i++)
|
||||
{
|
||||
global_map[offset + dofs*vd + i] = elem_vdof[dofs*vd + dof_map[i]];
|
||||
}
|
||||
}
|
||||
offset += vdofs;
|
||||
}
|
||||
|
||||
// Store and use a set of offsets and indices instead of this map
|
||||
|
||||
// Zero the offset vector
|
||||
offsets = 0;
|
||||
|
||||
// Keep track of how many local dof point to its global dof
|
||||
// Count how many times each dof gets hit
|
||||
for (int i = 0; i < local_size; i++)
|
||||
{
|
||||
const int g = global_map[i];
|
||||
++offsets[g + 1];
|
||||
}
|
||||
// Aggregate the offsets
|
||||
for (int i = 1; i <= global_size; i++)
|
||||
{
|
||||
offsets[i] += offsets[i - 1];
|
||||
}
|
||||
|
||||
for (int i = 0; i < local_size; i++)
|
||||
{
|
||||
const int g = global_map[i];
|
||||
indices[offsets[g]++] = i;
|
||||
}
|
||||
|
||||
// Shift the offset vector back by one, since it was used as a
|
||||
// counter above.
|
||||
for (int i = global_size; i > 0; i--)
|
||||
{
|
||||
offsets[i] = offsets[i - 1];
|
||||
}
|
||||
offsets[0] = 0;
|
||||
}
|
||||
|
||||
BilinearFormOperator::BilinearFormOperator(IntegratorMap *_map)
|
||||
: bf(NULL), mbf(NULL),
|
||||
trial_fes(NULL), test_fes(NULL),
|
||||
trial_gs(false), test_gs(false),
|
||||
trial_offsets(NULL), trial_indices(NULL),
|
||||
test_offsets(NULL), test_indices(NULL),
|
||||
X(NULL), Y(NULL),
|
||||
map(_map) { }
|
||||
|
||||
BilinearFormOperator::~BilinearFormOperator()
|
||||
{
|
||||
delete map;
|
||||
Clear();
|
||||
}
|
||||
|
||||
void BilinearFormOperator::Assemble(BilinearForm *_bf)
|
||||
{
|
||||
if (_bf != bf)
|
||||
{
|
||||
bf = _bf;
|
||||
height = bf->Height();
|
||||
width = bf->Width();
|
||||
|
||||
Init(bf->FESpace(), NULL);
|
||||
|
||||
// Delete the old integrator list -- Note that this does not
|
||||
// delete the integrators themselves (since the original
|
||||
// bilinear form owns these)
|
||||
lfesi.DeleteAll();
|
||||
|
||||
// Add the integrators from bf->fesi
|
||||
Array<LinearFESpaceIntegrator*> &other_fesi = *(bf->GetFESI());
|
||||
for (int i = 0; i < other_fesi.Size(); i++)
|
||||
{
|
||||
lfesi.Append(other_fesi[i]);
|
||||
}
|
||||
|
||||
if (map)
|
||||
{
|
||||
Array<BilinearFormIntegrator*> &dbfi = *(bf->GetDBFI());
|
||||
for (int i = 0; i < dbfi.Size(); i++)
|
||||
{
|
||||
lfesi.Append(map->DomainIntegrator(dbfi[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assemble();
|
||||
}
|
||||
|
||||
void BilinearFormOperator::Assemble(MixedBilinearForm *_mbf)
|
||||
{
|
||||
if (_mbf != mbf)
|
||||
{
|
||||
mbf = _mbf;
|
||||
height = bf->Height();
|
||||
width = bf->Width();
|
||||
|
||||
Init(mbf->TrialFESpace(), mbf->TestFESpace());
|
||||
|
||||
// Delete the old integrator list -- Note that this does not
|
||||
// delete the integrators themselves (since the original mixed
|
||||
// bilinear form owns these)
|
||||
lfesi.DeleteAll();
|
||||
|
||||
// Add the integrators from mbf->fesi
|
||||
Array<LinearFESpaceIntegrator*> &other_fesi = *(mbf->GetFESI());
|
||||
for (int i = 0; i < other_fesi.Size(); i++)
|
||||
{
|
||||
lfesi.Append(other_fesi[i]);
|
||||
}
|
||||
|
||||
if (map)
|
||||
{
|
||||
Array<BilinearFormIntegrator*> &dbfi = *(mbf->GetDBFI());
|
||||
for (int i = 0; i < dbfi.Size(); i++)
|
||||
{
|
||||
lfesi.Append(map->DomainIntegrator(dbfi[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assemble();
|
||||
}
|
||||
|
||||
void BilinearFormOperator::Assemble()
|
||||
{
|
||||
// Linear assembly
|
||||
for (int i = 0; i < lfesi.Size(); i++)
|
||||
{
|
||||
lfesi[i]->Assemble(trial_fes, test_fes);
|
||||
}
|
||||
}
|
||||
|
||||
void BilinearFormOperator::Clear()
|
||||
{
|
||||
delete trial_offsets;
|
||||
delete trial_indices;
|
||||
|
||||
if (test_fes)
|
||||
{
|
||||
delete test_offsets;
|
||||
delete test_indices;
|
||||
}
|
||||
|
||||
if (trial_gs) delete X;
|
||||
if (test_gs) delete Y;
|
||||
}
|
||||
|
||||
void BilinearFormOperator::Init(FiniteElementSpace *_trial_fes,
|
||||
FiniteElementSpace *_test_fes)
|
||||
{
|
||||
if ((_trial_fes != trial_fes) || (_test_fes != test_fes))
|
||||
{
|
||||
// Clear before recreating
|
||||
Clear();
|
||||
|
||||
trial_fes = _trial_fes;
|
||||
test_fes = _test_fes;
|
||||
BuildDofMaps(trial_fes, trial_offsets, trial_indices);
|
||||
|
||||
if (test_fes != NULL)
|
||||
{
|
||||
BuildDofMaps(test_fes, test_offsets, test_indices);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Point to the trial offsets and indices
|
||||
test_offsets = trial_offsets;
|
||||
test_indices = trial_indices;
|
||||
}
|
||||
|
||||
X = new Vector(trial_indices->Size());
|
||||
Y = new Vector(test_indices->Size());
|
||||
}
|
||||
|
||||
const FiniteElementSpace *actual_test_fes =
|
||||
(test_fes != NULL) ? test_fes : trial_fes;
|
||||
trial_gs = test_gs = true;
|
||||
if (dynamic_cast<const L2_FECollection *>(trial_fes->FEColl()))
|
||||
{
|
||||
trial_gs = test_gs = false;
|
||||
}
|
||||
else if (dynamic_cast<const L2_FECollection *>(actual_test_fes->FEColl()))
|
||||
{
|
||||
test_gs = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BilinearFormOperator::LToEVector(const Array<int> &offsets,
|
||||
const Array<int> &indices,
|
||||
const Vector &v, Vector &V) const
|
||||
{
|
||||
const int size = v.Size();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
const int offset = offsets[i];
|
||||
const int next_offset = offsets[i + 1];
|
||||
const double dof_value = v(i);
|
||||
for (int j = offset; j < next_offset; j++) { V(indices[j]) = dof_value; }
|
||||
}
|
||||
}
|
||||
|
||||
void BilinearFormOperator::EToLVector(const Array<int> &offsets,
|
||||
const Array<int> &indices,
|
||||
const Vector &V, Vector &v) const
|
||||
{
|
||||
// NOTE: This method ADDS to the output v
|
||||
const int size = v.Size();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
const int offset = offsets[i];
|
||||
const int next_offset = offsets[i + 1];
|
||||
double dof_value = 0;
|
||||
for (int j = offset; j < next_offset; j++) { dof_value += V(indices[j]); }
|
||||
v(i) += dof_value;
|
||||
}
|
||||
}
|
||||
|
||||
void BilinearFormOperator::AddMult(const Vector &x, Vector &y) const
|
||||
{
|
||||
if (trial_gs) { LToEVector(*trial_offsets, *trial_indices, x, *X); }
|
||||
else { X = const_cast<Vector *>(&x); }
|
||||
|
||||
if (!test_gs) { Y = &y; }
|
||||
|
||||
*Y = 0.0;
|
||||
for (int i = 0; i < lfesi.Size(); i++) lfesi[i]->AddMult(*X, *Y);
|
||||
for (int i = 0; i < nlfesi.Size(); i++) nlfesi[i]->AddMult(*X, *Y);
|
||||
|
||||
if (test_gs) { EToLVector(*test_offsets, *test_indices, *Y, y); }
|
||||
}
|
||||
|
||||
|
||||
void BilinearFormOperator::AddMultTranspose(const Vector &x, Vector &y) const
|
||||
{
|
||||
if (test_gs) { LToEVector(*test_offsets, *test_indices, x, *X); }
|
||||
else { X = const_cast<Vector *>(&x); }
|
||||
|
||||
if (!trial_gs) { Y = &y; }
|
||||
|
||||
*Y = 0.0;
|
||||
for (int i = 0; i < lfesi.Size(); i++) lfesi[i]->AddMultTranspose(*X, *Y);
|
||||
for (int i = 0; i < nlfesi.Size(); i++) nlfesi[i]->AddMultTranspose(*X, *Y);
|
||||
|
||||
if (trial_gs) { EToLVector(*trial_offsets, *trial_indices, *Y, y); }
|
||||
}
|
||||
|
||||
void BilinearFormOperator::Mult(const Vector &x, Vector &y) const
|
||||
{ y = 0.0; AddMult(x, y); }
|
||||
|
||||
}
|
||||
@@ -1,96 +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.
|
||||
//
|
||||
// Defines the general object for the abstraction of bilinear and
|
||||
// nonlinear forms.
|
||||
|
||||
#ifndef MFEM_BILINEARFORMOPER
|
||||
#define MFEM_BILINEARFORMOPER
|
||||
|
||||
#include "../config/config.hpp"
|
||||
#include "../linalg/linalg.hpp"
|
||||
#include "fespace.hpp"
|
||||
#include "nonlininteg.hpp"
|
||||
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
struct IntegratorMap
|
||||
{
|
||||
virtual LinearFESpaceIntegrator *DomainIntegrator(BilinearFormIntegrator *integ) const
|
||||
{ mfem_error("Not supported."); return NULL; }
|
||||
virtual LinearFESpaceIntegrator *InteriorFaceIntegrator(BilinearFormIntegrator *integ) const
|
||||
{ mfem_error("Not supported."); return NULL; }
|
||||
virtual LinearFESpaceIntegrator *BdrFaceIntegrator(BilinearFormIntegrator *integ) const
|
||||
{ mfem_error("Not supported."); return NULL; }
|
||||
|
||||
virtual NonlinearFESpaceIntegrator *DomainIntegrator(NonlinearFormIntegrator *integ) const
|
||||
{ mfem_error("Not supported."); return NULL; }
|
||||
|
||||
virtual ~IntegratorMap() { }
|
||||
};
|
||||
|
||||
class BilinearFormOperator : public Operator
|
||||
{
|
||||
protected:
|
||||
BilinearForm *bf; // Do not own
|
||||
MixedBilinearForm *mbf; // Do not own
|
||||
|
||||
FiniteElementSpace *trial_fes; // Do not own
|
||||
FiniteElementSpace *test_fes; // Do not own
|
||||
bool trial_gs, test_gs;
|
||||
|
||||
Array<int> *trial_offsets, *trial_indices;
|
||||
Array<int> *test_offsets, *test_indices;
|
||||
mutable Vector *X;
|
||||
mutable Vector *Y;
|
||||
|
||||
Array<LinearFESpaceIntegrator*> lfesi;
|
||||
Array<NonlinearFESpaceIntegrator*> nlfesi;
|
||||
|
||||
IntegratorMap *map;
|
||||
|
||||
// Convert between vector types before calling Mult.
|
||||
void LToEVector(const Array<int> &offsets, const Array<int> &indices,
|
||||
const Vector &v, Vector &V) const;
|
||||
void EToLVector(const Array<int> &offsets, const Array<int> &indices,
|
||||
const Vector &V, Vector &v) const;
|
||||
|
||||
void Clear();
|
||||
|
||||
void Init(FiniteElementSpace *_trial_fes, FiniteElementSpace *_test_fes);
|
||||
|
||||
public:
|
||||
// Create an empty object or assemble what is needed by the
|
||||
// bilinear form integrators to later compute the action.
|
||||
BilinearFormOperator(IntegratorMap *_map = NULL);
|
||||
~BilinearFormOperator();
|
||||
|
||||
void Assemble();
|
||||
void Assemble(BilinearForm *bf);
|
||||
void Assemble(MixedBilinearForm *bf);
|
||||
|
||||
/// Perform the action of the bilinear form on a vector and set y.
|
||||
virtual void Mult(const Vector &x, Vector &y) const;
|
||||
|
||||
virtual const Operator *GetProlongation() const { return trial_fes->GetProlongationMatrix(); }
|
||||
virtual const Operator *GetRestriction() const { return trial_fes->GetRestrictionMatrix(); }
|
||||
|
||||
/// Perform the action of the bilinear form on a vector and add to y.
|
||||
void AddMult(const Vector &x, Vector &y) const;
|
||||
|
||||
/// Perform the (transposed) action of the bilinear form on a vector and add to y.
|
||||
void AddMultTranspose(const Vector &x, Vector &y) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
+6
-14
@@ -61,19 +61,6 @@ void BilinearFormIntegrator::AssembleElementVector(
|
||||
" is not implemented for this class.");
|
||||
}
|
||||
|
||||
void BilinearFormIntegrator::AssembleMult(
|
||||
const Vector &x, Vector& y)
|
||||
{
|
||||
mfem_error("BilinearFormIntegrator::AssembleMult\n"
|
||||
" is not implemented fot this class.");
|
||||
}
|
||||
|
||||
void BilinearFormIntegrator::AssembleMultTranspose(
|
||||
const Vector &x, Vector& y)
|
||||
{
|
||||
mfem_error("BilinearFormIntegrator::AssembleMultTranspose\n"
|
||||
" is not implemented fot this class.");
|
||||
}
|
||||
|
||||
void TransposeIntegrator::AssembleElementMatrix (
|
||||
const FiniteElement &el, ElementTransformation &Trans, DenseMatrix &elmat)
|
||||
@@ -710,7 +697,7 @@ double DiffusionIntegrator::ComputeFluxEnergy
|
||||
}
|
||||
else
|
||||
{
|
||||
MQ->Eval(mq, Trans, ip);
|
||||
MQ->Eval(mq, Trans, ip);
|
||||
energy += w * mq.InnerProduct(pointflux, pointflux);
|
||||
}
|
||||
|
||||
@@ -729,6 +716,7 @@ double DiffusionIntegrator::ComputeFluxEnergy
|
||||
return energy;
|
||||
}
|
||||
|
||||
|
||||
void MassIntegrator::AssembleElementMatrix
|
||||
( const FiniteElement &el, ElementTransformation &Trans,
|
||||
DenseMatrix &elmat )
|
||||
@@ -819,6 +807,7 @@ void MassIntegrator::AssembleElementMatrix2(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BoundaryMassIntegrator::AssembleFaceMatrix(
|
||||
const FiniteElement &el1, const FiniteElement &el2,
|
||||
FaceElementTransformations &Trans, DenseMatrix &elmat)
|
||||
@@ -1637,6 +1626,7 @@ void VectorCurlCurlIntegrator::AssembleElementMatrix(
|
||||
ir = &IntRules.Get(el.GetGeomType(), order);
|
||||
}
|
||||
|
||||
elmat.SetSize(dof*dim);
|
||||
elmat = 0.0;
|
||||
for (int i = 0; i < ir->GetNPoints(); i++)
|
||||
{
|
||||
@@ -2065,6 +2055,7 @@ void DivDivIntegrator::AssembleElementMatrix(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void VectorDiffusionIntegrator::AssembleElementMatrix(
|
||||
const FiniteElement &el,
|
||||
ElementTransformation &Trans,
|
||||
@@ -2308,6 +2299,7 @@ void DGTraceIntegrator::AssembleFaceMatrix(const FiniteElement &el1,
|
||||
}
|
||||
ir = &IntRules.Get(Trans.FaceGeom, order);
|
||||
}
|
||||
|
||||
for (int p = 0; p < ir->GetNPoints(); p++)
|
||||
{
|
||||
const IntegrationPoint &ip = ir->IntPoint(p);
|
||||
|
||||
@@ -80,17 +80,6 @@ public:
|
||||
Vector &flux, Vector *d_energy = NULL)
|
||||
{ return 0.0; }
|
||||
|
||||
/** Assemble any element or face-specific terms required for the
|
||||
action with the bilinear form integrator. Later applied with
|
||||
AssembleVector. */
|
||||
virtual void AssembleOperator(const FiniteElementSpace *trial_fes,
|
||||
const FiniteElementSpace *test_fes) { }
|
||||
|
||||
/** Compute `y = A * x` where A is the bilinear form integrator for
|
||||
all elements/faces. */
|
||||
virtual void AssembleMult(const Vector &fun, Vector &vect);
|
||||
virtual void AssembleMultTranspose(const Vector &fun, Vector &vect);
|
||||
|
||||
virtual ~BilinearFormIntegrator() { }
|
||||
};
|
||||
|
||||
@@ -1633,11 +1622,6 @@ public:
|
||||
virtual double ComputeFluxEnergy(const FiniteElement &fluxelem,
|
||||
ElementTransformation &Trans,
|
||||
Vector &flux, Vector *d_energy = NULL);
|
||||
|
||||
// Friend partial assembly version so it has access to the coefficients.
|
||||
friend class PADiffusionIntegrator;
|
||||
// TODO: Add a GetPAIntegrator method here
|
||||
// PAIntegrator* GetPAIntegrator(type);
|
||||
};
|
||||
|
||||
/** Class for local mass matrix assembling a(u,v) := (Q u, v) */
|
||||
@@ -1665,9 +1649,6 @@ public:
|
||||
const FiniteElement &test_fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &elmat);
|
||||
|
||||
// Friend partial assembly version so it has access to the coefficients.
|
||||
friend class PAMassIntegrator;
|
||||
};
|
||||
|
||||
class BoundaryMassIntegrator : public MassIntegrator
|
||||
@@ -1761,9 +1742,6 @@ public:
|
||||
const FiniteElement &test_fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &elmat);
|
||||
|
||||
// Friend partial assembly version so it has access to the coefficients.
|
||||
friend class PAMassIntegrator;
|
||||
};
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -209,7 +209,7 @@ void VectorRestrictedCoefficient::Eval(
|
||||
}
|
||||
else
|
||||
{
|
||||
M.SetSize(vdim);
|
||||
M.SetSize(vdim, ir.GetNPoints());
|
||||
M = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,6 +164,7 @@ ConduitDataCollection::SetProtocol(const std::string &protocol)
|
||||
//---------------------------------------------------------------------------//
|
||||
mfem::Mesh *
|
||||
ConduitDataCollection::BlueprintMeshToMesh(const Node &n_mesh,
|
||||
const std::string &main_toplogy_name,
|
||||
bool zero_copy)
|
||||
{
|
||||
// n_conv holds converted data (when necessary for mfem api)
|
||||
@@ -172,11 +173,31 @@ ConduitDataCollection::BlueprintMeshToMesh(const Node &n_mesh,
|
||||
// can't return a mesh that zero copies the conduit data
|
||||
Node n_conv;
|
||||
|
||||
MFEM_ASSERT(n_mesh.has_path("coordsets/coords"),
|
||||
"Expected topology named \"coords\" "
|
||||
"(node is missing path \"coordsets/coords\")");
|
||||
//
|
||||
// we need to find the topology and its coordset.
|
||||
//
|
||||
|
||||
const Node &n_coordset = n_mesh["coordsets/coords"];
|
||||
std::string topo_name = main_toplogy_name;
|
||||
// if topo name is not set, look for first topology
|
||||
if (topo_name == "")
|
||||
{
|
||||
topo_name = n_mesh["topologies"].schema().child_name(0);
|
||||
}
|
||||
|
||||
MFEM_ASSERT(n_mesh.has_path("topologies/" + topo_name),
|
||||
"Expected topology named \"" + topo_name + "\" "
|
||||
"(node is missing path \"topologies/" + topo_name + "\")");
|
||||
|
||||
// find the coord set
|
||||
std::string coords_name =
|
||||
n_mesh["topologies"][topo_name]["coordset"].as_string();
|
||||
|
||||
|
||||
MFEM_ASSERT(n_mesh.has_path("coordsets/" + coords_name),
|
||||
"Expected topology named \"" + coords_name + "\" "
|
||||
"(node is missing path \"coordsets/" + coords_name + "\")");
|
||||
|
||||
const Node &n_coordset = n_mesh["coordsets"][coords_name];
|
||||
const Node &n_coordset_vals = n_coordset["values"];
|
||||
|
||||
// get the number of dims of the coordset
|
||||
@@ -238,17 +259,15 @@ ConduitDataCollection::BlueprintMeshToMesh(const Node &n_mesh,
|
||||
n_tmp["y"].set(DataType::c_double(num_verts));
|
||||
}
|
||||
|
||||
Node &n_conv_coords_vals = n_conv["coordsets/coords/values"];
|
||||
Node &n_conv_coords_vals = n_conv["coordsets"][coords_name]["values"];
|
||||
blueprint::mcarray::to_interleaved(n_tmp,
|
||||
n_conv_coords_vals);
|
||||
verts_ptr = n_conv_coords_vals[0].value();
|
||||
}
|
||||
|
||||
MFEM_ASSERT(n_mesh.has_path("topologies/main"),
|
||||
"Expected topology named \"main\" "
|
||||
"(node is missing path \"topologies/main\")");
|
||||
|
||||
const Node &n_mesh_topo = n_mesh["topologies/main"];
|
||||
|
||||
const Node &n_mesh_topo = n_mesh["topologies"][topo_name];
|
||||
std::string mesh_ele_shape = n_mesh_topo["elements/shape"].as_string();
|
||||
|
||||
mfem::Geometry::Type mesh_geo = ShapeNameToGeomType(mesh_ele_shape);
|
||||
@@ -265,7 +284,8 @@ ConduitDataCollection::BlueprintMeshToMesh(const Node &n_mesh,
|
||||
}
|
||||
else
|
||||
{
|
||||
Node &n_mesh_conn_conv= n_conv["topologies/main/elements/connectivity"];
|
||||
Node &n_mesh_conn_conv=
|
||||
n_conv["topologies"][topo_name]["elements/connectivity"];
|
||||
n_mesh_conn.to_int_array(n_mesh_conn_conv);
|
||||
elem_indices = n_mesh_conn_conv.value();
|
||||
}
|
||||
@@ -281,33 +301,46 @@ ConduitDataCollection::BlueprintMeshToMesh(const Node &n_mesh,
|
||||
// table lookup, even if we don't have boundary info.
|
||||
mfem::Geometry::Type bndry_geo = mfem::Geometry::POINT;
|
||||
|
||||
if ( n_mesh.has_path("topologies/boundary") )
|
||||
if ( n_mesh_topo.has_child("boundary_topology") )
|
||||
{
|
||||
const Node &n_bndry_topo = n_mesh["topologies/boundary"];
|
||||
std::string bndry_ele_shape = n_bndry_topo["elements/shape"].as_string();
|
||||
std::string bndry_topo_name = n_mesh_topo["boundary_topology"].as_string();
|
||||
|
||||
bndry_geo = ShapeNameToGeomType(bndry_ele_shape);
|
||||
int num_idxs_per_bndry_ele = Geometry::NumVerts[mesh_geo];
|
||||
// In VisIt, we encountered a case were a mesh specified a boundary
|
||||
// topology, but the boundary topology was omitted from the blueprint
|
||||
// index, so it's data could not be obtained.
|
||||
//
|
||||
// This guard prevents an error in that case, allowing the mesh to be
|
||||
// created without boundary info
|
||||
|
||||
const Node &n_bndry_conn = n_bndry_topo["elements/connectivity"];
|
||||
|
||||
// mfem requires ints, we could have int64s, etc convert if necessary
|
||||
if ( n_bndry_conn.dtype().is_int() &&
|
||||
n_bndry_conn.is_compact())
|
||||
if (n_mesh["topologies"].has_child(bndry_topo_name))
|
||||
{
|
||||
bndry_indices = n_bndry_conn.value();
|
||||
}
|
||||
else
|
||||
{
|
||||
Node &(n_bndry_conn_conv) = n_conv["topologies/boundary/elements/connectivity"];
|
||||
n_bndry_conn.to_int_array(n_bndry_conn_conv);
|
||||
bndry_indices = (n_bndry_conn_conv).value();
|
||||
const Node &n_bndry_topo = n_mesh["topologies"][bndry_topo_name];
|
||||
std::string bndry_ele_shape = n_bndry_topo["elements/shape"].as_string();
|
||||
|
||||
}
|
||||
bndry_geo = ShapeNameToGeomType(bndry_ele_shape);
|
||||
int num_idxs_per_bndry_ele = Geometry::NumVerts[mesh_geo];
|
||||
|
||||
num_bndry_ele =
|
||||
n_bndry_topo["elements/connectivity"].dtype().number_of_elements();
|
||||
num_bndry_ele = num_bndry_ele / num_idxs_per_bndry_ele;
|
||||
const Node &n_bndry_conn = n_bndry_topo["elements/connectivity"];
|
||||
|
||||
// mfem requires ints, we could have int64s, etc convert if necessary
|
||||
if ( n_bndry_conn.dtype().is_int() &&
|
||||
n_bndry_conn.is_compact())
|
||||
{
|
||||
bndry_indices = n_bndry_conn.value();
|
||||
}
|
||||
else
|
||||
{
|
||||
Node &(n_bndry_conn_conv) =
|
||||
n_conv["topologies"][bndry_topo_name]["elements/connectivity"];
|
||||
n_bndry_conn.to_int_array(n_bndry_conn_conv);
|
||||
bndry_indices = (n_bndry_conn_conv).value();
|
||||
|
||||
}
|
||||
|
||||
num_bndry_ele =
|
||||
n_bndry_topo["elements/connectivity"].dtype().number_of_elements();
|
||||
num_bndry_ele = num_bndry_ele / num_idxs_per_bndry_ele;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -609,14 +642,17 @@ ConduitDataCollection::BlueprintFieldToGridFunction(Mesh *mesh,
|
||||
//---------------------------------------------------------------------------//
|
||||
void
|
||||
ConduitDataCollection::MeshToBlueprintMesh(Mesh *mesh,
|
||||
Node &n_mesh)
|
||||
Node &n_mesh,
|
||||
const std::string &coordset_name,
|
||||
const std::string &main_topology_name,
|
||||
const std::string &boundary_topology_name)
|
||||
{
|
||||
int dim = mesh->SpaceDimension();
|
||||
|
||||
MFEM_ASSERT(dim >= 1 && dim <= 3, "invalid mesh dimension");
|
||||
|
||||
////////////////////////////////////////////
|
||||
// Setup main coordset "coords"
|
||||
// Setup main coordset
|
||||
////////////////////////////////////////////
|
||||
|
||||
// Assumes mfem::Vertex has the layout of a double array.
|
||||
@@ -628,38 +664,40 @@ ConduitDataCollection::MeshToBlueprintMesh(Mesh *mesh,
|
||||
MFEM_ASSERT( ( stride == 3 * sizeof(double) ),
|
||||
"Unexpected stride for Vertex");
|
||||
|
||||
n_mesh["coordsets/coords/type"] = "explicit";
|
||||
Node &n_mesh_coords = n_mesh["coordsets"][coordset_name];
|
||||
n_mesh_coords["type"] = "explicit";
|
||||
|
||||
|
||||
double *coords_ptr = mesh->GetVertex(0);
|
||||
|
||||
n_mesh["coordsets/coords/values/x"].set_external(coords_ptr,
|
||||
num_vertices,
|
||||
0,
|
||||
stride);
|
||||
n_mesh_coords["values/x"].set_external(coords_ptr,
|
||||
num_vertices,
|
||||
0,
|
||||
stride);
|
||||
|
||||
if (dim >= 2)
|
||||
{
|
||||
n_mesh["coordsets/coords/values/y"].set_external(coords_ptr,
|
||||
num_vertices,
|
||||
sizeof(double),
|
||||
stride);
|
||||
n_mesh_coords["values/y"].set_external(coords_ptr,
|
||||
num_vertices,
|
||||
sizeof(double),
|
||||
stride);
|
||||
}
|
||||
if (dim >= 3)
|
||||
{
|
||||
n_mesh["coordsets/coords/values/z"].set_external(coords_ptr,
|
||||
num_vertices,
|
||||
sizeof(double) * 2,
|
||||
stride);
|
||||
n_mesh_coords["values/z"].set_external(coords_ptr,
|
||||
num_vertices,
|
||||
sizeof(double) * 2,
|
||||
stride);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////
|
||||
// Setup main topo "main"
|
||||
// Setup main topo
|
||||
////////////////////////////////////////////
|
||||
|
||||
Node &n_topo = n_mesh["topologies/main"];
|
||||
Node &n_topo = n_mesh["topologies"][main_topology_name];
|
||||
|
||||
n_topo["type"] = "unstructured";
|
||||
n_topo["coordset"] = "coords";
|
||||
n_topo["coordset"] = coordset_name;
|
||||
|
||||
Element::Type ele_type = static_cast<Element::Type>(mesh->GetElement(
|
||||
0)->GetType());
|
||||
@@ -702,7 +740,8 @@ ConduitDataCollection::MeshToBlueprintMesh(Mesh *mesh,
|
||||
if (gf_mesh_nodes != NULL)
|
||||
{
|
||||
GridFunctionToBlueprintField(gf_mesh_nodes,
|
||||
n_mesh["fields/mesh_nodes"]);
|
||||
n_mesh["fields/mesh_nodes"],
|
||||
main_topology_name);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////
|
||||
@@ -712,7 +751,7 @@ ConduitDataCollection::MeshToBlueprintMesh(Mesh *mesh,
|
||||
Node &n_mesh_att = n_mesh["fields/element_attribute"];
|
||||
|
||||
n_mesh_att["association"] = "element";
|
||||
n_mesh_att["topology"] = "main";
|
||||
n_mesh_att["topology"] = main_topology_name;
|
||||
n_mesh_att["values"].set(DataType::c_int(num_ele));
|
||||
|
||||
int_array att_vals = n_mesh_att["values"].value();
|
||||
@@ -728,10 +767,12 @@ ConduitDataCollection::MeshToBlueprintMesh(Mesh *mesh,
|
||||
// guard vs if we have boundary elements
|
||||
if (mesh->GetNBE() > 0)
|
||||
{
|
||||
Node &n_bndry_topo = n_mesh["topologies/boundary"];
|
||||
n_topo["boundary_topology"] = boundary_topology_name;
|
||||
|
||||
Node &n_bndry_topo = n_mesh["topologies"][boundary_topology_name];
|
||||
|
||||
n_bndry_topo["type"] = "unstructured";
|
||||
n_bndry_topo["coordset"] = "coords";
|
||||
n_bndry_topo["coordset"] = coordset_name;
|
||||
|
||||
Element::Type bndry_ele_type = static_cast<Element::Type>(mesh->GetBdrElement(
|
||||
0)->GetType());
|
||||
@@ -767,7 +808,7 @@ ConduitDataCollection::MeshToBlueprintMesh(Mesh *mesh,
|
||||
Node &n_bndry_mesh_att = n_mesh["fields/boundary_attribute"];
|
||||
|
||||
n_bndry_mesh_att["association"] = "element";
|
||||
n_bndry_mesh_att["topology"] = "boundary";
|
||||
n_bndry_mesh_att["topology"] = boundary_topology_name;
|
||||
n_bndry_mesh_att["values"].set(DataType::c_int(num_bndry_ele));
|
||||
|
||||
int_array bndry_att_vals = n_bndry_mesh_att["values"].value();
|
||||
@@ -781,10 +822,11 @@ ConduitDataCollection::MeshToBlueprintMesh(Mesh *mesh,
|
||||
//---------------------------------------------------------------------------//
|
||||
void
|
||||
ConduitDataCollection::GridFunctionToBlueprintField(mfem::GridFunction *gf,
|
||||
Node &n_field)
|
||||
Node &n_field,
|
||||
const std::string &main_topology_name)
|
||||
{
|
||||
n_field["basis"] = gf->FESpace()->FEColl()->Name();
|
||||
n_field["topology"] = "main";
|
||||
n_field["topology"] = main_topology_name;
|
||||
|
||||
int vdim = gf->FESpace()->GetVDim();
|
||||
int ndofs = gf->FESpace()->GetNDofs();
|
||||
|
||||
@@ -148,17 +148,25 @@ public:
|
||||
|
||||
Zero-copies as much data as possible.
|
||||
|
||||
Describes the mesh's coordinates with a coordinate set entry named
|
||||
`coords`. Describes the mesh with a topology entry named 'main'. If the
|
||||
mesh has nodes, these are described in a field entry named
|
||||
`mesh_nodes`. If the mesh has an attribute field, this is described in a
|
||||
field entry named `mesh_attribute`.
|
||||
@a coordset_name, @a main_topology_name, and @a boundary_topology_name
|
||||
control the names used for the mesh blueprint entries.
|
||||
|
||||
With the default set of names, this method describes the mesh's
|
||||
coordinates with a coordinate set entry named `coords`. Describes the
|
||||
mesh with a topology entry named 'main'. If the mesh has nodes, these
|
||||
are described in a field entry named `mesh_nodes`. If the mesh has an
|
||||
attribute field, this is described in a field entry named
|
||||
`mesh_attribute`.
|
||||
|
||||
If the mesh has boundary info, this is described in a topology entry
|
||||
named `boundary`. If the boundary has an attribute field, this is
|
||||
described in a field entry named `boundary_attribute`.
|
||||
*/
|
||||
static void MeshToBlueprintMesh(Mesh *m, conduit::Node &out);
|
||||
static void MeshToBlueprintMesh(Mesh *m,
|
||||
conduit::Node &out,
|
||||
const std::string &coordset_name = "coords",
|
||||
const std::string &main_topology_name = "main",
|
||||
const std::string &boundary_topology_name = "boundary");
|
||||
|
||||
/// Describes a MFEM grid function using the mesh blueprint
|
||||
/** Sets up passed conduit::Node out to describe the given grid function
|
||||
@@ -166,18 +174,26 @@ public:
|
||||
|
||||
Zero-copies as much data as possible.
|
||||
|
||||
The resulting field is associated with the topology `main`.
|
||||
@a main_toplogy_name is used to set the associated topology name.
|
||||
With the default setting, the resulting field is associated with the
|
||||
topology `main`.
|
||||
*/
|
||||
static void GridFunctionToBlueprintField(GridFunction *gf, conduit::Node &out);
|
||||
static void GridFunctionToBlueprintField(GridFunction *gf,
|
||||
conduit::Node &out,
|
||||
const std::string &main_topology_name = "main");
|
||||
|
||||
/// Constructs and MFEM mesh from a Conduit Blueprint Description
|
||||
/** If zero_copy == true, tries to construct a mesh that points to the data
|
||||
/** @a main_topology_name is used to select which topology to use, when
|
||||
empty ("") the first topology entry will be used.
|
||||
|
||||
If zero_copy == true, tries to construct a mesh that points to the data
|
||||
described by the conduit node. This is only possible if the data in the
|
||||
node matches the data types needed for the MFEM API (ints for
|
||||
connectivity, doubles for field values, etc). If these constraints are
|
||||
not met, a mesh that owns the data is created and returned.
|
||||
*/
|
||||
static Mesh *BlueprintMeshToMesh(const conduit::Node &n_mesh,
|
||||
const std::string &main_toplogy_name = "",
|
||||
bool zero_copy = false);
|
||||
|
||||
/// Constructs and MFEM Grid Function from a Conduit Blueprint Description
|
||||
|
||||
-1337
File diff suppressed because it is too large
Load Diff
+49
-14
@@ -10,6 +10,7 @@
|
||||
// Software Foundation) version 2.1 dated February 1999.
|
||||
|
||||
#include "fem.hpp"
|
||||
#include "../mesh/nurbs.hpp"
|
||||
#include "../general/text.hpp"
|
||||
#include "picojson.h"
|
||||
|
||||
@@ -331,6 +332,25 @@ DataCollection::~DataCollection()
|
||||
|
||||
// class VisItDataCollection implementation
|
||||
|
||||
void VisItDataCollection::UpdateMeshInfo()
|
||||
{
|
||||
if (mesh)
|
||||
{
|
||||
spatial_dim = mesh->SpaceDimension();
|
||||
topo_dim = mesh->Dimension();
|
||||
if (mesh->NURBSext)
|
||||
{
|
||||
visit_levels_of_detail =
|
||||
std::max(visit_levels_of_detail, mesh->NURBSext->GetOrder());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
spatial_dim = 0;
|
||||
topo_dim = 0;
|
||||
}
|
||||
}
|
||||
|
||||
VisItDataCollection::VisItDataCollection(const std::string& collection_name,
|
||||
Mesh *mesh)
|
||||
: DataCollection(collection_name, mesh)
|
||||
@@ -338,17 +358,10 @@ VisItDataCollection::VisItDataCollection(const std::string& collection_name,
|
||||
appendRankToFileName = true; // always include rank in file names
|
||||
cycle = 0; // always include cycle in directory names
|
||||
|
||||
if (mesh)
|
||||
{
|
||||
spatial_dim = mesh->SpaceDimension();
|
||||
topo_dim = mesh->Dimension();
|
||||
}
|
||||
else
|
||||
{
|
||||
spatial_dim = 0;
|
||||
topo_dim = 0;
|
||||
}
|
||||
visit_levels_of_detail = 1;
|
||||
visit_max_levels_of_detail = 32;
|
||||
|
||||
UpdateMeshInfo();
|
||||
}
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
@@ -362,9 +375,11 @@ VisItDataCollection::VisItDataCollection(MPI_Comm comm,
|
||||
MPI_Comm_size(comm, &num_procs);
|
||||
appendRankToFileName = true; // always include rank in file names
|
||||
cycle = 0; // always include cycle in directory names
|
||||
spatial_dim = 0;
|
||||
topo_dim = 0;
|
||||
|
||||
visit_levels_of_detail = 1;
|
||||
visit_max_levels_of_detail = 32;
|
||||
|
||||
UpdateMeshInfo();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -372,8 +387,7 @@ void VisItDataCollection::SetMesh(Mesh *new_mesh)
|
||||
{
|
||||
DataCollection::SetMesh(new_mesh);
|
||||
appendRankToFileName = true;
|
||||
spatial_dim = mesh->SpaceDimension();
|
||||
topo_dim = mesh->Dimension();
|
||||
UpdateMeshInfo();
|
||||
}
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
@@ -392,6 +406,26 @@ void VisItDataCollection::RegisterField(const std::string& name,
|
||||
{
|
||||
DataCollection::RegisterField(name, gf);
|
||||
field_info_map[name] = VisItFieldInfo("nodes", gf->VectorDim());
|
||||
|
||||
int LOD = 1;
|
||||
if (gf->FESpace()->GetNURBSext())
|
||||
{
|
||||
LOD = gf->FESpace()->GetNURBSext()->GetOrder();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int e=0; e<gf->FESpace()->GetNE() ; e++)
|
||||
{
|
||||
LOD = std::max(LOD,gf->FESpace()->GetFE(e)->GetOrder());
|
||||
}
|
||||
}
|
||||
|
||||
visit_levels_of_detail = std::max(visit_levels_of_detail, LOD);
|
||||
}
|
||||
|
||||
void VisItDataCollection::SetLevelsOfDetail(int levels_of_detail)
|
||||
{
|
||||
visit_levels_of_detail = levels_of_detail;
|
||||
}
|
||||
|
||||
void VisItDataCollection::SetMaxLevelsOfDetail(int max_levels_of_detail)
|
||||
@@ -595,6 +629,7 @@ std::string VisItDataCollection::GetVisItRootString()
|
||||
{
|
||||
ftags["assoc"] = picojson::value((it->second).association);
|
||||
ftags["comps"] = picojson::value(to_string((it->second).num_components));
|
||||
ftags["lod"] = picojson::value(to_string(visit_levels_of_detail));
|
||||
field["path"] = picojson::value(path_str + it->first + file_ext_format);
|
||||
field["tags"] = picojson::value(ftags);
|
||||
fields[it->first] = picojson::value(field);
|
||||
|
||||
@@ -398,6 +398,7 @@ protected:
|
||||
// Additional data needed in the VisIt root file, which describes the mesh
|
||||
// and all the fields in the collection
|
||||
int spatial_dim, topo_dim;
|
||||
int visit_levels_of_detail;
|
||||
int visit_max_levels_of_detail;
|
||||
std::map<std::string, VisItFieldInfo> field_info_map;
|
||||
typedef std::map<std::string, VisItFieldInfo>::iterator FieldInfoMapIterator;
|
||||
@@ -407,6 +408,8 @@ protected:
|
||||
/// Read in a VisIt root file in JSON format
|
||||
void ParseVisItRootString(const std::string& json);
|
||||
|
||||
void UpdateMeshInfo();
|
||||
|
||||
// Helper functions for Load()
|
||||
void LoadVisItRootFile(const std::string& root_name);
|
||||
void LoadMesh();
|
||||
@@ -437,6 +440,9 @@ public:
|
||||
/// Add a grid function to the collection and update the root file
|
||||
virtual void RegisterField(const std::string& field_name, GridFunction *gf);
|
||||
|
||||
/// Set VisIt parameter: default levels of detail for the MultiresControl
|
||||
void SetLevelsOfDetail(int levels_of_detail);
|
||||
|
||||
/// Set VisIt parameter: maximum levels of detail for the MultiresControl
|
||||
void SetMaxLevelsOfDetail(int max_levels_of_detail);
|
||||
|
||||
|
||||
@@ -1,760 +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.
|
||||
|
||||
//This file contains useful functions to compute fluxes for DG methods.
|
||||
|
||||
#include <vector>
|
||||
#include "fem.hpp"
|
||||
#include "dalg.hpp"
|
||||
|
||||
using std::vector;
|
||||
using std::pair;
|
||||
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the canonical coordinate vectors e_1 and e_2.
|
||||
*/
|
||||
void getBaseVector2D(Vector& e1, Vector& e2)
|
||||
{
|
||||
e1.SetSize(2);
|
||||
e1(0) = 1;
|
||||
e1(1) = 0;
|
||||
e2.SetSize(2);
|
||||
e2(0) = 0;
|
||||
e2(1) = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the canonical coordinate vectors e_1, e_2 and e_3.
|
||||
*/
|
||||
void getBaseVector3D(Vector& e1, Vector& e2, Vector& e3)
|
||||
{
|
||||
e1.SetSize(3);
|
||||
e1(0) = 1;
|
||||
e1(1) = 0;
|
||||
e1(2) = 0;
|
||||
e2.SetSize(3);
|
||||
e2(0) = 0;
|
||||
e2(1) = 1;
|
||||
e2(2) = 0;
|
||||
e3.SetSize(3);
|
||||
e3(0) = 0;
|
||||
e3(1) = 0;
|
||||
e3(2) = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* A function that initialize the local coordinate base for a face with
|
||||
* indice face_ind.
|
||||
* This returns the local face coordinate base expressed in reference
|
||||
* element coordinate.
|
||||
*/
|
||||
// Highly dependent of the node ordering from geom.cpp
|
||||
void InitFaceCoord2D(const int face_id, IntMatrix& base)
|
||||
{
|
||||
//Vector e1,e2;
|
||||
//getBaseVector2D(e1,e2);
|
||||
base.Zero();
|
||||
switch(face_id)
|
||||
{
|
||||
case 0://SOUTH
|
||||
base(0,0)= 1;//base.SetCol(0, e1);
|
||||
base(1,1)=-1;//base.SetCol(1,-e2);
|
||||
break;
|
||||
case 1://EAST
|
||||
base(1,0)= 1;//base.SetCol(0, e2);
|
||||
base(0,1)= 1;//base.SetCol(1, e1);
|
||||
break;
|
||||
case 2://NORTH
|
||||
base(0,0)=-1;//base.SetCol(0,-e1);
|
||||
base(1,1)= 1;//base.SetCol(1, e2);
|
||||
break;
|
||||
case 3://WEST
|
||||
base(1,0)=-1;//base.SetCol(0,-e2);
|
||||
base(0,1)= 1;//base.SetCol(1, e1);
|
||||
break;
|
||||
default:
|
||||
mfem_error("The face_ind exceeds the number of faces in this dimension.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Highly dependent of the node ordering from geom.cpp
|
||||
void InitFaceCoord3D(const int face_id, IntMatrix& base)
|
||||
{
|
||||
//Vector e1,e2,e3;
|
||||
//getBaseVector3D(e1,e2,e3);
|
||||
base.Zero();
|
||||
switch(face_id)
|
||||
{
|
||||
case 0://BOTTOM
|
||||
base(0,0)= 1;//base.SetCol(0, e1);
|
||||
base(1,1)=-1;//base.SetCol(1,-e2);
|
||||
base(2,2)=-1;//base.SetCol(2,-e3);
|
||||
break;
|
||||
case 1://SOUTH
|
||||
base(0,0)= 1;//base.SetCol(0, e1);
|
||||
base(2,1)= 1;//base.SetCol(1, e3);
|
||||
base(1,2)=-1;//base.SetCol(2,-e2);
|
||||
break;
|
||||
case 2://EAST
|
||||
base(1,0)= 1;//base.SetCol(0, e2);
|
||||
base(2,1)= 1;//base.SetCol(1, e3);
|
||||
base(0,2)= 1;//base.SetCol(2, e1);
|
||||
break;
|
||||
case 3://NORTH
|
||||
base(0,0)=-1;//base.SetCol(0,-e1);
|
||||
base(2,1)= 1;//base.SetCol(1, e3);
|
||||
base(1,2)= 1;//base.SetCol(2, e2);
|
||||
break;
|
||||
case 4://WEST
|
||||
base(1,0)=-1;//base.SetCol(0,-e2);
|
||||
base(2,1)= 1;//base.SetCol(1, e3);
|
||||
base(0,2)=-1;//base.SetCol(2,-e1);
|
||||
break;
|
||||
case 5://TOP
|
||||
base(0,0)= 1;//base.SetCol(0, e1);
|
||||
base(1,1)= 1;//base.SetCol(1, e2);
|
||||
base(2,2)= 1;//base.SetCol(2, e3);
|
||||
break;
|
||||
default:
|
||||
mfem_error("The face_ind exceeds the number of faces in this dimension.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Maps the coordinate vectors of the first face to the coordinate vectors of the second face.
|
||||
* nb_rot is the number of rotation to opperate so that the first node of each face match.
|
||||
* The result map contains pairs of int, where the first int is the cofficient, and the
|
||||
* second int is the indice of the second face vector.
|
||||
*/
|
||||
// There shouldn't be any rotation in 2D.
|
||||
void GetLocalCoordMap2D(vector<pair<int,int> >& map, const int nb_rot)
|
||||
{
|
||||
map.resize(2);
|
||||
//First and second coordinate vectors should always be of opposite direction in 2D.
|
||||
//TODO Maybe not
|
||||
map[0] = pair<int,int>(-1,0);
|
||||
map[1] = pair<int,int>(-1,1);
|
||||
}
|
||||
|
||||
// Default parameter nb_rot=0 should be only use with a structured mesh.
|
||||
// Rotations follow the ordering of the nodes.
|
||||
/*void GetLocalCoordMap3D(vector<pair<int,int> >& map, const int nb_rot)
|
||||
{
|
||||
map.resize(3);
|
||||
// Normal to the face are always of opposite direction
|
||||
map[2] = pair<int,int>(-1,2);
|
||||
// nb_rot determines how local coordinates are oriented from one face to the other.
|
||||
// See case 2 for an example.
|
||||
switch(nb_rot)
|
||||
{
|
||||
case 0:
|
||||
map[0] = pair<int,int>( 1,1);
|
||||
map[1] = pair<int,int>( 1,0);
|
||||
break;
|
||||
case 1:
|
||||
map[0] = pair<int,int>(-1,0);
|
||||
map[1] = pair<int,int>( 1,1);
|
||||
break;
|
||||
case 2:
|
||||
//first vector equals -1 times the second vector of the other face coordinates
|
||||
map[0] = pair<int,int>(-1,1);
|
||||
//second vector equals -1 times the first vector of the other face coordinates
|
||||
map[1] = pair<int,int>(-1,0);
|
||||
break;
|
||||
case 3:
|
||||
map[0] = pair<int,int>( 1,0);
|
||||
map[1] = pair<int,int>(-1,1);
|
||||
break;
|
||||
default:
|
||||
mfem_error("There shouldn't be that many rotations.");
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
|
||||
void GetLocalCoordMap3D(vector< pair<int,int> >& map, const int orientation)
|
||||
{
|
||||
map.resize(3);
|
||||
// orientation determines how local coordinates are oriented from one face to the other.
|
||||
// See case 2 for an example.
|
||||
switch(orientation)
|
||||
{
|
||||
case 0://{0, 1, 2, 3}
|
||||
map[0] = pair<int,int>( 1,0);
|
||||
map[1] = pair<int,int>( 1,1);
|
||||
map[2] = pair<int,int>( 1,2);
|
||||
break;
|
||||
case 1://{0, 3, 2, 1}
|
||||
map[0] = pair<int,int>( 1,1);
|
||||
map[1] = pair<int,int>( 1,0);
|
||||
map[2] = pair<int,int>(-1,2);
|
||||
break;
|
||||
case 2://{1, 2, 3, 0}
|
||||
//first vector equals -1 times the second vector of the other face coordinates
|
||||
map[0] = pair<int,int>(-1,1);
|
||||
//second vector equals -1 times the first vector of the other face coordinates
|
||||
map[1] = pair<int,int>( 1,0);
|
||||
//third vector equals -1 times the third vector of the other face coordinates
|
||||
map[2] = pair<int,int>( 1,2);
|
||||
break;
|
||||
case 3://{1, 0, 3, 2}
|
||||
map[0] = pair<int,int>(-1,0);
|
||||
map[1] = pair<int,int>( 1,1);
|
||||
map[2] = pair<int,int>(-1,2);
|
||||
break;
|
||||
case 4://{2, 3, 0, 1}
|
||||
map[0] = pair<int,int>(-1,0);
|
||||
map[1] = pair<int,int>(-1,1);
|
||||
map[2] = pair<int,int>( 1,2);
|
||||
break;
|
||||
case 5://{2, 1, 0, 3}
|
||||
map[0] = pair<int,int>(-1,1);
|
||||
map[1] = pair<int,int>(-1,0);
|
||||
map[2] = pair<int,int>(-1,2);
|
||||
break;
|
||||
case 6://{3, 0, 1, 2}
|
||||
map[0] = pair<int,int>( 1,1);
|
||||
map[1] = pair<int,int>(-1,0);
|
||||
map[2] = pair<int,int>( 1,2);
|
||||
break;
|
||||
case 7://{3, 2, 1, 0}
|
||||
map[0] = pair<int,int>( 1,0);
|
||||
map[1] = pair<int,int>(-1,1);
|
||||
map[2] = pair<int,int>(-1,2);
|
||||
break;
|
||||
default:
|
||||
mfem_error("There shouldn't be that many orientations.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the change of matrix P from base_K2 to base_K1 according to the mapping map.
|
||||
*/
|
||||
void GetChangeOfBasis(const IntMatrix& base_K1, IntMatrix& base_K2,
|
||||
const vector<pair<int,int> >& map, IntMatrix& P)
|
||||
{
|
||||
/* int dim = map.size();
|
||||
for (int j = 0; j < dim; j++)
|
||||
{
|
||||
int i = 0;
|
||||
//we look if the vector is colinear with e_j
|
||||
// Can be replaced by base_K2(j,i)!=0
|
||||
while (base_K2(j,i)!=0) i++;
|
||||
int coeff = map[i].first;
|
||||
int ind = map[i].second;
|
||||
for (int k = 0; k < dim; ++k)
|
||||
{
|
||||
P(k,j) = coeff * base_K1(k,ind);
|
||||
}
|
||||
}*/
|
||||
//TODO make it valid for 3D!!!
|
||||
int dim = base_K1.Height();
|
||||
// for (int i = 0; i < dim; ++i)
|
||||
// {
|
||||
// int coeff = map[i].first;
|
||||
// int ind = map[i].second;
|
||||
// for (int j = 0; j < dim; ++j)
|
||||
// {
|
||||
// int sum = 0;
|
||||
// for (int k = 0; k < dim; ++k)
|
||||
// {
|
||||
// sum += coeff*base_K1(i,k)*base_K2(j,k);
|
||||
// }
|
||||
// P(ind,j) = sum;
|
||||
// }
|
||||
// }
|
||||
int i,j,ind;
|
||||
double coeff;
|
||||
for (int n = 0; n < dim; ++n)
|
||||
{
|
||||
i = 0;
|
||||
while( base_K1(i,n) == 0 ) ++i;
|
||||
j = 0;
|
||||
ind = map[n].second;
|
||||
while( base_K2(j,ind) == 0 ) ++j;
|
||||
coeff = map[n].first;
|
||||
P(i,j) = coeff * base_K1(i,n) * base_K2(j,ind);
|
||||
}
|
||||
}
|
||||
|
||||
void GetChangeOfBasis2D(const int face_id1, const int face_id2, IntMatrix& P)
|
||||
{
|
||||
// We add 8 because of C++ stupid definition of modulo
|
||||
int nb_rot = (8 + face_id2 - face_id1 - 2)%4;
|
||||
// if (face_id2!=-1)
|
||||
// {
|
||||
// cout << "face_id1=" << face_id1 << ", face_id2=" << face_id2 << ", nb_rot=" << nb_rot << endl;
|
||||
// }
|
||||
P.Zero();
|
||||
switch(nb_rot)
|
||||
{
|
||||
case 0://Id=R^4
|
||||
P(0,0) = 1;
|
||||
P(1,1) = 1;
|
||||
break;
|
||||
case 1://R
|
||||
P(1,0) = 1;
|
||||
P(0,1) =-1;
|
||||
break;
|
||||
case 2://R²
|
||||
P(0,0) =-1;
|
||||
P(1,1) =-1;
|
||||
break;
|
||||
case 3://R³
|
||||
P(1,0) =-1;
|
||||
P(0,1) = 1;
|
||||
break;
|
||||
default:mfem_error("C++ modulo error in GetChangeOfBasis2D");
|
||||
}
|
||||
}
|
||||
|
||||
void GetChangeOfBasis(const int permutation, IntMatrix& P)
|
||||
{
|
||||
int code1 = permutation/100;
|
||||
int ind1 = code1/2;
|
||||
int val1 = code1%2==0?-1:1;
|
||||
int code2 = (permutation%100)/10;
|
||||
int ind2 = code2/2;
|
||||
int val2 = code2%2==0?-1:1;
|
||||
int code3 = permutation%10;
|
||||
int ind3 = code3/2;
|
||||
int val3 = code3%2==0?-1:1;
|
||||
P.Zero();
|
||||
P(ind1,0) = val1;
|
||||
P(ind2,1) = val2;
|
||||
P(ind3,2) = val3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the face_id that identifies the face on the reference element, and nb_rot the
|
||||
* "rotations" the face did between reference to physical spaces.
|
||||
*/
|
||||
void GetIdRotInfo(const int face_info, int& face_id, int& nb_rot){
|
||||
int orientation = face_info % 64;
|
||||
face_id = face_info / 64;
|
||||
// Test if my understanding of mfem code is correct, error if not
|
||||
//MFEM_ASSERT(orientation % 2 == 0, "Unexpected inside out face");
|
||||
nb_rot = orientation;// / 2;
|
||||
}
|
||||
|
||||
void GetFaceInfo(const Mesh* mesh, const int face, int& ind_elt1, int& ind_elt2, int& face_id1, int& face_id2, int& nb_rot1, int& nb_rot2)
|
||||
{
|
||||
// We collect the indices of the two elements on the face, element1 is the master element,
|
||||
// the one that defines the normal to the face.
|
||||
mesh->GetFaceElements(face,&ind_elt1,&ind_elt2);
|
||||
int info_elt1, info_elt2;
|
||||
// We collect the informations on the face for the two elements.
|
||||
mesh->GetFaceInfos(face,&info_elt1,&info_elt2);
|
||||
GetIdRotInfo(info_elt1,face_id1,nb_rot1);//nb_rot1 is always 0 by convention
|
||||
GetIdRotInfo(info_elt2,face_id2,nb_rot2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the permutation id, so that we can permute dofs to be in a structured case.
|
||||
*/
|
||||
int Permutation2D(const int face_id_trial, const int face_id_test)
|
||||
{
|
||||
int perm = face_id_trial - face_id_test - 2;
|
||||
perm = perm < 0 ? perm+4 : perm;
|
||||
return perm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an integer that encrypts P.
|
||||
*/
|
||||
void Permutation3D(const int face_id1, const int face_id2, const int orientation, int& perm1, int& perm2)
|
||||
{
|
||||
IntMatrix K1(3,3);
|
||||
K1.Zero();
|
||||
InitFaceCoord3D(face_id1, K1);
|
||||
IntMatrix K2(3,3);
|
||||
K2.Zero();
|
||||
InitFaceCoord3D(face_id2, K2);
|
||||
vector< pair<int,int> > map;
|
||||
GetLocalCoordMap3D(map, orientation);
|
||||
IntMatrix P(3,3);
|
||||
P.Zero();
|
||||
GetChangeOfBasis(K1, K2, map, P);
|
||||
// cout << "orientation=" << orientation << endl;
|
||||
// cout << P(0,0) << ", " << P(0,1) << ", " << P(0,2) << endl;
|
||||
// cout << P(1,0) << ", " << P(1,1) << ", " << P(1,2) << endl;
|
||||
// cout << P(2,0) << ", " << P(2,1) << ", " << P(2,2) << endl;
|
||||
perm1 = 0;
|
||||
// Encrypts first column
|
||||
perm1 += 100*(0*(P(0,0)==-1) + 1*(P(0,0)==1) + 2*(P(1,0)==-1) + 3*(P(1,0)==1) + 4*(P(2,0)==-1) + 5*(P(2,0)==1));
|
||||
// Encrypts second column
|
||||
perm1 += 10 *(0*(P(0,1)==-1) + 1*(P(0,1)==1) + 2*(P(1,1)==-1) + 3*(P(1,1)==1) + 4*(P(2,1)==-1) + 5*(P(2,1)==1));
|
||||
// Encrypts third column
|
||||
perm1 += (0*(P(0,2)==-1) + 1*(P(0,2)==1) + 2*(P(1,2)==-1) + 3*(P(1,2)==1) + 4*(P(2,2)==-1) + 5*(P(2,2)==1));
|
||||
// Encrypts the transposed permutation matrix in a second integer.
|
||||
perm2 = 0;
|
||||
perm2 += 100*(0*(P(0,0)==-1) + 1*(P(0,0)==1) + 2*(P(0,1)==-1) + 3*(P(0,1)==1) + 4*(P(0,2)==-1) + 5*(P(0,2)==1));
|
||||
perm2 += 10 *(0*(P(1,0)==-1) + 1*(P(1,0)==1) + 2*(P(1,1)==-1) + 3*(P(1,1)==1) + 4*(P(1,2)==-1) + 5*(P(1,2)==1));
|
||||
perm2 += (0*(P(2,0)==-1) + 1*(P(2,0)==1) + 2*(P(2,1)==-1) + 3*(P(2,1)==1) + 4*(P(2,2)==-1) + 5*(P(2,2)==1));
|
||||
}
|
||||
|
||||
void GetPermutation(const int dim, const int face_id1, const int face_id2, const int orientation, int& perm1, int& perm2)
|
||||
{
|
||||
switch(dim){
|
||||
case 1:
|
||||
mfem_error("Not yet implemented");
|
||||
break;
|
||||
case 2:
|
||||
perm1 = Permutation2D(face_id1, face_id2);
|
||||
perm2 = Permutation2D(face_id2, face_id1);
|
||||
break;
|
||||
case 3:
|
||||
Permutation3D(face_id1, face_id2, orientation, perm1, perm2);
|
||||
break;
|
||||
default:
|
||||
mfem_error("Dimension of the problem too high.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hardcoded permutation due to arbitrary hardcoded orientation in geom.cpp.
|
||||
* Will break if geom.cpp changes.
|
||||
* This function could be improved by returning the 'permutation' parameters once,
|
||||
* instead of recomputing them for every quadrature point...
|
||||
*/
|
||||
int GetFaceQuadIndex3D(const int face_id, const int orientation, const int qind, const int quads, Tensor<1,int>& ind_f)
|
||||
{
|
||||
// cout << "orientation=" << orientation << endl;
|
||||
int& k1 = ind_f(0);
|
||||
int& k2 = ind_f(1);
|
||||
int kf1,kf2;
|
||||
kf1 = qind%quads;
|
||||
kf2 = qind/quads;
|
||||
switch(face_id)
|
||||
{
|
||||
case 0://BOTTOM
|
||||
switch(orientation)
|
||||
{
|
||||
case 0://{0, 1, 2, 3}
|
||||
k1 = kf1;
|
||||
k2 = quads-1-kf2;
|
||||
break;
|
||||
case 1://{0, 3, 2, 1}
|
||||
k1 = quads-1-kf2;
|
||||
k2 = kf1;
|
||||
break;
|
||||
case 2://{1, 2, 3, 0}
|
||||
k1 = quads-1-kf2;
|
||||
k2 = quads-1-kf1;
|
||||
break;
|
||||
case 3://{1, 0, 3, 2}
|
||||
k1 = quads-1-kf1;
|
||||
k2 = quads-1-kf2;
|
||||
break;
|
||||
case 4://{2, 3, 0, 1}
|
||||
k1 = quads-1-kf1;
|
||||
k2 = kf2;
|
||||
break;
|
||||
case 5://{2, 1, 0, 3}
|
||||
k1 = kf2;
|
||||
k2 = quads-1-kf1;
|
||||
break;
|
||||
case 6://{3, 0, 1, 2}
|
||||
k1 = kf2;
|
||||
k2 = kf1;
|
||||
break;
|
||||
case 7://{3, 2, 1, 0}
|
||||
k1 = kf1;
|
||||
k2 = kf2;
|
||||
break;
|
||||
default:
|
||||
mfem_error("This orientation does not exist in 3D");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1://SOUTH
|
||||
switch(orientation)
|
||||
{
|
||||
case 0://{0, 1, 2, 3}
|
||||
k1 = kf1;
|
||||
k2 = kf2;
|
||||
break;
|
||||
case 1://{0, 3, 2, 1}
|
||||
k1 = kf2;
|
||||
k2 = kf1;
|
||||
break;
|
||||
case 2://{1, 2, 3, 0}
|
||||
k1 = kf2;
|
||||
k2 = quads-1-kf1;
|
||||
break;
|
||||
case 3://{1, 0, 3, 2}
|
||||
k1 = quads-1-kf1;
|
||||
k2 = kf2;
|
||||
break;
|
||||
case 4://{2, 3, 0, 1}
|
||||
k1 = quads-1-kf1;
|
||||
k2 = quads-1-kf2;
|
||||
break;
|
||||
case 5://{2, 1, 0, 3}
|
||||
k1 = quads-1-kf2;
|
||||
k2 = quads-1-kf1;
|
||||
break;
|
||||
case 6://{3, 0, 1, 2}
|
||||
k1 = quads-1-kf2;
|
||||
k2 = kf1;
|
||||
break;
|
||||
case 7://{3, 2, 1, 0}
|
||||
k1 = kf1;
|
||||
k2 = quads-1-kf2;
|
||||
break;
|
||||
default:
|
||||
mfem_error("This orientation does not exist in 3D");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2://EAST
|
||||
switch(orientation)
|
||||
{
|
||||
case 0://{0, 1, 2, 3}
|
||||
k1 = kf1;
|
||||
k2 = kf2;
|
||||
break;
|
||||
case 1://{0, 3, 2, 1}
|
||||
k1 = kf2;
|
||||
k2 = kf1;
|
||||
break;
|
||||
case 2://{1, 2, 3, 0}
|
||||
k1 = kf2;
|
||||
k2 = quads-1-kf1;
|
||||
break;
|
||||
case 3://{1, 0, 3, 2}
|
||||
k1 = quads-1-kf1;
|
||||
k2 = kf2;
|
||||
break;
|
||||
case 4://{2, 3, 0, 1}
|
||||
k1 = quads-1-kf1;
|
||||
k2 = quads-1-kf2;
|
||||
break;
|
||||
case 5://{2, 1, 0, 3}
|
||||
k1 = quads-1-kf2;
|
||||
k2 = quads-1-kf1;
|
||||
break;
|
||||
case 6://{3, 0, 1, 2}
|
||||
k1 = quads-1-kf2;
|
||||
k2 = kf1;
|
||||
break;
|
||||
case 7://{3, 2, 1, 0}
|
||||
k1 = kf1;
|
||||
k2 = quads-1-kf2;
|
||||
break;
|
||||
default:
|
||||
mfem_error("This orientation does not exist in 3D");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3://NORTH
|
||||
switch(orientation)
|
||||
{
|
||||
case 0://{0, 1, 2, 3}
|
||||
k1 = quads-1-kf1;
|
||||
k2 = kf2;
|
||||
break;
|
||||
case 1://{0, 3, 2, 1}
|
||||
k1 = kf2;
|
||||
k2 = quads-1-kf1;
|
||||
break;
|
||||
case 2://{1, 2, 3, 0}
|
||||
k1 = kf2;
|
||||
k2 = kf1;
|
||||
break;
|
||||
case 3://{1, 0, 3, 2}
|
||||
k1 = kf1;
|
||||
k2 = kf2;
|
||||
break;
|
||||
case 4://{2, 3, 0, 1}
|
||||
k1 = kf1;
|
||||
k2 = quads-1-kf2;
|
||||
break;
|
||||
case 5://{2, 1, 0, 3}
|
||||
k1 = quads-1-kf2;
|
||||
k2 = kf1;
|
||||
break;
|
||||
case 6://{3, 0, 1, 2}
|
||||
k1 = quads-1-kf2;
|
||||
k2 = quads-1-kf1;
|
||||
break;
|
||||
case 7://{3, 2, 1, 0}
|
||||
k1 = quads-1-kf1;
|
||||
k2 = quads-1-kf2;
|
||||
break;
|
||||
default:
|
||||
mfem_error("This orientation does not exist in 3D");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 4://WEST
|
||||
switch(orientation)
|
||||
{
|
||||
case 0://{0, 1, 2, 3}
|
||||
k1 = quads-1-kf1;
|
||||
k2 = kf2;
|
||||
break;
|
||||
case 1://{0, 3, 2, 1}
|
||||
k1 = kf2;
|
||||
k2 = quads-1-kf1;
|
||||
break;
|
||||
case 2://{1, 2, 3, 0}
|
||||
k1 = kf2;
|
||||
k2 = kf1;
|
||||
break;
|
||||
case 3://{1, 0, 3, 2}
|
||||
k1 = kf1;
|
||||
k2 = kf2;
|
||||
break;
|
||||
case 4://{2, 3, 0, 1}
|
||||
k1 = kf1;
|
||||
k2 = quads-1-kf2;
|
||||
break;
|
||||
case 5://{2, 1, 0, 3}
|
||||
k1 = quads-1-kf2;
|
||||
k2 = kf1;
|
||||
break;
|
||||
case 6://{3, 0, 1, 2}
|
||||
k1 = quads-1-kf2;
|
||||
k2 = quads-1-kf1;
|
||||
break;
|
||||
case 7://{3, 2, 1, 0}
|
||||
k1 = quads-1-kf1;
|
||||
k2 = quads-1-kf2;
|
||||
break;
|
||||
default:
|
||||
mfem_error("This orientation does not exist in 3D");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 5://TOP
|
||||
switch(orientation)
|
||||
{
|
||||
case 0://{0, 1, 2, 3}
|
||||
k1 = kf1;
|
||||
k2 = kf2;
|
||||
break;
|
||||
case 1://{0, 3, 2, 1}
|
||||
k1 = kf2;
|
||||
k2 = kf1;
|
||||
break;
|
||||
case 2://{1, 2, 3, 0}
|
||||
k1 = kf2;
|
||||
k2 = quads-1-kf1;
|
||||
break;
|
||||
case 3://{1, 0, 3, 2}
|
||||
k1 = quads-1-kf1;
|
||||
k2 = kf2;
|
||||
break;
|
||||
case 4://{2, 3, 0, 1}
|
||||
k1 = quads-1-kf1;
|
||||
k2 = quads-1-kf2;
|
||||
break;
|
||||
case 5://{2, 1, 0, 3}
|
||||
k1 = quads-1-kf2;
|
||||
k2 = quads-1-kf1;
|
||||
break;
|
||||
case 6://{3, 0, 1, 2}
|
||||
k1 = quads-1-kf2;
|
||||
k2 = kf1;
|
||||
break;
|
||||
case 7://{3, 2, 1, 0}
|
||||
k1 = kf1;
|
||||
k2 = quads-1-kf2;
|
||||
break;
|
||||
default:
|
||||
mfem_error("This orientation does not exist in 3D");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
mfem_error("This face_id does not exist in 3D");
|
||||
break;
|
||||
}
|
||||
return k1 + quads*k2;
|
||||
}
|
||||
|
||||
int GetFaceQuadIndex(const int dim, const int face_id, const int orientation, const int qind, const int quads, Tensor<1,int>& ind_f)
|
||||
{
|
||||
int res = 0;
|
||||
switch(dim)
|
||||
{
|
||||
case 1:
|
||||
break;
|
||||
case 2:
|
||||
if(face_id<=1){//SOUTH or EAST (canonical ordering)
|
||||
res = ind_f(0) = qind;
|
||||
}else{//NORTH or WEST (counter-canonical ordering)
|
||||
res = ind_f(0) = quads-1-qind;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
res = GetFaceQuadIndex3D(face_id, orientation, qind, quads, ind_f);
|
||||
break;
|
||||
default:
|
||||
mfem_error("Dimension too high.");
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
const int GetGlobalQuadIndex(const int dim, const int face_id, const int quads, Tensor<1,int>& ind_f)
|
||||
{
|
||||
switch(dim)
|
||||
{
|
||||
case 1:
|
||||
if (face_id==0)//WEST
|
||||
{
|
||||
return 0;
|
||||
}else{//EAST
|
||||
return quads-1;
|
||||
}
|
||||
case 2:
|
||||
switch(face_id)
|
||||
{
|
||||
case 0://SOUTH
|
||||
return ind_f(0);
|
||||
case 1://EAST
|
||||
return quads-1 + ind_f(0)*quads;
|
||||
case 2://NORTH
|
||||
return ind_f(0) + (quads-1)*quads;
|
||||
case 3://WEST
|
||||
return ind_f(0)*quads;
|
||||
}
|
||||
case 3:
|
||||
switch(face_id)
|
||||
{
|
||||
case 0://BOTTOM
|
||||
return ind_f(0) + ind_f(1)*quads;
|
||||
case 1://SOUTH
|
||||
return ind_f(0) + ind_f(1)*quads*quads;
|
||||
case 2://EAST
|
||||
return (quads-1) + ind_f(0)*quads + ind_f(1)*quads*quads;
|
||||
case 3://NORTH
|
||||
return ind_f(0) + (quads-1)*quads + ind_f(1)*quads*quads;
|
||||
case 4://WEST
|
||||
return ind_f(0)*quads + ind_f(1)*quads*quads;
|
||||
case 5://TOP
|
||||
return ind_f(0) + ind_f(1)*quads + (quads-1)*quads*quads;
|
||||
}
|
||||
default:
|
||||
mfem_error("Dimension too high.");
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,119 +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.
|
||||
|
||||
//This file contains useful functions to compute fluxes for DG methods.
|
||||
|
||||
|
||||
#ifndef MFEM_DGFACEFUNC
|
||||
#define MFEM_DGFACEFUNC
|
||||
#include "dalg.hpp"
|
||||
|
||||
using std::vector;
|
||||
using std::pair;
|
||||
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns the canonical coordinate vectors e_1 and e_2.
|
||||
*/
|
||||
void getBaseVector2D(Vector& e1, Vector& e2);
|
||||
|
||||
/**
|
||||
* Returns the canonical coordinate vectors e_1, e_2 and e_3.
|
||||
*/
|
||||
void getBaseVector3D(Vector& e1, Vector& e2, Vector& e3);
|
||||
|
||||
/** A function that initialize the local coordinate base for a face with
|
||||
* indice face_ind.
|
||||
* This returns the local face coordinate base expressed in reference
|
||||
* element coordinate.
|
||||
*/
|
||||
// Highly dependent of the node ordering from geom.cpp
|
||||
void InitFaceCoord2D(const int face_id, IntMatrix& base);
|
||||
|
||||
// Highly dependent of the node ordering from geom.cpp
|
||||
void InitFaceCoord3D(const int face_id, IntMatrix& base);
|
||||
|
||||
/** Maps the coordinate vectors of the first face to the coordinate vectors of the second face.
|
||||
* nb_rot is the number of rotation to opperate so that the first node of each face match.
|
||||
* The result map contains pairs of int, where the first int is a direction cofficient,
|
||||
* and the second int is the indice of the second face vector.
|
||||
*/
|
||||
// There shouldn't be any rotation in 2D.
|
||||
void GetLocalCoordMap2D(vector<pair<int,int> >& map, const int nb_rot = 0);
|
||||
|
||||
// Rotations follow the ordering of the nodes.
|
||||
void GetLocalCoordMap3D(vector<pair<int,int> >& map, const int nb_rot);
|
||||
|
||||
/**
|
||||
* Returns the change of matrix P from base_K2 to base_K1 according to the mapping map.
|
||||
*/
|
||||
void GetChangeOfBasis(const IntMatrix& base_K1, IntMatrix& base_K2,
|
||||
const vector<pair<int,int> >& map, IntMatrix& P);
|
||||
|
||||
void GetChangeOfBasis(const int permutation, IntMatrix& P);
|
||||
|
||||
/**
|
||||
* Returns the change of coordinate from second element to first element on a 2D face.
|
||||
*/
|
||||
void GetChangeOfBasis2D(const int face_id1, const int face_id2, IntMatrix& P);
|
||||
|
||||
/**
|
||||
* Returns the indices, face ID, and number of rotations, of the two element sharing a face.
|
||||
* The number of rotations is relative to the element 1, so nb_rot1 is always 0.
|
||||
*/
|
||||
void GetFaceInfo(const Mesh* mesh, const int face,
|
||||
int& ind_elt1, int& ind_elt2,
|
||||
int& face_id1, int& face_id2,
|
||||
int& nb_rot1, int& nb_rot2);
|
||||
|
||||
/**
|
||||
* Returns the face_id that identifies the face on the reference element, and nb_rot the
|
||||
* "rotations" the face did between reference to physical spaces.
|
||||
*/
|
||||
void GetIdRotInfo(const int face_info, int& face_id, int& nb_rot);
|
||||
|
||||
/**
|
||||
* Returns an integer identifying the permutation to apply to be in structured-
|
||||
* like configuration for 2D hex meshes.
|
||||
*/
|
||||
int Permutation2D(const int face_id_trial, const int face_id_test);
|
||||
|
||||
/**
|
||||
* Returns an integer identifying the permutation to apply to be in structured-
|
||||
* like configuration for 3D hex meshes.
|
||||
*/
|
||||
void Permutation3D(const int face_id1, const int face_id2, const int orientation, int& perm1, int& perm2);
|
||||
|
||||
/**
|
||||
* Returns an integer identifying the permutation to apply to be in structured-
|
||||
* like configuration.
|
||||
*/
|
||||
void GetPermutation(const int dim, const int face_id1, const int face_id2, const int orientation, int& perm1, int& perm2);
|
||||
|
||||
int GetFaceQuadIndex3D(const int face_id, const int orientation, const int qind, const int quads, Tensor<1,int>& ind_f);
|
||||
|
||||
/**
|
||||
* Returns the indices of a quadrature point on the face of an hex element relative to the index of the quadrature
|
||||
* point on the reference face.
|
||||
*/
|
||||
int GetFaceQuadIndex(const int dim, const int face_id, const int orientation, const int qind, const int quads, Tensor<1,int>& ind_f);
|
||||
|
||||
/**
|
||||
* Returns the indices of a quadrature point on the element relative to the index of the quadrature
|
||||
* point on the reference face.
|
||||
*/
|
||||
const int GetGlobalQuadIndex(const int dim, const int face_id, const int quads, Tensor<1,int>& ind_f);
|
||||
|
||||
}
|
||||
|
||||
#endif // MFEM_DGFACEFUNC
|
||||
@@ -1,174 +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.
|
||||
|
||||
|
||||
// This file contains a prototype version for Discontinuous Galerkin Partial assembly
|
||||
|
||||
#ifndef MFEM_DGPABILININTEG
|
||||
#define MFEM_DGPABILININTEG
|
||||
|
||||
#include "../config/config.hpp"
|
||||
#include "bilininteg.hpp"
|
||||
#include "dalg.hpp"
|
||||
|
||||
#include "fem.hpp"
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include "../linalg/vector.hpp"
|
||||
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
/**
|
||||
* The different operators available for the Kernels
|
||||
*/
|
||||
enum PAOp { BtDB, BtDG, GtDB, GtDG };
|
||||
|
||||
|
||||
/**
|
||||
* A class that describes the Convection Equation using DG for Partial Assembly.
|
||||
*/
|
||||
class DGConvectionEquation
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Defines the Kernel to apply to the Domain
|
||||
*/
|
||||
static const PAOp OpName = BtDG;
|
||||
|
||||
/**
|
||||
* Defines the variables needed to build D for the Domain kernel
|
||||
*/
|
||||
struct Args {
|
||||
Args(VectorCoefficient& _q, double _a = 1.0, double _b = -1.0) : q(_q), a(_a), b(_b) {}
|
||||
VectorCoefficient& q;
|
||||
double a;
|
||||
double b;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the values of the D tensor at a given integration Point.
|
||||
*/
|
||||
void evalD(Tensor<1>& res, ElementTransformation *Tr, const IntegrationPoint& ip,
|
||||
const Args& args)
|
||||
{
|
||||
const int dim = res.size(0);
|
||||
Vector qvec(dim);
|
||||
const DenseMatrix& locD = Tr->AdjugateJacobian();
|
||||
args.q.Eval(qvec, *Tr, ip);
|
||||
for (int i = 0; i < dim; ++i)
|
||||
{
|
||||
double val = 0.0;
|
||||
for (int j = 0; j < dim; ++j)
|
||||
{
|
||||
val += locD(i,j) * qvec(j);
|
||||
}
|
||||
res(i) = ip.weight * args.a * val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the values of the D tensor at a given integration Point.
|
||||
*/
|
||||
void evalD(Tensor<1>& res, ElementTransformation *Tr, const IntegrationPoint& ip,
|
||||
const Tensor<2>& Jac, const Args& args)
|
||||
{
|
||||
const int dim = res.size(0);
|
||||
Vector qvec(dim);
|
||||
args.q.Eval(qvec, *Tr, ip);
|
||||
Tensor<2> Adj(dim,dim);
|
||||
adjugate(Jac,Adj);
|
||||
for (int i = 0; i < dim; ++i)
|
||||
{
|
||||
double val = 0.0;
|
||||
for (int j = 0; j < dim; ++j)
|
||||
{
|
||||
val += Adj(i,j) * qvec(j);
|
||||
}
|
||||
res(i) = ip.weight * args.a * val;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the Kernel to apply to the Faces
|
||||
*/
|
||||
static const PAOp FaceOpName = BtDB;
|
||||
|
||||
/**
|
||||
* Returns the values of the Dint and Dext tensors at a given integration Point for
|
||||
* each element over a face.
|
||||
*/
|
||||
void evalFaceD(double& res11, double& res21, double& res22, double& res12,
|
||||
const FaceElementTransformations* face_tr, const Vector& normal,
|
||||
const IntegrationPoint& ip1, const IntegrationPoint& ip2,
|
||||
const Args& args)
|
||||
{
|
||||
const int dim = normal.Size();
|
||||
Vector qvec(dim);
|
||||
// FIXME: qvec might be discontinuous if not constant with a periodic mesh
|
||||
// We should then use the evaluation on Elem2 and eip2
|
||||
args.q.Eval( qvec, *(face_tr->Elem1), ip1 );
|
||||
const double res = qvec * normal;
|
||||
const double a = -args.a, b = args.b;
|
||||
res11 = ip1.weight * ( a/2 * res + b * abs(res) );
|
||||
res21 = ip1.weight * ( a/2 * res - b * abs(res) );
|
||||
res22 = ip1.weight * ( - a/2 * res + b * abs(res) );
|
||||
res12 = ip1.weight * ( - a/2 * res - b * abs(res) );
|
||||
}
|
||||
|
||||
void evalFaceD(double& res11, double& res21, double& res22, double& res12,
|
||||
const FaceElementTransformations* face_tr, const Vector& normal,
|
||||
const IntegrationPoint& ip1, const IntegrationPoint& ip2,
|
||||
const Tensor<2>& Jac1, const Tensor<2>& Jac2,
|
||||
const Args& args)
|
||||
{
|
||||
const int dim = normal.Size();
|
||||
Vector qvec(dim);
|
||||
// FIXME: qvec might be discontinuous if not constant with a periodic mesh
|
||||
// We should then use the evaluation on Elem2 and eip2
|
||||
args.q.Eval( qvec, *(face_tr->Elem1), ip1 );
|
||||
const double res = qvec * normal;
|
||||
const double a = -args.a, b = args.b;
|
||||
res11 = ip1.weight * ( a/2 * res + b * abs(res) );
|
||||
res21 = ip1.weight * ( a/2 * res - b * abs(res) );
|
||||
res22 = ip1.weight * ( - a/2 * res + b * abs(res) );
|
||||
res12 = ip1.weight * ( - a/2 * res - b * abs(res) );
|
||||
}
|
||||
};
|
||||
|
||||
class MassEquation
|
||||
{
|
||||
public:
|
||||
static const PAOp OpName = BtDB;
|
||||
|
||||
struct ArgsEmpty{};
|
||||
|
||||
void evalD(double& res, ElementTransformation* Tr, const IntegrationPoint& ip,
|
||||
const Tensor<2>& Jac, ArgsEmpty args = {})
|
||||
{
|
||||
res = ip.weight * det(Jac);
|
||||
}
|
||||
|
||||
struct ArgsCoeff
|
||||
{
|
||||
Coefficient& coeff;
|
||||
};
|
||||
|
||||
void evalD(double& res, ElementTransformation* Tr, const IntegrationPoint& ip,
|
||||
const Tensor<2>& Jac, ArgsCoeff& args)
|
||||
{
|
||||
res = args.coeff.Eval(*Tr, ip) * ip.weight * det(Jac);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //MFEM_DGPABILININTEG
|
||||
File diff suppressed because it is too large
Load Diff
-1347
File diff suppressed because it is too large
Load Diff
+114
@@ -6598,6 +6598,34 @@ void Poly_1D::CalcChebyshev(const int p, const double x, double *u, double *d)
|
||||
}
|
||||
}
|
||||
|
||||
void Poly_1D::CalcChebyshev(const int p, const double x, double *u, double *d,
|
||||
double *dd)
|
||||
{
|
||||
// recursive definition, z in [-1,1]
|
||||
// T_0(z) = 1, T_1(z) = z
|
||||
// T_{n+1}(z) = 2*z*T_n(z) - T_{n-1}(z)
|
||||
// T'_n(z) = n*U_{n-1}(z)
|
||||
// U_0(z) = 1 U_1(z) = 2*z
|
||||
// U_{n+1}(z) = 2*z*U_n(z) - U_{n-1}(z)
|
||||
// U_n(z) = z*U_{n-1}(z) + T_n(z) = z*T'_n(z)/n + T_n(z)
|
||||
// T'_{n+1}(z) = (n + 1)*(z*T'_n(z)/n + T_n(z))
|
||||
// T''_{n+1}(z) = (n + 1)*(2*(n + 1)*T'_n(z) + z*T''_n(z)) / n
|
||||
double z;
|
||||
u[0] = 1.;
|
||||
d[0] = 0.;
|
||||
dd[0]= 0.;
|
||||
if (p == 0) { return; }
|
||||
u[1] = z = 2.*x - 1.;
|
||||
d[1] = 2.;
|
||||
dd[1] = 0;
|
||||
for (int n = 1; n < p; n++)
|
||||
{
|
||||
u[n+1] = 2*z*u[n] - u[n-1];
|
||||
d[n+1] = (n + 1)*(z*d[n]/n + 2*u[n]);
|
||||
dd[n+1] = (n + 1)*(2.*(n + 1)*d[n] + z*dd[n])/n;
|
||||
}
|
||||
}
|
||||
|
||||
const double *Poly_1D::GetPoints(const int p, const int btype)
|
||||
{
|
||||
BasisType::Check(btype);
|
||||
@@ -7463,8 +7491,12 @@ H1_TriangleElement::H1_TriangleElement(const int p, const int btype)
|
||||
dshape_x.SetSize(p + 1);
|
||||
dshape_y.SetSize(p + 1);
|
||||
dshape_l.SetSize(p + 1);
|
||||
ddshape_x.SetSize(p + 1);
|
||||
ddshape_y.SetSize(p + 1);
|
||||
ddshape_l.SetSize(p + 1);
|
||||
u.SetSize(Dof);
|
||||
du.SetSize(Dof, Dim);
|
||||
ddu.SetSize(Dof, (Dim * (Dim + 1)) / 2 );
|
||||
#else
|
||||
Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1);
|
||||
#endif
|
||||
@@ -7568,6 +7600,38 @@ void H1_TriangleElement::CalcDShape(const IntegrationPoint &ip,
|
||||
Ti.Mult(du, dshape);
|
||||
}
|
||||
|
||||
void H1_TriangleElement::CalcHessian(const IntegrationPoint &ip,
|
||||
DenseMatrix &ddshape) const
|
||||
{
|
||||
const int p = Order;
|
||||
#ifdef MFEM_THREAD_SAFE
|
||||
Vector shape_x(p + 1), shape_y(p + 1), shape_l(p + 1);
|
||||
Vector dshape_x(p + 1), dshape_y(p + 1), dshape_l(p + 1);
|
||||
Vector ddshape_x(p + 1), ddshape_y(p + 1), ddshape_l(p + 1);
|
||||
DenseMatrix ddu(Dof, Dim);
|
||||
#endif
|
||||
|
||||
poly1d.CalcBasis(p, ip.x, shape_x, dshape_x, ddshape_x);
|
||||
poly1d.CalcBasis(p, ip.y, shape_y, dshape_y, ddshape_y);
|
||||
poly1d.CalcBasis(p, 1. - ip.x - ip.y, shape_l, dshape_l, ddshape_l);
|
||||
|
||||
for (int o = 0, j = 0; j <= p; j++)
|
||||
for (int i = 0; i + j <= p; i++)
|
||||
{
|
||||
int k = p - i - j;
|
||||
// u_xx, u_xy, u_yy
|
||||
ddu(o,0) = ((ddshape_x(i) * shape_l(k)) - 2. * (dshape_x(i) * dshape_l(k)) +
|
||||
(shape_x(i) * ddshape_l(k))) * shape_y(j);
|
||||
ddu(o,1) = (((shape_x(i) * ddshape_l(k)) - dshape_x(i) * dshape_l(k)) * shape_y(
|
||||
j)) + (((dshape_x(i) * shape_l(k)) - (shape_x(i) * dshape_l(k))) * dshape_y(j));
|
||||
ddu(o,2) = ((ddshape_y(j) * shape_l(k)) - 2. * (dshape_y(j) * dshape_l(k)) +
|
||||
(shape_y(j) * ddshape_l(k))) * shape_x(i);
|
||||
o++;
|
||||
}
|
||||
|
||||
Ti.Mult(ddu, ddshape);
|
||||
}
|
||||
|
||||
|
||||
H1_TetrahedronElement::H1_TetrahedronElement(const int p, const int btype)
|
||||
: NodalFiniteElement(3, Geometry::TETRAHEDRON, ((p + 1)*(p + 2)*(p + 3))/6,
|
||||
@@ -7584,8 +7648,13 @@ H1_TetrahedronElement::H1_TetrahedronElement(const int p, const int btype)
|
||||
dshape_y.SetSize(p + 1);
|
||||
dshape_z.SetSize(p + 1);
|
||||
dshape_l.SetSize(p + 1);
|
||||
ddshape_x.SetSize(p + 1);
|
||||
ddshape_y.SetSize(p + 1);
|
||||
ddshape_z.SetSize(p + 1);
|
||||
ddshape_l.SetSize(p + 1);
|
||||
u.SetSize(Dof);
|
||||
du.SetSize(Dof, Dim);
|
||||
ddu.SetSize(Dof, (Dim * (Dim + 1)) / 2);
|
||||
#else
|
||||
Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1);
|
||||
#endif
|
||||
@@ -7738,6 +7807,51 @@ void H1_TetrahedronElement::CalcDShape(const IntegrationPoint &ip,
|
||||
Ti.Mult(du, dshape);
|
||||
}
|
||||
|
||||
void H1_TetrahedronElement::CalcHessian(const IntegrationPoint &ip,
|
||||
DenseMatrix &ddshape) const
|
||||
{
|
||||
const int p = Order;
|
||||
|
||||
#ifdef MFEM_THREAD_SAFE
|
||||
Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1);
|
||||
Vector dshape_x(p + 1), dshape_y(p + 1), dshape_z(p + 1), dshape_l(p + 1);
|
||||
Vector ddshape_x(p + 1), ddshape_y(p + 1), ddshape_z(p + 1), ddshape_l(p + 1);
|
||||
DenseMatrix ddu(Dof, ((Dim + 1) * Dim) / 2);
|
||||
#endif
|
||||
|
||||
poly1d.CalcBasis(p, ip.x, shape_x, dshape_x, ddshape_x);
|
||||
poly1d.CalcBasis(p, ip.y, shape_y, dshape_y, ddshape_y);
|
||||
poly1d.CalcBasis(p, ip.z, shape_z, dshape_z, ddshape_z);
|
||||
poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z, shape_l, dshape_l, ddshape_l);
|
||||
|
||||
for (int o = 0, k = 0; k <= p; k++)
|
||||
for (int j = 0; j + k <= p; j++)
|
||||
for (int i = 0; i + j + k <= p; i++)
|
||||
{
|
||||
// u_xx, u_xy, u_xz, u_yy, u_yz, u_zz
|
||||
int l = p - i - j - k;
|
||||
ddu(o,0) = ((ddshape_x(i) * shape_l(l)) - 2. * (dshape_x(i) * dshape_l(l)) +
|
||||
(shape_x(i) * ddshape_l(l))) * shape_y(j) * shape_z(k);
|
||||
ddu(o,1) = ((dshape_y(j) * ((dshape_x(i) * shape_l(l)) -
|
||||
(shape_x(i) * dshape_l(l)))) +
|
||||
(shape_y(j) * ((ddshape_l(l) * shape_x(i)) -
|
||||
(dshape_x(i) * dshape_l(l)))))* shape_z(k);
|
||||
ddu(o,2) = ((dshape_z(k) * ((dshape_x(i) * shape_l(l)) -
|
||||
(shape_x(i) * dshape_l(l)))) +
|
||||
(shape_z(k) * ((ddshape_l(l) * shape_x(i)) -
|
||||
(dshape_x(i) * dshape_l(l)))))* shape_y(j);
|
||||
ddu(o,3) = ((ddshape_y(j) * shape_l(l)) - 2. * (dshape_y(j) * dshape_l(l)) +
|
||||
(shape_y(j) * ddshape_l(l))) * shape_x(i) * shape_z(k);
|
||||
ddu(o,4) = ((dshape_z(k) * ((dshape_y(j) * shape_l(l)) -
|
||||
(shape_y(j)*dshape_l(l))) ) +
|
||||
(shape_z(k)* ((ddshape_l(l)*shape_y(j)) -
|
||||
(dshape_y(j) * dshape_l(l)) ) ) )* shape_x(i);
|
||||
ddu(o,5) = ((ddshape_z(k) * shape_l(l)) - 2. * (dshape_z(k) * dshape_l(l)) +
|
||||
(shape_z(k) * ddshape_l(l))) * shape_y(j) * shape_x(i);
|
||||
o++;
|
||||
}
|
||||
Ti.Mult(ddu, ddshape);
|
||||
}
|
||||
|
||||
H1Pos_TriangleElement::H1Pos_TriangleElement(const int p)
|
||||
: PositiveFiniteElement(2, Geometry::TRIANGLE, ((p + 1)*(p + 2))/2, p,
|
||||
|
||||
+18
-2
@@ -1564,6 +1564,8 @@ private:
|
||||
|
||||
static void CalcChebyshev(const int p, const double x, double *u);
|
||||
static void CalcChebyshev(const int p, const double x, double *u, double *d);
|
||||
static void CalcChebyshev(const int p, const double x, double *u, double *d,
|
||||
double *dd);
|
||||
|
||||
QuadratureFunctions1D quad_func;
|
||||
|
||||
@@ -1618,6 +1620,14 @@ public:
|
||||
// { CalcLegendre(p, x, u, d); }
|
||||
{ CalcChebyshev(p, x, u, d); }
|
||||
|
||||
// Evaluate the values, derivatives and second derivatives of a hierarchical 1D basis at point x
|
||||
static void CalcBasis(const int p, const double x, double *u, double *d,
|
||||
double *dd)
|
||||
// { CalcMono(p, x, u, d); }
|
||||
// { CalcBernstein(p, x, u, d); }
|
||||
// { CalcLegendre(p, x, u, d); }
|
||||
{ CalcChebyshev(p, x, u, d, dd); }
|
||||
|
||||
// Evaluate a representation of a Delta function at point x
|
||||
static double CalcDelta(const int p, const double x)
|
||||
{ return pow(x, (double) p); }
|
||||
@@ -1820,7 +1830,8 @@ class H1_TriangleElement : public NodalFiniteElement
|
||||
private:
|
||||
#ifndef MFEM_THREAD_SAFE
|
||||
mutable Vector shape_x, shape_y, shape_l, dshape_x, dshape_y, dshape_l, u;
|
||||
mutable DenseMatrix du;
|
||||
mutable Vector ddshape_x, ddshape_y, ddshape_l;
|
||||
mutable DenseMatrix du, ddu;
|
||||
#endif
|
||||
DenseMatrixInverse Ti;
|
||||
|
||||
@@ -1829,6 +1840,8 @@ public:
|
||||
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const;
|
||||
virtual void CalcDShape(const IntegrationPoint &ip,
|
||||
DenseMatrix &dshape) const;
|
||||
virtual void CalcHessian(const IntegrationPoint &ip,
|
||||
DenseMatrix &ddshape) const;
|
||||
};
|
||||
|
||||
|
||||
@@ -1838,7 +1851,8 @@ private:
|
||||
#ifndef MFEM_THREAD_SAFE
|
||||
mutable Vector shape_x, shape_y, shape_z, shape_l;
|
||||
mutable Vector dshape_x, dshape_y, dshape_z, dshape_l, u;
|
||||
mutable DenseMatrix du;
|
||||
mutable Vector ddshape_x, ddshape_y, ddshape_z, ddshape_l;
|
||||
mutable DenseMatrix du, ddu;
|
||||
#endif
|
||||
DenseMatrixInverse Ti;
|
||||
|
||||
@@ -1848,6 +1862,8 @@ public:
|
||||
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const;
|
||||
virtual void CalcDShape(const IntegrationPoint &ip,
|
||||
DenseMatrix &dshape) const;
|
||||
virtual void CalcHessian(const IntegrationPoint &ip,
|
||||
DenseMatrix &ddshape) const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
#include "linearform.hpp"
|
||||
#include "nonlinearform.hpp"
|
||||
#include "bilinearform.hpp"
|
||||
#include "bilinearformoper.hpp"
|
||||
#include "painteg.hpp"
|
||||
#include "hybridization.hpp"
|
||||
#include "datacollection.hpp"
|
||||
#include "estimators.hpp"
|
||||
|
||||
+5
-15
@@ -249,16 +249,6 @@ public:
|
||||
/// Returns number of degrees of freedom.
|
||||
inline int GetNDofs() const { return ndofs; }
|
||||
|
||||
/// Returns number of degrees of freedom in each direction.
|
||||
inline const int GetNDofs1d() const { return GetFE(0)->GetOrder()+1; }
|
||||
|
||||
/// Returns number of quadrature points in each direction.
|
||||
inline const int GetNQuads1d(const int order) const
|
||||
{
|
||||
const IntegrationRule &ir1d = IntRules.Get(Geometry::SEGMENT, order);
|
||||
return ir1d.GetNPoints();
|
||||
}
|
||||
|
||||
/// Return the number of vector dofs, i.e. GetNDofs() x GetVDim().
|
||||
inline int GetVSize() const { return vdim * ndofs; }
|
||||
|
||||
@@ -311,9 +301,9 @@ public:
|
||||
ElementTransformation *GetElementTransformation(int i) const
|
||||
{ return mesh->GetElementTransformation(i); }
|
||||
|
||||
/** Returns the transformation defining the i-th element in the user-defined
|
||||
variable. */
|
||||
void GetElementTransformation(int i, IsoparametricTransformation *ElTr) const
|
||||
/** @brief Returns the transformation defining the @a i-th element in the
|
||||
user-defined variable @a ElTr. */
|
||||
void GetElementTransformation(int i, IsoparametricTransformation *ElTr)
|
||||
{ mesh->GetElementTransformation(i, ElTr); }
|
||||
|
||||
/// Returns ElementTransformation for the @a i-th boundary element.
|
||||
@@ -567,10 +557,10 @@ public:
|
||||
virtual ~QuadratureSpace() { delete [] element_offsets; }
|
||||
|
||||
/// Return the total number of quadrature points.
|
||||
int GetSize() { return size; }
|
||||
int GetSize() const { return size; }
|
||||
|
||||
/// Get the IntegrationRule associated with mesh element @a idx.
|
||||
const IntegrationRule &GetElementIntRule(int idx)
|
||||
const IntegrationRule &GetElementIntRule(int idx) const
|
||||
{ return *int_rule[mesh->GetElementBaseGeometry(idx)]; }
|
||||
|
||||
/// Write the QuadratureSpace to the stream @a out.
|
||||
|
||||
@@ -1492,6 +1492,8 @@ void GridFunction::ProjectCoefficient(Coefficient *coeff[])
|
||||
transf->SetIntPoint(&ip);
|
||||
for (d = 0; d < vdim; d++)
|
||||
{
|
||||
if (!coeff[d]) { continue; }
|
||||
|
||||
val = coeff[d]->Eval(*transf, ip);
|
||||
if ( (ind = vdofs[fdof*d+j]) < 0 )
|
||||
{
|
||||
@@ -1586,6 +1588,8 @@ void GridFunction::ProjectBdrCoefficient(
|
||||
transf->SetIntPoint(&ip);
|
||||
for (d = 0; d < vdim; d++)
|
||||
{
|
||||
if (!coeff[d]) { continue; }
|
||||
|
||||
val = coeff[d]->Eval(*transf, ip);
|
||||
if ( (ind = vdofs[fdof*d+j]) < 0 )
|
||||
{
|
||||
@@ -1627,6 +1631,8 @@ void GridFunction::ProjectBdrCoefficient(
|
||||
vals.SetSize(fe->GetDof());
|
||||
for (d = 0; d < vdim; d++)
|
||||
{
|
||||
if (!coeff[d]) { continue; }
|
||||
|
||||
fe->Project(*coeff[d], *transf, vals);
|
||||
for (int k = 0; k < vals.Size(); k++)
|
||||
{
|
||||
@@ -2577,6 +2583,24 @@ QuadratureFunction::QuadratureFunction(Mesh *mesh, std::istream &in)
|
||||
Load(in, vdim*qspace->GetSize());
|
||||
}
|
||||
|
||||
QuadratureFunction & QuadratureFunction::operator=(double value)
|
||||
{
|
||||
Vector::operator=(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
QuadratureFunction & QuadratureFunction::operator=(const Vector &v)
|
||||
{
|
||||
MFEM_ASSERT(qspace && v.Size() == qspace->GetSize(), "");
|
||||
Vector::operator=(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
QuadratureFunction & QuadratureFunction::operator=(const QuadratureFunction &v)
|
||||
{
|
||||
return this->operator=((const Vector &)v);
|
||||
}
|
||||
|
||||
void QuadratureFunction::Save(std::ostream &out) const
|
||||
{
|
||||
qspace->Save(out);
|
||||
|
||||
+58
-1
@@ -472,8 +472,21 @@ public:
|
||||
/// Set the QuadratureSpace ownership flag.
|
||||
void SetOwnsSpace(bool own) { own_qspace = own; }
|
||||
|
||||
/// Redefine '=' for QuadratureFunction = constant.
|
||||
QuadratureFunction &operator=(double value);
|
||||
|
||||
/// Copy the data from @a v.
|
||||
/** The size of @a v must be equal to the size of the QuadratureSpace
|
||||
@a qspace. */
|
||||
QuadratureFunction &operator=(const Vector &v);
|
||||
|
||||
/// Copy the data from @a v.
|
||||
/** The QuadratureFunctions @a v and @a *this must have QuadratureSpaces with
|
||||
the same size. */
|
||||
QuadratureFunction &operator=(const QuadratureFunction &v);
|
||||
|
||||
/// Get the IntegrationRule associated with mesh element @a idx.
|
||||
const IntegrationRule &GetElementIntRule(int idx)
|
||||
const IntegrationRule &GetElementIntRule(int idx) const
|
||||
{ return qspace->GetElementIntRule(idx); }
|
||||
|
||||
/// Return all values associated with mesh element @a idx in a Vector.
|
||||
@@ -485,6 +498,15 @@ public:
|
||||
*/
|
||||
inline void GetElementValues(int idx, Vector &values);
|
||||
|
||||
/// Return all values associated with mesh element @a idx in a Vector.
|
||||
/** The result is stored in the Vector @a values as a copy of the
|
||||
global values.
|
||||
|
||||
Inside the Vector @a values, the index `i+vdim*j` corresponds to the
|
||||
`i`-th vector component at the `j`-th quadrature point.
|
||||
*/
|
||||
inline void GetElementValues(int idx, Vector &values) const;
|
||||
|
||||
/// Return all values associated with mesh element @a idx in a DenseMatrix.
|
||||
/** The result is stored in the DenseMatrix @a values as a reference to the
|
||||
global values.
|
||||
@@ -494,6 +516,15 @@ public:
|
||||
*/
|
||||
inline void GetElementValues(int idx, DenseMatrix &values);
|
||||
|
||||
/// Return all values associated with mesh element @a idx in a const DenseMatrix.
|
||||
/** The result is stored in the DenseMatrix @a values as a copy of the
|
||||
global values.
|
||||
|
||||
Inside the DenseMatrix @a values, the `(i,j)` entry corresponds to the
|
||||
`i`-th vector component at the `j`-th quadrature point.
|
||||
*/
|
||||
inline void GetElementValues(int idx, DenseMatrix &values) const;
|
||||
|
||||
/// Write the QuadratureFunction to the stream @a out.
|
||||
void Save(std::ostream &out) const;
|
||||
};
|
||||
@@ -567,6 +598,18 @@ inline void QuadratureFunction::GetElementValues(int idx, Vector &values)
|
||||
values.NewDataAndSize(data + vdim*s_offset, vdim*sl_size);
|
||||
}
|
||||
|
||||
inline void QuadratureFunction::GetElementValues(int idx, Vector &values) const
|
||||
{
|
||||
const int s_offset = qspace->element_offsets[idx];
|
||||
const int sl_size = qspace->element_offsets[idx+1] - s_offset;
|
||||
values.SetSize(vdim*sl_size);
|
||||
double *q = data + vdim*s_offset;
|
||||
for (int i = 0; i<values.Size(); i++)
|
||||
{
|
||||
values(i) = *(q++);
|
||||
}
|
||||
}
|
||||
|
||||
inline void QuadratureFunction::GetElementValues(int idx, DenseMatrix &values)
|
||||
{
|
||||
const int s_offset = qspace->element_offsets[idx];
|
||||
@@ -574,6 +617,20 @@ inline void QuadratureFunction::GetElementValues(int idx, DenseMatrix &values)
|
||||
values.Reset(data + vdim*s_offset, vdim, sl_size);
|
||||
}
|
||||
|
||||
inline void QuadratureFunction::GetElementValues(int idx,
|
||||
DenseMatrix &values) const
|
||||
{
|
||||
const int s_offset = qspace->element_offsets[idx];
|
||||
const int sl_size = qspace->element_offsets[idx+1] - s_offset;
|
||||
values.SetSize(vdim, sl_size);
|
||||
double *q = data + vdim*s_offset;
|
||||
for (int j = 0; j<sl_size; j++)
|
||||
for (int i = 0; i<vdim; i++)
|
||||
{
|
||||
values(i,j) = *(q++);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mfem
|
||||
|
||||
#endif
|
||||
|
||||
@@ -31,6 +31,7 @@ public:
|
||||
|
||||
void Set(const double *p, const int dim)
|
||||
{
|
||||
MFEM_ASSERT(1 <= dim && dim <= 3, "invalid dim: " << dim);
|
||||
x = p[0];
|
||||
if (dim > 1)
|
||||
{
|
||||
@@ -44,6 +45,7 @@ public:
|
||||
|
||||
void Get(double *p, const int dim) const
|
||||
{
|
||||
MFEM_ASSERT(1 <= dim && dim <= 3, "invalid dim: " << dim);
|
||||
p[0] = x;
|
||||
if (dim > 1)
|
||||
{
|
||||
|
||||
+1
-63
@@ -13,7 +13,6 @@
|
||||
#define MFEM_NONLININTEG
|
||||
|
||||
#include "../config/config.hpp"
|
||||
#include "fespace.hpp"
|
||||
#include "fe.hpp"
|
||||
#include "coefficient.hpp"
|
||||
|
||||
@@ -30,7 +29,7 @@ protected:
|
||||
const IntegrationRule *IntRule;
|
||||
|
||||
NonlinearFormIntegrator(const IntegrationRule *ir = NULL)
|
||||
: IntRule(NULL) { }
|
||||
: IntRule(ir) { }
|
||||
|
||||
public:
|
||||
/** @brief Prescribe a fixed IntegrationRule to use (when @a ir != NULL) or
|
||||
@@ -72,67 +71,6 @@ public:
|
||||
virtual ~NonlinearFormIntegrator() { }
|
||||
};
|
||||
|
||||
|
||||
class Integrator
|
||||
{
|
||||
protected:
|
||||
const IntegrationRule *IntRule;
|
||||
|
||||
public:
|
||||
Integrator(const IntegrationRule *_IntRule = NULL) :
|
||||
IntRule(_IntRule) { }
|
||||
|
||||
void SetIntegrationRule(const IntegrationRule *ir) { IntRule = ir; }
|
||||
};
|
||||
|
||||
|
||||
class LinearFESpaceIntegrator : public Integrator
|
||||
{
|
||||
public:
|
||||
LinearFESpaceIntegrator(const IntegrationRule *_IntRule = NULL) :
|
||||
Integrator(_IntRule) { }
|
||||
|
||||
virtual ~LinearFESpaceIntegrator() { }
|
||||
|
||||
/// Internally assemble the integrator for the specific trial and
|
||||
/// test spaces (with an optional vector u for semilinear forms).
|
||||
virtual void Assemble(FiniteElementSpace *trial_fes,
|
||||
FiniteElementSpace *test_fes) { }
|
||||
|
||||
/// Apply the action A * x = y.
|
||||
virtual void AddMult(const Vector &x, Vector &y)
|
||||
{ mfem_error("Not supported"); }
|
||||
|
||||
/// Apply the transposed action A^T * x = y.
|
||||
virtual void AddMultTranspose(const Vector &x, Vector &y)
|
||||
{ mfem_error("Not supported"); }
|
||||
};
|
||||
|
||||
|
||||
class NonlinearFESpaceIntegrator : public Integrator
|
||||
{
|
||||
public:
|
||||
NonlinearFESpaceIntegrator(const IntegrationRule *_IntRule = NULL) :
|
||||
Integrator(_IntRule) { }
|
||||
|
||||
virtual ~NonlinearFESpaceIntegrator() { }
|
||||
|
||||
/// Internally assemble the integrator for the specific trial and
|
||||
/// test spaces (with an optional vector u for semilinear forms).
|
||||
virtual void Assemble(FiniteElementSpace *trial_fes,
|
||||
FiniteElementSpace *test_fes,
|
||||
const Vector &u) { }
|
||||
|
||||
/// Apply the action A(u) * x = y.
|
||||
virtual void AddMult(const Vector &x, Vector &y)
|
||||
{ mfem_error("Not supported"); }
|
||||
|
||||
/// Apply the transposed action A(u)^T * x = y.
|
||||
virtual void AddMultTranspose(const Vector &x, Vector &y)
|
||||
{ mfem_error("Not supported"); }
|
||||
};
|
||||
|
||||
|
||||
/** The abstract base class BlockNonlinearFormIntegrator is
|
||||
a generalization of the NonlinearFormIntegrator class suitable
|
||||
for block state vectors. */
|
||||
|
||||
-704
@@ -1,704 +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.
|
||||
|
||||
// Implementation of FESpaceIntegrators.
|
||||
|
||||
#include "fem.hpp"
|
||||
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
static void ComputeBasis1d(const FiniteElement *fe,
|
||||
const TensorBasisElement *tfe, int ir_order,
|
||||
DenseMatrix &shape1d)
|
||||
{
|
||||
// Compute the 1d shape functions and gradients
|
||||
const Poly_1D::Basis &basis1d = tfe->GetBasis1D();
|
||||
const IntegrationRule &ir1d = IntRules.Get(Geometry::SEGMENT, ir_order);
|
||||
|
||||
const int quads1d = ir1d.GetNPoints();
|
||||
const int dofs = fe->GetOrder() + 1;
|
||||
|
||||
shape1d.SetSize(dofs, quads1d);
|
||||
|
||||
Vector u(dofs);
|
||||
for (int k = 0; k < quads1d; k++)
|
||||
{
|
||||
const IntegrationPoint &ip = ir1d.IntPoint(k);
|
||||
basis1d.Eval(ip.x, u);
|
||||
for (int i = 0; i < dofs; i++)
|
||||
{
|
||||
shape1d(i, k) = u(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ComputeBasis1d(const FiniteElement *fe,
|
||||
const TensorBasisElement *tfe, int ir_order,
|
||||
DenseMatrix &shape1d, DenseMatrix &dshape1d)
|
||||
{
|
||||
// Compute the 1d shape functions and gradients
|
||||
const Poly_1D::Basis &basis1d = tfe->GetBasis1D();
|
||||
const IntegrationRule &ir1d = IntRules.Get(Geometry::SEGMENT, ir_order);
|
||||
|
||||
const int quads1d = ir1d.GetNPoints();
|
||||
const int dofs = fe->GetOrder() + 1;
|
||||
|
||||
shape1d.SetSize(dofs, quads1d);
|
||||
dshape1d.SetSize(dofs, quads1d);
|
||||
|
||||
Vector u(dofs);
|
||||
Vector d(dofs);
|
||||
for (int k = 0; k < quads1d; k++)
|
||||
{
|
||||
const IntegrationPoint &ip = ir1d.IntPoint(k);
|
||||
basis1d.Eval(ip.x, u, d);
|
||||
for (int i = 0; i < dofs; i++)
|
||||
{
|
||||
shape1d(i, k) = u(i);
|
||||
dshape1d(i, k) = d(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PADiffusionIntegrator::Assemble(FiniteElementSpace *_trial_fes,
|
||||
FiniteElementSpace *_test_fes)
|
||||
{
|
||||
// Assumption: trial and test fespaces are the same (no mixed forms yet)
|
||||
fes = _trial_fes;
|
||||
|
||||
// Assumption: all are same finite elements
|
||||
const FiniteElement *fe = fes->GetFE(0);
|
||||
|
||||
// Get the corresponding tensor basis element
|
||||
const TensorBasisElement *tfe = dynamic_cast<const TensorBasisElement*>(fe);
|
||||
|
||||
// Set integration rule
|
||||
int ir_order;
|
||||
if (!IntRule)
|
||||
{
|
||||
const int dim = fe->GetDim();
|
||||
if (fe->Space() == FunctionSpace::Pk)
|
||||
{
|
||||
ir_order = 2*fe->GetOrder() - 2;
|
||||
}
|
||||
else
|
||||
// order = 2*fe.GetOrder() - 2; // <-- this seems to work fine too
|
||||
{
|
||||
ir_order = 2*fe->GetOrder() + dim - 1;
|
||||
}
|
||||
|
||||
if (fe->Space() == FunctionSpace::rQk)
|
||||
{
|
||||
SetIntegrationRule(&RefinedIntRules.Get(fe->GetGeomType(), ir_order));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetIntegrationRule(&IntRules.Get(fe->GetGeomType(), ir_order));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ir_order = IntRule->GetOrder();
|
||||
}
|
||||
|
||||
// Store the 1d shape functions and gradients
|
||||
ComputeBasis1d(fes->GetFE(0), tfe, ir_order, shape1d, dshape1d);
|
||||
|
||||
// Create the operator
|
||||
const int elems = fes->GetNE();
|
||||
const int dim = fe->GetDim();
|
||||
const int quads = IntRule->GetNPoints();
|
||||
const int entries = dim * (dim + 1) / 2;
|
||||
Dtensor.SetSize(entries, quads, elems);
|
||||
|
||||
DenseMatrix invdfdx(dim, dim);
|
||||
DenseMatrix mat(dim, dim);
|
||||
DenseMatrix cmat(dim, dim);
|
||||
|
||||
Coefficient *coeff = integ->Q;
|
||||
MatrixCoefficient *mcoeff = integ->MQ;
|
||||
for (int e = 0; e < fes->GetNE(); e++)
|
||||
{
|
||||
ElementTransformation *Tr = fes->GetElementTransformation(e);
|
||||
DenseMatrix &Dmat = Dtensor(e);
|
||||
for (int k = 0; k < quads; k++)
|
||||
{
|
||||
const IntegrationPoint &ip = IntRule->IntPoint(k);
|
||||
Tr->SetIntPoint(&ip);
|
||||
const DenseMatrix &temp = Tr->AdjugateJacobian();
|
||||
MultABt(temp, temp, mat);
|
||||
mat *= ip.weight / Tr->Weight();
|
||||
|
||||
if (coeff != NULL)
|
||||
{
|
||||
const double c = coeff->Eval(*Tr, ip);
|
||||
for (int j = 0, l = 0; j < dim; j++)
|
||||
for (int i = j; i < dim; i++, l++)
|
||||
{
|
||||
Dmat(l, k) = c * mat(i, j);
|
||||
}
|
||||
|
||||
}
|
||||
else if (mcoeff != NULL)
|
||||
{
|
||||
mcoeff->Eval(cmat, *Tr, ip);
|
||||
for (int j = 0, l = 0; j < dim; j++)
|
||||
for (int i = j; i < dim; i++, l++)
|
||||
{
|
||||
Dmat(l, k) = cmat(i, j) * mat(i, j);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int j = 0, l = 0; j < dim; j++)
|
||||
for (int i = j; i < dim; i++, l++)
|
||||
{
|
||||
Dmat(l, k) = mat(i, j);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PADiffusionIntegrator::MultSeg(const Vector &V, Vector &U)
|
||||
{
|
||||
const int dofs1d = shape1d.Height();
|
||||
const int quads1d = shape1d.Width();
|
||||
const int quads = quads1d;
|
||||
const int vdim = fes->GetVDim();
|
||||
|
||||
Vector Q(quads1d);
|
||||
|
||||
int offset = 0;
|
||||
for (int e = 0; e < fes->GetNE(); ++e)
|
||||
{
|
||||
for (int vd = 0; vd < vdim; ++vd)
|
||||
{
|
||||
const Vector Vmat(V.GetData() + offset, dofs1d);
|
||||
Vector Umat(U.GetData() + offset, dofs1d);
|
||||
|
||||
// Q_k1 = dshape_j1_k1 * V_i1
|
||||
dshape1d.MultTranspose(Vmat, Q);
|
||||
|
||||
double *data_q = Q.GetData();
|
||||
const double *data_d = Dtensor(e).GetData();
|
||||
for (int k = 0; k < quads; ++k)
|
||||
{
|
||||
data_q[k] *= data_d[k];
|
||||
}
|
||||
|
||||
// Q_k1 = dshape_j1_k1 * Q_k1
|
||||
dshape1d.AddMult(Q, Umat);
|
||||
|
||||
// increment offset into E-vectors.
|
||||
offset += dofs1d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PADiffusionIntegrator::MultQuad(const Vector &V, Vector &U)
|
||||
{
|
||||
const int dim = 2;
|
||||
const int terms = dim*(dim+1)/2;
|
||||
const int vdim = fes->GetVDim();
|
||||
|
||||
const int dofs1d = shape1d.Height();
|
||||
const int quads1d = shape1d.Width();
|
||||
|
||||
const int dofs = dofs1d * dofs1d;
|
||||
const int quads = IntRule->GetNPoints();
|
||||
|
||||
DenseTensor QQ(quads1d, quads1d, dim);
|
||||
DenseMatrix DQ(dofs1d, quads1d);
|
||||
|
||||
int offset = 0;
|
||||
for (int e = 0; e < fes->GetNE(); ++e)
|
||||
{
|
||||
for (int vd = 0; vd < vdim; ++vd)
|
||||
{
|
||||
const DenseMatrix Vmat(V.GetData() + offset, dofs1d, dofs1d);
|
||||
DenseMatrix Umat(U.GetData() + offset, dofs1d, dofs1d);
|
||||
|
||||
// DQ_j2_k1 = E_j1_j2 * dshape_j1_k1 -- contract in x direction
|
||||
// QQ_0_k1_k2 = DQ_j2_k1 * shape_j2_k2 -- contract in y direction
|
||||
MultAtB(Vmat, dshape1d, DQ);
|
||||
MultAtB(DQ, shape1d, QQ(0));
|
||||
|
||||
// DQ_j2_k1 = E_j1_j2 * shape_j1_k1 -- contract in x direction
|
||||
// QQ_1_k1_k2 = DQ_j2_k1 * dshape_j2_k2 -- contract in y direction
|
||||
MultAtB(Vmat, shape1d, DQ);
|
||||
MultAtB(DQ, dshape1d, QQ(1));
|
||||
|
||||
// QQ_c_k1_k2 = Dmat_c_d_k1_k2 * QQ_d_k1_k2
|
||||
// NOTE: (k1, k2) = k -- 1d index over tensor product of quad points
|
||||
double *data_qq = QQ(0).GetData();
|
||||
const double *data_d = Dtensor(e).GetData();
|
||||
for (int k = 0; k < quads; ++k)
|
||||
{
|
||||
const double D00 = data_d[terms*k + 0];
|
||||
const double D01 = data_d[terms*k + 1];
|
||||
const double D11 = data_d[terms*k + 2];
|
||||
|
||||
const double q0 = data_qq[0*quads + k];
|
||||
const double q1 = data_qq[1*quads + k];
|
||||
|
||||
data_qq[0*quads + k] = D00 * q0 + D01 * q1;
|
||||
data_qq[1*quads + k] = D01 * q0 + D11 * q1;
|
||||
}
|
||||
|
||||
// DQ_i2_k1 = shape_i2_k2 * QQ_0_k1_k2
|
||||
// U_i1_i2 += dshape_i1_k1 * DQ_i2_k1
|
||||
MultABt(shape1d, QQ(0), DQ);
|
||||
AddMultABt(dshape1d, DQ, Umat);
|
||||
|
||||
// DQ_i2_k1 = dshape_i2_k2 * QQ_1_k1_k2
|
||||
// U_i1_i2 += shape_i1_k1 * DQ_i2_k1
|
||||
MultABt(dshape1d, QQ(1), DQ);
|
||||
AddMultABt(shape1d, DQ, Umat);
|
||||
|
||||
// increment offset
|
||||
offset += dofs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PADiffusionIntegrator::MultHex(const Vector &V, Vector &U)
|
||||
{
|
||||
const int dim = 3;
|
||||
const int terms = dim*(dim+1)/2;
|
||||
const int vdim = fes->GetVDim();
|
||||
|
||||
const int dofs1d = shape1d.Height();
|
||||
const int quads1d = shape1d.Width();
|
||||
|
||||
const int dofs = dofs1d * dofs1d * dofs1d;
|
||||
const int quads = IntRule->GetNPoints();
|
||||
|
||||
DenseMatrix Q(quads1d, dim);
|
||||
DenseTensor QQ(quads1d, quads1d, dim);
|
||||
|
||||
Array<double> QQQmem(quads1d * quads1d * quads1d * dim);
|
||||
double *data_qqq = QQQmem.GetData();
|
||||
DenseTensor QQQ0(data_qqq + 0*quads, quads1d, quads1d, quads1d);
|
||||
DenseTensor QQQ1(data_qqq + 1*quads, quads1d, quads1d, quads1d);
|
||||
DenseTensor QQQ2(data_qqq + 2*quads, quads1d, quads1d, quads1d);
|
||||
|
||||
int offset = 0;
|
||||
for (int e = 0; e < fes->GetNE(); ++e)
|
||||
{
|
||||
for (int vd = 0; vd < vdim; ++vd)
|
||||
{
|
||||
const DenseTensor Vmat(V.GetData() + offset, dofs1d, dofs1d, dofs1d);
|
||||
DenseTensor Umat(U.GetData() + offset, dofs1d, dofs1d, dofs1d);
|
||||
|
||||
// QQQ_0_k1_k2_k3 = dshape_j1_k1 * shape_j2_k2 * shape_j3_k3 * Vmat_j1_j2_j3
|
||||
// QQQ_1_k1_k2_k3 = shape_j1_k1 * dshape_j2_k2 * shape_j3_k3 * Vmat_j1_j2_j3
|
||||
// QQQ_2_k1_k2_k3 = shape_j1_k1 * shape_j2_k2 * dshape_j3_k3 * Vmat_j1_j2_j3
|
||||
QQQ0 = 0.; QQQ1 = 0.; QQQ2 = 0.;
|
||||
for (int j3 = 0; j3 < dofs1d; ++j3)
|
||||
{
|
||||
QQ = 0.;
|
||||
for (int j2 = 0; j2 < dofs1d; ++j2)
|
||||
{
|
||||
Q = 0.;
|
||||
for (int j1 = 0; j1 < dofs1d; ++j1)
|
||||
{
|
||||
for (int k1 = 0; k1 < quads1d; ++k1)
|
||||
{
|
||||
Q(k1, 0) += Vmat(j1, j2, j3) * dshape1d(j1, k1);
|
||||
Q(k1, 1) += Vmat(j1, j2, j3) * shape1d(j1, k1);
|
||||
}
|
||||
}
|
||||
for (int k2 = 0; k2 < quads1d; ++k2)
|
||||
for (int k1 = 0; k1 < quads1d; ++k1)
|
||||
{
|
||||
QQ(k1, k2, 0) += Q(k1, 0) * shape1d(j2, k2);
|
||||
QQ(k1, k2, 1) += Q(k1, 1) * dshape1d(j2, k2);
|
||||
QQ(k1, k2, 2) += Q(k1, 1) * shape1d(j2, k2);
|
||||
}
|
||||
}
|
||||
for (int k3 = 0; k3 < quads1d; ++k3)
|
||||
for (int k2 = 0; k2 < quads1d; ++k2)
|
||||
for (int k1 = 0; k1 < quads1d; ++k1)
|
||||
{
|
||||
QQQ0(k1, k2, k3) += QQ(k1, k2, 0) * shape1d(j3, k3);
|
||||
QQQ1(k1, k2, k3) += QQ(k1, k2, 1) * shape1d(j3, k3);
|
||||
QQQ2(k1, k2, k3) += QQ(k1, k2, 2) * dshape1d(j3, k3);
|
||||
}
|
||||
}
|
||||
|
||||
// QQQ_c_k1_k2_k3 = Dmat_c_d_k1_k2_k3 * QQQ_d_k1_k2_k3
|
||||
// NOTE: (k1, k2, k3) = q -- 1d quad point index
|
||||
const double *data_d = Dtensor(e).GetData();
|
||||
for (int k = 0; k < quads; ++k)
|
||||
{
|
||||
const double D00 = data_d[terms*k + 0];
|
||||
const double D01 = data_d[terms*k + 1];
|
||||
const double D02 = data_d[terms*k + 2];
|
||||
const double D11 = data_d[terms*k + 3];
|
||||
const double D12 = data_d[terms*k + 4];
|
||||
const double D22 = data_d[terms*k + 5];
|
||||
|
||||
const double q0 = data_qqq[0*quads + k];
|
||||
const double q1 = data_qqq[1*quads + k];
|
||||
const double q2 = data_qqq[2*quads + k];
|
||||
|
||||
data_qqq[0*quads + k] = D00 * q0 + D01 * q1 + D02 * q2;
|
||||
data_qqq[1*quads + k] = D01 * q0 + D11 * q1 + D12 * q2;
|
||||
data_qqq[2*quads + k] = D02 * q0 + D12 * q1 + D22 * q2;
|
||||
}
|
||||
|
||||
// Apply transpose of the first operator that takes V -> QQQd -- QQQd -> U
|
||||
for (int k3 = 0; k3 < quads1d; ++k3)
|
||||
{
|
||||
QQ = 0.;
|
||||
for (int k2 = 0; k2 < quads1d; ++k2)
|
||||
{
|
||||
Q = 0.;
|
||||
for (int k1 = 0; k1 < quads1d; ++k1)
|
||||
{
|
||||
for (int i1 = 0; i1 < dofs1d; ++i1)
|
||||
{
|
||||
Q(i1, 0) += QQQ0(k1, k2, k3) * dshape1d(i1, k1);
|
||||
Q(i1, 1) += QQQ1(k1, k2, k3) * shape1d(i1, k1);
|
||||
Q(i1, 2) += QQQ2(k1, k2, k3) * shape1d(i1, k1);
|
||||
}
|
||||
}
|
||||
for (int i2 = 0; i2 < dofs1d; ++i2)
|
||||
for (int i1 = 0; i1 < dofs1d; ++i1)
|
||||
{
|
||||
QQ(i1, i2, 0) += Q(i1, 0) * shape1d(i2, k2);
|
||||
QQ(i1, i2, 1) += Q(i1, 1) * dshape1d(i2, k2);
|
||||
QQ(i1, i2, 2) += Q(i1, 2) * shape1d(i2, k2);
|
||||
}
|
||||
}
|
||||
for (int i3 = 0; i3 < dofs1d; ++i3)
|
||||
for (int i2 = 0; i2 < dofs1d; ++i2)
|
||||
for (int i1 = 0; i1 < dofs1d; ++i1)
|
||||
{
|
||||
Umat(i1, i2, i3) +=
|
||||
QQ(i1, i2, 0) * shape1d(i3, k3) +
|
||||
QQ(i1, i2, 1) * shape1d(i3, k3) +
|
||||
QQ(i1, i2, 2) * dshape1d(i3, k3);
|
||||
}
|
||||
}
|
||||
|
||||
// increment offset
|
||||
offset += dofs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PADiffusionIntegrator::AddMult(const Vector &x, Vector &y)
|
||||
{
|
||||
const int dim = fes->GetMesh()->Dimension();
|
||||
|
||||
switch (dim)
|
||||
{
|
||||
case 1: MultSeg(x, y); break;
|
||||
case 2: MultQuad(x, y); break;
|
||||
case 3: MultHex(x, y); break;
|
||||
default: mfem_error("Not yet supported"); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PAMassIntegrator::Assemble(FiniteElementSpace *_trial_fes,
|
||||
FiniteElementSpace *_test_fes)
|
||||
{
|
||||
// Assumption: trial and test fespaces are the same (no mixed forms yet)
|
||||
fes = _trial_fes;
|
||||
|
||||
// Assumption: all are same finite elements
|
||||
const FiniteElement *fe = fes->GetFE(0);
|
||||
|
||||
// Get the corresponding tensor basis element
|
||||
const TensorBasisElement *tfe = dynamic_cast<const TensorBasisElement*>(fe);
|
||||
|
||||
// Set integration rule
|
||||
int ir_order;
|
||||
if (!IntRule)
|
||||
{
|
||||
// int order = 2 * el.GetOrder();
|
||||
// ir_order = 2 * fe.GetOrder() + Trans.OrderW();
|
||||
ir_order = 2 * fe->GetOrder() + 1;
|
||||
|
||||
if (fe->Space() == FunctionSpace::rQk)
|
||||
{
|
||||
SetIntegrationRule(&RefinedIntRules.Get(fe->GetGeomType(), ir_order));
|
||||
}
|
||||
else
|
||||
{
|
||||
SetIntegrationRule(&IntRules.Get(fe->GetGeomType(), ir_order));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ir_order = IntRule->GetOrder();
|
||||
}
|
||||
|
||||
ComputeBasis1d(fes->GetFE(0), tfe, ir_order, shape1d);
|
||||
|
||||
// Create the operator
|
||||
const int nelem = fes->GetNE();
|
||||
const int dim = fe->GetDim();
|
||||
const int quads = IntRule->GetNPoints();
|
||||
const int vdim = integ ? 1 : dim;
|
||||
Dtensor.SetSize(quads, vdim, nelem);
|
||||
|
||||
Coefficient *coeff = NULL;
|
||||
VectorCoefficient *vcoeff = NULL;
|
||||
if (integ)
|
||||
{
|
||||
coeff = integ->Q;
|
||||
}
|
||||
else if (vinteg)
|
||||
{
|
||||
coeff = vinteg->Q;
|
||||
vcoeff = vinteg->VQ;
|
||||
if (vinteg->MQ != NULL) mfem_error("Not supported.");
|
||||
}
|
||||
DenseMatrix invdfdx(dim, dim);
|
||||
DenseMatrix mat(dim, dim);
|
||||
Vector cv(vdim);
|
||||
for (int e = 0; e < fes->GetNE(); e++)
|
||||
{
|
||||
ElementTransformation *Tr = fes->GetElementTransformation(e);
|
||||
DenseMatrix &Dmat = Dtensor(e);
|
||||
for (int k = 0; k < quads; k++)
|
||||
{
|
||||
const IntegrationPoint &ip = IntRule->IntPoint(k);
|
||||
Tr->SetIntPoint(&ip);
|
||||
const double weight = ip.weight * Tr->Weight();
|
||||
if (vcoeff != NULL)
|
||||
{
|
||||
vcoeff->Eval(cv, *Tr, ip);
|
||||
}
|
||||
for (int v = 0; v < vdim; v++)
|
||||
{
|
||||
Dmat(k, v) = weight;
|
||||
if (coeff != NULL) Dmat(k, v) *= coeff->Eval(*Tr, ip);
|
||||
else if (vcoeff != NULL)
|
||||
{
|
||||
Dmat(k, v) *= cv(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PAMassIntegrator::MultSeg(const Vector &V, Vector &U)
|
||||
{
|
||||
const int dofs1d = shape1d.Height();
|
||||
const int quads1d = shape1d.Width();
|
||||
const int quads = quads1d;
|
||||
const int vdim = fes->GetVDim();
|
||||
|
||||
Vector Q(quads1d);
|
||||
|
||||
int offset = 0;
|
||||
for (int e = 0; e < fes->GetNE(); ++e)
|
||||
{
|
||||
DenseMatrix &Dmat = Dtensor(e);
|
||||
for (int vd = 0; vd < vdim; ++vd)
|
||||
{
|
||||
const Vector Vmat(V.GetData() + offset, dofs1d);
|
||||
Vector Umat(U.GetData() + offset, dofs1d);
|
||||
|
||||
// Q_k1 = dshape_j1_k1 * V_i1
|
||||
shape1d.MultTranspose(Vmat, Q);
|
||||
|
||||
double *data_q = Q.GetData();
|
||||
const double *data_d = Dmat.GetColumn(vd);
|
||||
for (int k = 0; k < quads; ++k) { data_q[k] *= data_d[k]; }
|
||||
|
||||
// Q_k1 = dshape_j1_k1 * Q_k1
|
||||
shape1d.AddMult(Q, Umat);
|
||||
|
||||
// Increment offset into E-vectors.
|
||||
offset += dofs1d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PAMassIntegrator::MultQuad(const Vector &V, Vector &U)
|
||||
{
|
||||
const int dofs1d = shape1d.Height();
|
||||
const int quads1d = shape1d.Width();
|
||||
|
||||
const int dofs = dofs1d * dofs1d;
|
||||
const int quads = IntRule->GetNPoints();
|
||||
const int vdim = fes->GetVDim();
|
||||
|
||||
DenseMatrix QQ(quads1d, quads1d);
|
||||
DenseMatrix DQ(dofs1d, quads1d);
|
||||
|
||||
int offset = 0;
|
||||
for (int e = 0; e < fes->GetNE(); ++e)
|
||||
{
|
||||
DenseMatrix &Dmat = Dtensor(e);
|
||||
for (int vd = 0; vd < vdim; ++vd)
|
||||
{
|
||||
const DenseMatrix Vmat(V.GetData() + offset, dofs1d, dofs1d);
|
||||
DenseMatrix Umat(U.GetData() + offset, dofs1d, dofs1d);
|
||||
|
||||
// DQ_j2_k1 = E_j1_j2 * dshape_j1_k1 -- contract in x direction
|
||||
// QQ_0_k1_k2 = DQ_j2_k1 * shape_j2_k2 -- contract in y direction
|
||||
MultAtB(Vmat, shape1d, DQ);
|
||||
MultAtB(DQ, shape1d, QQ);
|
||||
|
||||
// QQ_c_k1_k2 = Dmat_c_d_k1_k2 * QQ_d_k1_k2
|
||||
// NOTE: (k1, k2) = k -- 1d index over tensor product of quad points
|
||||
double *data_qq = QQ.GetData();
|
||||
const double *data_d = Dmat.GetColumn(vd);
|
||||
for (int k = 0; k < quads; ++k) { data_qq[k] *= data_d[k]; }
|
||||
|
||||
// DQ_i2_k1 = shape_i2_k2 * QQ_0_k1_k2
|
||||
// U_i1_i2 += dshape_i1_k1 * DQ_i2_k1
|
||||
MultABt(shape1d, QQ, DQ);
|
||||
AddMultABt(shape1d, DQ, Umat);
|
||||
|
||||
// increment offset
|
||||
offset += dofs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PAMassIntegrator::MultHex(const Vector &V, Vector &U)
|
||||
{
|
||||
const int dofs1d = shape1d.Height();
|
||||
const int quads1d = shape1d.Width();
|
||||
|
||||
const int dofs = dofs1d * dofs1d * dofs1d;
|
||||
const int quads = IntRule->GetNPoints();
|
||||
const int vdim = fes->GetVDim();
|
||||
|
||||
Vector Q(quads1d);
|
||||
DenseMatrix QQ(quads1d, quads1d);
|
||||
DenseTensor QQQ(quads1d, quads1d, quads1d);
|
||||
|
||||
int offset = 0;
|
||||
for (int e = 0; e < fes->GetNE(); ++e)
|
||||
{
|
||||
DenseMatrix &Dmat = Dtensor(e);
|
||||
for (int vd = 0; vd < vdim; ++vd)
|
||||
{
|
||||
const DenseTensor Vmat(V.GetData() + offset, dofs1d, dofs1d, dofs1d);
|
||||
DenseTensor Umat(U.GetData() + offset, dofs1d, dofs1d, dofs1d);
|
||||
|
||||
// QQQ_k1_k2_k3 = shape_j1_k1 * shape_j2_k2 * shape_j3_k3 * Vmat_j1_j2_j3
|
||||
QQQ = 0.;
|
||||
for (int j3 = 0; j3 < dofs1d; ++j3)
|
||||
{
|
||||
QQ = 0.;
|
||||
for (int j2 = 0; j2 < dofs1d; ++j2)
|
||||
{
|
||||
Q = 0.;
|
||||
for (int j1 = 0; j1 < dofs1d; ++j1)
|
||||
{
|
||||
for (int k1 = 0; k1 < quads1d; ++k1)
|
||||
{
|
||||
Q(k1) += Vmat(j1, j2, j3) * shape1d(j1, k1);
|
||||
}
|
||||
}
|
||||
for (int k2 = 0; k2 < quads1d; ++k2)
|
||||
for (int k1 = 0; k1 < quads1d; ++k1)
|
||||
{
|
||||
QQ(k1, k2) += Q(k1) * shape1d(j2, k2);
|
||||
}
|
||||
}
|
||||
for (int k3 = 0; k3 < quads1d; ++k3)
|
||||
for (int k2 = 0; k2 < quads1d; ++k2)
|
||||
for (int k1 = 0; k1 < quads1d; ++k1)
|
||||
{
|
||||
QQQ(k1, k2, k3) += QQ(k1, k2) * shape1d(j3, k3);
|
||||
}
|
||||
}
|
||||
|
||||
// QQQ_k1_k2_k3 = Dmat_k1_k2_k3 * QQQ_k1_k2_k3
|
||||
// NOTE: (k1, k2, k3) = q -- 1d quad point index
|
||||
double *data_qqq = QQQ.GetData(0);
|
||||
const double *data_d = Dmat.GetColumn(vd);
|
||||
for (int k = 0; k < quads; ++k) { data_qqq[k] *= data_d[k]; }
|
||||
|
||||
// Apply transpose of the first operator that takes V -> QQQ -- QQQ -> U
|
||||
for (int k3 = 0; k3 < quads1d; ++k3)
|
||||
{
|
||||
QQ = 0.;
|
||||
for (int k2 = 0; k2 < quads1d; ++k2)
|
||||
{
|
||||
Q = 0.;
|
||||
for (int k1 = 0; k1 < quads1d; ++k1)
|
||||
{
|
||||
for (int i1 = 0; i1 < dofs1d; ++i1)
|
||||
{
|
||||
Q(i1) += QQQ(k1, k2, k3) * shape1d(i1, k1);
|
||||
}
|
||||
}
|
||||
for (int i2 = 0; i2 < dofs1d; ++i2)
|
||||
for (int i1 = 0; i1 < dofs1d; ++i1)
|
||||
{
|
||||
QQ(i1, i2) += Q(i1) * shape1d(i2, k2);
|
||||
}
|
||||
}
|
||||
for (int i3 = 0; i3 < dofs1d; ++i3)
|
||||
for (int i2 = 0; i2 < dofs1d; ++i2)
|
||||
for (int i1 = 0; i1 < dofs1d; ++i1)
|
||||
{
|
||||
Umat(i1, i2, i3) += shape1d(i3, k3) * QQ(i1, i2);
|
||||
}
|
||||
}
|
||||
|
||||
// increment offset
|
||||
offset += dofs;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PAMassIntegrator::AddMult(const Vector &x, Vector &y)
|
||||
{
|
||||
const int dim = fes->GetMesh()->Dimension();
|
||||
|
||||
switch (dim)
|
||||
{
|
||||
case 1: MultSeg(x, y); break;
|
||||
case 2: MultQuad(x, y); break;
|
||||
case 3: MultHex(x, y); break;
|
||||
default: mfem_error("Not yet supported"); break;
|
||||
}
|
||||
}
|
||||
|
||||
LinearFESpaceIntegrator *PAIntegratorMap::DomainIntegrator(BilinearFormIntegrator *integ) const
|
||||
{
|
||||
{
|
||||
DiffusionIntegrator *actual_integ = dynamic_cast<DiffusionIntegrator*>(integ);
|
||||
if (actual_integ) { return new PADiffusionIntegrator(actual_integ); }
|
||||
}
|
||||
{
|
||||
MassIntegrator *actual_integ = dynamic_cast<MassIntegrator*>(integ);
|
||||
if (actual_integ) { return new PAMassIntegrator(actual_integ); }
|
||||
}
|
||||
{
|
||||
VectorMassIntegrator *actual_integ = dynamic_cast<VectorMassIntegrator*>(integ);
|
||||
if (actual_integ) { return new PAMassIntegrator(actual_integ); }
|
||||
}
|
||||
|
||||
mfem_error("Not supported.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,90 +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.
|
||||
|
||||
// This file contains FESpaceIntegrators.
|
||||
|
||||
|
||||
#ifndef MFEM_PAINTEG
|
||||
#define MFEM_PAINTEG
|
||||
|
||||
#include "../config/config.hpp"
|
||||
#include "nonlininteg.hpp"
|
||||
#include "bilinearformoper.hpp"
|
||||
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
// These integrators use constructors based on the non-PA versions so
|
||||
// that the options are consistent. If that is not the case, the
|
||||
// friendship can be revoked and those constructors can be removed.
|
||||
|
||||
/** Class for computing the action of (grad(u), grad(v)) from a scalar
|
||||
* fespace using a partially assembled operator at quadrature
|
||||
* points. */
|
||||
class PADiffusionIntegrator : public LinearFESpaceIntegrator
|
||||
{
|
||||
protected:
|
||||
// Carry pointer in order to have access to coefficient
|
||||
DiffusionIntegrator *integ; // Own this
|
||||
const FiniteElementSpace *fes; // TODO: support mixed spaces
|
||||
DenseTensor Dtensor;
|
||||
DenseMatrix shape1d, dshape1d;
|
||||
|
||||
// Action methods
|
||||
void MultSeg(const Vector &V, Vector &U);
|
||||
void MultQuad(const Vector &V, Vector &U);
|
||||
void MultHex(const Vector &V, Vector &U);
|
||||
|
||||
public:
|
||||
PADiffusionIntegrator(DiffusionIntegrator *_integ) : integ(_integ) {}
|
||||
~PADiffusionIntegrator() { delete integ; }
|
||||
|
||||
virtual void Assemble(FiniteElementSpace *trial_fes,
|
||||
FiniteElementSpace *test_fes);
|
||||
|
||||
virtual void AddMult(const Vector &x, Vector &y);
|
||||
};
|
||||
|
||||
/** Class for computing the action of (u, v) from a scalar fespace
|
||||
* using a partially assembled operator at quadrature points. */
|
||||
class PAMassIntegrator : public LinearFESpaceIntegrator
|
||||
{
|
||||
protected:
|
||||
MassIntegrator *integ; // Own this
|
||||
VectorMassIntegrator *vinteg; // Own this
|
||||
const FiniteElementSpace *fes; // TODO: support mixed spaces
|
||||
DenseTensor Dtensor;
|
||||
DenseMatrix shape1d;
|
||||
|
||||
// Action methods
|
||||
void MultSeg(const Vector &V, Vector &U);
|
||||
void MultQuad(const Vector &V, Vector &U);
|
||||
void MultHex(const Vector &V, Vector &U);
|
||||
|
||||
public:
|
||||
PAMassIntegrator(MassIntegrator *_integ) : integ(_integ), vinteg(NULL) {}
|
||||
PAMassIntegrator(VectorMassIntegrator *_vinteg) : integ(NULL), vinteg(_vinteg) {}
|
||||
~PAMassIntegrator() { delete integ; delete vinteg; }
|
||||
|
||||
virtual void Assemble(FiniteElementSpace *_trial_fes,
|
||||
FiniteElementSpace *_test_fes);
|
||||
|
||||
virtual void AddMult(const Vector &x, Vector &y);
|
||||
};
|
||||
|
||||
struct PAIntegratorMap : public IntegratorMap
|
||||
{
|
||||
virtual LinearFESpaceIntegrator *DomainIntegrator(BilinearFormIntegrator *integ) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,266 +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.
|
||||
|
||||
// This file contains operator-based bilinear form integrators used
|
||||
// with BilinearFormOperator.
|
||||
|
||||
#ifndef MFEM_PAK
|
||||
#define MFEM_PAK
|
||||
|
||||
#include "fem.hpp"
|
||||
#include "../config/config.hpp"
|
||||
#include "bilininteg.hpp"
|
||||
#include "dalg.hpp"
|
||||
#include "dgfacefunctions.hpp"
|
||||
#include "domainkernels.hpp"
|
||||
#include "facekernels.hpp"
|
||||
#include "solverkernels.hpp"
|
||||
#include <iostream>
|
||||
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
// //
|
||||
// //
|
||||
// PARTIAL ASSEMBLY INTEGRATORS //
|
||||
// //
|
||||
// //
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
|
||||
/////////////////////////////
|
||||
// Domain Kernel Interface //
|
||||
/////////////////////////////
|
||||
|
||||
struct ElementInfo
|
||||
{
|
||||
int dim;
|
||||
int k;
|
||||
int e;
|
||||
ElementTransformation* tr;
|
||||
IntegrationPoint ip;
|
||||
Tensor<2> J_ek;
|
||||
};
|
||||
|
||||
/**
|
||||
* A partial assembly Integrator class for domain integrals.
|
||||
* Takes an 'Equation' template parameter, that must contain 'OpName' of
|
||||
* type 'PAOp' and a function named 'evalD', that receives a 'res' vector,
|
||||
* the element transformation and the integration point, and then whatever
|
||||
* is needed to compute at the point (Coefficient, VectorCoeffcient, etc...).
|
||||
* The 'IMPL' template parameter allows to switch between different implementations
|
||||
* of the tensor contraction kernels.
|
||||
*/
|
||||
template < typename Equation,
|
||||
template<typename,PAOp> class IMPL = DomainMult>
|
||||
class PADomainInt
|
||||
: public LinearFESpaceIntegrator, public IMPL<Equation,Equation::OpName>, public Operator
|
||||
{
|
||||
private:
|
||||
typedef IMPL<Equation,Equation::OpName> Op;
|
||||
|
||||
public:
|
||||
/**
|
||||
* The constructor is templated so that the argument needed for 'evalD' can be
|
||||
* packed arbitrarily ('evalD' with the corresponding signature must exist).
|
||||
*/
|
||||
template <typename Args>
|
||||
PADomainInt(FiniteElementSpace *fes, const int order, const Args& args)
|
||||
: LinearFESpaceIntegrator(&IntRules.Get(fes->GetFE(0)->GetGeomType(), order)),
|
||||
Op(fes,order,args),
|
||||
Operator()
|
||||
{
|
||||
const int nb_elts = fes->GetNE();
|
||||
const int quads = IntRule->GetNPoints();
|
||||
const FiniteElement* fe = fes->GetFE(0);
|
||||
const int dim = fe->GetDim();
|
||||
this->InitD(dim,quads,nb_elts);
|
||||
Tensor<1> Jac1D(dim*dim*quads*nb_elts);
|
||||
EvalJacobians(dim,fes,order,Jac1D);
|
||||
Tensor<4> Jac(Jac1D.getData(),dim,dim,quads,nb_elts);
|
||||
for (int e = 0; e < nb_elts; ++e)
|
||||
{
|
||||
ElementTransformation *Tr = fes->GetElementTransformation(e);
|
||||
for (int k = 0; k < quads; ++k)
|
||||
{
|
||||
Tensor<2> J_ek(&Jac(0,0,k,e),dim,dim);
|
||||
const IntegrationPoint &ip = IntRule->IntPoint(k);
|
||||
Tr->SetIntPoint(&ip);
|
||||
this->evalEq(dim, k, e, Tr, ip, J_ek, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const typename Op::DTensor& getD() const
|
||||
{
|
||||
return Op::getD();
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the partial assembly operator.
|
||||
*/
|
||||
virtual void AddMult(const Vector &fun, Vector &vect)
|
||||
{
|
||||
int dim = this->fes->GetFE(0)->GetDim();
|
||||
switch(dim)
|
||||
{
|
||||
case 1:this->Mult1d(fun,vect); break;
|
||||
case 2:this->Mult2d(fun,vect); break;
|
||||
case 3:this->Mult3d(fun,vect); break;
|
||||
default: mfem_error("More than # dimension not yet supported"); break;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Mult(const Vector &fun, Vector &vect) const{
|
||||
int dim = this->fes->GetFE(0)->GetDim();
|
||||
switch(dim)
|
||||
{
|
||||
case 1:this->Mult1d(fun,vect); break;
|
||||
case 2:this->Mult2d(fun,vect); break;
|
||||
case 3:this->Mult3d(fun,vect); break;
|
||||
default: mfem_error("More than # dimension not yet supported"); break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
///////////////////////////
|
||||
// Face Kernel Interface //
|
||||
///////////////////////////
|
||||
|
||||
struct FaceInfo
|
||||
{
|
||||
int dim; // The problem dimension
|
||||
int k1, k2; // The indices of
|
||||
IntegrationPoint eip1, eip2; // The integration points on each element
|
||||
Vector* normal; // The normal to the face
|
||||
int ind_elt1, ind_elt2; // The indices of the elements
|
||||
int face_id1, face_id2; // The face ID for the face according to each element
|
||||
FaceElementTransformations* face_tr; // The Face transformation
|
||||
Tensor<2> J_e1, J_e2; // The Jacobians for each element at their respective quadrature point
|
||||
};
|
||||
|
||||
/**
|
||||
* A partial assembly Integrator interface class for face integrals.
|
||||
* The template parameters have the same role as for 'PADomainInt'.
|
||||
*/
|
||||
template <typename Equation, template<typename,PAOp> class IMPL = FaceMult>
|
||||
class PAFaceInt
|
||||
: public LinearFESpaceIntegrator, public IMPL<Equation,Equation::FaceOpName>
|
||||
{
|
||||
private:
|
||||
typedef IMPL<Equation,Equation::FaceOpName> Op;
|
||||
|
||||
public:
|
||||
template <typename Args>
|
||||
PAFaceInt(FiniteElementSpace* fes, const int order, Args& args)
|
||||
: LinearFESpaceIntegrator(&IntRules.Get(fes->GetFE(0)->GetGeomType(), order)),
|
||||
Op(fes, order, args)
|
||||
{
|
||||
const int dim = fes->GetFE(0)->GetDim();
|
||||
const int quads1d = fes->GetNQuads1d(order);
|
||||
Mesh* mesh = fes->GetMesh();
|
||||
const int nb_elts = fes->GetNE();
|
||||
const int nb_faces_elt = 2*dim;
|
||||
const int nb_faces = mesh->GetNumFaces();
|
||||
int geom;
|
||||
switch(dim){
|
||||
case 1:geom = Geometry::POINT;break;
|
||||
case 2:geom = Geometry::SEGMENT;break;
|
||||
case 3:geom = Geometry::SQUARE;break;
|
||||
}
|
||||
const IntegrationRule& ir = IntRules.Get(geom, order);
|
||||
const int quads = ir.GetNPoints();
|
||||
Vector qvec(dim);
|
||||
Tensor<1> normal(dim);
|
||||
Vector n(normal.getData(),dim);
|
||||
// Vector n(dim);
|
||||
this->init(dim,quads,nb_elts,nb_faces_elt);
|
||||
// !!! Should not be recomputed... !!!
|
||||
Tensor<1> Jac1D(dim*dim*quads*quads1d*nb_elts);
|
||||
EvalJacobians(dim,fes,order,Jac1D);
|
||||
Tensor<4> Jac(Jac1D.getData(),dim,dim,quads*quads1d,nb_elts);// Creating a view
|
||||
// !!! !!!
|
||||
// We have a per face approach for the fluxes
|
||||
for (int face = 0; face < nb_faces; ++face)
|
||||
{
|
||||
int ind_elt1, ind_elt2;
|
||||
int face_id1, face_id2;
|
||||
int nb_rot1, nb_rot2;
|
||||
GetFaceInfo(mesh, face, ind_elt1, ind_elt2, face_id1, face_id2, nb_rot1, nb_rot2);
|
||||
FaceElementTransformations* face_tr = mesh->GetFaceElementTransformations(face);
|
||||
int perm1, perm2;
|
||||
// cout << "ind_elt1=" << ind_elt1 << ", face_id1=" << face_id1 << ", nb_rot1=" << nb_rot1 << ", ind_elt2=" << ind_elt2 << ", face_id2=" << face_id2 << ", nb_rot2=" << nb_rot2 << endl;
|
||||
for (int kf = 0; kf < quads; ++kf)
|
||||
{
|
||||
const IntegrationPoint& ip = ir.IntPoint(kf);
|
||||
if(ind_elt2!=-1){//Not a boundary face
|
||||
Tensor<1,int> ind_f1(dim-1), ind_f2(dim-1);
|
||||
// We compute the lexicographical index on each face
|
||||
int k1 = GetFaceQuadIndex(dim,face_id1,nb_rot1,kf,quads1d,ind_f1);
|
||||
int k2 = GetFaceQuadIndex(dim,face_id2,nb_rot2,kf,quads1d,ind_f2);
|
||||
this->initFaceData(dim,ind_elt1,face_id1,nb_rot1,perm1,ind_elt2,face_id2,nb_rot2,perm2);
|
||||
face_tr->Face->SetIntPoint( &ip );
|
||||
IntegrationPoint eip1;
|
||||
face_tr->Loc1.Transform(ip,eip1);
|
||||
eip1.weight = ip.weight;//Sets the weight since Transform doesn't do it...
|
||||
// face_tr->Elem1->SetIntPoint( &eip1 );
|
||||
IntegrationPoint eip2;
|
||||
face_tr->Loc2.Transform(ip,eip2);
|
||||
eip2.weight = ip.weight;//Sets the weight since Transform doesn't do it...
|
||||
// face_tr->Elem2->SetIntPoint( &eip2 );
|
||||
int kg1 = GetGlobalQuadIndex(dim,face_id1,quads1d,ind_f1);
|
||||
int kg2 = GetGlobalQuadIndex(dim,face_id2,quads1d,ind_f2);
|
||||
Tensor<2> J_e1(&Jac(0,0,kg1,ind_elt1),dim,dim);
|
||||
Tensor<2> J_e2(&Jac(0,0,kg2,ind_elt2),dim,dim);
|
||||
Tensor<2> Adj(dim,dim);
|
||||
adjugate(J_e1,Adj);
|
||||
calcOrtho( Adj, face_id1, normal); // normal*determinant (risky, bug prone)
|
||||
this->evalEq(dim,k1,k2,n,ind_elt1,face_id1,ind_elt2,face_id2,face_tr,eip1,eip2,J_e1,J_e2,args);
|
||||
// FaceInfo face_info = {dim,k1,k2,n,ind_elt1,face_id1,ind_elt2,face_id2,face_tr,eip1,eip2,J_e1,J_e2};
|
||||
// this->evalEq(face_info,args);
|
||||
}else{//Boundary face
|
||||
this->initBoundaryFaceData(ind_elt1,face_id1);
|
||||
// TODO: Something should be done here when there is boundary conditions!
|
||||
// D11(ind) = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Perform the action of the BilinearFormIntegrator
|
||||
virtual void AddMult(const Vector &fun, Vector &vect)
|
||||
{
|
||||
int dim = this->fes->GetFE(0)->GetDim();
|
||||
switch(dim)
|
||||
{
|
||||
case 1:
|
||||
mfem_error("Not yet implemented");
|
||||
break;
|
||||
case 2:
|
||||
this->EvalInt2D(fun, vect);
|
||||
this->EvalExt2D(fun, vect);
|
||||
break;
|
||||
case 3:
|
||||
this->EvalInt3D(fun, vect);
|
||||
this->EvalExt3D(fun, vect);
|
||||
break;
|
||||
default:
|
||||
mfem_error("Face Kernel does not exist for this dimension.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //MFEM_PAK
|
||||
@@ -239,20 +239,6 @@ void ParBilinearForm::Assemble(int skip_zeros)
|
||||
}
|
||||
}
|
||||
|
||||
void ParBilinearForm::AssembleForm(BilinearFormOperator &A, int skip_zeros)
|
||||
{
|
||||
A.Assemble(this);
|
||||
oper = &A;
|
||||
oper_type = MFEM_FORMOPER;
|
||||
}
|
||||
|
||||
void ParBilinearForm::AssembleForm(HypreParMatrix &A, int skip_zeros)
|
||||
{
|
||||
Assemble(skip_zeros);
|
||||
oper = &A;
|
||||
oper_type = Hypre_ParCSR;
|
||||
}
|
||||
|
||||
void ParBilinearForm
|
||||
::ParallelEliminateEssentialBC(const Array<int> &bdr_attr_is_ess,
|
||||
HypreParMatrix &A, const HypreParVector &X,
|
||||
@@ -338,43 +324,6 @@ void ParBilinearForm::FormLinearSystem(
|
||||
}
|
||||
}
|
||||
|
||||
template <typename OpType>
|
||||
void ParBilinearForm::FormLinearSystem(const Array<int> &ess_tdof_list, Vector &x, Vector &b,
|
||||
OpType &A, Vector &X, Vector &B,
|
||||
int copy_interior)
|
||||
{
|
||||
OperatorHandle Ah;
|
||||
FormLinearSystem(ess_tdof_list, x, b, Ah, X, B, copy_interior);
|
||||
OpType *A_ptr = Ah.Is<OpType>();
|
||||
MFEM_VERIFY(A_ptr, "invalid OpType used");
|
||||
A.MakeRef(*A_ptr);
|
||||
}
|
||||
|
||||
template <>
|
||||
void ParBilinearForm::FormLinearSystem<Operator*>(const Array<int> &ess_tdof_list, Vector &x, Vector &b,
|
||||
Operator * &A, Vector &X, Vector &B,
|
||||
int copy_interior)
|
||||
{
|
||||
if (oper_type == Hypre_ParCSR)
|
||||
{
|
||||
HypreParMatrix &Amat = static_cast<HypreParMatrix&>(*oper);
|
||||
FormLinearSystem(ess_tdof_list, x, b, Amat,
|
||||
X, B, copy_interior);
|
||||
HypreParMatrix *M = new HypreParMatrix;
|
||||
M->MakeRef(Amat);
|
||||
A = M;
|
||||
}
|
||||
else if (oper_type == MFEM_FORMOPER)
|
||||
{
|
||||
oper->FormLinearSystem(ess_tdof_list, x, b, A, X, B, copy_interior);
|
||||
}
|
||||
else
|
||||
{
|
||||
mfem_error("Not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ParBilinearForm::FormSystemMatrix(const Array<int> &ess_tdof_list,
|
||||
OperatorHandle &A)
|
||||
{
|
||||
|
||||
@@ -70,9 +70,6 @@ public:
|
||||
/// Assemble the local matrix
|
||||
void Assemble(int skip_zeros = 1);
|
||||
|
||||
void AssembleForm(BilinearFormOperator &A, int skip_zeros = 1);
|
||||
void AssembleForm(HypreParMatrix &A, int skip_zeros = 1);
|
||||
|
||||
/// Returns the matrix assembled on the true dofs, i.e. P^t A P.
|
||||
/** The returned matrix has to be deleted by the caller. */
|
||||
HypreParMatrix *ParallelAssemble() { return ParallelAssemble(mat); }
|
||||
@@ -181,7 +178,14 @@ public:
|
||||
template <typename OpType>
|
||||
void FormLinearSystem(const Array<int> &ess_tdof_list, Vector &x, Vector &b,
|
||||
OpType &A, Vector &X, Vector &B,
|
||||
int copy_interior = 0);
|
||||
int copy_interior = 0)
|
||||
{
|
||||
OperatorHandle Ah;
|
||||
FormLinearSystem(ess_tdof_list, x, b, Ah, X, B, copy_interior);
|
||||
OpType *A_ptr = Ah.Is<OpType>();
|
||||
MFEM_VERIFY(A_ptr, "invalid OpType used");
|
||||
A.MakeRef(*A_ptr);
|
||||
}
|
||||
|
||||
/// Form the linear system matrix @a A, see FormLinearSystem() for details.
|
||||
void FormSystemMatrix(const Array<int> &ess_tdof_list, OperatorHandle &A);
|
||||
|
||||
+18
-18
@@ -1229,7 +1229,7 @@ void ParFiniteElementSpace::GetGhostDofs(int entity, const MeshId &id,
|
||||
}
|
||||
}
|
||||
|
||||
void ParFiniteElementSpace::GetBareDofs(int entity, const MeshId &id,
|
||||
void ParFiniteElementSpace::GetBareDofs(int entity, int index,
|
||||
Array<int> &dofs) const
|
||||
{
|
||||
int ned, ghost, first;
|
||||
@@ -1238,25 +1238,25 @@ void ParFiniteElementSpace::GetBareDofs(int entity, const MeshId &id,
|
||||
case 0:
|
||||
ned = fec->DofForGeometry(Geometry::POINT);
|
||||
ghost = pncmesh->GetNVertices();
|
||||
first = (id.index < ghost)
|
||||
? id.index*ned // regular vertex
|
||||
: ndofs + (id.index - ghost)*ned; // ghost vertex
|
||||
first = (index < ghost)
|
||||
? index*ned // regular vertex
|
||||
: ndofs + (index - ghost)*ned; // ghost vertex
|
||||
break;
|
||||
|
||||
case 1:
|
||||
ned = fec->DofForGeometry(Geometry::SEGMENT);
|
||||
ghost = pncmesh->GetNEdges();
|
||||
first = (id.index < ghost)
|
||||
? nvdofs + id.index*ned // regular edge
|
||||
: ndofs + ngvdofs + (id.index - ghost)*ned; // ghost edge
|
||||
first = (index < ghost)
|
||||
? nvdofs + index*ned // regular edge
|
||||
: ndofs + ngvdofs + (index - ghost)*ned; // ghost edge
|
||||
break;
|
||||
|
||||
default:
|
||||
ned = fec->DofForGeometry(mesh->GetFaceBaseGeometry(0));
|
||||
ghost = pncmesh->GetNFaces();
|
||||
first = (id.index < ghost)
|
||||
? nvdofs + nedofs + id.index*ned // regular face
|
||||
: ndofs + ngvdofs + ngedofs + (id.index - ghost)*ned; // ghost
|
||||
first = (index < ghost)
|
||||
? nvdofs + nedofs + index*ned // regular face
|
||||
: ndofs + ngvdofs + ngedofs + (index - ghost)*ned; // ghost
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1674,7 +1674,7 @@ void ParFiniteElementSpace::ForwardRow(const PMatrixRow &row, int dof,
|
||||
|
||||
#ifdef MFEM_DEBUG_PMATRIX
|
||||
void ParFiniteElementSpace
|
||||
::DebugDumpDOFs(std::ofstream &os,
|
||||
::DebugDumpDOFs(std::ostream &os,
|
||||
const SparseMatrix &deps,
|
||||
const Array<GroupId> &dof_group,
|
||||
const Array<GroupId> &dof_owner,
|
||||
@@ -1800,9 +1800,6 @@ int ParFiniteElementSpace
|
||||
}
|
||||
}
|
||||
|
||||
// make sure all master DOFs are transmitted to participating slave ranks
|
||||
pncmesh->AugmentMasterGroups();
|
||||
|
||||
deps.Finalize();
|
||||
}
|
||||
|
||||
@@ -1820,7 +1817,7 @@ int ParFiniteElementSpace
|
||||
// initialize dof_group[], dof_owner[]
|
||||
for (int entity = 0; entity <= 2; entity++)
|
||||
{
|
||||
const NCMesh::NCList &list = pncmesh->GetSharedList(entity);
|
||||
const NCMesh::NCList &list = pncmesh->GetNCList(entity);
|
||||
|
||||
std::size_t lsize[3] =
|
||||
{ list.conforming.size(), list.masters.size(), list.slaves.size() };
|
||||
@@ -1834,13 +1831,16 @@ int ParFiniteElementSpace
|
||||
(l == 1) ? (const MeshId&) list.masters[i]
|
||||
/* */ : (const MeshId&) list.slaves[i];
|
||||
|
||||
GetBareDofs(entity, id, dofs);
|
||||
GroupId owner = pncmesh->GetEntityOwnerId(entity, id.index);
|
||||
GroupId group = pncmesh->GetEntityGroupId(entity, id.index);
|
||||
|
||||
GetBareDofs(entity, id.index, dofs);
|
||||
|
||||
for (int j = 0; j < dofs.Size(); j++)
|
||||
{
|
||||
int dof = dofs[j];
|
||||
dof_owner[dof] = pncmesh->GetOwnerId(entity, id.index);
|
||||
dof_group[dof] = pncmesh->GetGroupId(entity, id.index);
|
||||
dof_owner[dof] = owner;
|
||||
dof_group[dof] = group;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user